summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.xml279
-rw-r--r--docs/development/scala.dbc/SQLTypes.dot48
-rw-r--r--gitignore.SAMPLE5
-rw-r--r--lib/forkjoin.jar.desired.sha12
-rw-r--r--lib/scala-compiler.jar.desired.sha12
-rw-r--r--lib/scala-library-src.jar.desired.sha12
-rw-r--r--lib/scala-library.jar.desired.sha12
-rw-r--r--project/Build.scala12
-rw-r--r--src/build/genprod.scala249
-rw-r--r--src/build/maven/maven-deploy.xml3
-rw-r--r--src/build/maven/scala-dbc-pom.xml61
-rw-r--r--src/build/maven/scala-library-pom.xml6
-rw-r--r--src/build/pack.xml5
-rw-r--r--src/compiler/scala/reflect/internal/AnnotationInfos.scala43
-rw-r--r--src/compiler/scala/reflect/internal/CapturedVariables.scala36
-rw-r--r--src/compiler/scala/reflect/internal/ClassfileConstants.scala2
-rw-r--r--src/compiler/scala/reflect/internal/ClassfileModel.scala169
-rw-r--r--src/compiler/scala/reflect/internal/ConstantPool.scala78
-rw-r--r--src/compiler/scala/reflect/internal/Constants.scala10
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala760
-rw-r--r--src/compiler/scala/reflect/internal/Flags.scala217
-rw-r--r--src/compiler/scala/reflect/internal/FreeVars.scala60
-rw-r--r--src/compiler/scala/reflect/internal/FrontEnds.scala75
-rw-r--r--src/compiler/scala/reflect/internal/HasFlags.scala181
-rw-r--r--src/compiler/scala/reflect/internal/Importers.scala61
-rw-r--r--src/compiler/scala/reflect/internal/JvmClassInfo.scala220
-rw-r--r--src/compiler/scala/reflect/internal/NameManglers.scala212
-rw-r--r--src/compiler/scala/reflect/internal/Names.scala11
-rw-r--r--src/compiler/scala/reflect/internal/Positions.scala38
-rw-r--r--src/compiler/scala/reflect/internal/Required.scala7
-rw-r--r--src/compiler/scala/reflect/internal/Scopes.scala2
-rw-r--r--src/compiler/scala/reflect/internal/StdAttachments.scala10
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala609
-rw-r--r--src/compiler/scala/reflect/internal/SymbolCreations.scala112
-rw-r--r--src/compiler/scala/reflect/internal/SymbolFlags.scala175
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala75
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala1472
-rw-r--r--src/compiler/scala/reflect/internal/TreeBuildUtil.scala66
-rw-r--r--src/compiler/scala/reflect/internal/TreeGen.scala20
-rw-r--r--src/compiler/scala/reflect/internal/TreeInfo.scala217
-rw-r--r--src/compiler/scala/reflect/internal/TreePrinters.scala24
-rw-r--r--src/compiler/scala/reflect/internal/Trees.scala112
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala358
-rw-r--r--src/compiler/scala/reflect/internal/pickling/UnPickler.scala45
-rw-r--r--src/compiler/scala/reflect/internal/settings/MutableSettings.scala2
-rw-r--r--src/compiler/scala/reflect/internal/transform/Erasure.scala7
-rw-r--r--src/compiler/scala/reflect/internal/transform/UnCurry.scala16
-rw-r--r--src/compiler/scala/reflect/internal/util/Collections.scala45
-rw-r--r--src/compiler/scala/reflect/internal/util/Origins.scala2
-rw-r--r--src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala168
-rw-r--r--src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala6
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Aliases.scala21
-rw-r--r--src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala14
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Context.scala27
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Enclosures.scala23
-rw-r--r--src/compiler/scala/reflect/makro/runtime/FrontEnds.scala44
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Infrastructure.scala34
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Names.scala20
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Reifiers.scala34
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Settings.scala36
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Symbols.scala10
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Traces.scala8
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Typers.scala75
-rw-r--r--src/compiler/scala/reflect/makro/runtime/Util.scala34
-rw-r--r--src/compiler/scala/reflect/makro/util/Traces.scala18
-rw-r--r--src/compiler/scala/reflect/reify/Errors.scala60
-rw-r--r--src/compiler/scala/reflect/reify/NodePrinters.scala111
-rw-r--r--src/compiler/scala/reflect/reify/Phases.scala42
-rw-r--r--src/compiler/scala/reflect/reify/Reifier.scala164
-rw-r--r--src/compiler/scala/reflect/reify/codegen/AnnotationInfos.scala56
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Names.scala15
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Positions.scala18
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Symbols.scala184
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Trees.scala259
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Types.scala168
-rw-r--r--src/compiler/scala/reflect/reify/codegen/Util.scala112
-rw-r--r--src/compiler/scala/reflect/reify/package.scala59
-rw-r--r--src/compiler/scala/reflect/reify/phases/Calculate.scala60
-rw-r--r--src/compiler/scala/reflect/reify/phases/Metalevels.scala150
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reify.scala65
-rw-r--r--src/compiler/scala/reflect/reify/phases/Reshape.scala290
-rw-r--r--src/compiler/scala/reflect/runtime/AbstractFile.scala11
-rw-r--r--src/compiler/scala/reflect/runtime/ClassLoaders.scala25
-rw-r--r--src/compiler/scala/reflect/runtime/ConversionUtil.scala1
-rw-r--r--src/compiler/scala/reflect/runtime/JavaToScala.scala232
-rw-r--r--src/compiler/scala/reflect/runtime/Memoizer.scala15
-rw-r--r--src/compiler/scala/reflect/runtime/Mirror.scala38
-rw-r--r--src/compiler/scala/reflect/runtime/RuntimeTypes.scala27
-rw-r--r--src/compiler/scala/reflect/runtime/Settings.scala2
-rw-r--r--src/compiler/scala/reflect/runtime/SymbolLoaders.scala (renamed from src/compiler/scala/reflect/runtime/Loaders.scala)7
-rw-r--r--src/compiler/scala/reflect/runtime/SymbolTable.scala23
-rw-r--r--src/compiler/scala/reflect/runtime/SynchronizedOps.scala2
-rw-r--r--src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala75
-rw-r--r--src/compiler/scala/reflect/runtime/ToolBoxes.scala363
-rw-r--r--src/compiler/scala/reflect/runtime/TreeBuildUtil.scala49
-rw-r--r--src/compiler/scala/reflect/runtime/Universe.scala20
-rw-r--r--src/compiler/scala/reflect/runtime/package.scala5
-rw-r--r--src/compiler/scala/tools/ant/Scaladoc.scala70
-rw-r--r--src/compiler/scala/tools/asm/AnnotationVisitor.java157
-rw-r--r--src/compiler/scala/tools/asm/AnnotationWriter.java322
-rw-r--r--src/compiler/scala/tools/asm/Attribute.java254
-rw-r--r--src/compiler/scala/tools/asm/ByteVector.java293
-rw-r--r--src/compiler/scala/tools/asm/ClassReader.java2216
-rw-r--r--src/compiler/scala/tools/asm/ClassVisitor.java277
-rw-r--r--src/compiler/scala/tools/asm/ClassWriter.java1672
-rw-r--r--src/compiler/scala/tools/asm/CustomAttr.java20
-rw-r--r--src/compiler/scala/tools/asm/Edge.java75
-rw-r--r--src/compiler/scala/tools/asm/FieldVisitor.java115
-rw-r--r--src/compiler/scala/tools/asm/FieldWriter.java271
-rw-r--r--src/compiler/scala/tools/asm/Frame.java1435
-rw-r--r--src/compiler/scala/tools/asm/Handle.java159
-rw-r--r--src/compiler/scala/tools/asm/Handler.java118
-rw-r--r--src/compiler/scala/tools/asm/Item.java297
-rw-r--r--src/compiler/scala/tools/asm/Label.java555
-rw-r--r--src/compiler/scala/tools/asm/MethodVisitor.java588
-rw-r--r--src/compiler/scala/tools/asm/MethodWriter.java2666
-rw-r--r--src/compiler/scala/tools/asm/Opcodes.java358
-rw-r--r--src/compiler/scala/tools/asm/Type.java865
-rw-r--r--src/compiler/scala/tools/asm/signature/SignatureReader.java229
-rw-r--r--src/compiler/scala/tools/asm/signature/SignatureVisitor.java228
-rw-r--r--src/compiler/scala/tools/asm/signature/SignatureWriter.java227
-rw-r--r--src/compiler/scala/tools/asm/tree/AbstractInsnNode.java238
-rw-r--r--src/compiler/scala/tools/asm/tree/AnnotationNode.java224
-rw-r--r--src/compiler/scala/tools/asm/tree/ClassNode.java371
-rw-r--r--src/compiler/scala/tools/asm/tree/FieldInsnNode.java106
-rw-r--r--src/compiler/scala/tools/asm/tree/FieldNode.java243
-rw-r--r--src/compiler/scala/tools/asm/tree/FrameNode.java211
-rw-r--r--src/compiler/scala/tools/asm/tree/IincInsnNode.java80
-rw-r--r--src/compiler/scala/tools/asm/tree/InnerClassNode.java101
-rw-r--r--src/compiler/scala/tools/asm/tree/InsnList.java578
-rw-r--r--src/compiler/scala/tools/asm/tree/InsnNode.java84
-rw-r--r--src/compiler/scala/tools/asm/tree/IntInsnNode.java84
-rw-r--r--src/compiler/scala/tools/asm/tree/InvokeDynamicInsnNode.java100
-rw-r--r--src/compiler/scala/tools/asm/tree/JumpInsnNode.java92
-rw-r--r--src/compiler/scala/tools/asm/tree/LabelNode.java78
-rw-r--r--src/compiler/scala/tools/asm/tree/LdcInsnNode.java77
-rw-r--r--src/compiler/scala/tools/asm/tree/LineNumberNode.java82
-rw-r--r--src/compiler/scala/tools/asm/tree/LocalVariableNode.java115
-rw-r--r--src/compiler/scala/tools/asm/tree/LookupSwitchInsnNode.java116
-rw-r--r--src/compiler/scala/tools/asm/tree/MethodInsnNode.java107
-rw-r--r--src/compiler/scala/tools/asm/tree/MethodNode.java645
-rw-r--r--src/compiler/scala/tools/asm/tree/MultiANewArrayInsnNode.java81
-rw-r--r--src/compiler/scala/tools/asm/tree/TableSwitchInsnNode.java115
-rw-r--r--src/compiler/scala/tools/asm/tree/TryCatchBlockNode.java94
-rw-r--r--src/compiler/scala/tools/asm/tree/TypeInsnNode.java87
-rw-r--r--src/compiler/scala/tools/asm/tree/VarInsnNode.java90
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/Analyzer.java549
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/AnalyzerException.java64
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/BasicInterpreter.java365
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/BasicValue.java108
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/BasicVerifier.java459
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/Frame.java709
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/Interpreter.java204
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/SimpleVerifier.java329
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/SmallSet.java134
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/SourceInterpreter.java206
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/SourceValue.java97
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/Subroutine.java93
-rw-r--r--src/compiler/scala/tools/asm/tree/analysis/Value.java45
-rw-r--r--src/compiler/scala/tools/asm/util/ASMifiable.java53
-rw-r--r--src/compiler/scala/tools/asm/util/ASMifier.java1238
-rw-r--r--src/compiler/scala/tools/asm/util/CheckAnnotationAdapter.java142
-rw-r--r--src/compiler/scala/tools/asm/util/CheckClassAdapter.java603
-rw-r--r--src/compiler/scala/tools/asm/util/CheckFieldAdapter.java97
-rw-r--r--src/compiler/scala/tools/asm/util/CheckMethodAdapter.java1668
-rw-r--r--src/compiler/scala/tools/asm/util/CheckSignatureAdapter.java329
-rw-r--r--src/compiler/scala/tools/asm/util/Printer.java558
-rw-r--r--src/compiler/scala/tools/asm/util/SignatureChecker.java47
-rw-r--r--src/compiler/scala/tools/asm/util/Textifiable.java54
-rw-r--r--src/compiler/scala/tools/asm/util/Textifier.java1286
-rw-r--r--src/compiler/scala/tools/asm/util/TraceAnnotationVisitor.java96
-rw-r--r--src/compiler/scala/tools/asm/util/TraceClassVisitor.java232
-rw-r--r--src/compiler/scala/tools/asm/util/TraceFieldVisitor.java78
-rw-r--r--src/compiler/scala/tools/asm/util/TraceMethodVisitor.java264
-rw-r--r--src/compiler/scala/tools/asm/util/TraceSignatureVisitor.java318
-rw-r--r--src/compiler/scala/tools/cmd/FromString.scala6
-rw-r--r--src/compiler/scala/tools/cmd/gen/AnyVals.scala81
-rw-r--r--src/compiler/scala/tools/cmd/program/DumpClass.scala40
-rw-r--r--src/compiler/scala/tools/nsc/ClassLoaders.scala64
-rw-r--r--src/compiler/scala/tools/nsc/CompilationUnits.scala22
-rw-r--r--src/compiler/scala/tools/nsc/CompileSocket.scala4
-rw-r--r--src/compiler/scala/tools/nsc/CompilerCommand.scala2
-rw-r--r--src/compiler/scala/tools/nsc/GenericRunnerSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala132
-rw-r--r--src/compiler/scala/tools/nsc/MacroContext.scala10
-rw-r--r--src/compiler/scala/tools/nsc/PhaseAssembly.scala1
-rw-r--r--src/compiler/scala/tools/nsc/Phases.scala3
-rw-r--r--src/compiler/scala/tools/nsc/ReflectGlobal.scala7
-rw-r--r--src/compiler/scala/tools/nsc/ReflectMain.scala11
-rw-r--r--src/compiler/scala/tools/nsc/ToolBoxes.scala84
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala47
-rw-r--r--src/compiler/scala/tools/nsc/ast/FreeVars.scala26
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala81
-rw-r--r--src/compiler/scala/tools/nsc/ast/Positions.scala44
-rw-r--r--src/compiler/scala/tools/nsc/ast/Reifiers.scala761
-rw-r--r--src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala75
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala1
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeDSL.scala9
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeGen.scala78
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreeInfo.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala156
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala242
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala53
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala14
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Tokens.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala22
-rw-r--r--src/compiler/scala/tools/nsc/backend/JavaPlatform.scala16
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Members.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala61
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/Primitives.scala19
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala6
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala40
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala3288
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala32
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala7
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/backend/opt/Inliners.scala47
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala6
-rw-r--r--src/compiler/scala/tools/nsc/doc/Settings.scala131
-rw-r--r--src/compiler/scala/tools/nsc/doc/Uncompilable.scala6
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala12
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala8
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala160
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/conversionbg.gifbin0 -> 167 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js2
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.js158
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js5442
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-implicits.pngbin0 -> 1150 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-right-implicits.pngbin0 -> 646 bytes
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css101
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js104
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala107
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala3
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala125
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala520
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/model/TreeFactory.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/BuildManager.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RangePositions.scala5
-rw-r--r--src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala25
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/FindOccurrences.scala28
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala22
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala12
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala117
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala183
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala216
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala14
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/NamedParam.scala15
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Naming.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Phased.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala52
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala57
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ReplVals.scala35
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/RichClass.scala13
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala161
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/package.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/session/package.scala1
-rw-r--r--src/compiler/scala/tools/nsc/io/AbstractFile.scala3
-rw-r--r--src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala6
-rw-r--r--src/compiler/scala/tools/nsc/io/File.scala1
-rw-r--r--src/compiler/scala/tools/nsc/io/Jar.scala1
-rw-r--r--src/compiler/scala/tools/nsc/io/Path.scala1
-rw-r--r--src/compiler/scala/tools/nsc/io/Pickler.scala8
-rw-r--r--src/compiler/scala/tools/nsc/io/PlainFile.scala1
-rw-r--r--src/compiler/scala/tools/nsc/io/package.scala5
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala14
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaScanners.scala1
-rw-r--r--src/compiler/scala/tools/nsc/matching/MatchSupport.scala6
-rw-r--r--src/compiler/scala/tools/nsc/matching/Matrix.scala3
-rw-r--r--src/compiler/scala/tools/nsc/matching/ParallelMatching.scala1
-rw-r--r--src/compiler/scala/tools/nsc/matching/PatternBindings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/matching/Patterns.scala6
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugin.scala2
-rw-r--r--src/compiler/scala/tools/nsc/plugins/Plugins.scala4
-rw-r--r--src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala11
-rw-r--r--src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala1
-rw-r--r--src/compiler/scala/tools/nsc/scratchpad/Executor.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/AbsSettings.scala2
-rw-r--r--src/compiler/scala/tools/nsc/settings/AestheticSettings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/settings/MutableSettings.scala8
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala159
-rw-r--r--src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Positions.scala30
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala10
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTable.scala3
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala266
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala166
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala21
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala1
-rw-r--r--src/compiler/scala/tools/nsc/transform/AddInterfaces.scala204
-rw-r--r--src/compiler/scala/tools/nsc/transform/CleanUp.scala15
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala33
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala26
-rw-r--r--src/compiler/scala/tools/nsc/transform/LazyVals.scala92
-rw-r--r--src/compiler/scala/tools/nsc/transform/Mixin.scala287
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala164
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala306
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala83
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala87
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala206
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala196
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala81
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala1456
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala201
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Modes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala148
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala28
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala (renamed from src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala)241
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala92
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala10
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Taggings.scala71
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala45
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala23
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala918
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Unapplies.scala17
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala14
-rw-r--r--src/compiler/scala/tools/nsc/util/CommandLineParser.scala3
-rw-r--r--src/compiler/scala/tools/nsc/util/Exceptional.scala1
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala134
-rw-r--r--src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala12
-rw-r--r--src/compiler/scala/tools/nsc/util/Statistics.scala55
-rw-r--r--src/compiler/scala/tools/nsc/util/WeakHashSet.scala3
-rw-r--r--src/compiler/scala/tools/nsc/util/package.scala2
-rw-r--r--src/compiler/scala/tools/reflect/Invoked.scala2
-rw-r--r--src/compiler/scala/tools/reflect/UniversalFn.scala4
-rw-r--r--src/compiler/scala/tools/reflect/package.scala22
-rw-r--r--src/compiler/scala/tools/util/StringOps.scala10
-rw-r--r--src/continuations/library/scala/util/continuations/ControlContext.scala2
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala88
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala4
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala214
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala19
-rw-r--r--src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala48
-rw-r--r--src/dbc/scala/dbc/DataType.scala69
-rw-r--r--src/dbc/scala/dbc/Database.scala187
-rw-r--r--src/dbc/scala/dbc/Syntax.scala47
-rw-r--r--src/dbc/scala/dbc/Utilities.scala28
-rw-r--r--src/dbc/scala/dbc/Value.scala27
-rw-r--r--src/dbc/scala/dbc/Vendor.scala41
-rw-r--r--src/dbc/scala/dbc/datatype/ApproximateNumeric.scala57
-rw-r--r--src/dbc/scala/dbc/datatype/Boolean.scala31
-rw-r--r--src/dbc/scala/dbc/datatype/Character.scala40
-rw-r--r--src/dbc/scala/dbc/datatype/CharacterLargeObject.scala31
-rw-r--r--src/dbc/scala/dbc/datatype/CharacterString.scala24
-rw-r--r--src/dbc/scala/dbc/datatype/CharacterVarying.scala41
-rw-r--r--src/dbc/scala/dbc/datatype/ExactNumeric.scala65
-rw-r--r--src/dbc/scala/dbc/datatype/Factory.scala250
-rw-r--r--src/dbc/scala/dbc/datatype/Numeric.scala32
-rw-r--r--src/dbc/scala/dbc/datatype/String.scala24
-rw-r--r--src/dbc/scala/dbc/datatype/Unknown.scala34
-rw-r--r--src/dbc/scala/dbc/exception/IncompatibleSchema.scala19
-rw-r--r--src/dbc/scala/dbc/package.scala6
-rw-r--r--src/dbc/scala/dbc/result/Field.scala63
-rw-r--r--src/dbc/scala/dbc/result/FieldMetadata.scala40
-rw-r--r--src/dbc/scala/dbc/result/Relation.scala84
-rw-r--r--src/dbc/scala/dbc/result/Status.scala28
-rw-r--r--src/dbc/scala/dbc/result/Tuple.scala42
-rw-r--r--src/dbc/scala/dbc/statement/DerivedColumn.scala38
-rw-r--r--src/dbc/scala/dbc/statement/Expression.scala28
-rw-r--r--src/dbc/scala/dbc/statement/Insert.scala31
-rw-r--r--src/dbc/scala/dbc/statement/InsertionData.scala40
-rw-r--r--src/dbc/scala/dbc/statement/IsolationLevel.scala32
-rw-r--r--src/dbc/scala/dbc/statement/JoinType.scala56
-rw-r--r--src/dbc/scala/dbc/statement/Jointure.scala45
-rw-r--r--src/dbc/scala/dbc/statement/Relation.scala55
-rw-r--r--src/dbc/scala/dbc/statement/Select.scala99
-rw-r--r--src/dbc/scala/dbc/statement/SetQuantifier.scala38
-rw-r--r--src/dbc/scala/dbc/statement/Status.scala32
-rw-r--r--src/dbc/scala/dbc/statement/Table.scala38
-rw-r--r--src/dbc/scala/dbc/statement/Transaction.scala55
-rw-r--r--src/dbc/scala/dbc/statement/Update.scala47
-rw-r--r--src/dbc/scala/dbc/statement/expression/Aggregate.scala35
-rw-r--r--src/dbc/scala/dbc/statement/expression/BinaryOperator.scala33
-rw-r--r--src/dbc/scala/dbc/statement/expression/Constant.scala23
-rw-r--r--src/dbc/scala/dbc/statement/expression/Default.scala22
-rw-r--r--src/dbc/scala/dbc/statement/expression/Field.scala40
-rw-r--r--src/dbc/scala/dbc/statement/expression/FunctionCall.scala33
-rw-r--r--src/dbc/scala/dbc/statement/expression/Select.scala28
-rw-r--r--src/dbc/scala/dbc/statement/expression/SetFunction.scala40
-rw-r--r--src/dbc/scala/dbc/statement/expression/TypeCast.scala32
-rw-r--r--src/dbc/scala/dbc/statement/expression/UnaryOperator.scala33
-rw-r--r--src/dbc/scala/dbc/syntax/DataTypeUtil.scala98
-rw-r--r--src/dbc/scala/dbc/syntax/Database.scala33
-rw-r--r--src/dbc/scala/dbc/syntax/Statement.scala274
-rw-r--r--src/dbc/scala/dbc/syntax/StatementExpression.scala221
-rw-r--r--src/dbc/scala/dbc/value/ApproximateNumeric.scala28
-rw-r--r--src/dbc/scala/dbc/value/Boolean.scala27
-rw-r--r--src/dbc/scala/dbc/value/Character.scala35
-rw-r--r--src/dbc/scala/dbc/value/CharacterLargeObject.scala35
-rw-r--r--src/dbc/scala/dbc/value/CharacterVarying.scala35
-rw-r--r--src/dbc/scala/dbc/value/Conversion.scala156
-rw-r--r--src/dbc/scala/dbc/value/ExactNumeric.scala35
-rw-r--r--src/dbc/scala/dbc/value/Factory.scala95
-rw-r--r--src/dbc/scala/dbc/value/Unknown.scala27
-rw-r--r--src/dbc/scala/dbc/vendor/PostgreSQL.scala29
-rw-r--r--src/detach/library/scala/remoting/Channel.scala32
-rw-r--r--src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java414
-rw-r--r--src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java195
-rw-r--r--src/intellij/dbc.iml.SAMPLE3
-rw-r--r--src/intellij/scala-lang.ipr.SAMPLE1
-rw-r--r--src/library/rootdoc.txt4
-rw-r--r--src/library/scala/Array.scala65
-rw-r--r--src/library/scala/Boolean.scala4
-rw-r--r--src/library/scala/Byte.scala211
-rw-r--r--src/library/scala/Char.scala210
-rw-r--r--src/library/scala/DelayedInit.scala32
-rw-r--r--src/library/scala/Double.scala162
-rw-r--r--src/library/scala/Dynamic.scala23
-rw-r--r--src/library/scala/Either.scala19
-rw-r--r--src/library/scala/Enumeration.scala9
-rw-r--r--src/library/scala/Float.scala163
-rw-r--r--src/library/scala/Function0.scala6
-rw-r--r--src/library/scala/Function1.scala8
-rw-r--r--src/library/scala/Function10.scala7
-rw-r--r--src/library/scala/Function11.scala7
-rw-r--r--src/library/scala/Function12.scala7
-rw-r--r--src/library/scala/Function13.scala7
-rw-r--r--src/library/scala/Function14.scala7
-rw-r--r--src/library/scala/Function15.scala7
-rw-r--r--src/library/scala/Function16.scala7
-rw-r--r--src/library/scala/Function17.scala7
-rw-r--r--src/library/scala/Function18.scala7
-rw-r--r--src/library/scala/Function19.scala7
-rw-r--r--src/library/scala/Function2.scala11
-rw-r--r--src/library/scala/Function20.scala7
-rw-r--r--src/library/scala/Function21.scala7
-rw-r--r--src/library/scala/Function22.scala7
-rw-r--r--src/library/scala/Function3.scala7
-rw-r--r--src/library/scala/Function4.scala7
-rw-r--r--src/library/scala/Function5.scala7
-rw-r--r--src/library/scala/Function6.scala7
-rw-r--r--src/library/scala/Function7.scala7
-rw-r--r--src/library/scala/Function8.scala7
-rw-r--r--src/library/scala/Function9.scala7
-rw-r--r--src/library/scala/Int.scala209
-rw-r--r--src/library/scala/Long.scala208
-rw-r--r--src/library/scala/LowPriorityImplicits.scala1
-rw-r--r--src/library/scala/Option.scala26
-rw-r--r--src/library/scala/Predef.scala152
-rw-r--r--src/library/scala/Product1.scala2
-rw-r--r--src/library/scala/Product10.scala2
-rw-r--r--src/library/scala/Product11.scala2
-rw-r--r--src/library/scala/Product12.scala2
-rw-r--r--src/library/scala/Product13.scala2
-rw-r--r--src/library/scala/Product14.scala2
-rw-r--r--src/library/scala/Product15.scala2
-rw-r--r--src/library/scala/Product16.scala2
-rw-r--r--src/library/scala/Product17.scala2
-rw-r--r--src/library/scala/Product18.scala2
-rw-r--r--src/library/scala/Product19.scala2
-rw-r--r--src/library/scala/Product2.scala2
-rw-r--r--src/library/scala/Product20.scala2
-rw-r--r--src/library/scala/Product21.scala2
-rw-r--r--src/library/scala/Product22.scala2
-rw-r--r--src/library/scala/Product3.scala2
-rw-r--r--src/library/scala/Product4.scala2
-rw-r--r--src/library/scala/Product5.scala2
-rw-r--r--src/library/scala/Product6.scala2
-rw-r--r--src/library/scala/Product7.scala2
-rw-r--r--src/library/scala/Product8.scala2
-rw-r--r--src/library/scala/Product9.scala2
-rw-r--r--src/library/scala/ScalaObject.scala (renamed from src/dbc/scala/dbc/statement/Statement.scala)14
-rw-r--r--src/library/scala/Short.scala210
-rw-r--r--src/library/scala/StringContext.scala28
-rw-r--r--src/library/scala/Tuple2.scala104
-rw-r--r--src/library/scala/Tuple3.scala120
-rw-r--r--src/library/scala/Unit.scala4
-rw-r--r--src/library/scala/annotation/ClassfileAnnotation.scala2
-rw-r--r--src/library/scala/annotation/bridge.scala1
-rw-r--r--src/library/scala/annotation/meta/companionClass.scala17
-rw-r--r--src/library/scala/annotation/meta/companionMethod.scala17
-rw-r--r--src/library/scala/annotation/meta/companionObject.scala14
-rw-r--r--src/library/scala/annotation/meta/languageFeature.scala (renamed from src/dbc/scala/dbc/exception/UnsupportedFeature.scala)17
-rw-r--r--src/library/scala/annotation/switch.scala4
-rw-r--r--src/library/scala/annotation/unspecialized.scala (renamed from src/dbc/scala/dbc/statement/SetClause.scala)22
-rw-r--r--src/library/scala/collection/BitSet.scala2
-rw-r--r--src/library/scala/collection/BitSetLike.scala2
-rw-r--r--src/library/scala/collection/DefaultMap.scala2
-rw-r--r--src/library/scala/collection/GenIterableLike.scala5
-rw-r--r--src/library/scala/collection/GenMapLike.scala2
-rw-r--r--src/library/scala/collection/GenSeqLike.scala14
-rw-r--r--src/library/scala/collection/GenSetLike.scala16
-rw-r--r--src/library/scala/collection/GenTraversableLike.scala51
-rw-r--r--src/library/scala/collection/GenTraversableOnce.scala8
-rw-r--r--src/library/scala/collection/IndexedSeq.scala2
-rw-r--r--src/library/scala/collection/IndexedSeqLike.scala2
-rw-r--r--src/library/scala/collection/Iterable.scala2
-rw-r--r--src/library/scala/collection/IterableLike.scala14
-rw-r--r--src/library/scala/collection/IterableViewLike.scala1
-rw-r--r--src/library/scala/collection/Iterator.scala31
-rw-r--r--src/library/scala/collection/LinearSeq.scala2
-rw-r--r--src/library/scala/collection/Map.scala4
-rw-r--r--src/library/scala/collection/MapLike.scala7
-rw-r--r--src/library/scala/collection/Seq.scala2
-rw-r--r--src/library/scala/collection/SeqExtractors.scala6
-rw-r--r--src/library/scala/collection/SeqLike.scala55
-rw-r--r--src/library/scala/collection/SeqProxyLike.scala2
-rw-r--r--src/library/scala/collection/SeqViewLike.scala5
-rw-r--r--src/library/scala/collection/Set.scala2
-rw-r--r--src/library/scala/collection/SetLike.scala9
-rw-r--r--src/library/scala/collection/Traversable.scala9
-rw-r--r--src/library/scala/collection/TraversableLike.scala10
-rw-r--r--src/library/scala/collection/TraversableOnce.scala52
-rw-r--r--src/library/scala/collection/TraversableProxyLike.scala2
-rw-r--r--src/library/scala/collection/TraversableViewLike.scala21
-rw-r--r--src/library/scala/collection/concurrent/Map.scala2
-rw-r--r--src/library/scala/collection/convert/DecorateAsJava.scala2
-rw-r--r--src/library/scala/collection/convert/DecorateAsScala.scala1
-rw-r--r--src/library/scala/collection/convert/WrapAsJava.scala1
-rw-r--r--src/library/scala/collection/convert/WrapAsScala.scala1
-rw-r--r--src/library/scala/collection/generic/ArrayTagTraversableFactory.scala (renamed from src/library/scala/collection/generic/ClassManifestTraversableFactory.scala)14
-rw-r--r--src/library/scala/collection/generic/BitSetFactory.scala2
-rw-r--r--src/library/scala/collection/generic/Clearable.scala (renamed from src/dbc/scala/dbc/statement/AccessMode.scala)32
-rw-r--r--src/library/scala/collection/generic/GenMapFactory.scala3
-rw-r--r--src/library/scala/collection/generic/GenSeqFactory.scala9
-rw-r--r--src/library/scala/collection/generic/GenSetFactory.scala3
-rw-r--r--src/library/scala/collection/generic/GenTraversableFactory.scala6
-rw-r--r--src/library/scala/collection/generic/GenericArrayTagCompanion.scala (renamed from src/library/scala/collection/generic/GenericClassManifestCompanion.scala)11
-rw-r--r--src/library/scala/collection/generic/GenericArrayTagTraversableTemplate.scala30
-rw-r--r--src/library/scala/collection/generic/GenericClassManifestTraversableTemplate.scala25
-rw-r--r--src/library/scala/collection/generic/GenericCompanion.scala3
-rw-r--r--src/library/scala/collection/generic/GenericOrderedCompanion.scala1
-rw-r--r--src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala3
-rw-r--r--src/library/scala/collection/generic/GenericParCompanion.scala3
-rw-r--r--src/library/scala/collection/generic/GenericParTemplate.scala1
-rw-r--r--src/library/scala/collection/generic/GenericSeqCompanion.scala12
-rw-r--r--src/library/scala/collection/generic/GenericSetTemplate.scala2
-rw-r--r--src/library/scala/collection/generic/GenericTraversableTemplate.scala6
-rw-r--r--src/library/scala/collection/generic/Growable.scala6
-rw-r--r--src/library/scala/collection/generic/ImmutableMapFactory.scala2
-rw-r--r--src/library/scala/collection/generic/ImmutableSetFactory.scala1
-rw-r--r--src/library/scala/collection/generic/ImmutableSortedMapFactory.scala4
-rw-r--r--src/library/scala/collection/generic/ImmutableSortedSetFactory.scala8
-rw-r--r--src/library/scala/collection/generic/MapFactory.scala4
-rw-r--r--src/library/scala/collection/generic/MutableMapFactory.scala1
-rw-r--r--src/library/scala/collection/generic/MutableSetFactory.scala1
-rw-r--r--src/library/scala/collection/generic/MutableSortedSetFactory.scala5
-rw-r--r--src/library/scala/collection/generic/OrderedTraversableFactory.scala4
-rw-r--r--src/library/scala/collection/generic/ParFactory.scala3
-rw-r--r--src/library/scala/collection/generic/ParMapFactory.scala3
-rw-r--r--src/library/scala/collection/generic/ParSetFactory.scala1
-rw-r--r--src/library/scala/collection/generic/SeqFactory.scala1
-rw-r--r--src/library/scala/collection/generic/SetFactory.scala11
-rw-r--r--src/library/scala/collection/generic/Shrinkable.scala2
-rw-r--r--src/library/scala/collection/generic/SortedMapFactory.scala1
-rw-r--r--src/library/scala/collection/generic/SortedSetFactory.scala1
-rw-r--r--src/library/scala/collection/generic/Subtractable.scala4
-rw-r--r--src/library/scala/collection/generic/TraversableFactory.scala47
-rw-r--r--src/library/scala/collection/generic/TraversableForwarder.scala2
-rw-r--r--src/library/scala/collection/generic/package.scala9
-rw-r--r--src/library/scala/collection/immutable/BitSet.scala4
-rw-r--r--src/library/scala/collection/immutable/GenSeq.scala.disabled2
-rw-r--r--src/library/scala/collection/immutable/GenSet.scala.disabled2
-rw-r--r--src/library/scala/collection/immutable/HashMap.scala4
-rw-r--r--src/library/scala/collection/immutable/HashSet.scala6
-rw-r--r--src/library/scala/collection/immutable/IndexedSeq.scala2
-rw-r--r--src/library/scala/collection/immutable/IntMap.scala4
-rw-r--r--src/library/scala/collection/immutable/Iterable.scala4
-rw-r--r--src/library/scala/collection/immutable/LinearSeq.scala2
-rw-r--r--src/library/scala/collection/immutable/List.scala4
-rw-r--r--src/library/scala/collection/immutable/ListMap.scala3
-rw-r--r--src/library/scala/collection/immutable/ListSet.scala6
-rw-r--r--src/library/scala/collection/immutable/LongMap.scala4
-rw-r--r--src/library/scala/collection/immutable/Map.scala2
-rw-r--r--src/library/scala/collection/immutable/MapLike.scala3
-rw-r--r--src/library/scala/collection/immutable/NumericRange.scala9
-rw-r--r--src/library/scala/collection/immutable/PagedSeq.scala12
-rw-r--r--src/library/scala/collection/immutable/Queue.scala4
-rw-r--r--src/library/scala/collection/immutable/Range.scala13
-rw-r--r--src/library/scala/collection/immutable/Seq.scala4
-rw-r--r--src/library/scala/collection/immutable/Set.scala4
-rw-r--r--src/library/scala/collection/immutable/SortedMap.scala3
-rw-r--r--src/library/scala/collection/immutable/SortedSet.scala4
-rw-r--r--src/library/scala/collection/immutable/Stack.scala4
-rw-r--r--src/library/scala/collection/immutable/Stream.scala11
-rw-r--r--src/library/scala/collection/immutable/StringLike.scala6
-rw-r--r--src/library/scala/collection/immutable/StringOps.scala2
-rw-r--r--src/library/scala/collection/immutable/Traversable.scala2
-rw-r--r--src/library/scala/collection/immutable/TreeMap.scala3
-rw-r--r--src/library/scala/collection/immutable/TreeSet.scala4
-rw-r--r--src/library/scala/collection/immutable/TrieIterator.scala2
-rw-r--r--src/library/scala/collection/immutable/Vector.scala2
-rw-r--r--src/library/scala/collection/immutable/WrappedString.scala2
-rw-r--r--src/library/scala/collection/interfaces/IterableMethods.scala1
-rw-r--r--src/library/scala/collection/interfaces/SeqMethods.scala1
-rw-r--r--src/library/scala/collection/interfaces/SetMethods.scala1
-rw-r--r--src/library/scala/collection/interfaces/TraversableOnceMethods.scala2
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala4
-rw-r--r--src/library/scala/collection/mutable/ArrayBuilder.scala27
-rw-r--r--src/library/scala/collection/mutable/ArrayLike.scala2
-rw-r--r--src/library/scala/collection/mutable/ArrayOps.scala31
-rw-r--r--src/library/scala/collection/mutable/ArraySeq.scala4
-rw-r--r--src/library/scala/collection/mutable/ArrayStack.scala6
-rw-r--r--src/library/scala/collection/mutable/BitSet.scala4
-rw-r--r--src/library/scala/collection/mutable/Buffer.scala4
-rw-r--r--src/library/scala/collection/mutable/BufferLike.scala5
-rw-r--r--src/library/scala/collection/mutable/BufferProxy.scala2
-rw-r--r--src/library/scala/collection/mutable/Builder.scala2
-rw-r--r--src/library/scala/collection/mutable/ConcurrentMap.scala2
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedList.scala4
-rw-r--r--src/library/scala/collection/mutable/DoubleLinkedListLike.scala2
-rw-r--r--src/library/scala/collection/mutable/FlatArray.scala157
-rw-r--r--src/library/scala/collection/mutable/GenSeq.scala.disabled2
-rw-r--r--src/library/scala/collection/mutable/GenSet.scala.disabled2
-rw-r--r--src/library/scala/collection/mutable/GrowingBuilder.scala2
-rw-r--r--src/library/scala/collection/mutable/HashMap.scala4
-rw-r--r--src/library/scala/collection/mutable/HashSet.scala4
-rw-r--r--src/library/scala/collection/mutable/HashTable.scala2
-rw-r--r--src/library/scala/collection/mutable/IndexedSeq.scala2
-rw-r--r--src/library/scala/collection/mutable/IndexedSeqLike.scala2
-rw-r--r--src/library/scala/collection/mutable/IndexedSeqView.scala1
-rw-r--r--src/library/scala/collection/mutable/Iterable.scala2
-rw-r--r--src/library/scala/collection/mutable/LinearSeq.scala4
-rw-r--r--src/library/scala/collection/mutable/LinkedHashMap.scala12
-rw-r--r--src/library/scala/collection/mutable/LinkedHashSet.scala6
-rw-r--r--src/library/scala/collection/mutable/LinkedList.scala4
-rw-r--r--src/library/scala/collection/mutable/LinkedListLike.scala2
-rw-r--r--src/library/scala/collection/mutable/ListBuffer.scala4
-rw-r--r--src/library/scala/collection/mutable/ListMap.scala4
-rw-r--r--src/library/scala/collection/mutable/Map.scala2
-rw-r--r--src/library/scala/collection/mutable/MapLike.scala4
-rw-r--r--src/library/scala/collection/mutable/MultiMap.scala2
-rw-r--r--src/library/scala/collection/mutable/OpenHashMap.scala4
-rw-r--r--src/library/scala/collection/mutable/PriorityQueue.scala4
-rw-r--r--src/library/scala/collection/mutable/Queue.scala2
-rw-r--r--src/library/scala/collection/mutable/Seq.scala4
-rw-r--r--src/library/scala/collection/mutable/Set.scala4
-rw-r--r--src/library/scala/collection/mutable/SetLike.scala4
-rw-r--r--src/library/scala/collection/mutable/SortedSet.scala4
-rw-r--r--src/library/scala/collection/mutable/Stack.scala4
-rw-r--r--src/library/scala/collection/mutable/StringBuilder.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedBuffer.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedMap.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedQueue.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedSet.scala2
-rw-r--r--src/library/scala/collection/mutable/SynchronizedStack.scala2
-rw-r--r--src/library/scala/collection/mutable/Traversable.scala2
-rw-r--r--src/library/scala/collection/mutable/TreeSet.scala2
-rw-r--r--src/library/scala/collection/mutable/UnrolledBuffer.scala16
-rw-r--r--src/library/scala/collection/mutable/WeakHashMap.scala4
-rw-r--r--src/library/scala/collection/mutable/WrappedArray.scala45
-rw-r--r--src/library/scala/collection/mutable/WrappedArrayBuilder.scala26
-rw-r--r--src/library/scala/collection/parallel/ParIterable.scala2
-rw-r--r--src/library/scala/collection/parallel/ParIterableLike.scala43
-rw-r--r--src/library/scala/collection/parallel/ParIterableViewLike.scala1
-rw-r--r--src/library/scala/collection/parallel/TaskSupport.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashMap.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParHashSet.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParRange.scala2
-rw-r--r--src/library/scala/collection/parallel/immutable/ParSeq.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParSet.scala4
-rw-r--r--src/library/scala/collection/parallel/immutable/ParVector.scala4
-rw-r--r--src/library/scala/collection/parallel/mutable/ParArray.scala8
-rw-r--r--src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala2
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashMap.scala4
-rw-r--r--src/library/scala/collection/parallel/mutable/ParHashSet.scala4
-rw-r--r--src/library/scala/collection/parallel/mutable/ParSeq.scala4
-rw-r--r--src/library/scala/collection/parallel/mutable/ParSet.scala4
-rw-r--r--src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala2
-rw-r--r--src/library/scala/collection/parallel/package.scala1
-rw-r--r--src/library/scala/concurrent/Awaitable.scala9
-rw-r--r--src/library/scala/concurrent/ConcurrentPackageObject.scala76
-rw-r--r--src/library/scala/concurrent/ExecutionContext.scala45
-rw-r--r--src/library/scala/concurrent/Future.scala171
-rw-r--r--src/library/scala/concurrent/FutureTaskRunner.scala2
-rw-r--r--src/library/scala/concurrent/JavaConversions.scala1
-rw-r--r--src/library/scala/concurrent/ManagedBlocker.scala1
-rw-r--r--src/library/scala/concurrent/Promise.scala50
-rw-r--r--src/library/scala/concurrent/TaskRunner.scala2
-rw-r--r--src/library/scala/concurrent/ThreadPoolRunner.scala1
-rw-r--r--src/library/scala/concurrent/ThreadRunner.scala1
-rw-r--r--src/library/scala/concurrent/impl/AbstractPromise.java25
-rw-r--r--src/library/scala/concurrent/impl/ExecutionContextImpl.scala72
-rw-r--r--src/library/scala/concurrent/impl/Future.scala63
-rw-r--r--src/library/scala/concurrent/impl/NonFatal.scala37
-rw-r--r--src/library/scala/concurrent/impl/Promise.scala202
-rw-r--r--src/library/scala/concurrent/package.scala20
-rw-r--r--src/library/scala/concurrent/util/Duration.scala227
-rw-r--r--src/library/scala/concurrent/util/Unsafe.java35
-rw-r--r--src/library/scala/concurrent/util/duration/Classifier.scala9
-rw-r--r--src/library/scala/concurrent/util/duration/IntMult.scala18
-rw-r--r--src/library/scala/concurrent/util/duration/package.scala31
-rw-r--r--src/library/scala/io/BytePickle.scala2
-rw-r--r--src/library/scala/io/Codec.scala1
-rw-r--r--src/library/scala/io/Source.scala2
-rw-r--r--src/library/scala/language.scala124
-rw-r--r--src/library/scala/languageFeature.scala30
-rw-r--r--src/library/scala/math/BigDecimal.scala3
-rw-r--r--src/library/scala/math/BigInt.scala1
-rw-r--r--src/library/scala/math/Fractional.scala2
-rw-r--r--src/library/scala/math/Integral.scala2
-rw-r--r--src/library/scala/math/Numeric.scala6
-rw-r--r--src/library/scala/math/Ordered.scala2
-rw-r--r--src/library/scala/math/Ordering.scala1
-rw-r--r--src/library/scala/math/package.scala17
-rw-r--r--src/library/scala/package.scala19
-rw-r--r--src/library/scala/reflect/ArrayTag.scala25
-rw-r--r--src/library/scala/reflect/ClassManifest.scala43
-rw-r--r--src/library/scala/reflect/ClassTag.scala96
-rw-r--r--src/library/scala/reflect/DummyMirror.scala783
-rw-r--r--src/library/scala/reflect/DynamicProxy.scala74
-rw-r--r--src/library/scala/reflect/ErasureTag.scala23
-rw-r--r--src/library/scala/reflect/Manifest.scala53
-rw-r--r--src/library/scala/reflect/NoManifest.scala3
-rw-r--r--src/library/scala/reflect/OptManifest.scala3
-rw-r--r--src/library/scala/reflect/ReflectionUtils.scala49
-rw-r--r--src/library/scala/reflect/TagInterop.scala34
-rwxr-xr-xsrc/library/scala/reflect/api/AnnotationInfos.scala2
-rw-r--r--src/library/scala/reflect/api/Attachment.scala29
-rw-r--r--src/library/scala/reflect/api/ClassLoaders.scala16
-rw-r--r--src/library/scala/reflect/api/Exprs.scala19
-rw-r--r--src/library/scala/reflect/api/FreeVars.scala42
-rw-r--r--src/library/scala/reflect/api/FrontEnds.scala68
-rw-r--r--src/library/scala/reflect/api/Importers.scala19
-rw-r--r--src/library/scala/reflect/api/Mirror.scala17
-rwxr-xr-xsrc/library/scala/reflect/api/Names.scala8
-rw-r--r--src/library/scala/reflect/api/Positions.scala215
-rw-r--r--src/library/scala/reflect/api/RequiredFile.scala7
-rw-r--r--src/library/scala/reflect/api/RuntimeTypes.scala20
-rwxr-xr-xsrc/library/scala/reflect/api/Scopes.scala9
-rwxr-xr-xsrc/library/scala/reflect/api/StandardDefinitions.scala140
-rw-r--r--src/library/scala/reflect/api/StandardNames.scala156
-rwxr-xr-xsrc/library/scala/reflect/api/Symbols.scala200
-rw-r--r--src/library/scala/reflect/api/ToolBoxes.scala90
-rw-r--r--src/library/scala/reflect/api/TreeBuildUtil.scala143
-rw-r--r--src/library/scala/reflect/api/TreePrinters.scala6
-rw-r--r--src/library/scala/reflect/api/Trees.scala244
-rw-r--r--src/library/scala/reflect/api/TypeTags.scala254
-rwxr-xr-xsrc/library/scala/reflect/api/Types.scala114
-rwxr-xr-xsrc/library/scala/reflect/api/Universe.scala62
-rw-r--r--src/library/scala/reflect/macro/Context.scala36
-rw-r--r--src/library/scala/reflect/makro/Aliases.scala26
-rw-r--r--src/library/scala/reflect/makro/CapturedVariables.scala20
-rw-r--r--src/library/scala/reflect/makro/Context.scala44
-rw-r--r--src/library/scala/reflect/makro/Enclosures.scala53
-rw-r--r--src/library/scala/reflect/makro/FrontEnds.scala39
-rw-r--r--src/library/scala/reflect/makro/Infrastructure.scala73
-rw-r--r--src/library/scala/reflect/makro/Names.scala14
-rw-r--r--src/library/scala/reflect/makro/Reifiers.scala77
-rw-r--r--src/library/scala/reflect/makro/Settings.scala38
-rw-r--r--src/library/scala/reflect/makro/Symbols.scala24
-rw-r--r--src/library/scala/reflect/makro/Typers.scala85
-rw-r--r--src/library/scala/reflect/makro/Util.scala31
-rw-r--r--src/library/scala/reflect/makro/internal/Utils.scala146
-rw-r--r--src/library/scala/reflect/makro/internal/macroImpl.scala5
-rw-r--r--src/library/scala/reflect/package.scala52
-rw-r--r--src/library/scala/runtime/AbstractPartialFunction.scala8
-rw-r--r--src/library/scala/runtime/BoxesRunTime.java363
-rw-r--r--src/library/scala/runtime/RichDouble.scala12
-rw-r--r--src/library/scala/runtime/RichFloat.scala12
-rw-r--r--src/library/scala/runtime/RichInt.scala7
-rw-r--r--src/library/scala/runtime/RichLong.scala8
-rw-r--r--src/library/scala/runtime/ScalaRunTime.scala74
-rw-r--r--src/library/scala/runtime/SeqCharSequence.scala44
-rw-r--r--src/library/scala/runtime/Tuple2Zipped.scala130
-rw-r--r--src/library/scala/runtime/Tuple3Zipped.scala141
-rw-r--r--src/library/scala/runtime/package.scala12
-rw-r--r--src/library/scala/sys/BooleanProp.scala2
-rw-r--r--src/library/scala/sys/SystemProperties.scala2
-rw-r--r--src/library/scala/sys/process/Process.scala1
-rw-r--r--src/library/scala/testing/Show.scala8
-rw-r--r--src/library/scala/util/Marshal.scala33
-rw-r--r--src/library/scala/util/Random.scala23
-rw-r--r--src/library/scala/util/Sorting.scala16
-rw-r--r--src/library/scala/util/automata/BaseBerrySethi.scala2
-rw-r--r--src/library/scala/util/automata/NondetWordAutom.scala4
-rw-r--r--src/library/scala/util/automata/SubsetConstruction.scala2
-rw-r--r--src/library/scala/util/automata/WordBerrySethi.scala6
-rw-r--r--src/library/scala/util/control/Exception.scala8
-rw-r--r--src/library/scala/util/control/NoStackTrace.scala6
-rw-r--r--src/library/scala/util/matching/Regex.scala41
-rw-r--r--src/library/scala/util/parsing/ast/Binders.scala1
-rw-r--r--src/library/scala/util/parsing/combinator/ImplicitConversions.scala2
-rw-r--r--src/library/scala/util/parsing/combinator/PackratParsers.scala1
-rw-r--r--src/library/scala/util/parsing/combinator/Parsers.scala26
-rw-r--r--src/library/scala/util/parsing/combinator/RegexParsers.scala1
-rw-r--r--src/library/scala/util/parsing/combinator/lexical/Lexical.scala2
-rw-r--r--src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala1
-rw-r--r--src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala1
-rw-r--r--src/library/scala/util/parsing/combinator/testing/RegexTest.scala1
-rwxr-xr-xsrc/library/scala/xml/Elem.scala2
-rw-r--r--src/library/scala/xml/MetaData.scala2
-rw-r--r--src/library/scala/xml/NodeSeq.scala3
-rwxr-xr-xsrc/library/scala/xml/Utility.scala5
-rw-r--r--src/library/scala/xml/dtd/ContentModel.scala4
-rw-r--r--src/library/scala/xml/factory/LoggedNodeFactory.scala2
-rw-r--r--src/library/scala/xml/parsing/ConstructingParser.scala4
-rw-r--r--src/partest/scala/tools/partest/CompilerTest.scala11
-rw-r--r--src/partest/scala/tools/partest/ScaladocModelTest.scala78
-rw-r--r--src/partest/scala/tools/partest/SigTest.scala24
-rw-r--r--src/partest/scala/tools/partest/nest/CompileManager.scala98
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleFileManager.scala1
-rw-r--r--src/partest/scala/tools/partest/nest/ConsoleRunner.scala7
-rw-r--r--src/partest/scala/tools/partest/nest/TestFile.scala4
-rw-r--r--src/partest/scala/tools/partest/nest/Worker.scala89
-rw-r--r--src/scalacheck/org/scalacheck/Arbitrary.scala2
-rw-r--r--src/scalacheck/org/scalacheck/util/Buildable.scala2
-rw-r--r--src/scalap/scala/tools/scalap/JavaWriter.scala33
-rw-r--r--src/swing/scala/swing/Font.scala.disabled32
-rw-r--r--test/benchmarks/src/scala/collection/parallel/benchmarks/arrays/Resetting.scala8
-rw-r--r--test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/MatrixMultiplication.scala26
-rw-r--r--test/disabled/continuations-neg/infer0.check (renamed from test/files/continuations-neg/infer0.check)0
-rw-r--r--test/disabled/continuations-neg/infer0.scala (renamed from test/files/continuations-neg/infer0.scala)8
-rw-r--r--test/disabled/jvm/concurrent-future.check (renamed from test/files/jvm/concurrent-future.check)2
-rw-r--r--test/disabled/jvm/concurrent-future.scala (renamed from test/files/jvm/concurrent-future.scala)40
-rw-r--r--test/disabled/presentation/akka.check24
-rw-r--r--test/disabled/presentation/akka/src/akka/actor/Actor.scala4
-rw-r--r--test/disabled/presentation/akka/src/akka/actor/ActorRef.scala16
-rw-r--r--test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala30
-rw-r--r--test/disabled/presentation/akka/src/akka/event/EventHandler.scala4
-rw-r--r--test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala4
-rw-r--r--test/disabled/presentation/akka/src/akka/util/Helpers.scala2
-rw-r--r--test/disabled/presentation/shutdown-deadlock.check (renamed from test/files/presentation/shutdown-deadlock.check)0
-rw-r--r--test/disabled/presentation/shutdown-deadlock/ShutdownDeadlockTest.scala (renamed from test/files/presentation/shutdown-deadlock/ShutdownDeadlockTest.scala)0
-rw-r--r--test/disabled/presentation/shutdown-deadlock/src/arrays.scala (renamed from test/files/presentation/shutdown-deadlock/src/arrays.scala)0
-rw-r--r--test/disabled/presentation/simple-tests.check2
-rw-r--r--test/files/buildmanager/t2556_3/t2556_3.check4
-rw-r--r--test/files/buildmanager/t2559/D.scala6
-rw-r--r--test/files/buildmanager/t2559/t2559.check5
-rw-r--r--test/files/buildmanager/t2650_1/t2650_1.check1
-rw-r--r--test/files/buildmanager/t2657/t2657.check1
-rw-r--r--test/files/codelib/code.jar.desired.sha12
-rw-r--r--test/files/continuations-neg/t3718.check4
-rw-r--r--test/files/continuations-neg/t3718.scala3
-rw-r--r--test/files/continuations-run/match2.scala2
-rw-r--r--test/files/continuations-run/shift-pct.check25
-rw-r--r--test/files/continuations-run/shift-pct.scala30
-rw-r--r--test/files/continuations-run/t5472.check1
-rw-r--r--test/files/continuations-run/t5472.scala90
-rw-r--r--test/files/continuations-run/z1673.check (renamed from test/pending/run/reify_classfileann_b.check)0
-rw-r--r--test/files/continuations-run/z1673.scala31
-rw-r--r--test/files/jvm/annotations.scala4
-rw-r--r--test/files/jvm/future-spec/FutureTests.scala511
-rw-r--r--test/files/jvm/future-spec/PromiseTests.scala244
-rw-r--r--test/files/jvm/future-spec/main.scala108
-rw-r--r--[-rwxr-xr-x]test/files/jvm/interpreter.check740
-rw-r--r--test/files/jvm/interpreter.scala9
-rw-r--r--test/files/jvm/manifests-new.check58
-rw-r--r--test/files/jvm/manifests-new.scala109
-rw-r--r--test/files/jvm/manifests-old.check (renamed from test/files/jvm/manifests.check)0
-rw-r--r--test/files/jvm/manifests-old.scala (renamed from test/files/jvm/manifests.scala)10
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala300
-rw-r--r--test/files/jvm/serialization-new.check313
-rw-r--r--test/files/jvm/serialization-new.scala651
-rw-r--r--test/files/jvm/si5471.check2
-rw-r--r--test/files/jvm/si5471.scala17
-rw-r--r--test/files/jvm/signum.scala6
-rw-r--r--test/files/macros/Printf.scala39
-rw-r--r--test/files/macros/Test.scala8
-rw-r--r--test/files/macros/macros_v0001.bat40
-rw-r--r--test/files/macros/macros_v0001.sh30
-rw-r--r--test/files/neg/annot-nonconst.check4
-rw-r--r--test/files/neg/annot-nonconst.scala4
-rw-r--r--test/files/neg/applydynamic_sip.check10
-rw-r--r--test/files/neg/applydynamic_sip.scala10
-rw-r--r--test/files/neg/array-not-seq.check12
-rw-r--r--test/files/neg/checksensible.check200
-rw-r--r--test/files/neg/classtags_contextbound_a.check4
-rw-r--r--test/files/neg/classtags_contextbound_a.scala4
-rw-r--r--test/files/neg/classtags_contextbound_b.check4
-rw-r--r--test/files/neg/classtags_contextbound_b.scala5
-rw-r--r--test/files/neg/classtags_contextbound_c.check4
-rw-r--r--test/files/neg/classtags_contextbound_c.scala5
-rw-r--r--test/files/neg/classtags_dont_use_typetags.check4
-rw-r--r--test/files/neg/classtags_dont_use_typetags.scala3
-rw-r--r--test/files/neg/dbldef.check (renamed from test/pending/neg/dbldef.check)0
-rw-r--r--test/files/neg/dbldef.scala (renamed from test/pending/neg/dbldef.scala)0
-rw-r--r--test/files/neg/exhausting.flags2
-rw-r--r--test/files/neg/interop_classmanifests_arenot_concretetypetags.check4
-rw-r--r--test/files/neg/interop_classmanifests_arenot_concretetypetags.scala9
-rw-r--r--test/files/neg/interop_classtags_arenot_manifests.check7
-rw-r--r--test/files/neg/interop_classtags_arenot_manifests.scala17
-rw-r--r--test/files/neg/interop_erasuretags_arenot_classmanifests.check4
-rw-r--r--test/files/neg/interop_erasuretags_arenot_classmanifests.scala9
-rw-r--r--test/files/neg/interop_erasuretags_arenot_manifests.check4
-rw-r--r--test/files/neg/interop_erasuretags_arenot_manifests.scala9
-rw-r--r--test/files/neg/interop_typetags_arenot_classmanifests.check4
-rw-r--r--test/files/neg/interop_typetags_arenot_classmanifests.scala9
-rw-r--r--test/files/neg/interop_typetags_arenot_manifests.check4
-rw-r--r--test/files/neg/interop_typetags_arenot_manifests.scala9
-rw-r--r--test/files/neg/logImplicits.check8
-rw-r--r--test/files/neg/macro-argtype-mismatch.flags2
-rw-r--r--test/files/neg/macro-argtype-mismatch/Macros_1.scala3
-rw-r--r--test/files/neg/macro-basic-mamdmi.check5
-rw-r--r--test/files/neg/macro-basic-mamdmi.flags1
-rw-r--r--test/files/neg/macro-basic-mamdmi/Impls_Macros_Test_1.scala37
-rw-r--r--test/files/neg/macro-cyclic.check4
-rw-r--r--test/files/neg/macro-cyclic.flags1
-rw-r--r--test/files/neg/macro-cyclic/Impls_Macros_1.scala25
-rw-r--r--test/files/neg/macro-deprecate-idents.check52
-rw-r--r--test/files/neg/macro-deprecate-idents.flags1
-rw-r--r--test/files/neg/macro-deprecate-idents.scala56
-rw-r--r--test/files/neg/macro-invalidimpl-a.check4
-rw-r--r--test/files/neg/macro-invalidimpl-a.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-a/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidimpl-a/Macros_Test_2.scala9
-rw-r--r--test/files/neg/macro-invalidimpl-b.check4
-rw-r--r--test/files/neg/macro-invalidimpl-b.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-b/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidimpl-b/Macros_Test_2.scala9
-rw-r--r--test/files/neg/macro-invalidimpl-c.check4
-rw-r--r--test/files/neg/macro-invalidimpl-c.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-c/Impls_Macros_1.scala9
-rw-r--r--test/files/neg/macro-invalidimpl-c/Test_2.scala3
-rw-r--r--test/files/neg/macro-invalidimpl-d.check4
-rw-r--r--test/files/neg/macro-invalidimpl-d.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-d/Impls_1.scala7
-rw-r--r--test/files/neg/macro-invalidimpl-d/Macros_Test_2.scala7
-rw-r--r--test/files/neg/macro-invalidimpl-e.check13
-rw-r--r--test/files/neg/macro-invalidimpl-e.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-e/Impls_1.scala6
-rw-r--r--test/files/neg/macro-invalidimpl-e/Macros_Test_2.scala9
-rw-r--r--test/files/neg/macro-invalidimpl-f.check7
-rw-r--r--test/files/neg/macro-invalidimpl-f.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-f/Impls_1.scala11
-rw-r--r--test/files/neg/macro-invalidimpl-f/Macros_Test_2.scala9
-rw-r--r--test/files/neg/macro-invalidimpl-g.check7
-rw-r--r--test/files/neg/macro-invalidimpl-g.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-g/Impls_1.scala11
-rw-r--r--test/files/neg/macro-invalidimpl-g/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidimpl-h.check4
-rw-r--r--test/files/neg/macro-invalidimpl-h.flags1
-rw-r--r--test/files/neg/macro-invalidimpl-h/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidimpl-h/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidret-nontree.check7
-rw-r--r--test/files/neg/macro-invalidret-nontree.flags1
-rw-r--r--test/files/neg/macro-invalidret-nontree/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidret-nontree/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidret-nonuniversetree.check7
-rw-r--r--test/files/neg/macro-invalidret-nonuniversetree.flags1
-rw-r--r--test/files/neg/macro-invalidret-nonuniversetree/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidret-nonuniversetree/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidshape-a.check6
-rw-r--r--test/files/neg/macro-invalidshape-a.flags1
-rw-r--r--test/files/neg/macro-invalidshape-a/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidshape-a/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidshape-b.check6
-rw-r--r--test/files/neg/macro-invalidshape-b.flags1
-rw-r--r--test/files/neg/macro-invalidshape-b/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidshape-b/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidshape-c.check6
-rw-r--r--test/files/neg/macro-invalidshape-c.flags1
-rw-r--r--test/files/neg/macro-invalidshape-c/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidshape-c/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidshape-d.check8
-rw-r--r--test/files/neg/macro-invalidshape-d.flags1
-rw-r--r--test/files/neg/macro-invalidshape-d/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidshape-d/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-context-bounds.check4
-rw-r--r--test/files/neg/macro-invalidsig-context-bounds.flags1
-rw-r--r--test/files/neg/macro-invalidsig-context-bounds/Impls_1.scala8
-rw-r--r--test/files/neg/macro-invalidsig-context-bounds/Macros_Test_1.scala8
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badargc.check7
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badargc.flags1
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badargc/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badargc/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badtype.check7
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badtype.flags1
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badtype/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badtype/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badvarargs.check7
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badvarargs.flags1
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badvarargs/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-ctx-badvarargs/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-ctx-noctx.check7
-rw-r--r--test/files/neg/macro-invalidsig-ctx-noctx.flags1
-rw-r--r--test/files/neg/macro-invalidsig-ctx-noctx/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-ctx-noctx/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-implicit-params.check4
-rw-r--r--test/files/neg/macro-invalidsig-implicit-params.flags1
-rw-r--r--test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala18
-rw-r--r--test/files/neg/macro-invalidsig-implicit-params/Test_2.scala4
-rw-r--r--test/files/neg/macro-invalidsig-params-badargc.check7
-rw-r--r--test/files/neg/macro-invalidsig-params-badargc.flags1
-rw-r--r--test/files/neg/macro-invalidsig-params-badargc/Impls_Macros_1.scala9
-rw-r--r--test/files/neg/macro-invalidsig-params-badargc/Test_2.scala (renamed from test/files/neg/macro-noexpand/Test_2.scala)2
-rw-r--r--test/files/neg/macro-invalidsig-params-badtype.check7
-rw-r--r--test/files/neg/macro-invalidsig-params-badtype.flags1
-rw-r--r--test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala9
-rw-r--r--test/files/neg/macro-invalidsig-params-badtype/Test_2.scala (renamed from test/files/neg/macro-argtype-mismatch/Test_2.scala)2
-rw-r--r--test/files/neg/macro-invalidsig-params-badvarargs.check7
-rw-r--r--test/files/neg/macro-invalidsig-params-badvarargs.flags1
-rw-r--r--test/files/neg/macro-invalidsig-params-badvarargs/Impls_Macros_1.scala9
-rw-r--r--test/files/neg/macro-invalidsig-params-badvarargs/Test_2.scala4
-rw-r--r--test/files/neg/macro-invalidsig-params-namemismatch.check7
-rw-r--r--test/files/neg/macro-invalidsig-params-namemismatch.flags1
-rw-r--r--test/files/neg/macro-invalidsig-params-namemismatch/Impls_Macros_1.scala9
-rw-r--r--test/files/neg/macro-invalidsig-params-namemismatch/Test_2.scala4
-rw-r--r--test/files/neg/macro-invalidsig-tparams-badtype.check7
-rw-r--r--test/files/neg/macro-invalidsig-tparams-badtype.flags1
-rw-r--r--test/files/neg/macro-invalidsig-tparams-badtype/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-tparams-badtype/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-a.check4
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-a.flags1
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-a/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-a/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-b.check4
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-b.flags1
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-b/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-tparams-bounds-b/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-a.check4
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-a.flags1
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-a/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-a/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-b.check4
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-b.flags1
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-b/Impls_1.scala10
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-b/Macros_Test_2.scala11
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-c.check4
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-c.flags1
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-c/Impls_1.scala11
-rw-r--r--test/files/neg/macro-invalidsig-tparams-notparams-c/Macros_Test_2.scala11
-rw-r--r--test/files/neg/macro-invalidusage-badargs.check6
-rw-r--r--test/files/neg/macro-invalidusage-badargs.flags1
-rw-r--r--test/files/neg/macro-invalidusage-badargs/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidusage-badargs/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidusage-badbounds.check4
-rw-r--r--test/files/neg/macro-invalidusage-badbounds.flags1
-rw-r--r--test/files/neg/macro-invalidusage-badbounds/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidusage-badbounds/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidusage-badtargs.check4
-rw-r--r--test/files/neg/macro-invalidusage-badtargs.flags1
-rw-r--r--test/files/neg/macro-invalidusage-badtargs/Impls_1.scala5
-rw-r--r--test/files/neg/macro-invalidusage-badtargs/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-invalidusage-methodvaluesyntax.check4
-rw-r--r--test/files/neg/macro-invalidusage-methodvaluesyntax.flags1
-rw-r--r--test/files/neg/macro-invalidusage-methodvaluesyntax/Impls_1.scala9
-rw-r--r--test/files/neg/macro-invalidusage-methodvaluesyntax/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-noexpand.check2
-rw-r--r--test/files/neg/macro-noexpand.flags2
-rw-r--r--test/files/neg/macro-noexpand/Impls_1.scala5
-rw-r--r--test/files/neg/macro-noexpand/Macros_1.scala3
-rw-r--r--test/files/neg/macro-noexpand/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-noncompilertree.flags2
-rw-r--r--test/files/neg/macro-noncompilertree/Macros_1.scala3
-rw-r--r--test/files/neg/macro-nontree.flags2
-rw-r--r--test/files/neg/macro-nontree/Macros_1.scala3
-rw-r--r--test/files/neg/macro-nontypeablebody.check4
-rw-r--r--test/files/neg/macro-nontypeablebody.flags1
-rw-r--r--test/files/neg/macro-nontypeablebody/Impls_1.scala5
-rw-r--r--test/files/neg/macro-nontypeablebody/Macros_Test_2.scala8
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-a.check5
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-a.flags1
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-a/Impls_Macros_1.scala13
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-a/Test_2.scala4
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-b.check5
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-b.flags1
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala13
-rw-r--r--test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala4
-rw-r--r--test/files/neg/macro-override-method-overrides-macro.check5
-rw-r--r--test/files/neg/macro-override-method-overrides-macro.flags1
-rw-r--r--test/files/neg/macro-override-method-overrides-macro/Impls_1.scala15
-rw-r--r--test/files/neg/macro-override-method-overrides-macro/Macros_Test_2.scala15
-rw-r--r--test/files/neg/macro-reify-groundtypetag-hktypeparams-notags.check7
-rw-r--r--test/files/neg/macro-reify-groundtypetag-hktypeparams-notags/Test.scala9
-rw-r--r--test/files/neg/macro-reify-groundtypetag-typeparams-notags.check7
-rw-r--r--test/files/neg/macro-reify-groundtypetag-typeparams-notags/Test.scala9
-rw-r--r--test/files/neg/macro-reify-groundtypetag-usetypetag.check7
-rw-r--r--test/files/neg/macro-reify-groundtypetag-usetypetag/Test.scala9
-rw-r--r--test/files/neg/macro-without-xmacros-a.check17
-rw-r--r--test/files/neg/macro-without-xmacros-a/Impls_1.scala18
-rw-r--r--test/files/neg/macro-without-xmacros-a/Macros_2.scala12
-rw-r--r--test/files/neg/macro-without-xmacros-a/Test_3.scala (renamed from test/files/run/macro-basic/Test_2.scala)0
-rw-r--r--test/files/neg/macro-without-xmacros-b.check17
-rw-r--r--test/files/neg/macro-without-xmacros-b/Impls_1.scala18
-rw-r--r--test/files/neg/macro-without-xmacros-b/Macros_2.scala10
-rw-r--r--test/files/neg/macro-without-xmacros-b/Test_3.scala4
-rw-r--r--test/files/neg/overloaded-unapply.check3
-rw-r--r--test/files/neg/override.check2
-rw-r--r--test/files/neg/package-ob-case.flags2
-rw-r--r--test/files/neg/pat_unreachable.flags1
-rw-r--r--test/files/neg/patmatexhaust.flags2
-rw-r--r--test/files/neg/primitive-sigs-1.check6
-rw-r--r--test/files/neg/primitive-sigs-1/A.scala (renamed from test/files/neg/primitive-sigs-1/A_1.scala)0
-rw-r--r--test/files/neg/primitive-sigs-1/B.scala (renamed from test/files/neg/primitive-sigs-1/A_3.scala)2
-rw-r--r--test/files/neg/primitive-sigs-1/J.java (renamed from test/files/neg/primitive-sigs-1/J_2.java)2
-rw-r--r--test/files/neg/reify_ann2a.check4
-rw-r--r--test/files/neg/reify_ann2b.check9
-rw-r--r--test/files/neg/reify_ann2b.scala13
-rw-r--r--test/files/neg/sealed-java-enums.flags2
-rw-r--r--test/files/neg/switch.flags1
-rw-r--r--test/files/neg/t1878-typer.check4
-rw-r--r--test/files/neg/t1878-typer.scala6
-rw-r--r--test/files/neg/t1878.check21
-rw-r--r--test/files/neg/t1878.scala2
-rw-r--r--test/files/neg/t200.check3
-rw-r--r--test/files/neg/t2386.check4
-rw-r--r--test/files/neg/t2386.scala3
-rw-r--r--test/files/neg/t2775.check2
-rw-r--r--test/files/neg/t2779.check3
-rw-r--r--test/files/neg/t278.check3
-rw-r--r--test/files/neg/t3098.flags2
-rw-r--r--test/files/neg/t3189.check4
-rw-r--r--test/files/neg/t3189.scala (renamed from test/pending/neg/t3189.scala)0
-rw-r--r--test/files/neg/t3507-old.check (renamed from test/files/neg/t3507.check)8
-rw-r--r--test/files/neg/t3507-old.scala (renamed from test/files/neg/t3507.scala)0
-rw-r--r--test/files/neg/t3683a.flags2
-rw-r--r--test/files/neg/t3692-new.check (renamed from test/files/neg/t3692.check)8
-rw-r--r--test/files/neg/t3692-new.flags1
-rw-r--r--test/files/neg/t3692-new.scala19
-rw-r--r--test/files/neg/t3692-old.check8
-rw-r--r--test/files/neg/t3692-old.flags1
-rw-r--r--test/files/neg/t3692-old.scala (renamed from test/files/neg/t3692.scala)0
-rw-r--r--test/files/neg/t3816.check2
-rw-r--r--test/files/neg/t4134.check4
-rw-r--r--test/files/neg/t4134.scala30
-rw-r--r--test/files/neg/t4425.check2
-rw-r--r--test/files/neg/t4568.check4
-rw-r--r--test/files/neg/t4568.scala13
-rw-r--r--test/files/neg/t5106.check11
-rw-r--r--test/files/neg/t5106.scala5
-rw-r--r--test/files/neg/t5334_1.check4
-rw-r--r--test/files/neg/t5334_1.scala8
-rw-r--r--test/files/neg/t5334_2.check4
-rw-r--r--test/files/neg/t5334_2.scala8
-rw-r--r--test/files/neg/t5452-new.check8
-rw-r--r--test/files/neg/t5452-new.scala29
-rw-r--r--test/files/neg/t5452-old.check (renamed from test/files/neg/t5452.check)16
-rw-r--r--test/files/neg/t5452-old.scala (renamed from test/files/neg/t5452.scala)0
-rw-r--r--test/files/neg/t5504.check4
-rw-r--r--test/files/neg/t5504/s_1.scala4
-rw-r--r--test/files/neg/t5504/s_2.scala8
-rw-r--r--test/files/neg/t5510.check19
-rw-r--r--test/files/neg/t5510.scala7
-rw-r--r--test/files/neg/t5564.check4
-rw-r--r--test/files/neg/t5564.scala9
-rw-r--r--test/files/neg/t5578.check4
-rw-r--r--test/files/neg/t5578.scala39
-rw-r--r--test/files/neg/t5663-badwarneq.check22
-rw-r--r--test/files/neg/t5663-badwarneq.flags1
-rw-r--r--test/files/neg/t5663-badwarneq.scala76
-rw-r--r--test/files/neg/t5666.check37
-rw-r--r--test/files/neg/t5666.scala14
-rw-r--r--test/files/neg/t5689.check7
-rw-r--r--test/files/neg/t5689.flags1
-rw-r--r--test/files/neg/t5689.scala6
-rw-r--r--test/files/neg/t5702-neg-bad-and-wild.check28
-rw-r--r--test/files/neg/t5702-neg-bad-and-wild.scala29
-rw-r--r--test/files/neg/t5702-neg-bad-brace.check10
-rw-r--r--test/files/neg/t5702-neg-bad-brace.scala17
-rw-r--r--test/files/neg/t5702-neg-bad-xbrace.check7
-rw-r--r--test/files/neg/t5702-neg-bad-xbrace.scala31
-rw-r--r--test/files/neg/t5702-neg-ugly-xbrace.check19
-rw-r--r--test/files/neg/t5702-neg-ugly-xbrace.scala14
-rw-r--r--test/files/neg/t5728.check4
-rw-r--r--test/files/neg/t5728.scala7
-rw-r--r--test/files/neg/t591.check3
-rw-r--r--test/files/neg/t750.check15
-rw-r--r--test/files/neg/t750/AO_1.java5
-rw-r--r--test/files/neg/t750/Test_2.scala6
-rw-r--r--test/files/neg/t750b.check15
-rw-r--r--test/files/neg/t750b/AO.java5
-rw-r--r--test/files/neg/t750b/Test.scala6
-rw-r--r--test/files/neg/t800.check9
-rw-r--r--test/files/neg/t900.check4
-rw-r--r--test/files/neg/t963.check12
-rw-r--r--test/files/neg/t963.scala18
-rw-r--r--test/files/neg/tailrec.check6
-rw-r--r--test/files/neg/unreachablechar.flags1
-rw-r--r--test/files/pos/annot-inner.scala2
-rw-r--r--test/files/pos/annotDepMethType.scala2
-rw-r--r--test/files/pos/annotations.scala10
-rw-r--r--test/files/pos/attributes.scala14
-rw-r--r--test/files/pos/contextbounds-implicits-new.scala8
-rw-r--r--test/files/pos/contextbounds-implicits-old.scala (renamed from test/files/pos/contextbounds-implicits.scala)0
-rw-r--r--test/files/pos/gen-traversable-methods.scala20
-rw-r--r--test/files/pos/generic-sigs.scala4
-rw-r--r--test/files/pos/hkarray.flags2
-rw-r--r--test/files/pos/implicits-new.scala89
-rw-r--r--test/files/pos/implicits-old.scala (renamed from test/files/pos/implicits.scala)0
-rw-r--r--test/files/pos/liftcode_polymorphic.scala4
-rw-r--r--test/files/pos/macro-deprecate-dont-touch-backquotedidents.flags1
-rw-r--r--test/files/pos/macro-deprecate-dont-touch-backquotedidents.scala56
-rw-r--r--test/files/pos/macros.scala8
-rw-r--r--test/files/pos/manifest1-new.scala21
-rw-r--r--test/files/pos/manifest1-old.scala (renamed from test/files/pos/manifest1.scala)0
-rw-r--r--test/files/pos/no-widen-locals.scala (renamed from test/pending/pos/no-widen-locals.scala)0
-rw-r--r--test/files/pos/nothing_manifest_disambig-new.scala10
-rw-r--r--test/files/pos/nothing_manifest_disambig-old.scala (renamed from test/files/pos/nothing_manifest_disambig.scala)0
-rw-r--r--test/files/pos/spec-annotations.scala2
-rw-r--r--test/files/pos/spec-constr-new.scala7
-rw-r--r--test/files/pos/spec-constr-old.scala (renamed from test/files/pos/spec-constr.scala)0
-rw-r--r--test/files/pos/spec-doubledef-new.scala28
-rw-r--r--test/files/pos/spec-doubledef-old.scala (renamed from test/files/pos/spec-doubledef.scala)0
-rw-r--r--test/files/pos/spec-fields-new.scala10
-rw-r--r--test/files/pos/spec-fields-old.scala (renamed from test/files/pos/spec-fields.scala)0
-rw-r--r--test/files/pos/spec-params-new.scala32
-rw-r--r--test/files/pos/spec-params-old.scala (renamed from test/files/pos/spec-params.scala)0
-rw-r--r--test/files/pos/spec-sparsearray-new.scala24
-rw-r--r--test/files/pos/spec-sparsearray-old.scala (renamed from test/files/pos/spec-sparsearray.scala)0
-rw-r--r--test/files/pos/t1029/Test_1.scala2
-rw-r--r--test/files/pos/t1203.scala2
-rw-r--r--test/files/pos/t1279a.scala61
-rw-r--r--test/files/pos/t1357.scala (renamed from test/pending/pos/t1357.scala)0
-rw-r--r--test/files/pos/t1381-new.scala31
-rw-r--r--test/files/pos/t1381-old.scala (renamed from test/files/pos/t1381.scala)0
-rw-r--r--test/files/pos/t1439.flags2
-rw-r--r--test/files/pos/t1785.scala7
-rw-r--r--test/files/pos/t1942/A_1.scala2
-rw-r--r--test/files/pos/t2795-new.scala17
-rw-r--r--test/files/pos/t2795-old.scala (renamed from test/files/pos/t2795.scala)0
-rw-r--r--test/files/pos/t2868/pick_1.scala2
-rw-r--r--test/files/pos/t3363-new.scala18
-rw-r--r--[-rwxr-xr-x]test/files/pos/t3363-old.scala (renamed from test/files/pos/t3363.scala)0
-rw-r--r--test/files/pos/t3498-new.scala15
-rw-r--r--test/files/pos/t3498-old.scala (renamed from test/files/pos/t3498.scala)0
-rw-r--r--test/files/pos/t3800.scala2
-rw-r--r--test/files/pos/t3951/Coll_1.scala2
-rw-r--r--test/files/pos/t4910.scala6
-rw-r--r--test/files/pos/t5198.scala15
-rw-r--r--test/files/pos/t5223.scala6
-rw-r--r--test/files/pos/t5240.scala11
-rw-r--r--test/files/pos/t531.scala5
-rw-r--r--test/files/pos/t532.scala5
-rw-r--r--test/files/pos/t5542.flags1
-rw-r--r--test/files/pos/t5542.scala3
-rw-r--r--test/files/pos/t5644/BoxesRunTime.java836
-rw-r--r--test/files/pos/t5644/other.scala3
-rw-r--r--test/files/pos/t5667.scala6
-rw-r--r--test/files/pos/t5702-pos-infix-star.scala15
-rw-r--r--test/files/pos/t5703/Base.java3
-rw-r--r--test/files/pos/t5703/Impl.scala3
-rw-r--r--test/files/pos/t5706.flags1
-rw-r--r--test/files/pos/t5706.scala10
-rw-r--r--test/files/pos/t5720-ownerous.scala56
-rw-r--r--test/files/pos/t5727.scala31
-rw-r--r--test/files/pos/t5729.scala6
-rw-r--r--test/files/pos/t5769.scala8
-rw-r--r--test/files/pos/virtpatmat_alts_subst.flags2
-rw-r--r--test/files/pos/virtpatmat_anonfun_for.flags1
-rw-r--r--test/files/pos/virtpatmat_binding_opt.flags2
-rw-r--r--test/files/pos/virtpatmat_castbinder.flags2
-rw-r--r--test/files/pos/virtpatmat_exist1.flags2
-rw-r--r--test/files/pos/virtpatmat_exist2.flags2
-rw-r--r--test/files/pos/virtpatmat_exist3.flags2
-rw-r--r--test/files/pos/virtpatmat_exist_uncurry.scala6
-rw-r--r--test/files/pos/virtpatmat_gadt_array.flags2
-rw-r--r--test/files/pos/virtpatmat_infer_single_1.flags2
-rw-r--r--test/files/pos/virtpatmat_instof_valuetype.flags2
-rw-r--r--test/files/pos/virtpatmat_obj_in_case.flags2
-rw-r--r--test/files/pos/virtpatmat_partialfun_nsdnho.scala18
-rw-r--r--test/files/presentation/callcc-interpreter.check120
-rw-r--r--test/files/presentation/hyperlinks.check46
-rw-r--r--test/files/presentation/hyperlinks.flags2
-rw-r--r--test/files/presentation/hyperlinks/Runner.scala11
-rw-r--r--test/files/presentation/hyperlinks/src/NameDefaultTests.scala16
-rw-r--r--test/files/presentation/hyperlinks/src/PatMatTests.scala28
-rw-r--r--test/files/presentation/ide-bug-1000349.check68
-rw-r--r--test/files/presentation/ide-bug-1000475.check192
-rw-r--r--test/files/presentation/ide-bug-1000531.check241
-rw-r--r--test/files/presentation/implicit-member.check70
-rw-r--r--test/files/presentation/memory-leaks.check54
-rw-r--r--test/files/presentation/memory-leaks/MemoryLeaksTest.scala126
-rw-r--r--test/files/presentation/ping-pong.check142
-rw-r--r--test/files/presentation/visibility.check221
-rw-r--r--test/files/presentation/visibility/Test.scala5
-rw-r--r--test/files/presentation/visibility/src/Completions.scala40
-rw-r--r--test/files/run/Meter.check8
-rw-r--r--test/files/run/Meter.scala36
-rw-r--r--test/files/run/MeterCaseClass.check8
-rw-r--r--test/files/run/MeterCaseClass.scala36
-rw-r--r--test/files/run/applydynamic_sip.check22
-rw-r--r--test/files/run/applydynamic_sip.scala58
-rw-r--r--test/files/run/array-charSeq.check248
-rw-r--r--test/files/run/array-charSeq.scala27
-rw-r--r--test/files/run/arrayclone-new.scala106
-rw-r--r--test/files/run/arrayclone-old.scala (renamed from test/files/run/arrayclone.scala)0
-rw-r--r--test/files/run/arraytags_basic.check36
-rw-r--r--test/files/run/arraytags_basic.scala22
-rw-r--r--test/files/run/arraytags_core.check48
-rw-r--r--test/files/run/arraytags_core.scala50
-rw-r--r--test/files/run/arraytags_usage.check3
-rw-r--r--test/files/run/arraytags_usage.scala15
-rw-r--r--test/files/run/bugs.scala3
-rw-r--r--test/files/run/classtags_contextbound.check1
-rw-r--r--test/files/run/classtags_contextbound.scala5
-rw-r--r--test/files/run/classtags_core.check32
-rw-r--r--test/files/run/classtags_core.scala34
-rw-r--r--test/files/run/classtags_multi.check5
-rw-r--r--test/files/run/classtags_multi.scala7
-rw-r--r--test/files/run/classtags_use_concretetypetags.scala3
-rw-r--r--test/files/run/compiler-asSeenFrom.check36
-rw-r--r--test/files/run/concretetypetags_core.check32
-rw-r--r--test/files/run/concretetypetags_core.scala34
-rw-r--r--test/files/run/concretetypetags_multi.check5
-rw-r--r--test/files/run/concretetypetags_multi.scala7
-rw-r--r--test/files/run/constrained-types.check7
-rw-r--r--test/files/run/ctries-new/DumbHash.scala (renamed from test/files/run/ctries/DumbHash.scala)0
-rw-r--r--test/files/run/ctries-new/Wrap.scala (renamed from test/files/run/ctries/Wrap.scala)0
-rw-r--r--test/files/run/ctries-new/concmap.scala (renamed from test/files/run/ctries/concmap.scala)0
-rw-r--r--test/files/run/ctries-new/iterator.scala (renamed from test/files/run/ctries/iterator.scala)0
-rw-r--r--test/files/run/ctries-new/lnode.scala (renamed from test/files/run/ctries/lnode.scala)0
-rw-r--r--test/files/run/ctries-new/main.scala45
-rw-r--r--test/files/run/ctries-new/snapshot.scala (renamed from test/files/run/ctries/snapshot.scala)0
-rw-r--r--test/files/run/ctries-old/DumbHash.scala14
-rw-r--r--test/files/run/ctries-old/Wrap.scala9
-rw-r--r--test/files/run/ctries-old/concmap.scala188
-rw-r--r--test/files/run/ctries-old/iterator.scala289
-rw-r--r--test/files/run/ctries-old/lnode.scala61
-rw-r--r--test/files/run/ctries-old/main.scala (renamed from test/files/run/ctries/main.scala)0
-rw-r--r--test/files/run/ctries-old/snapshot.scala267
-rw-r--r--test/files/run/dynamic-proxy.check20
-rw-r--r--test/files/run/dynamic-proxy.flags1
-rw-r--r--test/files/run/dynamic-proxy.scala72
-rw-r--r--test/files/run/erasuretags_abstract.check4
-rw-r--r--test/files/run/erasuretags_abstract.scala9
-rw-r--r--test/files/run/erasuretags_basic.check24
-rw-r--r--test/files/run/erasuretags_basic.scala21
-rw-r--r--test/files/run/erasuretags_core.check32
-rw-r--r--test/files/run/erasuretags_core.scala34
-rw-r--r--test/files/run/erasuretags_usage.scala12
-rw-r--r--test/files/run/existentials-in-compiler.check16
-rw-r--r--test/files/run/existentials3-new.check24
-rw-r--r--test/files/run/existentials3-new.scala78
-rw-r--r--test/files/run/existentials3-old.check (renamed from test/files/run/existentials3.check)4
-rw-r--r--test/files/run/existentials3-old.scala (renamed from test/files/run/existentials3.scala)8
-rw-r--r--test/files/run/getClassTest-new.check (renamed from test/files/run/getClassTest.check)0
-rw-r--r--test/files/run/getClassTest-new.scala66
-rw-r--r--test/files/run/getClassTest-old.check18
-rw-r--r--test/files/run/getClassTest-old.scala (renamed from test/files/run/getClassTest.scala)10
-rw-r--r--test/files/run/hashhash.scala5
-rw-r--r--test/files/run/implicitclasses.scala10
-rw-r--r--test/files/run/inline-ex-handlers.check268
-rw-r--r--test/files/run/inner-parse.check87
-rw-r--r--test/files/run/inner-parse/J_1.java9
-rw-r--r--test/files/run/inner-parse/S_2.scala9
-rw-r--r--test/files/run/inner-parse/S_3.scala12
-rw-r--r--test/files/run/interop_classmanifests_arepartially_typetags.check6
-rw-r--r--test/files/run/interop_classmanifests_arepartially_typetags.scala10
-rw-r--r--test/files/run/interop_classtags_are_classmanifests.check6
-rw-r--r--test/files/run/interop_classtags_are_classmanifests.scala17
-rw-r--r--test/files/run/interop_concretetypetags_are_classmanifests.check3
-rw-r--r--test/files/run/interop_concretetypetags_are_classmanifests.scala9
-rw-r--r--test/files/run/interop_concretetypetags_are_manifests.check3
-rw-r--r--test/files/run/interop_concretetypetags_are_manifests.scala9
-rw-r--r--test/files/run/interop_manifests_are_classtags.check24
-rw-r--r--test/files/run/interop_manifests_are_classtags.scala23
-rw-r--r--test/files/run/interop_manifests_are_concretetypetags.check6
-rw-r--r--test/files/run/interop_manifests_are_concretetypetags.scala10
-rw-r--r--test/files/run/interop_manifests_are_typetags.check6
-rw-r--r--test/files/run/interop_manifests_are_typetags.scala10
-rw-r--r--test/files/run/is-valid-num.scala331
-rw-r--r--test/files/run/lazy-locals.check41
-rw-r--r--test/files/run/lazy-locals.scala85
-rw-r--r--test/files/run/macro-abort-fresh.check6
-rw-r--r--test/files/run/macro-abort-fresh.flags1
-rw-r--r--test/files/run/macro-abort-fresh/Macros_1.scala15
-rw-r--r--test/files/run/macro-abort-fresh/Test_2.scala6
-rw-r--r--test/files/run/macro-basic-ma-md-mi.check1
-rw-r--r--test/files/run/macro-basic-ma-md-mi.flags1
-rw-r--r--test/files/run/macro-basic-ma-md-mi/Impls_1.scala21
-rw-r--r--test/files/run/macro-basic-ma-md-mi/Macros_2.scala10
-rw-r--r--test/files/run/macro-basic-ma-md-mi/Test_3.scala4
-rw-r--r--test/files/run/macro-basic-ma-mdmi.check1
-rw-r--r--test/files/run/macro-basic-ma-mdmi.flags1
-rw-r--r--test/files/run/macro-basic-ma-mdmi/Impls_Macros_1.scala32
-rw-r--r--test/files/run/macro-basic-ma-mdmi/Test_2.scala4
-rw-r--r--test/files/run/macro-basic-mamd-mi.check1
-rw-r--r--test/files/run/macro-basic-mamd-mi.flags1
-rw-r--r--test/files/run/macro-basic-mamd-mi/Impls_1.scala19
-rw-r--r--test/files/run/macro-basic-mamd-mi/Macros_Test_2.scala15
-rw-r--r--test/files/run/macro-basic.check1
-rw-r--r--test/files/run/macro-basic.flags1
-rw-r--r--test/files/run/macro-basic/Macros_1.scala10
-rw-r--r--test/files/run/macro-bodyexpandstoimpl.check1
-rw-r--r--test/files/run/macro-bodyexpandstoimpl.flags1
-rw-r--r--test/files/run/macro-bodyexpandstoimpl/Impls_1.scala12
-rw-r--r--test/files/run/macro-bodyexpandstoimpl/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-declared-in-annotation.check1
-rw-r--r--test/files/run/macro-declared-in-annotation.flags1
-rw-r--r--test/files/run/macro-declared-in-annotation/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-annotation/Macros_2.scala8
-rw-r--r--test/files/run/macro-declared-in-annotation/Test_3.scala3
-rw-r--r--test/files/run/macro-declared-in-anonymous.check2
-rw-r--r--test/files/run/macro-declared-in-anonymous.flags1
-rw-r--r--test/files/run/macro-declared-in-anonymous/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-anonymous/Macros_Test_2.scala4
-rw-r--r--test/files/run/macro-declared-in-block.check2
-rw-r--r--test/files/run/macro-declared-in-block.flags1
-rw-r--r--test/files/run/macro-declared-in-block/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-block/Macros_Test_2.scala6
-rw-r--r--test/files/run/macro-declared-in-class-class.check2
-rw-r--r--test/files/run/macro-declared-in-class-class.flags1
-rw-r--r--test/files/run/macro-declared-in-class-class/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-class-class/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-declared-in-class-object.check2
-rw-r--r--test/files/run/macro-declared-in-class-object.flags1
-rw-r--r--test/files/run/macro-declared-in-class-object/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-class-object/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-declared-in-class.check2
-rw-r--r--test/files/run/macro-declared-in-class.flags1
-rw-r--r--test/files/run/macro-declared-in-class/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-class/Macros_Test_2.scala7
-rw-r--r--test/files/run/macro-declared-in-default-param.check5
-rw-r--r--test/files/run/macro-declared-in-default-param.flags1
-rw-r--r--test/files/run/macro-declared-in-default-param/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-default-param/Macros_Test_2.scala7
-rw-r--r--test/files/run/macro-declared-in-implicit-class.check2
-rw-r--r--test/files/run/macro-declared-in-implicit-class.flags1
-rw-r--r--test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala19
-rw-r--r--test/files/run/macro-declared-in-implicit-class/Test_2.scala4
-rw-r--r--test/files/run/macro-declared-in-method.check2
-rw-r--r--test/files/run/macro-declared-in-method.flags1
-rw-r--r--test/files/run/macro-declared-in-method/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-method/Macros_Test_2.scala8
-rw-r--r--test/files/run/macro-declared-in-object-class.check2
-rw-r--r--test/files/run/macro-declared-in-object-class.flags1
-rw-r--r--test/files/run/macro-declared-in-object-class/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-object-class/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-declared-in-object-object.check2
-rw-r--r--test/files/run/macro-declared-in-object-object.flags1
-rw-r--r--test/files/run/macro-declared-in-object-object/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-object-object/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-declared-in-object.check2
-rw-r--r--test/files/run/macro-declared-in-object.flags1
-rw-r--r--test/files/run/macro-declared-in-object/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-object/Macros_Test_2.scala7
-rw-r--r--test/files/run/macro-declared-in-package-object.check2
-rw-r--r--test/files/run/macro-declared-in-package-object.flags1
-rw-r--r--test/files/run/macro-declared-in-package-object/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-package-object/Macros_Test_2.scala8
-rw-r--r--test/files/run/macro-declared-in-refinement.check2
-rw-r--r--test/files/run/macro-declared-in-refinement.flags1
-rw-r--r--test/files/run/macro-declared-in-refinement/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-refinement/Macros_Test_2.scala6
-rw-r--r--test/files/run/macro-declared-in-trait.check15
-rw-r--r--test/files/run/macro-declared-in-trait.flags1
-rw-r--r--test/files/run/macro-declared-in-trait/Impls_1.scala11
-rw-r--r--test/files/run/macro-declared-in-trait/Macros_Test_2.scala13
-rw-r--r--test/files/run/macro-def-infer-return-type-a.check1
-rw-r--r--test/files/run/macro-def-infer-return-type-a.flags1
-rw-r--r--test/files/run/macro-def-infer-return-type-a/Impls_1.scala5
-rw-r--r--test/files/run/macro-def-infer-return-type-a/Macros_Test_2.scala4
-rw-r--r--test/files/run/macro-def-infer-return-type-b.check6
-rw-r--r--test/files/run/macro-def-infer-return-type-b.flags1
-rw-r--r--test/files/run/macro-def-infer-return-type-b/Impls_Macros_1.scala10
-rw-r--r--test/files/run/macro-def-infer-return-type-b/Test_2.scala6
-rw-r--r--test/files/run/macro-def-infer-return-type-c.check1
-rw-r--r--test/files/run/macro-def-infer-return-type-c.flags1
-rw-r--r--test/files/run/macro-def-infer-return-type-c/Impls_1.scala5
-rw-r--r--test/files/run/macro-def-infer-return-type-c/Macros_Test_2.scala4
-rw-r--r--test/files/run/macro-def-path-dependent-a.check1
-rw-r--r--test/files/run/macro-def-path-dependent-a.flags1
-rw-r--r--test/files/run/macro-def-path-dependent-a/Impls_Macros_1.scala21
-rw-r--r--test/files/run/macro-def-path-dependent-a/Test_2.scala3
-rw-r--r--test/files/run/macro-def-path-dependent-b.check1
-rw-r--r--test/files/run/macro-def-path-dependent-b.flags1
-rw-r--r--test/files/run/macro-def-path-dependent-b/Impls_Macros_1.scala20
-rw-r--r--test/files/run/macro-def-path-dependent-b/Test_2.scala3
-rw-r--r--test/files/run/macro-def-path-dependent-c.check1
-rw-r--r--test/files/run/macro-def-path-dependent-c.flags1
-rw-r--r--test/files/run/macro-def-path-dependent-c/Impls_Macros_1.scala20
-rw-r--r--test/files/run/macro-def-path-dependent-c/Test_2.scala3
-rw-r--r--test/files/run/macro-def-path-dependent-d.check1
-rw-r--r--test/files/run/macro-def-path-dependent-d.flags1
-rw-r--r--test/files/run/macro-def-path-dependent-d/Impls_Macros_1.scala8
-rw-r--r--test/files/run/macro-def-path-dependent-d/Test_2.scala3
-rw-r--r--test/files/run/macro-expand-implicit-macro-has-implicit.check1
-rw-r--r--test/files/run/macro-expand-implicit-macro-has-implicit.flags1
-rw-r--r--test/files/run/macro-expand-implicit-macro-has-implicit/Impls_1.scala9
-rw-r--r--test/files/run/macro-expand-implicit-macro-has-implicit/Macros_Test_2.scala5
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-implicit.check2
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-implicit.flags1
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-implicit/Impls_1.scala9
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-implicit/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-val.check1
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-val.flags1
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-val/Impls_1.scala9
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-val/Macros_Test_2.scala5
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-view.check1
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-view.flags1
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-view/Impls_1.scala9
-rw-r--r--test/files/run/macro-expand-implicit-macro-is-view/Macros_Test_2.scala9
-rw-r--r--test/files/run/macro-expand-multiple-arglists.check1
-rw-r--r--test/files/run/macro-expand-multiple-arglists.flags1
-rw-r--r--test/files/run/macro-expand-multiple-arglists/Impls_1.scala10
-rw-r--r--test/files/run/macro-expand-multiple-arglists/Macros_Test_2.scala4
-rw-r--r--test/files/run/macro-expand-nullary-generic.check6
-rw-r--r--test/files/run/macro-expand-nullary-generic.flags1
-rw-r--r--test/files/run/macro-expand-nullary-generic/Impls_1.scala14
-rw-r--r--test/files/run/macro-expand-nullary-generic/Macros_Test_2.scala15
-rw-r--r--test/files/run/macro-expand-nullary-nongeneric.check6
-rw-r--r--test/files/run/macro-expand-nullary-nongeneric.flags1
-rw-r--r--test/files/run/macro-expand-nullary-nongeneric/Impls_1.scala14
-rw-r--r--test/files/run/macro-expand-nullary-nongeneric/Macros_Test_2.scala15
-rw-r--r--test/files/run/macro-expand-overload.check6
-rw-r--r--test/files/run/macro-expand-overload.flags1
-rw-r--r--test/files/run/macro-expand-overload/Impls_1.scala15
-rw-r--r--test/files/run/macro-expand-overload/Macros_Test_2.scala20
-rw-r--r--test/files/run/macro-expand-override.check15
-rw-r--r--test/files/run/macro-expand-override.flags1
-rw-r--r--test/files/run/macro-expand-override/Impls_1.scala15
-rw-r--r--test/files/run/macro-expand-override/Macros_Test_2.scala43
-rw-r--r--test/files/run/macro-expand-recursive.check1
-rw-r--r--test/files/run/macro-expand-recursive.flags1
-rw-r--r--test/files/run/macro-expand-recursive/Impls_1.scala15
-rw-r--r--test/files/run/macro-expand-recursive/Macros_Test_2.scala8
-rw-r--r--test/files/run/macro-expand-tparams-bounds-a.check (renamed from test/pending/run/t5271_1.check)0
-rw-r--r--test/files/run/macro-expand-tparams-bounds-a.flags1
-rw-r--r--test/files/run/macro-expand-tparams-bounds-a/Impls_1.scala5
-rw-r--r--test/files/run/macro-expand-tparams-bounds-a/Macros_Test_2.scala8
-rw-r--r--test/files/run/macro-expand-tparams-bounds-b.check0
-rw-r--r--test/files/run/macro-expand-tparams-bounds-b.flags1
-rw-r--r--test/files/run/macro-expand-tparams-bounds-b/Impls_1.scala7
-rw-r--r--test/files/run/macro-expand-tparams-bounds-b/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-expand-tparams-explicit.check1
-rw-r--r--test/files/run/macro-expand-tparams-explicit.flags1
-rw-r--r--test/files/run/macro-expand-tparams-explicit/Impls_1.scala10
-rw-r--r--test/files/run/macro-expand-tparams-explicit/Macros_Test_2.scala4
-rw-r--r--test/files/run/macro-expand-tparams-implicit.check2
-rw-r--r--test/files/run/macro-expand-tparams-implicit.flags1
-rw-r--r--test/files/run/macro-expand-tparams-implicit/Impls_1.scala10
-rw-r--r--test/files/run/macro-expand-tparams-implicit/Macros_Test_2.scala5
-rw-r--r--test/files/run/macro-expand-tparams-only-in-impl.flags1
-rw-r--r--test/files/run/macro-expand-tparams-only-in-impl/Impls_1.scala5
-rw-r--r--test/files/run/macro-expand-tparams-only-in-impl/Macros_Test_2.scala8
-rw-r--r--test/files/run/macro-expand-tparams-optional.check1
-rw-r--r--test/files/run/macro-expand-tparams-optional.flags1
-rw-r--r--test/files/run/macro-expand-tparams-optional/Impls_1.scala9
-rw-r--r--test/files/run/macro-expand-tparams-optional/Macros_Test_2.scala4
-rw-r--r--test/files/run/macro-expand-tparams-prefix-a.check4
-rw-r--r--test/files/run/macro-expand-tparams-prefix-a.flags1
-rw-r--r--test/files/run/macro-expand-tparams-prefix-a/Impls_1.scala10
-rw-r--r--test/files/run/macro-expand-tparams-prefix-a/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-expand-tparams-prefix-b.check2
-rw-r--r--test/files/run/macro-expand-tparams-prefix-b.flags1
-rw-r--r--test/files/run/macro-expand-tparams-prefix-b/Impls_1.scala11
-rw-r--r--test/files/run/macro-expand-tparams-prefix-b/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c1.check3
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c1.flags1
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c1/Impls_1.scala12
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c1/Macros_Test_2.scala11
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c2.check3
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c2.flags1
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c2/Impls_Macros_1.scala18
-rw-r--r--test/files/run/macro-expand-tparams-prefix-c2/Test_2.scala5
-rw-r--r--test/files/run/macro-expand-tparams-prefix-d1.check3
-rw-r--r--test/files/run/macro-expand-tparams-prefix-d1.flags1
-rw-r--r--test/files/run/macro-expand-tparams-prefix-d1/Impls_1.scala12
-rw-r--r--test/files/run/macro-expand-tparams-prefix-d1/Macros_Test_2.scala11
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.check4
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.flags1
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Impls_1.scala9
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala10
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.check1
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.flags1
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Impls_1.scala13
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Macros_Test_2.scala8
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-varargs.check1
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-varargs.flags1
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-varargs/Impls_1.scala13
-rw-r--r--test/files/run/macro-expand-varargs-explicit-over-varargs/Macros_Test_2.scala8
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-nonvarargs.check1
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-nonvarargs.flags1
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Impls_1.scala9
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Macros_Test_2.scala7
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-varargs.check1
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-varargs.flags1
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-varargs/Impls_1.scala13
-rw-r--r--test/files/run/macro-expand-varargs-implicit-over-varargs/Macros_Test_2.scala7
-rw-r--r--test/files/run/macro-impl-default-params.check5
-rw-r--r--test/files/run/macro-impl-default-params.flags1
-rw-r--r--test/files/run/macro-impl-default-params/Impls_Macros_1.scala20
-rw-r--r--test/files/run/macro-impl-default-params/Test_2.scala4
-rw-r--r--test/files/run/macro-impl-rename-context.check2
-rw-r--r--test/files/run/macro-impl-rename-context.flags1
-rw-r--r--test/files/run/macro-impl-rename-context/Impls_Macros_1.scala15
-rw-r--r--test/files/run/macro-impl-rename-context/Test_2.scala4
-rw-r--r--test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.check5
-rw-r--r--test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.flags1
-rw-r--r--test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Impls_Macros_1.scala12
-rw-r--r--test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala6
-rw-r--r--test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.check0
-rw-r--r--test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.flags1
-rw-r--r--test/files/run/macro-invalidret-nontypeable.check3
-rw-r--r--test/files/run/macro-invalidret-nontypeable.flags1
-rw-r--r--test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala13
-rw-r--r--test/files/run/macro-invalidret-nontypeable/Test_2.scala6
-rw-r--r--test/files/run/macro-invalidusage-badret.check5
-rw-r--r--test/files/run/macro-invalidusage-badret.flags1
-rw-r--r--test/files/run/macro-invalidusage-badret/Impls_Macros_1.scala9
-rw-r--r--test/files/run/macro-invalidusage-badret/Test_2.scala6
-rw-r--r--test/files/run/macro-invalidusage-partialapplication.check3
-rw-r--r--test/files/run/macro-invalidusage-partialapplication.flags1
-rw-r--r--test/files/run/macro-invalidusage-partialapplication/Impls_Macros_1.scala14
-rw-r--r--test/files/run/macro-invalidusage-partialapplication/Test_2.scala6
-rw-r--r--test/files/run/macro-openmacros.check3
-rw-r--r--test/files/run/macro-openmacros.flags1
-rw-r--r--test/files/run/macro-openmacros/Impls_Macros_1.scala26
-rw-r--r--test/files/run/macro-openmacros/Test_2.scala3
-rw-r--r--test/files/run/macro-quasiinvalidbody-c.check1
-rw-r--r--test/files/run/macro-quasiinvalidbody-c.flags1
-rw-r--r--test/files/run/macro-quasiinvalidbody-c/Impls_Macros_1.scala9
-rw-r--r--test/files/run/macro-quasiinvalidbody-c/Test_2.scala4
-rw-r--r--test/files/run/macro-range.flags2
-rw-r--r--test/files/run/macro-range/Common_1.scala48
-rw-r--r--test/files/run/macro-range/Expansion_Impossible_2.scala53
-rw-r--r--test/files/run/macro-range/Expansion_Possible_3.scala7
-rw-r--r--test/files/run/macro-range/macro_range_1.scala99
-rw-r--r--test/files/run/macro-range/macro_range_2.scala99
-rw-r--r--test/files/run/macro-reflective-ma-normal-mdmi.check1
-rw-r--r--test/files/run/macro-reflective-ma-normal-mdmi.flags1
-rw-r--r--test/files/run/macro-reflective-ma-normal-mdmi/Impls_Macros_1.scala13
-rw-r--r--test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala5
-rw-r--r--test/files/run/macro-reflective-mamd-normal-mi.check1
-rw-r--r--test/files/run/macro-reflective-mamd-normal-mi/Impls_1.scala9
-rw-r--r--test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala17
-rw-r--r--test/files/run/macro-reify-basic.check1
-rw-r--r--test/files/run/macro-reify-basic.flags1
-rw-r--r--test/files/run/macro-reify-basic/Macros_1.scala11
-rw-r--r--test/files/run/macro-reify-basic/Test_2.scala3
-rw-r--r--test/files/run/macro-reify-eval-eval.check1
-rw-r--r--test/files/run/macro-reify-eval-eval.flags1
-rw-r--r--test/files/run/macro-reify-eval-eval/Macros_1.scala12
-rw-r--r--test/files/run/macro-reify-eval-eval/Test_2.scala3
-rw-r--r--test/files/run/macro-reify-eval-outside-reify.check1
-rw-r--r--test/files/run/macro-reify-eval-outside-reify.flags1
-rw-r--r--test/files/run/macro-reify-eval-outside-reify/Impls_Macros_1.scala12
-rw-r--r--test/files/run/macro-reify-eval-outside-reify/Test_2.scala5
-rw-r--r--test/files/run/macro-reify-freevars.check3
-rw-r--r--test/files/run/macro-reify-freevars.flags1
-rw-r--r--test/files/run/macro-reify-freevars/Macros_1.scala19
-rw-r--r--test/files/run/macro-reify-freevars/Test_2.scala9
-rw-r--r--test/files/run/macro-reify-groundtypetag-notypeparams.check2
-rw-r--r--test/files/run/macro-reify-groundtypetag-notypeparams/Test.scala6
-rw-r--r--test/files/run/macro-reify-groundtypetag-typeparams-tags.check2
-rw-r--r--test/files/run/macro-reify-groundtypetag-typeparams-tags/Test.scala9
-rw-r--r--test/files/run/macro-reify-nested-a.check0
-rw-r--r--test/files/run/macro-reify-nested-a.flags1
-rw-r--r--test/files/run/macro-reify-nested-a/Impls_Macros_1.scala43
-rw-r--r--test/files/run/macro-reify-nested-a/Test_2.scala4
-rw-r--r--test/files/run/macro-reify-nested-b.check0
-rw-r--r--test/files/run/macro-reify-nested-b.flags1
-rw-r--r--test/files/run/macro-reify-nested-b/Impls_Macros_1.scala43
-rw-r--r--test/files/run/macro-reify-nested-b/Test_2.scala4
-rw-r--r--test/files/run/macro-reify-ref-to-packageless.check1
-rw-r--r--test/files/run/macro-reify-ref-to-packageless.flags1
-rw-r--r--test/files/run/macro-reify-ref-to-packageless/Impls_1.scala6
-rw-r--r--test/files/run/macro-reify-ref-to-packageless/Test_2.scala4
-rw-r--r--test/files/run/macro-reify-tagful-a.check1
-rw-r--r--test/files/run/macro-reify-tagful-a.flags1
-rw-r--r--test/files/run/macro-reify-tagful-a/Macros_1.scala11
-rw-r--r--test/files/run/macro-reify-tagful-a/Test_2.scala4
-rw-r--r--test/files/run/macro-reify-tagless-a.check3
-rw-r--r--test/files/run/macro-reify-tagless-a.flags1
-rw-r--r--test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala11
-rw-r--r--test/files/run/macro-reify-tagless-a/Test_2.scala12
-rw-r--r--test/files/run/macro-reify-typetag-notypeparams.check2
-rw-r--r--test/files/run/macro-reify-typetag-notypeparams/Test.scala6
-rw-r--r--test/files/run/macro-reify-typetag-typeparams-notags.check2
-rw-r--r--test/files/run/macro-reify-typetag-typeparams-notags/Test.scala9
-rw-r--r--test/files/run/macro-reify-typetag-typeparams-tags.check2
-rw-r--r--test/files/run/macro-reify-typetag-typeparams-tags/Test.scala9
-rw-r--r--test/files/run/macro-reify-typetag-usegroundtypetag.check2
-rw-r--r--test/files/run/macro-reify-typetag-usegroundtypetag/Test.scala9
-rw-r--r--test/files/run/macro-reify-unreify.check1
-rw-r--r--test/files/run/macro-reify-unreify.flags1
-rw-r--r--test/files/run/macro-reify-unreify/Macros_1.scala19
-rw-r--r--test/files/run/macro-reify-unreify/Test_2.scala3
-rw-r--r--test/files/run/macro-reify-value-outside-reify.check1
-rw-r--r--test/files/run/macro-reify-value-outside-reify.flags1
-rw-r--r--test/files/run/macro-reify-value-outside-reify/Impls_Macros_1.scala12
-rw-r--r--test/files/run/macro-reify-value-outside-reify/Test_2.scala6
-rw-r--r--test/files/run/macro-repl-basic.check79
-rw-r--r--test/files/run/macro-repl-basic.scala31
-rw-r--r--test/files/run/macro-repl-dontexpand.check5
-rw-r--r--test/files/run/macro-repl-dontexpand.scala7
-rw-r--r--test/files/run/macro-rettype-mismatch.flags2
-rw-r--r--test/files/run/macro-rettype-mismatch/Macros_1.scala3
-rw-r--r--test/files/run/macro-rettype-mismatch/Test_2.scala16
-rw-r--r--test/files/run/macro-settings.check1
-rw-r--r--test/files/run/macro-settings.flags1
-rw-r--r--test/files/run/macro-settings/Impls_Macros_1.scala11
-rw-r--r--test/files/run/macro-settings/Test_2.scala3
-rw-r--r--test/files/run/macro-sip19-revised.check5
-rw-r--r--test/files/run/macro-sip19-revised.flags1
-rw-r--r--test/files/run/macro-sip19-revised/Impls_Macros_1.scala34
-rw-r--r--test/files/run/macro-sip19-revised/Test_2.scala12
-rw-r--r--test/files/run/macro-sip19.check5
-rw-r--r--test/files/run/macro-sip19.flags1
-rw-r--r--test/files/run/macro-sip19/Impls_Macros_1.scala25
-rw-r--r--test/files/run/macro-sip19/Test_2.scala16
-rw-r--r--test/files/run/macro-typecheck-implicitsdisabled.check2
-rw-r--r--test/files/run/macro-typecheck-implicitsdisabled.flags1
-rw-r--r--test/files/run/macro-typecheck-implicitsdisabled/Impls_Macros_1.scala28
-rw-r--r--test/files/run/macro-typecheck-implicitsdisabled/Test_2.scala4
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled.check5
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled.flags1
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala29
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled/Test_2.scala4
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled2.check5
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled2.flags1
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled2/Impls_Macros_1.scala29
-rw-r--r--test/files/run/macro-typecheck-macrosdisabled2/Test_2.scala4
-rw-r--r--test/files/run/macro-undetparams-consfromsls.check5
-rw-r--r--test/files/run/macro-undetparams-consfromsls.flags1
-rw-r--r--test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala17
-rw-r--r--test/files/run/macro-undetparams-consfromsls/Test_2.scala7
-rw-r--r--test/files/run/macro-undetparams-implicitval.check1
-rw-r--r--test/files/run/macro-undetparams-implicitval.flags1
-rw-r--r--test/files/run/macro-undetparams-implicitval/Test.scala4
-rw-r--r--test/files/run/macro-undetparams-macroitself.check2
-rw-r--r--test/files/run/macro-undetparams-macroitself.flags1
-rw-r--r--test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala7
-rw-r--r--test/files/run/macro-undetparams-macroitself/Test_2.scala4
-rw-r--r--test/files/run/manifests-new.scala147
-rw-r--r--test/files/run/manifests-old.scala (renamed from test/files/run/manifests.scala)67
-rw-r--r--test/files/run/nonlocalreturn.check1
-rw-r--r--test/files/run/nonlocalreturn.scala15
-rw-r--r--test/files/run/option-fold.check5
-rw-r--r--test/files/run/option-fold.scala19
-rw-r--r--test/files/run/packrat3.check2
-rw-r--r--test/files/run/patmat_unapp_abstype-new.check (renamed from test/files/run/patmat_unapp_abstype.check)2
-rw-r--r--test/files/run/patmat_unapp_abstype-new.flags1
-rw-r--r--test/files/run/patmat_unapp_abstype-new.scala83
-rw-r--r--test/files/run/patmat_unapp_abstype-old.check4
-rw-r--r--test/files/run/patmat_unapp_abstype-old.flags1
-rw-r--r--test/files/run/patmat_unapp_abstype-old.scala83
-rw-r--r--test/files/run/patmat_unapp_abstype.scala39
-rw-r--r--test/files/run/phantomValueClass.check1
-rw-r--r--test/files/run/phantomValueClass.scala10
-rw-r--r--test/files/run/primitive-sigs-2-new.check7
-rw-r--r--test/files/run/primitive-sigs-2-new.scala31
-rw-r--r--test/files/run/primitive-sigs-2-old.check (renamed from test/files/run/primitive-sigs-2.check)14
-rw-r--r--test/files/run/primitive-sigs-2-old.scala (renamed from test/files/run/primitive-sigs-2.scala)0
-rw-r--r--test/files/run/programmatic-main.check47
-rw-r--r--test/files/run/reflect-overload.scala16
-rw-r--r--test/files/run/reflection-implClass-new.scala38
-rw-r--r--test/files/run/reflection-implClass-old.scala (renamed from test/files/run/reflection-implClass.scala)4
-rw-r--r--test/files/run/reflection-simple.check45
-rw-r--r--test/files/run/reflection-simple.scala11
-rw-r--r--test/files/run/reify-repl-fail-gracefully.check21
-rw-r--r--test/files/run/reify-repl-fail-gracefully.scala10
-rw-r--r--test/files/run/reify_ann1a.check60
-rw-r--r--test/files/run/reify_ann1a.scala13
-rw-r--r--test/files/run/reify_ann1b.check60
-rw-r--r--test/files/run/reify_ann1b.scala13
-rw-r--r--test/files/run/reify_ann2a.check44
-rw-r--r--test/files/run/reify_ann2a.scala (renamed from test/files/neg/reify_ann2a.scala)13
-rw-r--r--test/files/run/reify_ann3.check21
-rw-r--r--test/files/run/reify_ann3.scala19
-rw-r--r--test/files/run/reify_ann4.check32
-rw-r--r--test/files/run/reify_ann4.scala23
-rw-r--r--test/files/run/reify_ann5.check22
-rw-r--r--test/files/run/reify_ann5.scala20
-rw-r--r--test/files/run/reify_anonymous.scala12
-rw-r--r--test/files/run/reify_classfileann_a.check36
-rw-r--r--test/files/run/reify_classfileann_a.scala13
-rw-r--r--test/files/run/reify_classfileann_b.check20
-rw-r--r--test/files/run/reify_classfileann_b.scala23
-rw-r--r--test/files/run/reify_closure1.scala9
-rw-r--r--test/files/run/reify_closure2a.scala9
-rw-r--r--test/files/run/reify_closure3a.scala9
-rw-r--r--test/files/run/reify_closure4a.scala9
-rw-r--r--test/files/run/reify_closure5a.scala17
-rw-r--r--test/files/run/reify_closure6.scala17
-rw-r--r--test/files/run/reify_closure7.scala17
-rw-r--r--test/files/run/reify_closure8a.scala10
-rw-r--r--test/files/run/reify_closure8b.check3
-rw-r--r--test/files/run/reify_closure8b.scala18
-rw-r--r--test/files/run/reify_closures10.scala10
-rw-r--r--test/files/run/reify_complex.scala12
-rw-r--r--test/files/run/reify_csv.check (renamed from test/pending/run/reify_csv.check)0
-rw-r--r--test/files/run/reify_csv.scala (renamed from test/pending/run/reify_csv.scala)12
-rw-r--r--test/files/run/reify_extendbuiltins.scala12
-rw-r--r--test/files/run/reify_for1.scala12
-rw-r--r--test/files/run/reify_fors.flags0
-rw-r--r--test/files/run/reify_fors.scala12
-rw-r--r--test/files/run/reify_generic.scala12
-rw-r--r--test/files/run/reify_generic2.scala12
-rw-r--r--test/files/run/reify_getter.scala11
-rw-r--r--test/files/run/reify_implicits-new.check (renamed from test/files/run/reify_implicits.check)0
-rw-r--r--test/files/run/reify_implicits-new.scala14
-rw-r--r--test/files/run/reify_implicits-old.check1
-rw-r--r--test/files/run/reify_implicits-old.scala (renamed from test/files/run/reify_implicits.scala)12
-rw-r--r--test/files/run/reify_inheritance.scala12
-rw-r--r--test/files/run/reify_inner1.scala12
-rw-r--r--test/files/run/reify_inner2.scala12
-rw-r--r--test/files/run/reify_inner3.scala12
-rw-r--r--test/files/run/reify_inner4.scala12
-rw-r--r--test/files/run/reify_lazyevaluation.check (renamed from test/pending/run/reify_lazyevaluation.check)0
-rw-r--r--test/files/run/reify_lazyevaluation.scala (renamed from test/pending/run/reify_lazyevaluation.scala)12
-rw-r--r--test/files/run/reify_maps.flags0
-rw-r--r--test/files/run/reify_maps.scala12
-rw-r--r--test/files/run/reify_metalevel_breach_+0_refers_to_1.check1
-rw-r--r--test/files/run/reify_metalevel_breach_+0_refers_to_1.scala13
-rw-r--r--test/files/run/reify_metalevel_breach_-1_refers_to_0_a.check1
-rw-r--r--test/files/run/reify_metalevel_breach_-1_refers_to_0_a.scala11
-rw-r--r--test/files/run/reify_metalevel_breach_-1_refers_to_0_b.check1
-rw-r--r--test/files/run/reify_metalevel_breach_-1_refers_to_0_b.scala15
-rw-r--r--test/files/run/reify_metalevel_breach_-1_refers_to_1.check1
-rw-r--r--test/files/run/reify_metalevel_breach_-1_refers_to_1.scala13
-rw-r--r--test/files/run/reify_nested_inner_refers_to_global.check1
-rw-r--r--test/files/run/reify_nested_inner_refers_to_global.scala14
-rw-r--r--test/files/run/reify_nested_inner_refers_to_local.check1
-rw-r--r--test/files/run/reify_nested_inner_refers_to_local.scala12
-rw-r--r--test/files/run/reify_nested_outer_refers_to_global.check1
-rw-r--r--test/files/run/reify_nested_outer_refers_to_global.scala16
-rw-r--r--test/files/run/reify_nested_outer_refers_to_local.check1
-rw-r--r--test/files/run/reify_nested_outer_refers_to_local.scala16
-rw-r--r--test/files/run/reify_newimpl_01.check1
-rw-r--r--test/files/run/reify_newimpl_01.scala11
-rw-r--r--test/files/run/reify_newimpl_02.check1
-rw-r--r--test/files/run/reify_newimpl_02.scala11
-rw-r--r--test/files/run/reify_newimpl_03.check1
-rw-r--r--test/files/run/reify_newimpl_03.scala11
-rw-r--r--test/files/run/reify_newimpl_04.check1
-rw-r--r--test/files/run/reify_newimpl_04.scala11
-rw-r--r--test/files/run/reify_newimpl_05.check1
-rw-r--r--test/files/run/reify_newimpl_05.scala12
-rw-r--r--test/files/run/reify_newimpl_06.check1
-rw-r--r--test/files/run/reify_newimpl_06.scala11
-rw-r--r--test/files/run/reify_newimpl_09.check1
-rw-r--r--test/files/run/reify_newimpl_09.scala11
-rw-r--r--test/files/run/reify_newimpl_10.check1
-rw-r--r--test/files/run/reify_newimpl_10.scala12
-rw-r--r--test/files/run/reify_newimpl_11.check2
-rw-r--r--test/files/run/reify_newimpl_11.scala17
-rw-r--r--test/files/run/reify_newimpl_12.check1
-rw-r--r--test/files/run/reify_newimpl_12.scala12
-rw-r--r--test/files/run/reify_newimpl_13.check2
-rw-r--r--test/files/run/reify_newimpl_13.scala19
-rw-r--r--test/files/run/reify_newimpl_14.check1
-rw-r--r--test/files/run/reify_newimpl_14.scala14
-rw-r--r--test/files/run/reify_newimpl_15.check1
-rw-r--r--test/files/run/reify_newimpl_15.scala13
-rw-r--r--test/files/run/reify_newimpl_16.check1
-rw-r--r--test/files/run/reify_newimpl_16.scala15
-rw-r--r--test/files/run/reify_newimpl_17.check2
-rw-r--r--test/files/run/reify_newimpl_17.scala18
-rw-r--r--test/files/run/reify_newimpl_18.check1
-rw-r--r--test/files/run/reify_newimpl_18.scala13
-rw-r--r--test/files/run/reify_newimpl_19.check2
-rw-r--r--test/files/run/reify_newimpl_19.scala18
-rw-r--r--test/files/run/reify_newimpl_20.check1
-rw-r--r--test/files/run/reify_newimpl_20.scala14
-rw-r--r--test/files/run/reify_newimpl_21.check1
-rw-r--r--test/files/run/reify_newimpl_21.scala18
-rw-r--r--test/files/run/reify_newimpl_22.check23
-rw-r--r--test/files/run/reify_newimpl_22.scala15
-rw-r--r--test/files/run/reify_newimpl_23.check22
-rw-r--r--test/files/run/reify_newimpl_23.scala14
-rw-r--r--test/files/run/reify_newimpl_24.check24
-rw-r--r--test/files/run/reify_newimpl_24.scala16
-rw-r--r--test/files/run/reify_newimpl_25.check21
-rw-r--r--test/files/run/reify_newimpl_25.scala13
-rw-r--r--test/files/run/reify_newimpl_26.check23
-rw-r--r--test/files/run/reify_newimpl_26.scala13
-rw-r--r--test/files/run/reify_newimpl_27.check1
-rw-r--r--test/files/run/reify_newimpl_27.scala13
-rw-r--r--test/files/run/reify_newimpl_28.check1
-rw-r--r--test/files/run/reify_newimpl_28.scala15
-rw-r--r--test/files/run/reify_newimpl_29.check1
-rw-r--r--test/files/run/reify_newimpl_29.scala13
-rw-r--r--test/files/run/reify_newimpl_30.check1
-rw-r--r--test/files/run/reify_newimpl_30.scala15
-rw-r--r--test/files/run/reify_newimpl_31.check1
-rw-r--r--test/files/run/reify_newimpl_31.scala13
-rw-r--r--test/files/run/reify_newimpl_32.check1
-rw-r--r--test/files/run/reify_newimpl_32.scala15
-rw-r--r--test/files/run/reify_newimpl_33.check1
-rw-r--r--test/files/run/reify_newimpl_33.scala14
-rw-r--r--test/files/run/reify_newimpl_34.check1
-rw-r--r--test/files/run/reify_newimpl_34.scala16
-rw-r--r--test/files/run/reify_newimpl_36.check1
-rw-r--r--test/files/run/reify_newimpl_36.scala14
-rw-r--r--test/files/run/reify_newimpl_37.check1
-rw-r--r--test/files/run/reify_newimpl_37.scala15
-rw-r--r--test/files/run/reify_newimpl_38.check1
-rw-r--r--test/files/run/reify_newimpl_38.scala14
-rw-r--r--test/files/run/reify_newimpl_39.check1
-rw-r--r--test/files/run/reify_newimpl_39.scala15
-rw-r--r--test/files/run/reify_newimpl_40.check1
-rw-r--r--test/files/run/reify_newimpl_40.scala15
-rw-r--r--test/files/run/reify_newimpl_41.check3
-rw-r--r--test/files/run/reify_newimpl_41.scala17
-rw-r--r--test/files/run/reify_newimpl_42.check3
-rw-r--r--test/files/run/reify_newimpl_42.scala16
-rw-r--r--test/files/run/reify_newimpl_43.check2
-rw-r--r--test/files/run/reify_newimpl_43.scala15
-rw-r--r--test/files/run/reify_newimpl_44.check2
-rw-r--r--test/files/run/reify_newimpl_44.scala15
-rw-r--r--test/files/run/reify_newimpl_45.check2
-rw-r--r--test/files/run/reify_newimpl_45.scala12
-rw-r--r--test/files/run/reify_newimpl_47.check1
-rw-r--r--test/files/run/reify_newimpl_47.scala15
-rw-r--r--test/files/run/reify_newimpl_48.check1
-rw-r--r--test/files/run/reify_newimpl_48.scala20
-rw-r--r--test/files/run/reify_newimpl_49.check3
-rw-r--r--test/files/run/reify_newimpl_49.scala15
-rw-r--r--test/files/run/reify_newimpl_50.check3
-rw-r--r--test/files/run/reify_newimpl_50.scala14
-rw-r--r--test/files/run/reify_newimpl_51.check3
-rw-r--r--test/files/run/reify_newimpl_51.scala17
-rw-r--r--test/files/run/reify_newimpl_52.check3
-rw-r--r--test/files/run/reify_newimpl_52.scala17
-rw-r--r--test/files/run/reify_printf.scala11
-rw-r--r--test/files/run/reify_properties.check (renamed from test/pending/run/reify_properties.check)0
-rw-r--r--test/files/run/reify_properties.scala (renamed from test/pending/run/reify_properties.scala)12
-rw-r--r--test/files/run/reify_sort.scala12
-rw-r--r--test/files/run/reify_sort1.scala12
-rw-r--r--test/files/run/reify_this.scala25
-rw-r--r--test/files/run/reify_timeofday.scala12
-rw-r--r--test/files/run/reify_typerefs_1a.check1
-rw-r--r--test/files/run/reify_typerefs_1a.scala15
-rw-r--r--test/files/run/reify_typerefs_1b.check1
-rw-r--r--test/files/run/reify_typerefs_1b.scala15
-rw-r--r--test/files/run/reify_typerefs_2a.check1
-rw-r--r--test/files/run/reify_typerefs_2a.scala17
-rw-r--r--test/files/run/reify_typerefs_2b.check1
-rw-r--r--test/files/run/reify_typerefs_2b.scala17
-rw-r--r--test/files/run/reify_typerefs_3a.check1
-rw-r--r--test/files/run/reify_typerefs_3a.scala17
-rw-r--r--test/files/run/reify_typerefs_3b.check1
-rw-r--r--test/files/run/reify_typerefs_3b.scala17
-rw-r--r--test/files/run/reify_varargs.scala12
-rw-r--r--test/files/run/repl-colon-type.check173
-rw-r--r--test/files/run/repl-colon-type.scala8
-rw-r--r--test/files/run/repl-parens.check2
-rw-r--r--test/files/run/repl-parens.scala4
-rw-r--r--test/files/run/repl-power.check64
-rw-r--r--test/files/run/repl-power.scala3
-rw-r--r--test/files/run/repl-reset.check2
-rw-r--r--test/files/run/repl-suppressed-warnings.scala1
-rw-r--r--test/files/run/repl-type-verbose.check186
-rw-r--r--test/files/run/repl-type-verbose.scala20
-rw-r--r--test/files/run/si5045.check6
-rw-r--r--test/files/run/si5045.scala46
-rw-r--r--test/files/run/t0421-new.check (renamed from test/files/run/t0421.check)0
-rw-r--r--test/files/run/t0421-new.scala30
-rw-r--r--test/files/run/t0421-old.check3
-rw-r--r--test/files/run/t0421-old.scala (renamed from test/files/run/t0421.scala)0
-rw-r--r--test/files/run/t0677-new.scala8
-rw-r--r--test/files/run/t0677-old.scala (renamed from test/files/run/t0677.scala)0
-rw-r--r--test/files/run/t1195-new.check6
-rw-r--r--test/files/run/t1195-new.scala26
-rw-r--r--test/files/run/t1195-old.check (renamed from test/files/run/t1195.check)12
-rw-r--r--test/files/run/t1195-old.scala (renamed from test/files/run/t1195.scala)2
-rw-r--r--test/files/run/t1247.check1
-rw-r--r--test/files/run/t1247.scala11
-rw-r--r--test/files/run/t1500.scala2
-rw-r--r--test/files/run/t1501.scala2
-rw-r--r--test/files/run/t1697.scala (renamed from test/pending/run/t1697.scala)0
-rw-r--r--test/files/run/t2236-new.scala17
-rw-r--r--[-rwxr-xr-x]test/files/run/t2236-old.scala (renamed from test/files/run/t2236.scala)0
-rw-r--r--test/files/run/t2337.check4
-rw-r--r--test/files/run/t2337.scala21
-rw-r--r--test/files/run/t2386-new.check2
-rw-r--r--test/files/run/t2386-new.scala5
-rw-r--r--test/files/run/t2886.check10
-rw-r--r--test/files/run/t2886.scala9
-rw-r--r--test/files/run/t3507-new.check1
-rw-r--r--test/files/run/t3507-new.scala15
-rw-r--r--test/files/run/t3569.check13
-rw-r--r--test/files/run/t3705.scala (renamed from test/pending/run/t3705.scala)0
-rw-r--r--test/files/run/t3758-old.scala (renamed from test/files/run/t3758.scala)2
-rw-r--r--test/files/run/t3798.check1
-rw-r--r--test/files/run/t3798.scala10
-rw-r--r--test/files/run/t3835.scala9
-rw-r--r--test/files/run/t4110-new.check2
-rw-r--r--test/files/run/t4110-new.scala11
-rw-r--r--test/files/run/t4110-old.check (renamed from test/files/run/t4110.check)0
-rw-r--r--test/files/run/t4110-old.scala (renamed from test/files/run/t4110.scala)2
-rw-r--r--test/files/run/t4172.check2
-rw-r--r--test/files/run/t4190.check3
-rw-r--r--test/files/run/t4190.scala6
-rw-r--r--test/files/run/t4216.check34
-rw-r--r--test/files/run/t4216.scala18
-rw-r--r--test/files/run/t4317/S_1.scala2
-rw-r--r--test/files/run/t4415.scala (renamed from test/pending/run/t4415.scala)0
-rw-r--r--test/files/run/t4536.check8
-rw-r--r--test/files/run/t4536.scala46
-rw-r--r--test/files/run/t4658.check12
-rw-r--r--test/files/run/t4658.scala14
-rw-r--r--test/files/run/t4710.check1
-rw-r--r--test/files/run/t4929.check1
-rw-r--r--test/files/run/t4929.scala42
-rw-r--r--test/files/run/t5018.scala37
-rw-r--r--test/files/run/t5040.check1
-rw-r--r--test/files/run/t5040.scala11
-rw-r--r--test/files/run/t5224.check18
-rw-r--r--test/files/run/t5224.scala7
-rw-r--r--test/files/run/t5225_1.check8
-rw-r--r--test/files/run/t5225_1.scala5
-rw-r--r--test/files/run/t5225_2.check8
-rw-r--r--test/files/run/t5225_2.scala5
-rw-r--r--test/files/run/t5229_1.scala12
-rw-r--r--test/files/run/t5229_2.scala9
-rw-r--r--test/files/run/t5230.scala9
-rw-r--r--test/files/run/t5258a.scala12
-rw-r--r--test/files/run/t5266_1.scala9
-rw-r--r--test/files/run/t5266_2.scala9
-rw-r--r--test/files/run/t5269.scala12
-rw-r--r--test/files/run/t5270.scala12
-rw-r--r--test/files/run/t5271_1.check23
-rw-r--r--test/files/run/t5271_1.scala10
-rw-r--r--test/files/run/t5271_2.check26
-rw-r--r--test/files/run/t5271_2.scala10
-rw-r--r--test/files/run/t5271_3.check40
-rw-r--r--test/files/run/t5271_3.scala10
-rw-r--r--test/files/run/t5271_4.scala12
-rw-r--r--test/files/run/t5272_1.flags0
-rw-r--r--test/files/run/t5272_1.scala12
-rw-r--r--test/files/run/t5272_2.flags0
-rw-r--r--test/files/run/t5272_2.scala12
-rw-r--r--test/files/run/t5273_1.flags0
-rw-r--r--test/files/run/t5273_1.scala12
-rw-r--r--test/files/run/t5273_2a.flags0
-rw-r--r--test/files/run/t5273_2a.scala12
-rw-r--r--test/files/run/t5273_2b.flags0
-rw-r--r--test/files/run/t5273_2b.scala12
-rw-r--r--test/files/run/t5274_1.scala12
-rw-r--r--test/files/run/t5274_2.scala12
-rw-r--r--test/files/run/t5275.scala12
-rw-r--r--test/files/run/t5276_1a.scala12
-rw-r--r--test/files/run/t5276_1b.scala12
-rw-r--r--test/files/run/t5276_2a.scala12
-rw-r--r--test/files/run/t5276_2b.scala12
-rw-r--r--test/files/run/t5277_1.scala12
-rw-r--r--test/files/run/t5277_2.scala12
-rw-r--r--test/files/run/t5279.scala12
-rw-r--r--test/files/run/t5334_1.scala12
-rw-r--r--test/files/run/t5334_2.scala12
-rw-r--r--test/files/run/t5335.scala12
-rw-r--r--test/files/run/t5415.scala10
-rw-r--r--test/files/run/t5419.check2
-rw-r--r--test/files/run/t5419.scala7
-rw-r--r--test/files/run/t5423.scala5
-rw-r--r--test/files/run/t5514.check19
-rw-r--r--test/files/run/t5514.scala35
-rw-r--r--test/files/run/t5535.check20
-rw-r--r--test/files/run/t5535.scala10
-rw-r--r--test/files/run/t5543.check3
-rw-r--r--test/files/run/t5543.scala26
-rw-r--r--test/files/run/t5577.check11
-rw-r--r--test/files/run/t5577.scala27
-rw-r--r--test/files/run/t5583.check20
-rw-r--r--test/files/run/t5583.scala11
-rw-r--r--test/files/run/t5590.check4
-rw-r--r--test/files/run/t5590.scala31
-rw-r--r--test/files/run/t5608.check1
-rw-r--r--test/files/run/t5608.scala12
-rw-r--r--test/files/run/t5612.check4
-rw-r--r--test/files/run/t5612.scala28
-rw-r--r--test/files/run/t5614.check3
-rw-r--r--test/files/run/t5614.flags1
-rw-r--r--test/files/run/t5614.scala5
-rw-r--r--test/files/run/t5629.check2
-rw-r--r--test/files/run/t5629.scala36
-rw-r--r--test/files/run/t5629b.check10
-rw-r--r--test/files/run/t5629b.scala41
-rw-r--r--test/files/run/t5648.check4
-rw-r--r--test/files/run/t5648.flags1
-rw-r--r--test/files/run/t5648.scala10
-rw-r--r--test/files/run/t5655.check30
-rw-r--r--test/files/run/t5655.scala10
-rw-r--r--test/files/run/t5656.check1
-rw-r--r--test/files/run/t5656.scala11
-rw-r--r--test/files/run/t5680.check3
-rw-r--r--test/files/run/t5680.scala7
-rw-r--r--test/files/run/t5688.check1
-rw-r--r--test/files/run/t5688.scala23
-rw-r--r--test/files/run/t5704.check1
-rw-r--r--test/files/run/t5704.flags1
-rw-r--r--test/files/run/t5704.scala16
-rw-r--r--test/files/run/t5713.check1
-rw-r--r--test/files/run/t5713.flags1
-rw-r--r--test/files/run/t5713/Impls_Macros_1.scala27
-rw-r--r--test/files/run/t5713/Test_2.scala5
-rw-r--r--test/files/run/toolbox_console_reporter.check0
-rw-r--r--test/files/run/toolbox_console_reporter.scala16
-rw-r--r--test/files/run/toolbox_default_reporter_is_silent.check1
-rw-r--r--test/files/run/toolbox_default_reporter_is_silent.scala13
-rw-r--r--test/files/run/toolbox_silent_reporter.check4
-rw-r--r--test/files/run/toolbox_silent_reporter.scala16
-rw-r--r--test/files/run/toolbox_typecheck_implicitsdisabled.check5
-rw-r--r--test/files/run/toolbox_typecheck_implicitsdisabled.scala24
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled.check5
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled.scala17
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled2.check5
-rw-r--r--test/files/run/toolbox_typecheck_macrosdisabled2.scala17
-rw-r--r--test/files/run/treePrint.scala11
-rw-r--r--test/files/run/tuple-zipped.scala4
-rw-r--r--test/files/run/typetags_core.check32
-rw-r--r--test/files/run/typetags_core.scala34
-rw-r--r--test/files/run/typetags_multi.check5
-rw-r--r--test/files/run/typetags_multi.scala7
-rw-r--r--test/files/run/virtpatmat_alts.flags2
-rw-r--r--test/files/run/virtpatmat_apply.flags2
-rw-r--r--test/files/run/virtpatmat_casting.flags2
-rw-r--r--test/files/run/virtpatmat_extends_product.flags2
-rw-r--r--test/files/run/virtpatmat_literal.flags2
-rw-r--r--test/files/run/virtpatmat_nested_lists.flags2
-rw-r--r--test/files/run/virtpatmat_npe.flags2
-rw-r--r--test/files/run/virtpatmat_opt_sharing.flags2
-rw-r--r--test/files/run/virtpatmat_partial.flags2
-rw-r--r--test/files/run/virtpatmat_partial_backquoted.check1
-rw-r--r--test/files/run/virtpatmat_partial_backquoted.scala12
-rw-r--r--test/files/run/virtpatmat_staging.flags2
-rw-r--r--test/files/run/virtpatmat_stringinterp.check1
-rw-r--r--test/files/run/virtpatmat_stringinterp.flags (renamed from test/files/pos/annotDepMethType.flags)0
-rw-r--r--test/files/run/virtpatmat_stringinterp.scala13
-rw-r--r--test/files/run/virtpatmat_switch.flags2
-rw-r--r--test/files/run/virtpatmat_tailcalls_verifyerror.flags2
-rw-r--r--test/files/run/virtpatmat_try.flags2
-rw-r--r--test/files/run/virtpatmat_typed.flags2
-rw-r--r--test/files/run/virtpatmat_unapply.flags2
-rw-r--r--test/files/run/virtpatmat_unapplyprod.flags2
-rw-r--r--test/files/run/virtpatmat_unapplyseq.flags2
-rw-r--r--test/files/run/virtpatmat_valdef.check1
-rw-r--r--test/files/run/virtpatmat_valdef.scala6
-rw-r--r--test/files/scalacheck/array-new.scala36
-rw-r--r--test/files/scalacheck/array-old.scala (renamed from test/files/scalacheck/array.scala)0
-rw-r--r--test/files/scalap/caseClass/result.test6
-rw-r--r--test/files/specialized/spec-matrix-new.check (renamed from test/files/specialized/spec-matrix.check)0
-rw-r--r--test/files/specialized/spec-matrix-new.scala80
-rw-r--r--test/files/specialized/spec-matrix-old.check2
-rw-r--r--test/files/specialized/spec-matrix-old.scala (renamed from test/files/specialized/spec-matrix.scala)0
-rw-r--r--test/files/specialized/spec-patmatch.check2
-rw-r--r--test/files/speclib/instrumented.jar.desired.sha12
-rw-r--r--test/instrumented/boxes.patch40
-rw-r--r--test/instrumented/library/scala/runtime/BoxesRunTime.java384
-rw-r--r--test/instrumented/library/scala/runtime/ScalaRunTime.scala93
-rw-r--r--test/instrumented/srt.patch17
-rw-r--r--test/pending/neg/reify_packed.check4
-rw-r--r--test/pending/neg/reify_packed.scala10
-rw-r--r--test/pending/neg/t1557.scala18
-rw-r--r--test/pending/neg/t2066.scala16
-rw-r--r--test/pending/neg/t3189.check7
-rw-r--r--test/pending/neg/t5378.scala19
-rw-r--r--test/pending/neg/t5618.check7
-rw-r--r--test/pending/neg/t5618.scala27
-rw-r--r--test/pending/pos/inference.scala20
-rw-r--r--test/pending/pos/t4683.scala11
-rw-r--r--test/pending/pos/t5399.scala15
-rw-r--r--test/pending/pos/t5399a.scala19
-rw-r--r--test/pending/pos/t5503.flags1
-rw-r--r--test/pending/pos/t5503.scala18
-rw-r--r--test/pending/pos/t5521.scala3
-rw-r--r--test/pending/pos/t5534.scala11
-rw-r--r--test/pending/pos/t5559.scala23
-rw-r--r--test/pending/pos/t5564.scala5
-rw-r--r--test/pending/pos/t5579.scala29
-rw-r--r--test/pending/pos/t5585.scala18
-rw-r--r--test/pending/pos/t5606.scala9
-rw-r--r--test/pending/pos/t5639/Bar.scala7
-rw-r--r--test/pending/pos/t5639/Foo.scala7
-rw-r--r--test/pending/pos/t5654.scala4
-rw-r--r--test/pending/pos/t5712.scala14
-rw-r--r--test/pending/presentation/t5708.check81
-rw-r--r--test/pending/presentation/t5708/Test.scala5
-rw-r--r--test/pending/presentation/t5708/src/Completions.scala11
-rw-r--r--test/pending/run/macro-expand-default.flags (renamed from test/files/pos/macros.flags)0
-rw-r--r--test/pending/run/macro-expand-default/Impls_1.scala10
-rw-r--r--test/pending/run/macro-expand-default/Macros_Test_2.scala8
-rw-r--r--test/pending/run/macro-expand-implicit-macro-defeats-type-inference.check6
-rw-r--r--test/pending/run/macro-expand-implicit-macro-defeats-type-inference.flags1
-rw-r--r--test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala10
-rw-r--r--test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Macros_Test_2.scala6
-rw-r--r--test/pending/run/macro-expand-implicit-macro-has-context-bound.check1
-rw-r--r--test/pending/run/macro-expand-implicit-macro-has-context-bound.flags (renamed from test/pending/run/macro-overload.flags)0
-rw-r--r--test/pending/run/macro-expand-implicit-macro-has-context-bound/Impls_1.scala10
-rw-r--r--test/pending/run/macro-expand-implicit-macro-has-context-bound/Macros_Test_2.scala4
-rw-r--r--test/pending/run/macro-expand-named.flags1
-rw-r--r--test/pending/run/macro-expand-named/Impls_1.scala10
-rw-r--r--test/pending/run/macro-expand-named/Macros_Test_2.scala5
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-e1.check3
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-e1.flags1
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-e1/Impls_1.scala12
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-e1/Macros_Test_2.scala13
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-f1.check3
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-f1.flags1
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-f1/Impls_1.scala12
-rw-r--r--test/pending/run/macro-expand-tparams-prefix-f1/Macros_Test_2.scala13
-rw-r--r--test/pending/run/macro-overload.check4
-rw-r--r--test/pending/run/macro-overload/Macros_1.scala9
-rw-r--r--test/pending/run/macro-overload/Test_2.scala6
-rw-r--r--test/pending/run/macro-quasiinvalidbody-a.check1
-rw-r--r--test/pending/run/macro-quasiinvalidbody-a.flags1
-rw-r--r--test/pending/run/macro-quasiinvalidbody-a/Impls_1.scala5
-rw-r--r--test/pending/run/macro-quasiinvalidbody-a/Macros_Test_2.scala10
-rw-r--r--test/pending/run/macro-quasiinvalidbody-b.check1
-rw-r--r--test/pending/run/macro-quasiinvalidbody-b.flags1
-rw-r--r--test/pending/run/macro-quasiinvalidbody-b/Impls_1.scala7
-rw-r--r--test/pending/run/macro-quasiinvalidbody-b/Macros_Test_2.scala10
-rw-r--r--test/pending/run/macro-reify-array.flags1
-rw-r--r--test/pending/run/macro-reify-array/Macros_1.scala11
-rw-r--r--test/pending/run/macro-reify-array/Test_2.scala4
-rw-r--r--test/pending/run/macro-reify-eval-vs-value.flags1
-rw-r--r--test/pending/run/macro-reify-eval-vs-value/Macros_1.scala25
-rw-r--r--test/pending/run/macro-reify-eval-vs-value/Test_2.scala5
-rw-r--r--test/pending/run/macro-reify-groundtypetag-hktypeparams-tags.check2
-rw-r--r--test/pending/run/macro-reify-groundtypetag-hktypeparams-tags/Test.scala9
-rw-r--r--test/pending/run/macro-reify-tagful-b.check1
-rw-r--r--test/pending/run/macro-reify-tagful-b.flags1
-rw-r--r--test/pending/run/macro-reify-tagful-b/Macros_1.scala11
-rw-r--r--test/pending/run/macro-reify-tagful-b/Test_2.scala4
-rw-r--r--test/pending/run/macro-reify-tagless-b.check3
-rw-r--r--test/pending/run/macro-reify-tagless-b.flags1
-rw-r--r--test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala11
-rw-r--r--test/pending/run/macro-reify-tagless-b/Test_2.scala11
-rw-r--r--test/pending/run/macro-reify-typetag-hktypeparams-notags.check2
-rw-r--r--test/pending/run/macro-reify-typetag-hktypeparams-notags/Test.scala9
-rw-r--r--test/pending/run/macro-reify-typetag-hktypeparams-tags.check2
-rw-r--r--test/pending/run/macro-reify-typetag-hktypeparams-tags/Test.scala9
-rw-r--r--test/pending/run/reify_addressbook.scala12
-rw-r--r--test/pending/run/reify_brainf_ck.scala12
-rw-r--r--test/pending/run/reify_callccinterpreter.scala12
-rw-r--r--test/pending/run/reify_classfileann_b.scala24
-rw-r--r--test/pending/run/reify_closure2b.scala9
-rw-r--r--test/pending/run/reify_closure3b.scala9
-rw-r--r--test/pending/run/reify_closure4b.scala9
-rw-r--r--test/pending/run/reify_closure5b.scala9
-rw-r--r--test/pending/run/reify_closure8b.check1
-rw-r--r--test/pending/run/reify_closure8b.scala16
-rw-r--r--test/pending/run/reify_closure9a.scala11
-rw-r--r--test/pending/run/reify_closure9b.scala11
-rw-r--r--test/pending/run/reify_closures11.scala11
-rw-r--r--test/pending/run/reify_gadts.scala12
-rw-r--r--test/pending/run/reify_newimpl_07.scala13
-rw-r--r--test/pending/run/reify_newimpl_08.scala15
-rw-r--r--test/pending/run/reify_newimpl_35.scala10
-rw-r--r--test/pending/run/reify_newimpl_46.scala12
-rw-r--r--test/pending/run/reify_newimpl_53.scala15
-rw-r--r--test/pending/run/reify_simpleinterpreter.scala12
-rw-r--r--test/pending/run/t4560.scala9
-rw-r--r--test/pending/run/t4728.check2
-rw-r--r--test/pending/run/t4728.scala11
-rw-r--r--test/pending/run/t5258b.scala12
-rw-r--r--test/pending/run/t5258c.scala12
-rw-r--r--test/pending/run/t5271_1.scala13
-rw-r--r--test/pending/run/t5271_2.check1
-rw-r--r--test/pending/run/t5271_2.scala15
-rw-r--r--test/pending/run/t5271_3.check1
-rw-r--r--test/pending/run/t5271_3.scala16
-rw-r--r--test/pending/run/t5418.scala12
-rw-r--r--test/pending/run/t5610a.check1
-rw-r--r--test/pending/run/t5610a.scala19
-rw-r--r--test/pending/run/t5610b.check1
-rw-r--r--test/pending/run/t5610b.scala21
-rw-r--r--test/pending/run/t5676.flags1
-rw-r--r--test/pending/run/t5676.scala25
-rw-r--r--test/pending/run/t5692.flags1
-rw-r--r--test/pending/run/t5692/Impls_Macros_1.scala9
-rw-r--r--test/pending/run/t5692/Test_2.scala4
-rw-r--r--test/pending/run/t5695.check2
-rw-r--r--test/pending/run/t5695/part_1.scala12
-rw-r--r--test/pending/run/t5695/part_2.scala8
-rw-r--r--test/pending/run/t5698/client.scala9
-rw-r--r--test/pending/run/t5698/server.scala22
-rw-r--r--test/pending/run/t5698/testmsg.scala5
-rw-r--r--test/pending/run/t5722.scala6
-rw-r--r--test/pending/run/t5726a.scala17
-rw-r--r--test/pending/run/t5726b.scala16
-rw-r--r--test/pending/shootout/meteor.scala64
-rw-r--r--test/scaladoc/resources/implicits-base-res.scala148
-rw-r--r--test/scaladoc/resources/implicits-chaining-res.scala50
-rw-r--r--test/scaladoc/resources/implicits-elimination-res.scala14
-rw-r--r--test/scaladoc/resources/implicits-scopes-res.scala52
-rw-r--r--test/scaladoc/resources/implicits-shadowing-res.scala64
-rw-r--r--test/scaladoc/resources/package-object-res.scala14
-rw-r--r--test/scaladoc/run/SI-5373.check2
-rw-r--r--test/scaladoc/run/SI-5373.scala6
-rw-r--r--test/scaladoc/run/implicits-base.check1
-rw-r--r--test/scaladoc/run/implicits-base.scala180
-rw-r--r--test/scaladoc/run/implicits-chaining.check1
-rw-r--r--test/scaladoc/run/implicits-chaining.scala65
-rw-r--r--test/scaladoc/run/implicits-elimination.check1
-rw-r--r--test/scaladoc/run/implicits-elimination.scala23
-rw-r--r--test/scaladoc/run/implicits-scopes.check1
-rw-r--r--test/scaladoc/run/implicits-scopes.scala77
-rw-r--r--test/scaladoc/run/implicits-shadowing.check1
-rw-r--r--test/scaladoc/run/implicits-shadowing.scala70
-rw-r--r--test/scaladoc/run/package-object.check2
-rw-r--r--test/scaladoc/run/package-object.scala15
-rw-r--r--test/scaladoc/run/usecase-var-expansion.check4
-rw-r--r--test/scaladoc/run/usecase-var-expansion.scala26
-rw-r--r--test/scaladoc/scalacheck/CommentFactoryTest.scala5
-rwxr-xr-xtools/binary-repo-lib.sh59
-rwxr-xr-xtools/cleanup-commit130
-rwxr-xr-xtools/codegen2
-rwxr-xr-xtools/dump-class6
-rw-r--r--tools/get-scala-commit-date.bat33
-rw-r--r--tools/get-scala-commit-sha.bat30
2316 files changed, 77296 insertions, 17326 deletions
diff --git a/build.xml b/build.xml
index 6f3e4a8d19..76d04b1282 100644
--- a/build.xml
+++ b/build.xml
@@ -8,10 +8,10 @@ SuperSabbus for Scala core, builds the scala library and compiler. It can also p
<!-- ===========================================================================
END-USER TARGETS
============================================================================ -->
-
+
<target name="build" depends="pack.done"
description="Builds the Scala compiler and library. Executables are in 'build/pack/bin'."/>
-
+
<target name="build-opt"
description="Builds the optimised Scala compiler and library. Executables are in 'build/pack/bin'.">
<antcall target="build">
@@ -34,20 +34,20 @@ END-USER TARGETS
<target name="docs" depends="docs.done"
description="Builds documentation for the Scala library. Scaladoc is in 'build/scaladoc/library'."/>
-
+
<target name="docscomp" depends="docs.comp"
description="Builds documentation for the Scala compiler and library. Scaladoc is in 'build/scaladoc'."/>
-
+
<target name="docsclean" depends="docs.clean"
description="Removes generated documentation. Distributions are untouched."/>
-
+
<target name="dist"
description="Makes a new distribution and tests it. Will remove existing binaries and documentation.">
<antcall target="locker.clean"/>
<antcall target="docs.clean"/>
<antcall target="all.done"/>
</target>
-
+
<target name="dist-opt"
description="Makes a new optimised distribution and tests it. Will remove existing binaries and documentation.">
<antcall target="dist">
@@ -67,7 +67,7 @@ END-USER TARGETS
<target name="distclean" depends="dist.clean"
description="Removes all distributions. Binaries and documentation are untouched."/>
-
+
<target name="replacestarr"
description="Replaces the Starr compiler and library by fresh ones built from current sources and tests them.">
<fail message="This target is not available on Windows. Use 'ant replacestarrwin' instead.">
@@ -81,7 +81,7 @@ END-USER TARGETS
<antcall target="locker.clean"/>
<antcall target="test.done"/>
</target>
-
+
<target name="replacestarr-opt"
description="Replaces the Starr compiler and library by fresh, optimised ones built from current sources and tests them.">
<antcall target="replacestarr">
@@ -103,7 +103,7 @@ END-USER TARGETS
<antcall target="locker.clean"/>
<antcall target="test.done"/>
</target>
-
+
<target name="replacelocker"
description="Replaces the Locker compiler and library by fresh ones built from current sources.">
<antcall target="palo.clean"/>
@@ -144,7 +144,7 @@ END-USER TARGETS
description="Requires forkjoin library to be rebuilt. Add this target before any other if class file format is incompatible.">
<property name="forkjoin.outdated" value="yes"/>
</target>
-
+
<!-- ===========================================================================
PROPERTIES
============================================================================ -->
@@ -159,7 +159,7 @@ PROPERTIES
<property name="lib-ant.dir" value="${lib.dir}/ant"/>
<property name="src.dir" value="${basedir}/src"/>
<property name="partest.dir" value="${basedir}/test"/>
-
+
<!-- For developers: any jars placed in this dir will be added to the classpath
of all targets and copied into quick/pack/etc builds. -->
<property name="lib-extra.dir" value="${lib.dir}/extra"/>
@@ -249,7 +249,7 @@ INITIALISATION
<!-- Resolve maven dependencies -->
<target name="init.maven.jars" depends="init.maven.tasks">
<artifact:dependencies pathId="dependency.classpath" filesetId="dependency.fileset">
- <dependency groupId="org.skife.com.typesafe.config" artifactId="typesafe-config" version="0.3.0"/>
+ <dependency groupId="com.typesafe" artifactId="config" version="0.4.0"/>
</artifact:dependencies>
</target>
@@ -274,16 +274,37 @@ INITIALISATION
<property name="version.suffix" value="-${version.bnum}"/>
</target>
- <target name="init.build.suffix.done" depends="init.build.release, init.build.patch.release"/>
+ <target name="init.hasmavensuffix" if="build.release" depends="init.build.patch.release, init.build.release">
+ <condition property="version.hasmavensuffix">
+ <not><equals arg1="${maven.version.suffix}" arg2=""/></not>
+ </condition>
+ </target>
+
+ <target name="init.osgi.suffix" if="version.hasmavensuffix" depends="init.hasmavensuffix">
+ <property name="osgi.version.suffix" value="${maven.version.suffix}"/>
+ </target>
+
+ <target name="init.osgi.suffix.final" if="build.release" unless="version.hasmavensuffix" depends="init.hasmavensuffix">
+ <property name="osgi.version.suffix" value="-VFINAL"/>
+ </target>
+
+
+ <target name="init.osgi.suffix.snapshot" unless="build.release" depends="init.hasmavensuffix">
+ <property name="osgi.version.suffix" value=""/>
+ </target>
+
+ <target name="init.build.suffix.done" depends="init.build.release, init.build.patch.release, init.osgi.suffix, init.osgi.suffix.final, init.osgi.suffix.snapshot"/>
<target name="init.version.git" depends="init.build.suffix.done">
<!-- Find out whether we are running on Windows -->
<condition property="os.win">
<os family="windows"/>
</condition>
-
+
<exec osfamily="unix" executable="tools/get-scala-commit-sha" outputproperty="git.commit.sha" failifexecutionfails="false" />
+ <exec osfamily="windows" executable="tools/get-scala-commit-sha.bat" outputproperty="git.commit.sha" failifexecutionfails="false" />
<exec osfamily="unix" executable="tools/get-scala-commit-date" outputproperty="git.commit.date" failifexecutionfails="false" />
+ <exec osfamily="windows" executable="tools/get-scala-commit-date.bat" outputproperty="git.commit.date" failifexecutionfails="false" />
<!-- some default in case something went wrong getting the revision -->
<property name="git.commit.sha" value="unknown"/>
<property name="git.commit.date" value="unknown"/>
@@ -294,7 +315,7 @@ INITIALISATION
value="${version.major}.${version.minor}.${version.patch}${version.suffix}${maven.version.suffix}"/>
<property
name="osgi.version.number"
- value="${version.major}.${version.minor}.${version.patch}.v${git.commit.date}${version.suffix}-${git.commit.sha}"/>
+ value="${version.major}.${version.minor}.${version.patch}.v${git.commit.date}${version.suffix}${osgi.version.suffix}-${git.commit.sha}"/>
</target>
<target name="init.version.snapshot" unless="build.release" depends="init.version.git">
@@ -312,12 +333,15 @@ INITIALISATION
<target name="init.version.done" depends="init.version.release, init.version.snapshot"/>
<target name="init" depends="init.jars, init.maven.jars, init.version.done">
+ <property name="scalac.args.always" value="-Xmacros" />
<!-- scalac.args.optimise is selectively overridden in certain antcall tasks. -->
<property name="scalac.args.optimise" value=""/>
<!-- scalac.args.quickonly are added to quick.* targets but not others (particularly, locker.)
- This is to facilitate testing new command line options which do not yet exist in starr. -->
+ This is to facilitate testing new command line options which do not yet exist in starr.
+ Note: These are also used by strap since they may affect JVM target or other and we'd like
+ to be able to test binary stability of features. -->
<property name="scalac.args.quickonly" value=""/>
- <property name="scalac.args.all" value="${scalac.args} ${scalac.args.optimise}"/>
+ <property name="scalac.args.all" value="${scalac.args.always} ${scalac.args} ${scalac.args.optimise}"/>
<property name="scalac.args.quick" value="${scalac.args.all} ${scalac.args.quickonly}"/>
<!-- Setting-up Ant contrib tasks -->
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant/ant-contrib.jar"/>
@@ -334,7 +358,7 @@ INITIALISATION
<!-- Local libs (developer use.) -->
<mkdir dir="${lib-extra.dir}"/>
-
+
<path id="lib.extra">
<!-- needs ant 1.7.1 -->
<!-- <fileset dir="${lib-extra.dir}" erroronmissingdir="false"> -->
@@ -361,6 +385,7 @@ INITIALISATION
<echo message=" java args: ${env.ANT_OPTS} ${jvm.opts}" />
<echo message=" javac args: ${javac.args}" />
<echo message=" scalac args: ${scalac.args.all}" />
+ <echo message="scalac quick args: ${scalac.args.quick}" />
<echo message=" git date: ${git.commit.date}" />
<echo message=" git hash: ${git.commit.sha}" />
<echo message=" maven version: ${maven.version.number}"/>
@@ -384,7 +409,7 @@ INITIALISATION
<pathelement location="${lib.dir}/forkjoin.jar"/>
<path refid="lib.extra"/>
</path>
- <taskdef resource="scala/tools/ant/sabbus/antlib.xml" classpathref="starr.classpath"/>
+ <taskdef resource="scala/tools/ant/sabbus/antlib.xml" classpathref="starr.classpath"/>
</target>
<!-- ===========================================================================
@@ -412,7 +437,7 @@ LOCAL REFERENCE BUILD (LOCKER)
classpath="${build-locker.dir}/classes/library"
includes="**/*.java"
target="1.5" source="1.5">
- <compilerarg line="${javac.args}"/>
+ <compilerarg line="${javac.args} -XDignore.symbol.file"/>
</javac>
<!-- NOTE: Potential problem with maximal command line length on Windows
(32768 characters for XP, since executed with Java's "exec"). See
@@ -447,7 +472,7 @@ LOCAL REFERENCE BUILD (LOCKER)
<touch file="${build-locker.dir}/library.complete" verbose="no"/>
<stopwatch name="locker.lib.timer" action="total"/>
</target>
-
+
<target name="locker.pre-comp" depends="locker.lib" unless="locker.available">
<condition property="locker.comp.needed">
<not><available file="${build-locker.dir}/compiler.complete"/></not>
@@ -457,6 +482,20 @@ LOCAL REFERENCE BUILD (LOCKER)
<target name="locker.comp" depends="locker.pre-comp" if="locker.comp.needed">
<stopwatch name="locker.comp.timer"/>
<mkdir dir="${build-locker.dir}/classes/compiler"/>
+ <!-- TODO If we have cross dependencies, move this below scalacfork... -->
+ <javac
+ srcdir="${src.dir}/compiler"
+ destdir="${build-locker.dir}/classes/compiler"
+ includes="**/*.java"
+ target="1.5" source="1.5">
+ <compilerarg line="${javac.args}"/>
+ <classpath>
+ <pathelement location="${build-locker.dir}/classes/library"/>
+ <pathelement location="${build-locker.dir}/classes/compiler"/>
+ <path refid="aux.libs"/>
+ <pathelement location="${jline.jar}"/>
+ </classpath>
+ </javac>
<scalacfork
destdir="${build-locker.dir}/classes/compiler"
compilerpathref="starr.classpath"
@@ -507,11 +546,11 @@ LOCAL REFERENCE BUILD (LOCKER)
<path refid="aux.libs"/>
</path>
</target>
-
+
<target name="locker.clean" depends="palo.clean">
<delete dir="${build-locker.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/>
</target>
-
+
<target name="locker.unlock.pre-lib">
<uptodate property="locker.lib.available" targetfile="${build-locker.dir}/library.complete">
<srcfiles dir="${src.dir}">
@@ -633,14 +672,13 @@ PACKED LOCKER BUILD (PALO)
<!-- ===========================================================================
QUICK BUILD (QUICK)
============================================================================ -->
-
+
<target name="quick.start" depends="locker.done"/>
<target name="quick.pre-lib" depends="quick.start">
<uptodate property="quick.lib.available" targetfile="${build-quick.dir}/library.complete">
<srcfiles dir="${src.dir}">
<include name="library/**"/>
- <include name="dbc/**"/>
<include name="continuations/**"/>
<include name="swing/**"/>
<include name="actors/**"/>
@@ -657,7 +695,7 @@ QUICK BUILD (QUICK)
classpath="${build-quick.dir}/classes/library"
includes="**/*.java"
target="1.5" source="1.5">
- <compilerarg line="${javac.args}"/>
+ <compilerarg line="${javac.args} -XDignore.symbol.file"/>
</javac>
<javac
srcdir="${src.dir}/actors"
@@ -690,15 +728,6 @@ QUICK BUILD (QUICK)
destdir="${build-quick.dir}/classes/library"
compilerpathref="locker.classpath"
params="${scalac.args.quick}"
- srcdir="${src.dir}/dbc"
- jvmargs="${scalacfork.jvmargs}">
- <include name="**/*.scala"/>
- <compilationpath refid="quick.compilation.path"/>
- </scalacfork>
- <scalacfork
- destdir="${build-quick.dir}/classes/library"
- compilerpathref="locker.classpath"
- params="${scalac.args.quick}"
srcdir="${src.dir}/swing"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -721,13 +750,13 @@ QUICK BUILD (QUICK)
<touch file="${build-quick.dir}/library.complete" verbose="no"/>
<stopwatch name="quick.lib.timer" action="total"/>
</target>
-
+
<target name="quick.newlibs" depends="quick.lib" if="libs.outdated">
<antcall target="libs.done" inheritRefs="true"/>
<property name="fjbg.jar" value="${build-libs.dir}/fjbg.jar"/>
<property name="msil.jar" value="${build-libs.dir}/msil.jar"/>
</target>
-
+
<target name="quick.libs" depends="quick.newlibs" unless="libs.outdated">
<property name="fjbg.jar" value="${lib.dir}/fjbg.jar"/>
<property name="msil.jar" value="${lib.dir}/msil.jar"/>
@@ -751,6 +780,20 @@ QUICK BUILD (QUICK)
<target name="quick.comp" depends="quick.pre-comp" unless="quick.comp.available">
<stopwatch name="quick.comp.timer"/>
<mkdir dir="${build-quick.dir}/classes/compiler"/>
+ <!-- TODO If we have cross dependencies, move this below scalacfork... -->
+ <javac
+ srcdir="${src.dir}/compiler"
+ destdir="${build-quick.dir}/classes/compiler"
+ includes="**/*.java"
+ target="1.5" source="1.5">
+ <compilerarg line="${javac.args}"/>
+ <classpath>
+ <pathelement location="${build-quick.dir}/classes/library"/>
+ <pathelement location="${build-quick.dir}/classes/compiler"/>
+ <path refid="aux.libs"/>
+ <pathelement location="${jline.jar}"/>
+ </classpath>
+ </javac>
<scalacfork
destdir="${build-quick.dir}/classes/compiler"
compilerpathref="locker.classpath"
@@ -824,7 +867,7 @@ QUICK BUILD (QUICK)
<scalacfork
destdir="${build-quick.dir}/classes/library"
compilerpathref="quick.classpath"
- params="${scalac.args.quick} -Xplugin-require:continuations"
+ params="${scalac.args.quick} -Xplugin-require:continuations -P:continuations:enable"
srcdir="${src.dir}/continuations/library"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -835,7 +878,7 @@ QUICK BUILD (QUICK)
<touch file="${build-quick.dir}/plugins.complete" verbose="no"/>
<stopwatch name="quick.plugins.timer" action="total"/>
</target>
-
+
<target name="quick.pre-scalacheck" depends="quick.plugins">
<uptodate property="quick.scalacheck.available" targetfile="${build-quick.dir}/scalacheck.complete">
<srcfiles dir="${src.dir}/scalacheck"/>
@@ -848,7 +891,7 @@ QUICK BUILD (QUICK)
<scalacfork
destdir="${build-quick.dir}/classes/scalacheck"
compilerpathref="quick.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/scalacheck"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -860,7 +903,7 @@ QUICK BUILD (QUICK)
<touch file="${build-quick.dir}/scalacheck.complete" verbose="no"/>
<stopwatch name="quick.scalacheck.timer" action="total"/>
</target>
-
+
<target name="quick.pre-scalap" depends="quick.scalacheck">
<uptodate property="quick.scalap.available" targetfile="${build-quick.dir}/scalap.complete">
<srcfiles dir="${src.dir}/scalap"/>
@@ -895,7 +938,7 @@ QUICK BUILD (QUICK)
<srcfiles dir="${src.dir}/partest"/>
</uptodate>
</target>
-
+
<target name="quick.partest" depends="quick.pre-partest" unless="quick.partest.available">
<stopwatch name="quick.partest.timer"/>
<mkdir dir="${build-quick.dir}/classes/partest"/>
@@ -990,7 +1033,7 @@ QUICK BUILD (QUICK)
<chmod perm="ugo+rx" file="${build-quick.dir}/bin/scalap"/>
<touch file="${build-quick.dir}/bin.complete" verbose="no"/>
</target>
-
+
<target name="quick.done" depends="quick.bin">
<path id="quick.classpath">
<pathelement location="${build-quick.dir}/classes/library"/>
@@ -1006,9 +1049,9 @@ QUICK BUILD (QUICK)
<!-- ===========================================================================
PACKED QUICK BUILD (PACK)
============================================================================ -->
-
+
<target name="pack.start" depends="quick.done"/>
-
+
<target name="pack.pre-lib" depends="pack.start">
<uptodate
property="pack.lib.available"
@@ -1025,17 +1068,11 @@ PACKED QUICK BUILD (PACK)
</copy>
<jar destfile="${build-pack.dir}/lib/scala-library.jar">
<fileset dir="${build-quick.dir}/classes/library">
- <exclude name="scala/dbc/**"/>
<exclude name="scala/swing/**"/>
<exclude name="scala/actors/**"/>
</fileset>
<zipfileset dirmode="755" filemode="644" src="${forkjoin.jar}"/>
</jar>
- <jar destfile="${build-pack.dir}/lib/scala-dbc.jar">
- <fileset dir="${build-quick.dir}/classes/library">
- <include name="scala/dbc/**"/>
- </fileset>
- </jar>
<jar destfile="${build-pack.dir}/lib/scala-swing.jar">
<fileset dir="${build-quick.dir}/classes/library">
<include name="scala/swing/**"/>
@@ -1047,7 +1084,7 @@ PACKED QUICK BUILD (PACK)
</fileset>
</jar>
</target>
-
+
<target name="pack.pre-comp" depends="pack.lib">
<uptodate
property="pack.comp.available"
@@ -1075,7 +1112,7 @@ PACKED QUICK BUILD (PACK)
</fileset>
</copy>
</target>
-
+
<target name="pack.pre-plugins" depends="pack.comp">
<uptodate
property="pack.plugins.available"
@@ -1089,13 +1126,13 @@ PACKED QUICK BUILD (PACK)
<fileset dir="${build-quick.dir}/classes/continuations-plugin"/>
</jar>
</target>
-
+
<target name="pack.scalacheck" depends="pack.plugins">
<jar destfile="${build-pack.dir}/lib/scalacheck.jar">
<fileset dir="${build-quick.dir}/classes/scalacheck"/>
</jar>
</target>
-
+
<target name="pack.pre-partest" depends="pack.scalacheck">
<uptodate
property="pack.partest.available"
@@ -1109,7 +1146,7 @@ PACKED QUICK BUILD (PACK)
<fileset dir="${build-quick.dir}/classes/partest"/>
</jar>
</target>
-
+
<target name="pack.pre-scalap" depends="pack.partest">
<uptodate
property="pack.scalap.available"
@@ -1121,10 +1158,10 @@ PACKED QUICK BUILD (PACK)
<mkdir dir="${build-pack.dir}/lib"/>
<jar destfile="${build-pack.dir}/lib/scalap.jar">
<fileset dir="${build-quick.dir}/classes/scalap"/>
- <fileset file="${src.dir}/scalap/decoder.properties"/>
+ <fileset file="${src.dir}/scalap/decoder.properties"/>
</jar>
</target>
-
+
<target name="pack.pre-bin" depends="pack.scalap">
<uptodate
property="pack.bin.available"
@@ -1168,7 +1205,7 @@ PACKED QUICK BUILD (PACK)
<chmod perm="ugo+rx" file="${build-pack.dir}/bin/scalap"/>
<touch file="${build-pack.dir}/bin.complete" verbose="no"/>
</target>
-
+
<target name="pack.done" depends="pack.bin">
<path id="pack.classpath">
<pathelement location="${build-pack.dir}/lib/scala-library.jar"/>
@@ -1191,14 +1228,13 @@ PACKED QUICK BUILD (PACK)
<!-- ===========================================================================
BOOTSTRAPPING BUILD (STRAP)
============================================================================ -->
-
+
<target name="strap.start" depends="pack.done"/>
-
+
<target name="strap.pre-lib" depends="strap.start">
<uptodate property="strap.lib.available" targetfile="${build-strap.dir}/library.complete">
<srcfiles dir="${src.dir}">
<include name="library/**"/>
- <include name="dbc/**"/>
<include name="swing/**"/>
<include name="actors/**"/>
</srcfiles>
@@ -1214,7 +1250,7 @@ BOOTSTRAPPING BUILD (STRAP)
classpath="${build-strap.dir}/classes/library"
includes="**/*.java"
target="1.5" source="1.5">
- <compilerarg line="${javac.args}"/>
+ <compilerarg line="${javac.args} -XDignore.symbol.file"/>
</javac>
<javac
srcdir="${src.dir}/actors"
@@ -1228,7 +1264,7 @@ BOOTSTRAPPING BUILD (STRAP)
destdir="${build-strap.dir}/classes/library"
compilerpathref="pack.classpath"
srcpath="${src.dir}/library"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/library"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1237,7 +1273,7 @@ BOOTSTRAPPING BUILD (STRAP)
<scalacfork
destdir="${build-strap.dir}/classes/library"
compilerpathref="pack.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/actors"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1246,16 +1282,7 @@ BOOTSTRAPPING BUILD (STRAP)
<scalacfork
destdir="${build-strap.dir}/classes/library"
compilerpathref="pack.classpath"
- params="${scalac.args.all}"
- srcdir="${src.dir}/dbc"
- jvmargs="${scalacfork.jvmargs}">
- <include name="**/*.scala"/>
- <compilationpath refid="strap.compilation.path"/>
- </scalacfork>
- <scalacfork
- destdir="${build-strap.dir}/classes/library"
- compilerpathref="pack.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/swing"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1278,7 +1305,7 @@ BOOTSTRAPPING BUILD (STRAP)
<touch file="${build-strap.dir}/library.complete" verbose="no"/>
<stopwatch name="strap.lib.timer" action="total"/>
</target>
-
+
<target name="strap.pre-comp" depends="strap.lib">
<uptodate property="strap.comp.available" targetfile="${build-strap.dir}/compiler.complete">
<srcfiles dir="${src.dir}/compiler"/>
@@ -1288,10 +1315,24 @@ BOOTSTRAPPING BUILD (STRAP)
<target name="strap.comp" depends="strap.pre-comp" unless="strap.comp.available">
<stopwatch name="strap.comp.timer"/>
<mkdir dir="${build-strap.dir}/classes/compiler"/>
+ <!-- TODO If we have cross dependencies, move this below scalacfork... -->
+ <javac
+ srcdir="${src.dir}/compiler"
+ destdir="${build-strap.dir}/classes/compiler"
+ includes="**/*.java"
+ target="1.5" source="1.5">
+ <compilerarg line="${javac.args}"/>
+ <classpath>
+ <pathelement location="${build-strap.dir}/classes/library"/>
+ <pathelement location="${build-strap.dir}/classes/compiler"/>
+ <path refid="aux.libs"/>
+ <pathelement location="${jline.jar}"/>
+ </classpath>
+ </javac>
<scalacfork
destdir="${build-strap.dir}/classes/compiler"
compilerpathref="pack.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/compiler"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1338,7 +1379,7 @@ BOOTSTRAPPING BUILD (STRAP)
<scalacfork
destdir="${build-strap.dir}/classes/continuations-plugin"
compilerpathref="pack.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/continuations/plugin"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1361,7 +1402,7 @@ BOOTSTRAPPING BUILD (STRAP)
<scalacfork
destdir="${build-strap.dir}/classes/library"
compilerpathref="pack.classpath"
- params="${scalac.args.all} -Xplugin-require:continuations"
+ params="${scalac.args.quick} -Xplugin-require:continuations -P:continuations:enable"
srcdir="${src.dir}/continuations/library"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1372,13 +1413,13 @@ BOOTSTRAPPING BUILD (STRAP)
<touch file="${build-strap.dir}/plugins.complete" verbose="no"/>
<stopwatch name="strap.plugins.timer" action="total"/>
</target>
-
+
<target name="strap.scalacheck" depends="strap.plugins">
<mkdir dir="${build-strap.dir}/classes/scalacheck"/>
<scalacfork
destdir="${build-strap.dir}/classes/scalacheck"
compilerpathref="pack.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/scalacheck"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1400,7 +1441,7 @@ BOOTSTRAPPING BUILD (STRAP)
<scalacfork
destdir="${build-strap.dir}/classes/scalap"
compilerpathref="pack.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/scalap"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1416,13 +1457,13 @@ BOOTSTRAPPING BUILD (STRAP)
<touch file="${build-strap.dir}/scalap.complete" verbose="no"/>
<stopwatch name="strap.scalap.timer" action="total"/>
</target>
-
+
<target name="strap.pre-partest" depends="strap.scalap">
<uptodate property="strap.partest.available" targetfile="${build-strap.dir}/partest.complete">
<srcfiles dir="${src.dir}/partest"/>
</uptodate>
</target>
-
+
<target name="strap.partest" depends="strap.pre-partest" unless="strap.partest.available">
<stopwatch name="strap.partest.timer"/>
<mkdir dir="${build-strap.dir}/classes/partest"/>
@@ -1442,7 +1483,7 @@ BOOTSTRAPPING BUILD (STRAP)
<scalacfork
destdir="${build-strap.dir}/classes/partest"
compilerpathref="pack.classpath"
- params="${scalac.args.all}"
+ params="${scalac.args.quick}"
srcdir="${src.dir}/partest"
jvmargs="${scalacfork.jvmargs}">
<include name="**/*.scala"/>
@@ -1474,9 +1515,9 @@ BOOTSTRAPPING BUILD (STRAP)
<!-- ===========================================================================
LIBRARIES (MSIL, FJBG maybe later)
============================================================================ -->
-
+
<target name="libs.start"/>
-
+
<target name="libs.pre-forkjoin" depends="libs.start">
<property name="java6.home" value="/home/linuxsoft/apps/java-1.6"/>
<fail message="Compiling forkjoin.jar requires java 1.6. Please set the property `java6.home` in build.properties or using `-Djava6.home=/path/to/java6`">
@@ -1492,7 +1533,7 @@ LIBRARIES (MSIL, FJBG maybe later)
</srcfiles>
</uptodate>
</target>
-
+
<target name="libs.forkjoin" depends="libs.pre-forkjoin" unless="libs.forkjoin.available">
<mkdir dir="${build-libs.dir}/classes/forkjoin"/>
<javac
@@ -1509,16 +1550,16 @@ LIBRARIES (MSIL, FJBG maybe later)
</javac>
<touch file="${build-libs.dir}/forkjoin.complete" verbose="no"/>
</target>
-
+
<target name="libs.pre-forkjoinpack" depends="libs.forkjoin">
</target>
-
+
<target name="libs.forkjoinpack" depends="libs.pre-forkjoinpack" unless="libs.forkjoinpack.available">
<jar destfile="${build-libs.dir}/forkjoin.jar">
<fileset dir="${build-libs.dir}/classes/forkjoin"/>
</jar>
</target>
-
+
<target name="libs.pre-msil" depends="libs.start">
<uptodate property="libs.msil.available" targetfile="${build-libs.dir}/msil.complete">
<srcfiles dir="${src.dir}/msil">
@@ -1527,7 +1568,7 @@ LIBRARIES (MSIL, FJBG maybe later)
</srcfiles>
</uptodate>
</target>
-
+
<target name="libs.msil" depends="libs.pre-msil" unless="libs.msil.available">
<mkdir dir="${build-libs.dir}/classes/msil"/>
<javac
@@ -1554,16 +1595,16 @@ LIBRARIES (MSIL, FJBG maybe later)
</scalacfork>
<touch file="${build-libs.dir}/msil.complete" verbose="no"/>
</target>
-
+
<target name="libs.pre-msilpack" depends="libs.msil">
</target>
-
+
<target name="libs.msilpack" depends="libs.pre-msilpack" unless="libs.msilpack.available">
<jar destfile="${build-libs.dir}/msil.jar">
<fileset dir="${build-libs.dir}/classes/msil"/>
</jar>
</target>
-
+
<target name="libs.pre-fjbg" depends="libs.start">
<uptodate property="libs.fjbg.available" targetfile="${build-libs.dir}/fjbg.complete">
<srcfiles dir="${src.dir}/fjbg">
@@ -1572,7 +1613,7 @@ LIBRARIES (MSIL, FJBG maybe later)
</srcfiles>
</uptodate>
</target>
-
+
<target name="libs.fjbg" depends="libs.pre-fjbg" unless="libs.fjbg.available">
<mkdir dir="${build-libs.dir}/classes/fjbg"/>
<javac
@@ -1586,10 +1627,10 @@ LIBRARIES (MSIL, FJBG maybe later)
</javac>
<touch file="${build-libs.dir}/fjbg.complete" verbose="no"/>
</target>
-
+
<target name="libs.pre-fjbgpack" depends="libs.fjbg">
</target>
-
+
<target name="libs.fjbgpack" depends="libs.pre-fjbgpack" unless="libs.fjbgpack.available">
<jar destfile="${build-libs.dir}/fjbg.jar">
<fileset dir="${build-libs.dir}/classes/fjbg"/>
@@ -1599,7 +1640,7 @@ LIBRARIES (MSIL, FJBG maybe later)
<target name="libs.done" depends="libs.msilpack, libs.fjbgpack"/>
<target name="forkjoin.done" depends="libs.forkjoinpack"/>
-
+
<target name="libs.clean" depends="pack.clean">
<delete dir="${build-libs.dir}" includeemptydirs="yes" quiet="yes" failonerror="no"/>
</target>
@@ -1607,7 +1648,7 @@ LIBRARIES (MSIL, FJBG maybe later)
<!-- ===========================================================================
DOCUMENTATION
============================================================================ -->
-
+
<target name="docs.start" depends="pack.done">
<macrodef name="doc-uptodate-check">
<attribute name="name" />
@@ -1637,12 +1678,11 @@ DOCUMENTATION
<property name="scaladoc.url" value="https://github.com/scala/scala/tree/${scaladoc.git.commit}/src"/>
<echo message="Scaladoc will point to ${scaladoc.url} for source files."/>
</target>
-
+
<target name="docs.pre-lib" depends="docs.start">
<doc-uptodate-check name="library" srcdir="${src.dir}">
<source-includes>
<include name="library/**"/>
- <include name="dbc/**"/>
<include name="swing/**"/>
<include name="actors/**"/>
</source-includes>
@@ -1656,13 +1696,14 @@ DOCUMENTATION
destdir="${build-docs.dir}/library"
doctitle="Scala Standard Library API (Scaladoc)"
docversion="${version.number}"
- docfooter="epfl"
+ docfooter="epfl"
docsourceurl="${scaladoc.url}€{FILE_PATH}.scala#L1"
docUncompilable="${src.dir}/library-aux"
sourcepath="${src.dir}"
classpathref="pack.classpath"
addparams="${scalac.args.all}"
- docRootContent="${src.dir}/library/rootdoc.txt">
+ docRootContent="${src.dir}/library/rootdoc.txt"
+ implicits="on" diagrams="on">
<src>
<files includes="${src.dir}/actors"/>
<files includes="${src.dir}/library/scala"/>
@@ -1743,7 +1784,8 @@ DOCUMENTATION
classpathref="pack.classpath"
srcdir="${src.dir}/compiler"
docRootContent="${src.dir}/compiler/rootdoc.txt"
- addparams="${scalac.args.all}">
+ addparams="${scalac.args.all}"
+ implicits="on" diagrams="on">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/compiler.complete" verbose="no"/>
@@ -1764,7 +1806,8 @@ DOCUMENTATION
sourcepath="${src.dir}"
classpathref="pack.classpath"
srcdir="${src.dir}/jline/src/main/java"
- addparams="${scalac.args.all}">
+ addparams="${scalac.args.all}"
+ implicits="on" diagrams="on">
<include name="**/*.scala"/>
<include name="**/*.java"/>
</scaladoc>
@@ -1787,7 +1830,8 @@ DOCUMENTATION
sourcepath="${src.dir}"
classpathref="pack.classpath"
srcdir="${src.dir}/scalap"
- addparams="${scalac.args.all}">
+ addparams="${scalac.args.all}"
+ implicits="on" diagrams="on">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/scalap.complete" verbose="no"/>
@@ -1808,7 +1852,8 @@ DOCUMENTATION
sourcepath="${src.dir}"
classpathref="pack.classpath"
srcdir="${src.dir}/partest"
- addparams="${scalac.args.all}">
+ addparams="${scalac.args.all}"
+ implicits="on" diagrams="on">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/partest.complete" verbose="no"/>
@@ -1829,7 +1874,8 @@ DOCUMENTATION
sourcepath="${src.dir}"
classpathref="pack.classpath"
srcdir="${src.dir}/continuations/plugin"
- addparams="${scalac.args.all}">
+ addparams="${scalac.args.all}"
+ implicits="on" diagrams="on">
<include name="**/*.scala"/>
</scaladoc>
<touch file="${build-docs.dir}/continuations-plugin.complete" verbose="no"/>
@@ -1861,7 +1907,7 @@ BOOTRAPING TEST AND TEST SUITE
<target name="test.classload" depends="pack.done">
<classloadVerify classpath="${build-pack.dir}/lib/scala-library.jar" />
</target>
-
+
<!-- this target will run only those tests found in test/debug -->
<target name="test.debug">
<antcall target="test.suite">
@@ -1935,7 +1981,7 @@ BOOTRAPING TEST AND TEST SUITE
<partest showlog="yes" erroronfailed="yes" javacmd="${java.home}/bin/java"
timeout="2400000"
srcdir="${partest.srcdir}"
- scalacopts="${scalac.args.optimise} -Xplugin-require:continuations">
+ scalacopts="${scalac.args.optimise} -Xplugin-require:continuations -P:continuations:enable">
<compilerarg value="-Xpluginsdir"/>
<compilerarg file="${build-quick.dir}/misc/scala-devel/plugins"/>
<compilationpath>
@@ -2024,9 +2070,6 @@ DISTRIBUTION
<fileset dir="${src.dir}/library"/>
<fileset dir="${src.dir}/continuations/library"/>
</jar>
- <jar destfile="${dist.dir}/src/scala-dbc-src.jar">
- <fileset dir="${src.dir}/dbc"/>
- </jar>
<jar destfile="${dist.dir}/src/scala-swing-src.jar">
<fileset dir="${src.dir}/swing"/>
</jar>
@@ -2114,7 +2157,6 @@ STABLE REFERENCE (STARR)
<fileset dir="${basedir}/src/library"/>
<fileset dir="${basedir}/src/swing"/>
<fileset dir="${basedir}/src/actors"/>
- <fileset dir="${basedir}/src/dbc"/>
</jar>
</target>
@@ -2152,7 +2194,7 @@ STABLE REFERENCE (STARR)
<!-- ===========================================================================
FORWARDED TARGETS FOR PACKAGING
============================================================================ -->
-
+
<target name="distpack" depends="dist.done, docs.all">
<ant antfile="${src.dir}/build/pack.xml" target="pack-all.done" inheritall="yes" inheritrefs="yes"/>
</target>
@@ -2167,7 +2209,7 @@ FORWARDED TARGETS FOR PACKAGING
<param name="scalac.args.optimise" value="-optimise"/>
</antcall>
</target>
-
+
<target name="distpack-maven-opt"
description="Builds an optimised maven distribution.">
<antcall target="distpack-maven">
@@ -2217,9 +2259,6 @@ POSITIONS
<param name="test.srcs" value="${src.dir}/actors"/>
</antcall>
<antcall target="test.positions.sub" inheritRefs="true">
- <param name="test.srcs" value="${src.dir}/dbc"/>
- </antcall>
- <antcall target="test.positions.sub" inheritRefs="true">
<param name="test.srcs" value="${src.dir}/swing"/>
</antcall>
<antcall target="test.positions.sub" inheritRefs="true">
diff --git a/docs/development/scala.dbc/SQLTypes.dot b/docs/development/scala.dbc/SQLTypes.dot
deleted file mode 100644
index 77c27cf729..0000000000
--- a/docs/development/scala.dbc/SQLTypes.dot
+++ /dev/null
@@ -1,48 +0,0 @@
-digraph SQLTypes {
- node [shape = record]
- DataType [label = "{DataType|nullable: Boolean}"]
- StringType [label = "{StringType|maxLength: Int}"]
- CharacterStringType [label = "{CharacterStringType|encoding: String}"]
- CharacterType [label = "{CharacterType|length: Int}"]
- CharacterVaryingType [label = "{CharacterVaryingType|length: Int}"]
- CharacterLargeObjectType [label = "CharacterLargeObjectType"]
- BinaryStringType [label = "BinaryStringType"]
- BinaryType [label = "{BinaryType|length: Int}"]
- BinaryVaryingType [label = "{BinaryVaryingType|length: Int}"]
- BinaryLargeObjectType [label = "BinaryLargeObjectType"]
- BooleanType [label = "BooleanType"]
- NumericType [label = "{NumericType|precisionRadix: Int\nprecision: Int}"]
- ExactNumericType [label = "{ExactNumericType|scale: Int}"]
- ApproximateNumericType [label = "ApproximateNumericType"]
- DateTimeType [label = "DateTimeType"]
- TimeType [label = "{TimeType|precisionRadix: Int\nsecondScale: Int}"]
- TimeWithoutTimezoneType [label = "TimeWithoutTimezoneType"]
- TimeWithTimezoneType [label = "TimeWithTimezoneType"]
- TimestampType [label = "{TimestampType|precisionRadix: Int\nsecondScale: Int}"]
- TimestampWithoutTimezoneType [label = "TimestampWithoutTimezoneType"]
- TimestampWithTimezoneType [label = "TimestampWithTimezoneType"]
- DateType [label = "DateType"]
- IntervalType [label = "{IntervalType|precisionRadix: Int\nsecondScale: Int}"]
- StringType -> DataType
- BooleanType -> DataType
- NumericType -> DataType
- DateTimeType -> DataType
- IntervalType -> DataType
- CharacterStringType -> StringType
- BinaryStringType -> StringType
- ExactNumericType -> NumericType
- ApproximateNumericType -> NumericType
- TimeType -> DateTimeType
- TimestampType -> DateTimeType
- DateType -> DateTimeType
- CharacterType -> CharacterStringType
- CharacterVaryingType -> CharacterStringType
- CharacterLargeObjectType -> CharacterStringType
- BinaryType -> BinaryStringType
- BinaryVaryingType -> BinaryStringType
- BinaryLargeObjectType -> BinaryStringType
- TimeWithoutTimezoneType -> TimeType
- TimeWithTimezoneType -> TimeType
- TimestampWithoutTimezoneType -> TimestampType
- TimestampWithTimezoneType -> TimestampType
-}
diff --git a/gitignore.SAMPLE b/gitignore.SAMPLE
index 3c15a5de9e..483ad4caca 100644
--- a/gitignore.SAMPLE
+++ b/gitignore.SAMPLE
@@ -27,4 +27,9 @@
/src/intellij/*.iml
/src/intellij/*.ipr
/src/intellij/*.iws
+/.cache
+/.idea
+/.settings
+# bak files produced by ./cleanup-commit
+*.bak
diff --git a/lib/forkjoin.jar.desired.sha1 b/lib/forkjoin.jar.desired.sha1
index d37b84d8c7..d31539daf4 100644
--- a/lib/forkjoin.jar.desired.sha1
+++ b/lib/forkjoin.jar.desired.sha1
@@ -1 +1 @@
-996fc132b05046112b9d4dc62e2d2c9057d836bc ?forkjoin.jar
+b5baf94dff8d3ca991d44a59add7bcbf6640379b ?forkjoin.jar
diff --git a/lib/scala-compiler.jar.desired.sha1 b/lib/scala-compiler.jar.desired.sha1
index 0bbbea1e7b..5a541f8cf3 100644
--- a/lib/scala-compiler.jar.desired.sha1
+++ b/lib/scala-compiler.jar.desired.sha1
@@ -1 +1 @@
-f9fcb59f3dbe1b060f8c57d4463dde5e0796951f ?scala-compiler.jar
+c020eccb8cf37963725985f36b44d070915cf4d2 ?scala-compiler.jar
diff --git a/lib/scala-library-src.jar.desired.sha1 b/lib/scala-library-src.jar.desired.sha1
index 51704e29c9..0ea32125f5 100644
--- a/lib/scala-library-src.jar.desired.sha1
+++ b/lib/scala-library-src.jar.desired.sha1
@@ -1 +1 @@
-d407ee67fa7e0d79e8e5786fb32ea7c9bdf5b088 ?scala-library-src.jar
+b85bc62675c2262a75ddcdd4df2dfc0ea0ddc2dd ?scala-library-src.jar
diff --git a/lib/scala-library.jar.desired.sha1 b/lib/scala-library.jar.desired.sha1
index 703eb006da..d059e861f0 100644
--- a/lib/scala-library.jar.desired.sha1
+++ b/lib/scala-library.jar.desired.sha1
@@ -1 +1 @@
-1d53671b52f2052c0690fcef9c9989150d8a4704 ?scala-library.jar
+31c7188cef85c28b84b9ce35bc6780996e5dd139 ?scala-library.jar
diff --git a/project/Build.scala b/project/Build.scala
index 7d80994c4a..c753b4901f 100644
--- a/project/Build.scala
+++ b/project/Build.scala
@@ -77,9 +77,9 @@ object ScalaBuild extends Build with Layers {
)
// Collections of projects to run 'compile' on.
- lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, dbc, forkjoin, fjbg)
+ lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, forkjoin, fjbg)
// Collection of projects to 'package' and 'publish' together.
- lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, dbc, continuationsPlugin, jline, scalap)
+ lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, continuationsPlugin, jline, scalap)
lazy val partestRunProjects = Seq(testsuite, continuationsTestsuite)
private def epflPomExtra = (
@@ -249,7 +249,6 @@ object ScalaBuild extends Build with Layers {
// TODO - Actors + swing separate jars...
lazy val dependentProjectSettings = settingOverrides ++ Seq(quickScalaInstance, quickScalaLibraryDependency, addCheaterDependency("scala-library"))
lazy val actors = Project("actors", file(".")) settings(dependentProjectSettings:_*) dependsOn(forkjoin % "provided")
- lazy val dbc = Project("dbc", file(".")) settings(dependentProjectSettings:_*)
// TODO - Remove actors dependency from pom...
lazy val swing = Project("swing", file(".")) settings(dependentProjectSettings:_*) dependsOn(actors % "provided")
// This project will generate man pages (in man1 and html) for scala.
@@ -489,7 +488,7 @@ object ScalaBuild extends Build with Layers {
genBin <<= genBinTask(genBinRunner, binDir, fullClasspath in Runtime, false),
binDir in genBinQuick <<= baseDirectory apply (_ / "target" / "bin"),
// Configure the classpath this way to avoid having .jar files and previous layers on the classpath.
- fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,dbc,fjbg,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq),
+ fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,fjbg,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq),
fullClasspath in Runtime in genBinQuick <++= (fullClasspath in Compile in jline),
genBinQuick <<= genBinTask(genBinRunner, binDir in genBinQuick, fullClasspath in Runtime in genBinQuick, true),
runManmakerMan <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitManPage", "man1", ".1"),
@@ -518,10 +517,9 @@ object ScalaBuild extends Build with Layers {
},
// Add in some more dependencies
makeDistMappings <<= (makeDistMappings,
- packageBin in swing in Compile,
- packageBin in dbc in Compile) map {
+ packageBin in swing in Compile) map {
(dist, s, d) =>
- dist ++ Seq(s -> "lib/scala-swing.jar", d -> "lib/scala-dbc.jar")
+ dist ++ Seq(s -> "lib/scala-swing.jar")
},
makeDist <<= (makeDistMappings, baseDirectory, streams) map { (maps, dir, s) =>
s.log.debug("Map = " + maps.mkString("\n"))
diff --git a/src/build/genprod.scala b/src/build/genprod.scala
index 6016f6fb92..8c91128de0 100644
--- a/src/build/genprod.scala
+++ b/src/build/genprod.scala
@@ -130,7 +130,7 @@ object FunctionOne extends Function(1) {
* @param g a function A => T1
* @return a new function `f` such that `f(x) == apply(g(x))`
*/
- def compose[A](g: A => T1): A => R = { x => apply(g(x)) }
+ @annotation.unspecialized def compose[A](g: A => T1): A => R = { x => apply(g(x)) }
/** Composes two instances of Function1 in a new Function1, with this function applied first.
*
@@ -138,7 +138,7 @@ object FunctionOne extends Function(1) {
* @param g a function R => A
* @return a new function `f` such that `f(x) == g(apply(x))`
*/
- def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }
+ @annotation.unspecialized def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }
"""
}
@@ -169,19 +169,20 @@ object Function {
class Function(val i: Int) extends Group("Function") with Arity {
def descriptiveComment = ""
- def functionNTemplate = """
+ def functionNTemplate =
+"""
* In the following example, the definition of %s is a
* shorthand for the anonymous class definition %s:
*
* {{{
- * object Main extends App { %s }
+ * object Main extends App {%s}
* }}}
*
* Note that `Function1` does not define a total function, as might
* be suggested by the existence of [[scala.PartialFunction]]. The only
* distinction between `Function1` and `PartialFunction` is that the
* latter can specify inputs which it will not handle.
- """
+"""
def toStr() = "\"" + ("<function%d>" format i) + "\""
def apply() = {
@@ -195,7 +196,7 @@ class Function(val i: Int) extends Group("Function") with Arity {
* @return the result of function application.
*/
def apply({funArgs}): R
- {moreMethods}
+{moreMethods}
override def toString() = {toStr}
}}
</file>
@@ -218,15 +219,15 @@ class Function(val i: Int) extends Group("Function") with Arity {
// f(x1,x2,x3,x4,x5,x6) == (f.curried)(x1)(x2)(x3)(x4)(x5)(x6)
def curryComment = {
-"""/** Creates a curried version of this function.
+""" /** Creates a curried version of this function.
*
* @return a function `f` such that `f%s == apply%s`
*/""".format(xdefs map ("(" + _ + ")") mkString, commaXs)
}
def tupleMethod = {
- def comment = """
- /** Creates a tupled version of this function: instead of %d arguments,
+ def comment =
+""" /** Creates a tupled version of this function: instead of %d arguments,
* it accepts a single [[scala.Tuple%d]] argument.
*
* @return a function `f` such that `f(%s) == f(Tuple%d%s) == apply%s`
@@ -234,14 +235,14 @@ class Function(val i: Int) extends Group("Function") with Arity {
""".format(i, i, commaXs, i, commaXs, commaXs)
def body = "case Tuple%d%s => apply%s".format(i, commaXs, commaXs)
- comment + " def tupled: Tuple%d%s => R = {\n %s\n }".format(i, invariantArgs, body)
+ comment + "\n @annotation.unspecialized def tupled: Tuple%d%s => R = {\n %s\n }".format(i, invariantArgs, body)
}
def curryMethod = {
val body = if (i < 5) shortCurry else longCurry
curryComment +
- " def curried: %s => R = {\n %s\n }\n".format(
+ "\n @annotation.unspecialized def curried: %s => R = {\n %s\n }\n".format(
targs mkString " => ", body
)
}
@@ -255,10 +256,7 @@ class Function(val i: Int) extends Group("Function") with Arity {
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz */
object Tuple {
- val zipImports = """
-import scala.collection.{ TraversableLike => TLike, IterableLike => ILike }
-import scala.collection.generic.{ CanBuildFrom => CBF }
-"""
+ val zipImports = ""
def make(i: Int) = apply(i)()
def apply(i: Int) = i match {
@@ -284,230 +282,11 @@ object TupleTwo extends Tuple(2)
* second element is the first element of this Tuple.
*/
def swap: Tuple2[T2,T1] = Tuple2(_2, _1)
-
- @deprecated("Use `zipped` instead.", "2.9.0")
- def zip[Repr1, El1, El2, To](implicit w1: T1 => TLike[El1, Repr1],
- w2: T2 => Iterable[El2],
- cbf1: CBF[Repr1, (El1, El2), To]): To = {
- zipped map ((x, y) => ((x, y)))
- }
-
- /** Wraps a tuple in a `Zipped`, which supports 2-ary generalisations of `map`, `flatMap`, `filter`, etc.
- * Note that there must be an implicit value to convert this tuple's types into a [[scala.collection.TraversableLike]]
- * or [[scala.collection.IterableLike]].
- * {{{
- * scala> val tuple = (List(1,2,3),List('a','b','c'))
- * tuple: (List[Int], List[Char]) = (List(1, 2, 3),List(a, b, c))
- *
- * scala> tuple.zipped map { (x,y) => x + ":" + y }
- * res6: List[java.lang.String] = List(1:a, 2:b, 3:c)
- * }}}
- *
- * @see Zipped
- * Note: will not terminate for infinite-sized collections.
- */
- def zipped[Repr1, El1, Repr2, El2](implicit w1: T1 => TLike[El1, Repr1], w2: T2 => ILike[El2, Repr2]): Zipped[Repr1, El1, Repr2, El2]
- = new Zipped[Repr1, El1, Repr2, El2](_1, _2)
-
- class Zipped[+Repr1, +El1, +Repr2, +El2](coll1: TLike[El1, Repr1], coll2: ILike[El2, Repr2]) { // coll2: ILike for filter
- def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- b.sizeHint(coll1)
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext)
- b += f(el1, elems2.next)
- else
- return b.result
- }
-
- b.result
- }
-
- def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext)
- b ++= f(el1, elems2.next)
- else
- return b.result
- }
-
- b.result
- }
-
- def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = {
- val b1 = cbf1(coll1.repr)
- val b2 = cbf2(coll2.repr)
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext) {
- val el2 = elems2.next
- if (f(el1, el2)) {
- b1 += el1
- b2 += el2
- }
- }
- else return (b1.result, b2.result)
- }
-
- (b1.result, b2.result)
- }
-
- def exists(f: (El1, El2) => Boolean): Boolean = {
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext) {
- if (f(el1, elems2.next))
- return true
- }
- else return false
- }
- false
- }
-
- def forall(f: (El1, El2) => Boolean): Boolean =
- !exists((x, y) => !f(x, y))
-
- def foreach[U](f: (El1, El2) => U): Unit = {
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext)
- f(el1, elems2.next)
- else
- return
- }
- }
- }
"""
}
object TupleThree extends Tuple(3) {
override def imports = Tuple.zipImports
- override def moreMethods = """
-
- @deprecated("Use `zipped` instead.", "2.9.0")
- def zip[Repr1, El1, El2, El3, To](implicit w1: T1 => TLike[El1, Repr1],
- w2: T2 => Iterable[El2],
- w3: T3 => Iterable[El3],
- cbf1: CBF[Repr1, (El1, El2, El3), To]): To = {
- zipped map ((x, y, z) => ((x, y, z)))
- }
-
- /** Wraps a tuple in a `Zipped`, which supports 3-ary generalisations of `map`, `flatMap`, `filter`, etc.
- * Note that there must be an implicit value to convert this tuple's types into a [[scala.collection.TraversableLike]]
- * or [[scala.collection.IterableLike]].
- * {{{
- * scala> val tuple = (List(1,2,3),List('a','b','c'),List("x","y","z"))
- * tuple: (List[Int], List[Char], List[java.lang.String]) = (List(1, 2, 3),List(a, b, c),List(x, y, z))
- *
- * scala> tuple.zipped map { (x,y,z) => x + ":" + y + ":" + z}
- * res8: List[java.lang.String] = List(1:a:x, 2:b:y, 3:c:z)
- * }}}
- *
- * @see Zipped
- * Note: will not terminate for infinite-sized collections.
- */
- def zipped[Repr1, El1, Repr2, El2, Repr3, El3](implicit w1: T1 => TLike[El1, Repr1],
- w2: T2 => ILike[El2, Repr2],
- w3: T3 => ILike[El3, Repr3]): Zipped[Repr1, El1, Repr2, El2, Repr3, El3]
- = new Zipped[Repr1, El1, Repr2, El2, Repr3, El3](_1, _2, _3)
-
- class Zipped[+Repr1, +El1, +Repr2, +El2, +Repr3, +El3](coll1: TLike[El1, Repr1],
- coll2: ILike[El2, Repr2],
- coll3: ILike[El3, Repr3]) {
- def map[B, To](f: (El1, El2, El3) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext)
- b += f(el1, elems2.next, elems3.next)
- else
- return b.result
- }
- b.result
- }
-
- def flatMap[B, To](f: (El1, El2, El3) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext)
- b ++= f(el1, elems2.next, elems3.next)
- else
- return b.result
- }
- b.result
- }
-
- def filter[To1, To2, To3](f: (El1, El2, El3) => Boolean)(
- implicit cbf1: CBF[Repr1, El1, To1],
- cbf2: CBF[Repr2, El2, To2],
- cbf3: CBF[Repr3, El3, To3]): (To1, To2, To3) = {
- val b1 = cbf1(coll1.repr)
- val b2 = cbf2(coll2.repr)
- val b3 = cbf3(coll3.repr)
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
- def result = (b1.result, b2.result, b3.result)
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext) {
- val el2 = elems2.next
- val el3 = elems3.next
-
- if (f(el1, el2, el3)) {
- b1 += el1
- b2 += el2
- b3 += el3
- }
- }
- else return result
- }
-
- result
- }
-
- def exists(f: (El1, El2, El3) => Boolean): Boolean = {
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext) {
- if (f(el1, elems2.next, elems3.next))
- return true
- }
- else return false
- }
- false
- }
-
- def forall(f: (El1, El2, El3) => Boolean): Boolean =
- !exists((x, y, z) => !f(x, y, z))
-
- def foreach[U](f: (El1, El2, El3) => U): Unit = {
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext)
- f(el1, elems2.next, elems3.next)
- else
- return
- }
- }
- }
-"""
}
class Tuple(val i: Int) extends Group("Tuple") with Arity {
@@ -578,7 +357,7 @@ class Product(val i: Int) extends Group("Product") with Arity {
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
"""
diff --git a/src/build/maven/maven-deploy.xml b/src/build/maven/maven-deploy.xml
index 7f8343a84e..ac0f8f745b 100644
--- a/src/build/maven/maven-deploy.xml
+++ b/src/build/maven/maven-deploy.xml
@@ -112,7 +112,6 @@
<deploy-local name="scala-compiler" version="@{version}" repository="@{repository}" />
<deploy-local-plugin name="continuations" version="@{version}" repository="@{repository}"/>
<deploy-local name="scala-actors" version="@{version}" repository="@{repository}" />
- <deploy-local name="scala-dbc" version="@{version}" repository="@{repository}" />
<deploy-local name="scala-swing" version="@{version}" repository="@{repository}"/>
<deploy-local name="scalap" version="@{version}" repository="@{repository}"/>
<deploy-local name="scala-partest" version="@{version}" repository="@{repository}"/>
@@ -171,7 +170,6 @@
</deploy-remote>
<deploy-remote name="jline" version="@{version}" repository="@{repository}"/>
<deploy-remote name="scala-compiler" version="@{version}" repository="@{repository}" />
- <deploy-remote name="scala-dbc" version="@{version}" repository="@{repository}" />
<deploy-remote name="scala-swing" version="@{version}" repository="@{repository}"/>
<deploy-remote name="scala-actors" version="@{version}" repository="@{repository}"/>
<deploy-remote name="scalap" version="@{version}" repository="@{repository}"/>
@@ -239,7 +237,6 @@
<deploy-remote-signed name="scala-library" version="@{version}" repository="@{repository}"/>
<deploy-remote-signed name="jline" version="@{version}" repository="@{repository}"/>
<deploy-remote-signed name="scala-compiler" version="@{version}" repository="@{repository}" />
- <deploy-remote-signed name="scala-dbc" version="@{version}" repository="@{repository}" />
<deploy-remote-signed name="scala-swing" version="@{version}" repository="@{repository}"/>
<deploy-remote-signed name="scala-actors" version="@{version}" repository="@{repository}"/>
<deploy-remote-signed name="scalap" version="@{version}" repository="@{repository}"/>
diff --git a/src/build/maven/scala-dbc-pom.xml b/src/build/maven/scala-dbc-pom.xml
deleted file mode 100644
index aa3d050c1e..0000000000
--- a/src/build/maven/scala-dbc-pom.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<project
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.scala-lang</groupId>
- <artifactId>scala-dbc</artifactId>
- <packaging>jar</packaging>
- <version>@VERSION@</version>
- <name>Scala Database Connectivity</name>
- <description>Connectivity for your DBs</description>
- <url>http://www.scala-lang.org/</url>
- <inceptionYear>2002</inceptionYear>
- <organization>
- <name>LAMP/EPFL</name>
- <url>http://lamp.epfl.ch/</url>
- </organization>
- <licenses>
- <license>
- <name>BSD-like</name>
- <url>http://www.scala-lang.org/downloads/license.html
- </url>
- <distribution>repo</distribution>
- </license>
- </licenses>
- <scm>
- <connection>scm:git:git://github.com/scala/scala.git</connection>
- <url>https://github.com/scala/scala.git</url>
- </scm>
- <issueManagement>
- <system>JIRA</system>
- <url>https://issues.scala-lang.org/</url>
- </issueManagement>
- <dependencies>
- <dependency>
- <groupId>org.scala-lang</groupId>
- <artifactId>scala-library</artifactId>
- <version>@VERSION@</version>
- </dependency>
- </dependencies>
- <distributionManagement>
- <repository>
- <id>scala-tools.org</id>
- <url>@RELEASE_REPOSITORY@</url>
- </repository>
- <snapshotRepository>
- <id>scala-tools.org</id>
- <url>@SNAPSHOT_REPOSITORY@</url>
- <uniqueVersion>false</uniqueVersion>
- </snapshotRepository>
- </distributionManagement>
- <developers>
- <developer>
- <id>lamp</id>
- <name>EPFL LAMP</name>
- </developer>
- <developer>
- <id>Typesafe</id>
- <name>Typesafe, Inc.</name>
- </developer>
- </developers>
-</project>
diff --git a/src/build/maven/scala-library-pom.xml b/src/build/maven/scala-library-pom.xml
index c3f8a4531c..e8db512125 100644
--- a/src/build/maven/scala-library-pom.xml
+++ b/src/build/maven/scala-library-pom.xml
@@ -32,9 +32,9 @@
</issueManagement>
<dependencies>
<dependency>
- <groupId>org.skife.com.typesafe.config</groupId>
- <artifactId>typesafe-config</artifactId>
- <version>0.3.0</version>
+ <groupId>com.typesafe</groupId>
+ <artifactId>config</artifactId>
+ <version>0.4.0</version>
</dependency>
</dependencies>
<distributionManagement>
diff --git a/src/build/pack.xml b/src/build/pack.xml
index 3bd4d7a199..f96c6b9799 100644
--- a/src/build/pack.xml
+++ b/src/build/pack.xml
@@ -137,7 +137,6 @@ MAIN DISTRIBUTION PACKAGING
<mvn-copy-lib mvn.artifact.name="jline"/>
<mvn-copy-lib mvn.artifact.name="scala-library"/>
<mvn-copy-lib mvn.artifact.name="scala-compiler"/>
- <mvn-copy-lib mvn.artifact.name="scala-dbc"/>
<mvn-copy-lib mvn.artifact.name="scala-swing"/>
<mvn-copy-lib mvn.artifact.name="scala-actors"/>
<mvn-copy-lib mvn.artifact.name="scala-partest"/>
@@ -202,11 +201,9 @@ MAIN DISTRIBUTION PACKAGING
basedir="${build-docs.dir}/continuations-plugin">
<include name="**/*"/>
</jar>
- <!-- TODO - Scala swing, dbc and actors should maybe have thier own jar, but creating it is SLOW. -->
+ <!-- TODO - Scala swing and actors should maybe have thier own jar, but creating it is SLOW. -->
<copy tofile="${dists.dir}/maven/${version.number}/scala-swing/scala-swing-docs.jar"
file="${dists.dir}/maven/${version.number}/scala-library/scala-library-docs.jar"/>
- <copy tofile="${dists.dir}/maven/${version.number}/scala-dbc/scala-dbc-docs.jar"
- file="${dists.dir}/maven/${version.number}/scala-library/scala-library-docs.jar"/>
<copy tofile="${dists.dir}/maven/${version.number}/scala-actors/scala-actors-docs.jar"
file="${dists.dir}/maven/${version.number}/scala-library/scala-library-docs.jar"/>
</target>
diff --git a/src/compiler/scala/reflect/internal/AnnotationInfos.scala b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
index 9a7c79d856..085537fc9f 100644
--- a/src/compiler/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/compiler/scala/reflect/internal/AnnotationInfos.scala
@@ -76,13 +76,34 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
*/
case class ScalaSigBytes(bytes: Array[Byte]) extends ClassfileAnnotArg {
override def toString = (bytes map { byte => (byte & 0xff).toHexString }).mkString("[ ", " ", " ]")
- lazy val encodedBytes = ByteCodecs.encode(bytes)
- def isLong: Boolean = (encodedBytes.length > 65535)
+ lazy val encodedBytes = ByteCodecs.encode(bytes) // TODO remove after migration to ASM-based GenJVM complete
+ def isLong: Boolean = (encodedBytes.length > 65535) // TODO remove after migration to ASM-based GenJVM complete
+ lazy val sevenBitsMayBeZero: Array[Byte] = {
+ mapToNextModSevenBits(scala.reflect.internal.pickling.ByteCodecs.encode8to7(bytes))
+ }
+ def fitsInOneString: Boolean = {
+ val numZeros = (sevenBitsMayBeZero count { b => b == 0 })
+ val res = (sevenBitsMayBeZero.length + numZeros) <= 65535
+ assert(this.isLong == !res, "As things stand, can't just swap in `fitsInOneString()` for `isLong()`")
+ res
+ }
def sigAnnot: Type =
if (this.isLong)
definitions.ScalaLongSignatureAnnotation.tpe
else
definitions.ScalaSignatureAnnotation.tpe
+
+ private def mapToNextModSevenBits(src: Array[Byte]): Array[Byte] = {
+ var i = 0
+ val srclen = src.length
+ while (i < srclen) {
+ val in = src(i)
+ src(i) = (if (in == 0x7f) 0.toByte else (in + 1).toByte)
+ i += 1
+ }
+ src
+ }
+
}
/** Represents a nested classfile annotation */
@@ -116,7 +137,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
// Classfile annot: args empty. Scala annot: assocs empty.
assert(args.isEmpty || assocs.isEmpty, atp)
- // @xeno.by: necessary for reification, see Reifiers.scala for more info
+ // necessary for reification, see Reifiers.scala for more info
private var orig: Tree = EmptyTree
def original = orig
def setOriginal(t: Tree): this.type = { orig = t; this }
@@ -168,24 +189,15 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
*
* `assocs` stores arguments to classfile annotations as name-value pairs.
*/
- sealed abstract class AnnotationInfo extends Product3[Type, List[Tree], List[(Name, ClassfileAnnotArg)]] {
+ sealed abstract class AnnotationInfo {
def atp: Type
def args: List[Tree]
def assocs: List[(Name, ClassfileAnnotArg)]
- // @xeno.by: necessary for reification, see Reifiers.scala for more info
+ // necessary for reification, see Reifiers.scala for more info
def original: Tree
def setOriginal(t: Tree): this.type
- /** Hand rolling Product. */
- def _1 = atp
- def _2 = args
- def _3 = assocs
- // @xeno.by: original hasn't become a product member for backward compatibility purposes
- // def _4 = original
- def canEqual(other: Any) = other.isInstanceOf[AnnotationInfo]
- override def productPrefix = "AnnotationInfo"
-
// see annotationArgRewriter
lazy val isTrivial = atp.isTrivial && !hasArgWhich(_.isInstanceOf[This])
@@ -269,8 +281,7 @@ trait AnnotationInfos extends api.AnnotationInfos { self: SymbolTable =>
}
}
- lazy val classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] =
- reflect.ClassManifest.classType(classOf[ClassfileAnnotArg])
+ lazy val classfileAnnotArgTag: ArrayTag[ClassfileAnnotArg] = arrayTag[ClassfileAnnotArg]
object UnmappableAnnotation extends CompleteAnnotationInfo(NoType, Nil, Nil)
}
diff --git a/src/compiler/scala/reflect/internal/CapturedVariables.scala b/src/compiler/scala/reflect/internal/CapturedVariables.scala
new file mode 100644
index 0000000000..77909d9157
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/CapturedVariables.scala
@@ -0,0 +1,36 @@
+package scala.reflect
+package internal
+
+import Flags._
+
+trait CapturedVariables { self: SymbolTable =>
+
+ import definitions._
+
+ /** Mark a variable as captured; i.e. force boxing in a *Ref type.
+ */
+ def captureVariable(vble: Symbol): Unit = vble setFlag CAPTURED
+
+ /** Mark given identifier as a reference to a captured variable itself
+ * suppressing dereferencing with the `elem` field.
+ */
+ def referenceCapturedVariable(vble: Symbol): Tree = ReferenceToBoxed(Ident(vble))
+
+ /** Convert type of a captured variable to *Ref type.
+ */
+ def capturedVariableType(vble: Symbol): Type =
+ capturedVariableType(vble, NoType, false)
+
+ /** Convert type of a captured variable to *Ref type.
+ */
+ def capturedVariableType(vble: Symbol, tpe: Type = NoType, erasedTypes: Boolean = false): Type = {
+ val tpe1 = if (tpe == NoType) vble.tpe else tpe
+ val symClass = tpe1.typeSymbol
+ def refType(valueRef: Map[Symbol, Symbol], objectRefClass: Symbol) =
+ if (isPrimitiveValueClass(symClass) && symClass != UnitClass) valueRef(symClass).tpe
+ else if (erasedTypes) objectRefClass.tpe
+ else appliedType(objectRefClass, tpe)
+ if (vble.hasAnnotation(VolatileAttr)) refType(volatileRefClass, VolatileObjectRefClass)
+ else refType(refClass, ObjectRefClass)
+ }
+}
diff --git a/src/compiler/scala/reflect/internal/ClassfileConstants.scala b/src/compiler/scala/reflect/internal/ClassfileConstants.scala
index eec72d082d..3346e9cccb 100644
--- a/src/compiler/scala/reflect/internal/ClassfileConstants.scala
+++ b/src/compiler/scala/reflect/internal/ClassfileConstants.scala
@@ -372,7 +372,7 @@ object ClassfileConstants {
}
def methodFlags(jflags: Int): Long = {
initFields(jflags)
- translateFlags(jflags, 0)
+ translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE else 0)
}
}
object FlagTranslation extends FlagTranslation { }
diff --git a/src/compiler/scala/reflect/internal/ClassfileModel.scala b/src/compiler/scala/reflect/internal/ClassfileModel.scala
new file mode 100644
index 0000000000..c96459037f
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/ClassfileModel.scala
@@ -0,0 +1,169 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect.internal
+
+import java.io.DataInput
+import ConstantPool._
+import ClassfileConstants._
+
+trait ClassfileModel {
+ type Result
+ type Entry
+ type InterfaceInfo
+ type MemberInfo
+ type AttributeInfo
+ type InnerClassInfo
+
+ protected implicit def EntryArrayTag: ArrayTag[Entry]
+ protected implicit def InterfaceInfoArrayTag: ArrayTag[InterfaceInfo]
+ protected implicit def MemberInfoArrayTag: ArrayTag[MemberInfo]
+ protected implicit def AttributeInfoArrayTag: ArrayTag[AttributeInfo]
+ protected implicit def InnerClassInfoArrayTag: ArrayTag[InnerClassInfo]
+
+ // These could be implemented to jump forward in the stream if the
+ // result is not wanted.
+ def readConstantPoolEntry(): Entry
+ def readInterface(): InterfaceInfo
+ def readMember(): MemberInfo
+ def readAttribute(): AttributeInfo
+ def readInnerClass(): InnerClassInfo
+
+ def createInfo(
+ version: JvmVersion,
+ entries: Array[Entry],
+ flags: Int,
+ name: String,
+ superName: String,
+ interfaces: Array[InterfaceInfo],
+ fields: Array[MemberInfo],
+ methods: Array[MemberInfo],
+ attributes: Array[AttributeInfo]
+ ): Result
+}
+
+abstract class StreamingClassfileModel extends ClassfileModel {
+ protected[this] val in: DataInput
+ private[this] var name: String = _
+ private[this] var entries: Array[PoolEntry] = _
+
+ type Entry = PoolEntry
+
+ // These translate null into "", it's less troublesome.
+ protected def nameAt(idx: Int) = entries(idx) match {
+ case x: Name_Info => stringAt(x.name_index).replace('/', '.')
+ case _ => ""
+ }
+ protected def stringAt(idx: Int) = entries(idx) match {
+ case x: Utf8_info => x.stringValue
+ case _ => ""
+ }
+
+ protected def u4 = in.readInt
+ protected def u2 = in.readUnsignedShort.toChar
+ protected def u1 = in.readUnsignedByte
+
+ // The constant_pool table is indexed from 1 to constant_pool_count−1.
+ protected def readConstantPool(): Array[Entry] = {
+ val count = u2
+ val entries = new Array[Entry](count)
+ var i = 1
+ while (i < count) {
+ val entry = readConstantPoolEntry()
+ entries(i) = entry
+ i += entry.width
+ }
+ entries
+ }
+ protected def readInterfaces() = {
+ val count = u2
+ val interfaces = new Array[InterfaceInfo](count)
+ var i = 0
+ while (i < count) {
+ interfaces(i) = readInterface()
+ i += 1
+ }
+ interfaces
+ }
+ protected def readMembers() = {
+ val count = u2
+ val arr = new Array[MemberInfo](count)
+ var i = 0
+ while (i < count) {
+ arr(i) = readMember()
+ i += 1
+ }
+ arr
+ }
+ protected def readAttributes(): Array[AttributeInfo] = {
+ val count = u2
+ val arr = new Array[AttributeInfo](count)
+ var i = 0
+ while (i < count) {
+ arr(i) = readAttribute()
+ i += 1
+ }
+ arr
+ }
+ protected def readInnerClasses() = {
+ val count = u2
+ val arr = new Array[InnerClassInfo](count)
+ var i = 0
+ while (i < count) {
+ arr(i) = readInnerClass()
+ i += 1
+ }
+ arr
+ }
+ protected def thisClass = name
+
+ def parse() = {
+ assert(u4 == JAVA_MAGIC, "Bad magic number")
+ val version = JvmVersion(u2, u2)
+ this.entries = readConstantPool()
+ val flags = u2.toShort
+ this.name = nameAt(u2)
+ val superName = nameAt(u2)
+ val interfaces = readInterfaces()
+ val fields = readMembers()
+ val methods = readMembers()
+ val attributes = readAttributes()
+
+ try createInfo(version, entries, flags, name, superName, interfaces, fields, methods, attributes)
+ finally entries = null
+ }
+}
+
+abstract class ScalacClassfileModel extends StreamingClassfileModel {
+ type Result = JvmClassInfo
+ type InterfaceInfo = String
+ type MemberInfo = JvmMemberInfo
+ type AttributeInfo = JvmAttributeInfo
+ type InnerClassInfo = JvmInnerClassInfo
+
+ protected implicit def EntryArrayTag = arrayTag[PoolEntry]
+ protected implicit def InterfaceInfoArrayTag = arrayTag[InterfaceInfo]
+ protected implicit def MemberInfoArrayTag = arrayTag[MemberInfo]
+ protected implicit def AttributeInfoArrayTag = arrayTag[AttributeInfo]
+ protected implicit def InnerClassInfoArrayTag = arrayTag[InnerClassInfo]
+
+ def readConstantPoolEntry(): PoolEntry
+ def readInterface(): String
+ def readMember(): JvmMemberInfo
+ def readAttribute(): JvmAttributeInfo
+ def readInnerClass(): JvmInnerClassInfo
+
+ def createInfo(
+ version: JvmVersion,
+ entries: Array[PoolEntry],
+ flags: Int,
+ name: String,
+ superName: String,
+ interfaces: Array[String],
+ fields: Array[JvmMemberInfo],
+ methods: Array[JvmMemberInfo],
+ attributes: Array[JvmAttributeInfo]
+ ): JvmClassInfo = new JvmClassInfo(name, superName, interfaces, fields, methods, attributes)
+}
diff --git a/src/compiler/scala/reflect/internal/ConstantPool.scala b/src/compiler/scala/reflect/internal/ConstantPool.scala
new file mode 100644
index 0000000000..f8dd7b9845
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/ConstantPool.scala
@@ -0,0 +1,78 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect.internal
+
+import ClassfileConstants._
+
+object ConstantPool {
+ final case class JvmVersion(minorVersion: Int, majorVersion: Int)
+
+ type UShort = Char
+
+ final val CONSTANT_Utf8 = 1
+ final val CONSTANT_Integer = 3
+ final val CONSTANT_Float = 4
+ final val CONSTANT_Long = 5
+ final val CONSTANT_Double = 6
+ final val CONSTANT_Class = 7
+ final val CONSTANT_String = 8
+ final val CONSTANT_Fieldref = 9
+ final val CONSTANT_Methodref = 10
+ final val CONSTANT_InterfaceMethodref = 11
+ final val CONSTANT_NameAndType = 12
+
+ /*
+ 4.2.2 Unqualified Names
+ Names of methods, fields and local variables are stored as unqualified
+ names. Unqualified names must not contain the characters '.', ';', '['
+ or '/'. Method names are further constrained so that, with the exception
+ of the special method names <init> and <clinit> (§3.9), they must not
+ contain the characters '<' or '>'.
+
+ 4.3 Descriptors and Signatures
+ A descriptor is a string representing the type of a field or method.
+ Descriptors are represented in the class file format using modified
+ UTF-8 strings (§4.4.7) and thus may be drawn, where not further
+ constrained, from the entire Unicode character set. A signature is a
+ string representing the generic type of a field or method, or generic
+ type information for a class declaration.
+ */
+ abstract class Name_Info(tag: Byte) extends PoolEntry(tag) {
+ def name_index: UShort
+ }
+ abstract class Ref_Info(tag: Byte) extends PoolEntry(tag) {
+ def class_index: UShort
+ def name_and_type_index: UShort
+ }
+ class Class_info(val name_index: UShort) extends Name_Info(CONSTANT_Class) { }
+ class Double_info(val value: Double) extends PoolEntry(CONSTANT_Double) {
+ override def width = 2
+ }
+ class Fieldref_info(val class_index: UShort, val name_and_type_index: UShort) extends Ref_Info(CONSTANT_Fieldref)
+ class Float_info(val value: Float) extends PoolEntry(CONSTANT_Float)
+ class Integer_info(val value: Int) extends PoolEntry(CONSTANT_Integer)
+ class InterfaceMethodref_info(val class_index: UShort, val name_and_type_index: UShort) extends Ref_Info(CONSTANT_InterfaceMethodref)
+ class Long_info(val value: Long) extends PoolEntry(CONSTANT_Long) {
+ override def width = 2
+ }
+ class Methodref_info(val class_index: UShort, val name_and_type_index: UShort) extends Ref_Info(CONSTANT_Methodref)
+ class NameAndType_info(val name_index: UShort, val descriptor_index: UShort) extends Name_Info(CONSTANT_NameAndType) {
+ override def toString = "NameAndType #%s:#%s;".format(name_index, descriptor_index)
+ }
+ class String_info(val string_index: UShort) extends PoolEntry(CONSTANT_String) { }
+ class Utf8_info(override val stringValue: String) extends PoolEntry(CONSTANT_Utf8) {
+ override def toString = ("Asciz " + stringValue).trim
+ }
+
+ abstract class PoolEntry(tag: Byte) {
+ def width = 1
+ def stringValue: String = sys.error("Not a String-valued constant pool entry: " + this)
+ override def toString = (
+ getClass.getName.split("[.$]").last + "/" + tag
+ )
+ }
+ object NoEntry extends PoolEntry(-1) { }
+}
diff --git a/src/compiler/scala/reflect/internal/Constants.scala b/src/compiler/scala/reflect/internal/Constants.scala
index c328cc49cb..135d18d5ad 100644
--- a/src/compiler/scala/reflect/internal/Constants.scala
+++ b/src/compiler/scala/reflect/internal/Constants.scala
@@ -26,7 +26,7 @@ trait Constants extends api.Constants {
final val DoubleTag = 9
final val StringTag = 10
final val NullTag = 11
- final val ClassTag = 12
+ final val ClazzTag = 12
// For supporting java enumerations inside java annotations (see ClassfileParser)
final val EnumTag = 13
@@ -43,7 +43,7 @@ trait Constants extends api.Constants {
case x: Double => DoubleTag
case x: String => StringTag
case x: Char => CharTag
- case x: Type => ClassTag
+ case x: Type => ClazzTag
case x: Symbol => EnumTag
case _ => throw new Error("bad constant value: " + value + " of class " + value.getClass)
}
@@ -70,7 +70,7 @@ trait Constants extends api.Constants {
case DoubleTag => DoubleClass.tpe
case StringTag => StringClass.tpe
case NullTag => NullClass.tpe
- case ClassTag => ClassType(value.asInstanceOf[Type])
+ case ClazzTag => ClassType(value.asInstanceOf[Type])
case EnumTag =>
// given (in java): "class A { enum E { VAL1 } }"
// - symbolValue: the symbol of the actual enumeration value (VAL1)
@@ -201,7 +201,7 @@ trait Constants extends api.Constants {
def stringValue: String =
if (value == null) "null"
- else if (tag == ClassTag) signature(typeValue)
+ else if (tag == ClazzTag) signature(typeValue)
else value.toString()
@switch def escapedChar(ch: Char): String = ch match {
@@ -221,7 +221,7 @@ trait Constants extends api.Constants {
tag match {
case NullTag => "null"
case StringTag => "\"" + escape(stringValue) + "\""
- case ClassTag => "classOf[" + signature(typeValue) + "]"
+ case ClazzTag => "classOf[" + signature(typeValue) + "]"
case CharTag => "'" + escapedChar(charValue) + "'"
case LongTag => longValue.toString() + "L"
case _ => String.valueOf(value)
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index 8ea3cd511a..1c3e11b040 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -6,14 +6,35 @@
package scala.reflect
package internal
-import annotation.{ switch }
+import annotation.{ switch, meta }
import scala.collection.{ mutable, immutable }
import Flags._
import PartialFunction._
+import scala.reflect.{ mirror => rm }
trait Definitions extends reflect.api.StandardDefinitions {
self: SymbolTable =>
+ object definitions extends DefinitionsClass
+
+ // [Eugene] find a way to make these non-lazy
+ lazy val ByteTpe = definitions.ByteClass.asType
+ lazy val ShortTpe = definitions.ShortClass.asType
+ lazy val CharTpe = definitions.CharClass.asType
+ lazy val IntTpe = definitions.IntClass.asType
+ lazy val LongTpe = definitions.LongClass.asType
+ lazy val FloatTpe = definitions.FloatClass.asType
+ lazy val DoubleTpe = definitions.DoubleClass.asType
+ lazy val BooleanTpe = definitions.BooleanClass.asType
+ lazy val UnitTpe = definitions.UnitClass.asType
+ lazy val AnyTpe = definitions.AnyClass.asType
+ lazy val ObjectTpe = definitions.ObjectClass.asType
+ lazy val AnyValTpe = definitions.AnyValClass.asType
+ lazy val AnyRefTpe = definitions.AnyRefClass.asType
+ lazy val NothingTpe = definitions.NothingClass.asType
+ lazy val NullTpe = definitions.NullClass.asType
+ lazy val StringTpe = definitions.StringClass.asType
+
/** Since both the value parameter types and the result type may
* require access to the type parameter symbols, we model polymorphic
* creation as a function from those symbols to (formal types, result type).
@@ -22,34 +43,21 @@ trait Definitions extends reflect.api.StandardDefinitions {
*/
private type PolyMethodCreator = List[Symbol] => (Option[List[Type]], Type)
- private def enterNewClass(owner: Symbol, name: TypeName, parents: List[Type], flags: Long = 0L): Symbol = {
+ private def enterNewClass(owner: Symbol, name: TypeName, parents: List[Type], flags: Long = 0L): ClassSymbol = {
val clazz = owner.newClassSymbol(name, NoPosition, flags)
clazz setInfoAndEnter ClassInfoType(parents, newScope, clazz)
}
- private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): Symbol = {
+ private def newMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): MethodSymbol = {
val msym = owner.newMethod(name.encode, NoPosition, flags)
val params = msym.newSyntheticValueParams(formals)
msym setInfo MethodType(params, restpe)
}
- private def enterNewMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): Symbol =
+ private def enterNewMethod(owner: Symbol, name: TermName, formals: List[Type], restpe: Type, flags: Long = 0L): MethodSymbol =
owner.info.decls enter newMethod(owner, name, formals, restpe, flags)
// the scala value classes
trait ValueClassDefinitions {
- self: definitions.type =>
-
- private[Definitions] def valueCache(name: Name) = {
- val res = (
- if (name.isTypeName) ScalaPackageClass.info member name
- else ScalaPackageClass.info member name suchThat (_ hasFlag MODULE)
- )
- if (res eq NoSymbol)
- abort("Could not find value classes! This is a catastrophic failure. scala " + scala.util.Properties.versionString)
- else res
- }
- private[Definitions] def valueModuleMethod(className: Name, methodName: Name): Symbol = {
- valueCache(className.toTermName).moduleClass.tpe member methodName
- }
+ self: DefinitionsClass =>
import ClassfileConstants._
@@ -75,8 +83,27 @@ trait Definitions extends reflect.api.StandardDefinitions {
tpnme.Unit -> VOID_TAG
)
+ private def catastrophicFailure() =
+ abort("Could not find value classes! This is a catastrophic failure. scala " +
+ scala.util.Properties.versionString)
+
+ private def valueClassSymbol(name: TypeName): ClassSymbol = {
+ getMember(ScalaPackageClass, name) match {
+ case x: ClassSymbol => x
+ case _ => catastrophicFailure()
+ }
+ }
+ private def valueClassCompanion(name: TermName): ModuleSymbol = {
+ getMember(ScalaPackageClass, name) match {
+ case x: ModuleSymbol => x
+ case _ => catastrophicFailure()
+ }
+ }
+ private def valueCompanionMember(className: Name, methodName: TermName): MethodSymbol =
+ getMemberMethod(valueClassCompanion(className.toTermName).moduleClass, methodName)
+
private def classesMap[T](f: Name => T) = symbolsMap(ScalaValueClassesNoUnit, f)
- private def symbolsMap[T](syms: List[Symbol], f: Name => T): Map[Symbol, T] = syms zip (syms map (x => f(x.name))) toMap
+ private def symbolsMap[T](syms: List[Symbol], f: Name => T): Map[Symbol, T] = mapFrom(syms)(x => f(x.name))
private def symbolsMapFilt[T](syms: List[Symbol], p: Name => Boolean, f: Name => T) = symbolsMap(syms filter (x => p(x.name)), f)
private def boxedName(name: Name) = sn.Boxed(name.toTypeName)
@@ -87,8 +114,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val boxedClass = classesMap(x => getClass(boxedName(x)))
lazy val refClass = classesMap(x => getRequiredClass("scala.runtime." + x + "Ref"))
lazy val volatileRefClass = classesMap(x => getRequiredClass("scala.runtime.Volatile" + x + "Ref"))
- lazy val boxMethod = classesMap(x => valueModuleMethod(x, nme.box))
- lazy val unboxMethod = classesMap(x => valueModuleMethod(x, nme.unbox))
+ lazy val boxMethod = classesMap(x => valueCompanionMember(x, nme.box))
+ lazy val unboxMethod = classesMap(x => valueCompanionMember(x, nme.unbox))
def isNumericSubClass(sub: Symbol, sup: Symbol) = (
(numericWeight contains sub)
@@ -97,27 +124,28 @@ trait Definitions extends reflect.api.StandardDefinitions {
)
/** Is symbol a numeric value class? */
- def isNumericValueClass(sym: Symbol): Boolean =
- numericWeight contains sym
+ def isNumericValueClass(sym: Symbol) = ScalaNumericValueClasses contains sym
def isGetClass(sym: Symbol) =
- (sym.name == nme.getClass_) && (sym.paramss.isEmpty || sym.paramss.head.isEmpty)
-
- lazy val UnitClass = valueCache(tpnme.Unit)
- lazy val ByteClass = valueCache(tpnme.Byte)
- lazy val ShortClass = valueCache(tpnme.Short)
- lazy val CharClass = valueCache(tpnme.Char)
- lazy val IntClass = valueCache(tpnme.Int)
- lazy val LongClass = valueCache(tpnme.Long)
- lazy val FloatClass = valueCache(tpnme.Float)
- lazy val DoubleClass = valueCache(tpnme.Double)
- lazy val BooleanClass = valueCache(tpnme.Boolean)
+ (sym.name == nme.getClass_) && flattensToEmpty(sym.paramss)
+
+ lazy val UnitClass = valueClassSymbol(tpnme.Unit)
+ lazy val ByteClass = valueClassSymbol(tpnme.Byte)
+ lazy val ShortClass = valueClassSymbol(tpnme.Short)
+ lazy val CharClass = valueClassSymbol(tpnme.Char)
+ lazy val IntClass = valueClassSymbol(tpnme.Int)
+ lazy val LongClass = valueClassSymbol(tpnme.Long)
+ lazy val FloatClass = valueClassSymbol(tpnme.Float)
+ lazy val DoubleClass = valueClassSymbol(tpnme.Double)
+ lazy val BooleanClass = valueClassSymbol(tpnme.Boolean)
lazy val Boolean_and = getMember(BooleanClass, nme.ZAND)
lazy val Boolean_or = getMember(BooleanClass, nme.ZOR)
lazy val Boolean_not = getMember(BooleanClass, nme.UNARY_!)
+ lazy val ScalaNumericValueClasses = ScalaValueClasses filterNot Set[Symbol](UnitClass, BooleanClass)
+
def ScalaValueClassesNoUnit = ScalaValueClasses filterNot (_ eq UnitClass)
- def ScalaValueClasses: List[Symbol] = List(
+ def ScalaValueClasses: List[ClassSymbol] = List(
UnitClass,
BooleanClass,
ByteClass,
@@ -129,15 +157,22 @@ trait Definitions extends reflect.api.StandardDefinitions {
DoubleClass
)
def ScalaValueClassCompanions: List[Symbol] = ScalaValueClasses map (_.companionSymbol)
+ def ScalaPrimitiveValueClasses: List[ClassSymbol] = ScalaValueClasses
}
- object definitions extends AbsDefinitions with ValueClassDefinitions {
+ abstract class DefinitionsClass extends AbsDefinitions with ValueClassDefinitions {
private var isInitialized = false
def isDefinitionsInitialized = isInitialized
// symbols related to packages
var emptypackagescope: Scope = null //debug
+ // TODO - having these as objects means they elude the attempt to
+ // add synchronization in SynchronizedSymbols. But we should either
+ // flip on object overrides or find some other accomodation, because
+ // lazy vals are unnecessarily expensive relative to objects and it
+ // is very beneficial for a handful of bootstrap symbols to have
+ // first class identities
sealed trait WellKnownSymbol extends Symbol {
this initFlags TopLevelCreationFlags
}
@@ -145,10 +180,12 @@ trait Definitions extends reflect.api.StandardDefinitions {
// type and term symbols respectively.
sealed trait RootSymbol extends WellKnownSymbol {
final override def isRootSymbol = true
+ override def owner = NoSymbol
+ override def typeOfThis = thisSym.tpe
}
// This is the package _root_. The actual root cannot be referenced at
// the source level, but _root_ is essentially a function => <root>.
- final object RootPackage extends ModuleSymbol(NoSymbol, NoPosition, nme.ROOTPKG) with RootSymbol {
+ final object RootPackage extends PackageSymbol(NoSymbol, NoPosition, nme.ROOTPKG) with RootSymbol {
this setInfo NullaryMethodType(RootClass.tpe)
RootClass.sourceModule = this
@@ -160,7 +197,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
// although it is probable that some symbols are created as direct children
// of NoSymbol to ensure they will not be stumbled upon. (We should designate
// a better encapsulated place for that.)
- final object RootClass extends ModuleClassSymbol(NoSymbol, NoPosition, tpnme.ROOT) with RootSymbol {
+ final object RootClass extends PackageClassSymbol(NoSymbol, NoPosition, tpnme.ROOT) with RootSymbol {
this setInfo rootLoader
override def isRoot = true
@@ -170,34 +207,33 @@ trait Definitions extends reflect.api.StandardDefinitions {
override def ownerOfNewSymbols = EmptyPackageClass
}
// The empty package, which holds all top level types without given packages.
- final object EmptyPackage extends ModuleSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
+ final object EmptyPackage extends PackageSymbol(RootClass, NoPosition, nme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
override def isEmptyPackage = true
}
- final object EmptyPackageClass extends ModuleClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
+ final object EmptyPackageClass extends PackageClassSymbol(RootClass, NoPosition, tpnme.EMPTY_PACKAGE_NAME) with WellKnownSymbol {
override def isEffectiveRoot = true
override def isEmptyPackageClass = true
}
// It becomes tricky to create dedicated objects for other symbols because
// of initialization order issues.
- lazy val JavaLangPackage = getModule(sn.JavaLang)
+ lazy val JavaLangPackage = getRequiredPackage(sn.JavaLang)
lazy val JavaLangPackageClass = JavaLangPackage.moduleClass
- lazy val ScalaPackage = getModule(nme.scala_)
+ lazy val ScalaPackage = getRequiredPackage(nme.scala_)
lazy val ScalaPackageClass = ScalaPackage.moduleClass
-
- lazy val RuntimePackage = getRequiredModule("scala.runtime")
+ lazy val RuntimePackage = getRequiredPackage("scala.runtime")
lazy val RuntimePackageClass = RuntimePackage.moduleClass
- lazy val JavaLangEnumClass = getRequiredClass("java.lang.Enum")
+ lazy val JavaLangEnumClass = requiredClass[java.lang.Enum[_]]
// convenient one-argument parameter lists
- lazy val anyparam = List(AnyClass.typeConstructor)
+ lazy val anyparam = List(AnyClass.tpe)
lazy val anyvalparam = List(AnyValClass.typeConstructor)
lazy val anyrefparam = List(AnyRefClass.typeConstructor)
// private parameter conveniences
- private def booltype = BooleanClass.typeConstructor
- private def inttype = IntClass.typeConstructor
- private def stringtype = StringClass.typeConstructor
+ private def booltype = BooleanClass.tpe
+ private def inttype = IntClass.tpe
+ private def stringtype = StringClass.tpe
// Java types
def javaTypeName(jclazz: Class[_]): TypeName = newTypeName(jclazz.getName)
@@ -240,9 +276,9 @@ trait Definitions extends reflect.api.StandardDefinitions {
}
// top types
- lazy val AnyClass = enterNewClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT)
- lazy val AnyRefClass = newAlias(ScalaPackageClass, tpnme.AnyRef, ObjectClass.typeConstructor)
- lazy val ObjectClass = getClass(sn.Object)
+ lazy val AnyClass = enterNewClass(ScalaPackageClass, tpnme.Any, Nil, ABSTRACT)
+ lazy val AnyRefClass = newAlias(ScalaPackageClass, tpnme.AnyRef, ObjectClass.tpe)
+ lazy val ObjectClass = getRequiredClass(sn.Object.toString)
// Note: this is not the type alias AnyRef, it's a companion-like
// object used by the @specialize annotation.
@@ -250,12 +286,13 @@ trait Definitions extends reflect.api.StandardDefinitions {
@deprecated("Use AnyRefModule", "2.10.0")
def Predef_AnyRef = AnyRefModule
- lazy val AnyValClass = ScalaPackageClass.info member tpnme.AnyVal orElse {
+ lazy val AnyValClass: ClassSymbol = (ScalaPackageClass.info member tpnme.AnyVal orElse {
val anyval = enterNewClass(ScalaPackageClass, tpnme.AnyVal, List(AnyClass.tpe, NotNullClass.tpe), ABSTRACT)
val av_constr = anyval.newClassConstructor(NoPosition)
anyval.info.decls enter av_constr
anyval
- }
+ }).asInstanceOf[ClassSymbol]
+
lazy val AnyVal_getClass = enterNewMethod(AnyValClass, nme.getClass_, Nil, getClassReturnType(AnyValClass.tpe))
// bottom types
@@ -264,7 +301,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
sealed abstract class BottomClassSymbol(name: TypeName, parent: Symbol) extends ClassSymbol(ScalaPackageClass, NoPosition, name) {
locally {
- this initFlags ABSTRACT | TRAIT | FINAL
+ this initFlags ABSTRACT | FINAL
this setInfoAndEnter ClassInfoType(List(parent.tpe), newScope, this)
}
final override def isBottomClass = true
@@ -280,24 +317,24 @@ trait Definitions extends reflect.api.StandardDefinitions {
}
// exceptions and other throwables
- lazy val ClassCastExceptionClass = getRequiredClass("java.lang.ClassCastException")
+ lazy val ClassCastExceptionClass = requiredClass[ClassCastException]
lazy val IndexOutOfBoundsExceptionClass = getClass(sn.IOOBException)
lazy val InvocationTargetExceptionClass = getClass(sn.InvTargetException)
- lazy val MatchErrorClass = getRequiredClass("scala.MatchError")
- lazy val NonLocalReturnControlClass = getRequiredClass("scala.runtime.NonLocalReturnControl")
+ lazy val MatchErrorClass = requiredClass[MatchError]
+ lazy val NonLocalReturnControlClass = requiredClass[scala.runtime.NonLocalReturnControl[_]]
lazy val NullPointerExceptionClass = getClass(sn.NPException)
lazy val ThrowableClass = getClass(sn.Throwable)
- lazy val UninitializedErrorClass = getRequiredClass("scala.UninitializedFieldError")
+ lazy val UninitializedErrorClass = requiredClass[UninitializedFieldError]
// fundamental reference classes
- lazy val PartialFunctionClass = getRequiredClass("scala.PartialFunction")
- lazy val AbstractPartialFunctionClass = getRequiredClass("scala.runtime.AbstractPartialFunction")
- lazy val SymbolClass = getRequiredClass("scala.Symbol")
- lazy val StringClass = getClass(sn.String)
+ lazy val PartialFunctionClass = requiredClass[PartialFunction[_,_]]
+ lazy val AbstractPartialFunctionClass = requiredClass[scala.runtime.AbstractPartialFunction[_,_]]
+ lazy val SymbolClass = requiredClass[scala.Symbol]
+ lazy val StringClass = requiredClass[java.lang.String]
lazy val StringModule = StringClass.linkedClassOfClass
- lazy val ClassClass = getClass(sn.Class)
+ lazy val ClassClass = requiredClass[java.lang.Class[_]]
def Class_getMethod = getMember(ClassClass, nme.getMethod_)
- lazy val DynamicClass = getRequiredClass("scala.Dynamic")
+ lazy val DynamicClass = requiredClass[Dynamic]
// fundamental modules
lazy val SysPackage = getPackageObject("scala.sys")
@@ -308,14 +345,14 @@ trait Definitions extends reflect.api.StandardDefinitions {
// Those modules and their module classes
lazy val UnqualifiedOwners = UnqualifiedModules.toSet ++ UnqualifiedModules.map(_.moduleClass)
- lazy val PredefModule: Symbol = getRequiredModule("scala.Predef")
+ lazy val PredefModule = requiredModule[scala.Predef.type]
lazy val PredefModuleClass = PredefModule.moduleClass
- def Predef_classOf = getMember(PredefModule, nme.classOf)
- def Predef_identity = getMember(PredefModule, nme.identity)
- def Predef_conforms = getMember(PredefModule, nme.conforms)
+ def Predef_classOf = getMember(PredefModule, nme.classOf)
+ def Predef_identity = getMember(PredefModule, nme.identity)
+ def Predef_conforms = getMember(PredefModule, nme.conforms)
def Predef_wrapRefArray = getMember(PredefModule, nme.wrapRefArray)
- def Predef_??? = getMember(PredefModule, nme.???)
+ def Predef_??? = getMember(PredefModule, nme.???)
/** Is `sym` a member of Predef with the given name?
* Note: DON't replace this by sym == Predef_conforms/etc, as Predef_conforms is a `def`
@@ -328,12 +365,12 @@ trait Definitions extends reflect.api.StandardDefinitions {
/** Specialization.
*/
- lazy val SpecializableModule = getRequiredModule("scala.Specializable")
- lazy val GroupOfSpecializable = SpecializableModule.info.member(newTypeName("Group"))
+ lazy val SpecializableModule = requiredModule[Specializable]
+ lazy val GroupOfSpecializable = getMember(SpecializableModule, tpnme.Group)
- lazy val ConsoleModule: Symbol = getRequiredModule("scala.Console")
- lazy val ScalaRunTimeModule: Symbol = getRequiredModule("scala.runtime.ScalaRunTime")
- lazy val SymbolModule: Symbol = getRequiredModule("scala.Symbol")
+ lazy val ConsoleModule: Symbol = requiredModule[scala.Console.type]
+ lazy val ScalaRunTimeModule: Symbol = requiredModule[scala.runtime.ScalaRunTime.type]
+ lazy val SymbolModule: Symbol = requiredModule[scala.Symbol.type]
lazy val Symbol_apply = SymbolModule.info decl nme.apply
def SeqFactory = getMember(ScalaRunTimeModule, nme.Seq)
@@ -343,15 +380,17 @@ trait Definitions extends reflect.api.StandardDefinitions {
def arrayCloneMethod = getMember(ScalaRunTimeModule, nme.array_clone)
def ensureAccessibleMethod = getMember(ScalaRunTimeModule, nme.ensureAccessible)
def scalaRuntimeSameElements = getMember(ScalaRunTimeModule, nme.sameElements)
+ def arrayClassMethod = getMember(ScalaRunTimeModule, nme.arrayClass)
+ def arrayElementClassMethod = getMember(ScalaRunTimeModule, nme.arrayElementClass)
// classes with special meanings
- lazy val StringAddClass = getRequiredClass("scala.runtime.StringAdd")
- lazy val ArrowAssocClass = getRequiredClass("scala.Predef.ArrowAssoc")
- lazy val StringAdd_+ = getMember(StringAddClass, nme.PLUS)
- lazy val NotNullClass = getRequiredClass("scala.NotNull")
- lazy val ScalaNumberClass = getRequiredClass("scala.math.ScalaNumber")
- lazy val TraitSetterAnnotationClass = getRequiredClass("scala.runtime.TraitSetter")
- lazy val DelayedInitClass = getRequiredClass("scala.DelayedInit")
+ lazy val StringAddClass = requiredClass[scala.runtime.StringAdd]
+ lazy val ArrowAssocClass = getRequiredClass("scala.Predef.ArrowAssoc") // SI-5731
+ lazy val StringAdd_+ = getMember(StringAddClass, nme.PLUS)
+ lazy val NotNullClass = getRequiredClass("scala.NotNull")
+ lazy val ScalaNumberClass = requiredClass[scala.math.ScalaNumber]
+ lazy val TraitSetterAnnotationClass = requiredClass[scala.runtime.TraitSetter]
+ lazy val DelayedInitClass = requiredClass[scala.DelayedInit]
def delayedInitMethod = getMember(DelayedInitClass, nme.delayedInit)
// a dummy value that communicates that a delayedInit call is compiler-generated
// from phase UnCurry to phase Constructors
@@ -359,19 +398,19 @@ trait Definitions extends reflect.api.StandardDefinitions {
// def delayedInitArgVal = EmptyPackageClass.newValue(NoPosition, nme.delayedInitArg)
// .setInfo(UnitClass.tpe)
- lazy val TypeConstraintClass = getRequiredClass("scala.annotation.TypeConstraint")
+ lazy val TypeConstraintClass = requiredClass[scala.annotation.TypeConstraint]
lazy val SingletonClass = enterNewClass(ScalaPackageClass, tpnme.Singleton, anyparam, ABSTRACT | TRAIT | FINAL)
- lazy val SerializableClass = getRequiredClass("scala.Serializable")
- lazy val JavaSerializableClass = getClass(sn.JavaSerializable) modifyInfo fixupAsAnyTrait
- lazy val ComparableClass = getRequiredClass("java.lang.Comparable") modifyInfo fixupAsAnyTrait
- lazy val JavaCloneableClass = getRequiredClass("java.lang.Cloneable")
- lazy val RemoteInterfaceClass = getRequiredClass("java.rmi.Remote")
- lazy val RemoteExceptionClass = getRequiredClass("java.rmi.RemoteException")
-
- lazy val ByNameParamClass = specialPolyClass(tpnme.BYNAME_PARAM_CLASS_NAME, COVARIANT)(_ => AnyClass.typeConstructor)
- lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.typeConstructor)
- lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.typeConstructor))
- lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.typeConstructor))
+ lazy val SerializableClass = requiredClass[scala.Serializable]
+ lazy val JavaSerializableClass = requiredClass[java.io.Serializable] modifyInfo fixupAsAnyTrait
+ lazy val ComparableClass = requiredClass[java.lang.Comparable[_]] modifyInfo fixupAsAnyTrait
+ lazy val JavaCloneableClass = requiredClass[java.lang.Cloneable]
+ lazy val RemoteInterfaceClass = requiredClass[java.rmi.Remote]
+ lazy val RemoteExceptionClass = requiredClass[java.rmi.RemoteException]
+
+ lazy val ByNameParamClass = specialPolyClass(tpnme.BYNAME_PARAM_CLASS_NAME, COVARIANT)(_ => AnyClass.tpe)
+ lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN_NAME, 0L)(_ => AnyClass.tpe)
+ lazy val JavaRepeatedParamClass = specialPolyClass(tpnme.JAVA_REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => arrayType(tparam.tpe))
+ lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS_NAME, COVARIANT)(tparam => seqType(tparam.tpe))
def isByNameParamType(tp: Type) = tp.typeSymbol == ByNameParamClass
def isScalaRepeatedParamType(tp: Type) = tp.typeSymbol == RepeatedParamClass
@@ -380,10 +419,10 @@ trait Definitions extends reflect.api.StandardDefinitions {
def isCastSymbol(sym: Symbol) = sym == Any_asInstanceOf || sym == Object_asInstanceOf
def isJavaVarArgsMethod(m: Symbol) = m.isMethod && isJavaVarArgs(m.info.params)
- def isJavaVarArgs(params: List[Symbol]) = params.nonEmpty && isJavaRepeatedParamType(params.last.tpe)
- def isScalaVarArgs(params: List[Symbol]) = params.nonEmpty && isScalaRepeatedParamType(params.last.tpe)
- def isVarArgsList(params: List[Symbol]) = params.nonEmpty && isRepeatedParamType(params.last.tpe)
- def isVarArgTypes(formals: List[Type]) = formals.nonEmpty && isRepeatedParamType(formals.last)
+ def isJavaVarArgs(params: Seq[Symbol]) = params.nonEmpty && isJavaRepeatedParamType(params.last.tpe)
+ def isScalaVarArgs(params: Seq[Symbol]) = params.nonEmpty && isScalaRepeatedParamType(params.last.tpe)
+ def isVarArgsList(params: Seq[Symbol]) = params.nonEmpty && isRepeatedParamType(params.last.tpe)
+ def isVarArgTypes(formals: Seq[Type]) = formals.nonEmpty && isRepeatedParamType(formals.last)
def hasRepeatedParam(tp: Type): Boolean = tp match {
case MethodType(formals, restpe) => isScalaVarArgs(formals) || hasRepeatedParam(restpe)
@@ -395,6 +434,10 @@ trait Definitions extends reflect.api.StandardDefinitions {
case TypeRef(_, ArrayClass, arg :: Nil) => isPrimitiveValueClass(arg.typeSymbol)
case _ => false
}
+ def isReferenceArray(tp: Type) = tp match {
+ case TypeRef(_, ArrayClass, arg :: Nil) => arg <:< AnyRefClass.tpe
+ case _ => false
+ }
def isArrayOfSymbol(tp: Type, elem: Symbol) = tp match {
case TypeRef(_, ArrayClass, arg :: Nil) => arg.typeSymbol == elem
case _ => false
@@ -403,90 +446,106 @@ trait Definitions extends reflect.api.StandardDefinitions {
lazy val MatchingStrategyClass = getRequiredClass("scala.MatchingStrategy")
// collections classes
- lazy val ConsClass = getRequiredClass("scala.collection.immutable.$colon$colon")
- lazy val IterableClass = getRequiredClass("scala.collection.Iterable")
- lazy val IteratorClass = getRequiredClass("scala.collection.Iterator")
- lazy val ListClass = getRequiredClass("scala.collection.immutable.List")
- lazy val SeqClass = getRequiredClass("scala.collection.Seq")
- lazy val StringBuilderClass = getRequiredClass("scala.collection.mutable.StringBuilder")
- lazy val TraversableClass = getRequiredClass("scala.collection.Traversable")
-
- lazy val ListModule = getRequiredModule("scala.collection.immutable.List")
+ lazy val ConsClass = requiredClass[scala.collection.immutable.::[_]]
+ lazy val IterableClass = requiredClass[scala.collection.Iterable[_]]
+ lazy val IteratorClass = requiredClass[scala.collection.Iterator[_]]
+ lazy val ListClass = requiredClass[scala.collection.immutable.List[_]]
+ lazy val SeqClass = requiredClass[scala.collection.Seq[_]]
+ lazy val StringBuilderClass = requiredClass[scala.collection.mutable.StringBuilder]
+ lazy val TraversableClass = requiredClass[scala.collection.Traversable[_]]
+
+ lazy val ListModule = requiredModule[scala.collection.immutable.List.type]
lazy val List_apply = getMember(ListModule, nme.apply)
- lazy val NilModule = getRequiredModule("scala.collection.immutable.Nil")
- lazy val SeqModule = getRequiredModule("scala.collection.Seq")
- lazy val IteratorModule = getRequiredModule("scala.collection.Iterator")
+ lazy val NilModule = requiredModule[scala.collection.immutable.Nil.type]
+ lazy val SeqModule = requiredModule[scala.collection.Seq.type]
+ lazy val IteratorModule = requiredModule[scala.collection.Iterator.type]
lazy val Iterator_apply = getMember(IteratorModule, nme.apply)
// arrays and their members
- lazy val ArrayModule = getRequiredModule("scala.Array")
+ lazy val ArrayModule = requiredModule[scala.Array.type]
lazy val ArrayModule_overloadedApply = getMember(ArrayModule, nme.apply)
- lazy val ArrayClass = getRequiredClass("scala.Array")
+ lazy val ArrayClass = getRequiredClass("scala.Array") // requiredClass[scala.Array[_]]
lazy val Array_apply = getMember(ArrayClass, nme.apply)
lazy val Array_update = getMember(ArrayClass, nme.update)
lazy val Array_length = getMember(ArrayClass, nme.length)
lazy val Array_clone = getMember(ArrayClass, nme.clone_)
// reflection / structural types
- lazy val SoftReferenceClass = getRequiredClass("java.lang.ref.SoftReference")
- lazy val WeakReferenceClass = getRequiredClass("java.lang.ref.WeakReference")
+ lazy val SoftReferenceClass = requiredClass[java.lang.ref.SoftReference[_]]
+ lazy val WeakReferenceClass = requiredClass[java.lang.ref.WeakReference[_]]
lazy val MethodClass = getClass(sn.MethodAsObject)
def methodClass_setAccessible = getMember(MethodClass, nme.setAccessible)
- lazy val EmptyMethodCacheClass = getRequiredClass("scala.runtime.EmptyMethodCache")
- lazy val MethodCacheClass = getRequiredClass("scala.runtime.MethodCache")
+ lazy val EmptyMethodCacheClass = requiredClass[scala.runtime.EmptyMethodCache]
+ lazy val MethodCacheClass = requiredClass[scala.runtime.MethodCache]
def methodCache_find = getMember(MethodCacheClass, nme.find_)
def methodCache_add = getMember(MethodCacheClass, nme.add_)
// scala.reflect
- lazy val ReflectApiUniverse = getRequiredClass("scala.reflect.api.Universe")
- lazy val ReflectMacroContext = getRequiredClass("scala.reflect.macro.Context")
- lazy val ReflectRuntimeMirror = getRequiredModule("scala.reflect.runtime.Mirror")
- def freeValueMethod = getMember(ReflectRuntimeMirror, nme.freeValue)
- lazy val ReflectPackage = getPackageObject("scala.reflect")
- def Reflect_mirror = getMember(ReflectPackage, nme.mirror)
-
- lazy val PartialManifestClass = getRequiredClass("scala.reflect.ClassManifest")
- lazy val PartialManifestModule = getRequiredModule("scala.reflect.ClassManifest")
- lazy val FullManifestClass = getRequiredClass("scala.reflect.Manifest")
- lazy val FullManifestModule = getRequiredModule("scala.reflect.Manifest")
- lazy val OptManifestClass = getRequiredClass("scala.reflect.OptManifest")
- lazy val NoManifest = getRequiredModule("scala.reflect.NoManifest")
-
- lazy val ScalaSignatureAnnotation = getRequiredClass("scala.reflect.ScalaSignature")
- lazy val ScalaLongSignatureAnnotation = getRequiredClass("scala.reflect.ScalaLongSignature")
+ lazy val ReflectPackageClass = getMember(ScalaPackageClass, nme.reflect)
+ lazy val ReflectPackage = requiredModule[scala.reflect.`package`.type]
+ def ReflectMirror = getMember(ReflectPackage, nme.mirror)
+ // [Eugene] is this a good place for ReflectMirrorPrefix?
+ def ReflectMirrorPrefix = gen.mkAttributedRef(ReflectMirror) setType singleType(ReflectMirror.owner.thisPrefix, ReflectMirror)
+
+ lazy val PartialManifestClass = requiredClass[scala.reflect.ClassManifest[_]]
+ lazy val PartialManifestModule = requiredModule[scala.reflect.ClassManifest.type]
+ lazy val FullManifestClass = requiredClass[scala.reflect.Manifest[_]]
+ lazy val FullManifestModule = requiredModule[scala.reflect.Manifest.type]
+ lazy val OptManifestClass = requiredClass[scala.reflect.OptManifest[_]]
+ lazy val NoManifest = requiredModule[scala.reflect.NoManifest.type]
+
+ lazy val ExprClass = getMember(requiredClass[scala.reflect.api.Exprs], tpnme.Expr)
+ def ExprTree = getMember(ExprClass, nme.tree)
+ def ExprTpe = getMember(ExprClass, nme.tpe)
+ def ExprEval = getMember(ExprClass, nme.eval)
+ def ExprValue = getMember(ExprClass, nme.value)
+ lazy val ExprModule = getMember(requiredClass[scala.reflect.api.Exprs], nme.Expr)
+
+ lazy val ArrayTagClass = requiredClass[scala.reflect.ArrayTag[_]]
+ lazy val ErasureTagClass = requiredClass[scala.reflect.ErasureTag[_]]
+ lazy val ClassTagModule = requiredModule[scala.reflect.ClassTag[_]]
+ lazy val ClassTagClass = requiredClass[scala.reflect.ClassTag[_]]
+ lazy val TypeTagsClass = requiredClass[scala.reflect.api.TypeTags]
+ lazy val TypeTagClass = getMemberClass(TypeTagsClass, tpnme.TypeTag)
+ lazy val TypeTagModule = getMemberModule(TypeTagsClass, nme.TypeTag)
+ lazy val ConcreteTypeTagClass = getMemberClass(TypeTagsClass, tpnme.ConcreteTypeTag)
+ lazy val ConcreteTypeTagModule = getMemberModule(TypeTagsClass, nme.ConcreteTypeTag)
+
+ def ArrayTagWrap = getMemberMethod(ArrayTagClass, nme.wrap)
+ def ArrayTagNewArray = getMemberMethod(ArrayTagClass, nme.newArray)
+ def ErasureTagErasure = getMemberMethod(ErasureTagClass, nme.erasure)
+ def ClassTagTpe = getMemberMethod(ClassTagClass, nme.tpe)
+ def TypeTagTpe = getMemberMethod(TypeTagClass, nme.tpe)
+
+ lazy val MacroContextClass = requiredClass[scala.reflect.makro.Context]
+ def MacroContextPrefix = getMember(MacroContextClass, nme.prefix)
+ def MacroContextPrefixType = getMember(MacroContextClass, tpnme.PrefixType)
+ def MacroContextMirror = getMember(MacroContextClass, nme.mirror)
+ def MacroContextReify = getMember(MacroContextClass, nme.reify)
+ lazy val MacroImplAnnotation = requiredClass[scala.reflect.makro.internal.macroImpl]
+ lazy val MacroInternalPackage = getPackageObject("scala.reflect.makro.internal")
+ def MacroInternal_materializeArrayTag = getMemberMethod(MacroInternalPackage, nme.materializeArrayTag)
+ def MacroInternal_materializeErasureTag = getMemberMethod(MacroInternalPackage, nme.materializeErasureTag)
+ def MacroInternal_materializeClassTag = getMemberMethod(MacroInternalPackage, nme.materializeClassTag)
+ def MacroInternal_materializeTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeTypeTag)
+ def MacroInternal_materializeConcreteTypeTag = getMemberMethod(MacroInternalPackage, nme.materializeConcreteTypeTag)
+
+ lazy val ScalaSignatureAnnotation = requiredClass[scala.reflect.ScalaSignature]
+ lazy val ScalaLongSignatureAnnotation = requiredClass[scala.reflect.ScalaLongSignature]
// Option classes
- lazy val OptionClass: Symbol = getRequiredClass("scala.Option")
- lazy val SomeClass: Symbol = getRequiredClass("scala.Some")
- lazy val NoneModule: Symbol = getRequiredModule("scala.None")
- lazy val SomeModule: Symbol = getRequiredModule("scala.Some")
-
- /** Note: don't use this manifest/type function for anything important,
- * as it is incomplete. Would love to have things like existential types
- * working, but very unfortunately the manifests just stuff the relevant
- * information into the toString method.
- */
- def manifestToType(m: OptManifest[_]): Type = m match {
- case m: ClassManifest[_] =>
- val sym = manifestToSymbol(m)
- val args = m.typeArguments
+ lazy val OptionClass: Symbol = requiredClass[Option[_]]
+ lazy val SomeClass: Symbol = requiredClass[Some[_]]
+ lazy val NoneModule: Symbol = requiredModule[scala.None.type]
+ lazy val SomeModule: Symbol = requiredModule[scala.Some.type]
- if ((sym eq NoSymbol) || args.isEmpty) sym.tpe
- else appliedType(sym.typeConstructor, args map manifestToType)
- case _ =>
- NoType
- }
+ // [Eugene] how do I make this work without casts?
+ // private lazy val importerFromRm = self.mkImporter(rm)
+ private lazy val importerFromRm = self.mkImporter(rm).asInstanceOf[self.Importer { val from: rm.type }]
- def manifestToSymbol(m: ClassManifest[_]): Symbol = m match {
- case x: scala.reflect.AnyValManifest[_] =>
- getMember(ScalaPackageClass, newTypeName("" + x))
- case _ =>
- val name = m.erasure.getName
- if (name endsWith nme.MODULE_SUFFIX_STRING)
- getModuleIfDefined(name stripSuffix nme.MODULE_SUFFIX_STRING)
- else
- getClassIfDefined(name)
- }
+ def compilerTypeFromTag(t: rm.TypeTag[_]): Type = importerFromRm.importType(t.tpe)
+
+ def compilerSymbolFromTag(t: rm.TypeTag[_]): Symbol = importerFromRm.importSymbol(t.sym)
// The given symbol represents either String.+ or StringAdd.+
def isStringAddition(sym: Symbol) = sym == String_+ || sym == StringAdd_+
@@ -503,33 +562,34 @@ trait Definitions extends reflect.api.StandardDefinitions {
def hasJavaMainMethod(path: String): Boolean =
hasJavaMainMethod(getModuleIfDefined(path))
- def isOptionType(tp: Type) = cond(tp.normalize) { case TypeRef(_, OptionClass, List(_)) => true }
- def isSomeType(tp: Type) = cond(tp.normalize) { case TypeRef(_, SomeClass, List(_)) => true }
- def isNoneType(tp: Type) = cond(tp.normalize) { case TypeRef(_, NoneModule, List(_)) => true }
+ def isOptionType(tp: Type) = tp.typeSymbol isSubClass OptionClass
+ def isSomeType(tp: Type) = tp.typeSymbol eq SomeClass
+ def isNoneType(tp: Type) = tp.typeSymbol eq NoneModule
- def optionType(tp: Type) = typeRef(NoPrefix, OptionClass, List(tp))
- def someType(tp: Type) = typeRef(NoPrefix, SomeClass, List(tp))
- def symbolType = typeRef(SymbolClass.typeConstructor.prefix, SymbolClass, List())
- def longType = typeRef(LongClass.typeConstructor.prefix, LongClass, List())
-
- // Product, Tuple, Function
+ // Product, Tuple, Function, AbstractFunction
private def mkArityArray(name: String, arity: Int, countFrom: Int = 1): Array[Symbol] = {
val list = countFrom to arity map (i => getRequiredClass("scala." + name + i))
if (countFrom == 0) list.toArray
else (NoSymbol +: list).toArray
}
+ private def aritySpecificType(symbolArray: Array[Symbol], args: List[Type], others: Type*): Type = {
+ val arity = args.length
+ if (arity >= symbolArray.length) NoType
+ else appliedType(symbolArray(arity), args ++ others: _*)
+ }
val MaxTupleArity, MaxProductArity, MaxFunctionArity = 22
- /** The maximal dimensions of a generic array creation.
- * I.e. new Array[Array[Array[Array[Array[T]]]]] creates a 5 times
- * nested array. More is not allowed.
- */
- val MaxArrayDims = 5
- lazy val TupleClass = mkArityArray("Tuple", MaxTupleArity)
- lazy val ProductClass = mkArityArray("Product", MaxProductArity)
- lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0)
+ lazy val ProductClass = { val arr = mkArityArray("Product", MaxProductArity) ; arr(0) = UnitClass ; arr }
+ lazy val TupleClass = mkArityArray("Tuple", MaxTupleArity)
+ lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0)
lazy val AbstractFunctionClass = mkArityArray("runtime.AbstractFunction", MaxFunctionArity, 0)
- lazy val isProductNClass = ProductClass.toSet
+
+ /** Creators for TupleN, ProductN, FunctionN. */
+ def tupleType(elems: List[Type]) = aritySpecificType(TupleClass, elems)
+ def productType(elems: List[Type]) = aritySpecificType(ProductClass, elems)
+ def functionType(formals: List[Type], restpe: Type) = aritySpecificType(FunctionClass, formals, restpe)
+ def abstractFunctionType(formals: List[Type], restpe: Type) = aritySpecificType(AbstractFunctionClass, formals, restpe)
+
def wrapArrayMethodName(elemtp: Type): TermName = elemtp.typeSymbol match {
case ByteClass => nme.wrapByteArray
case ShortClass => nme.wrapShortArray
@@ -546,10 +606,11 @@ trait Definitions extends reflect.api.StandardDefinitions {
}
@deprecated("Use isTupleType", "2.10.0")
- def isTupleTypeOrSubtype(tp: Type): Boolean = isTupleType(tp)
+ def isTupleTypeOrSubtype(tp: Type) = isTupleType(tp)
def tupleField(n: Int, j: Int) = getMember(TupleClass(n), nme.productAccessorName(j))
def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym)
+ def isProductNClass(sym: Symbol) = ProductClass contains sym
def unspecializedSymbol(sym: Symbol): Symbol = {
if (sym hasFlag SPECIALIZED) {
@@ -586,21 +647,13 @@ trait Definitions extends reflect.api.StandardDefinitions {
}
def isTupleType(tp: Type) = isTupleTypeDirect(tp.normalize)
- def tupleType(elems: List[Type]) = {
- val len = elems.length
- if (len <= MaxTupleArity) {
- val sym = TupleClass(len)
- typeRef(sym.typeConstructor.prefix, sym, elems)
- } else NoType
- }
-
- lazy val ProductRootClass: Symbol = getRequiredClass("scala.Product")
- def Product_productArity = getMember(ProductRootClass, nme.productArity)
- def Product_productElement = getMember(ProductRootClass, nme.productElement)
- // def Product_productElementName = getMember(ProductRootClass, nme.productElementName)
- def Product_iterator = getMember(ProductRootClass, nme.productIterator)
- def Product_productPrefix = getMember(ProductRootClass, nme.productPrefix)
- def Product_canEqual = getMember(ProductRootClass, nme.canEqual_)
+ lazy val ProductRootClass: ClassSymbol = requiredClass[scala.Product]
+ def Product_productArity = getMemberMethod(ProductRootClass, nme.productArity)
+ def Product_productElement = getMemberMethod(ProductRootClass, nme.productElement)
+ def Product_iterator = getMemberMethod(ProductRootClass, nme.productIterator)
+ def Product_productPrefix = getMemberMethod(ProductRootClass, nme.productPrefix)
+ def Product_canEqual = getMemberMethod(ProductRootClass, nme.canEqual_)
+ // def Product_productElementName = getMemberMethod(ProductRootClass, nme.productElementName)
def productProj(z:Symbol, j: Int): Symbol = getMember(z, nme.productAccessorName(j))
def productProj(n: Int, j: Int): Symbol = productProj(ProductClass(n), j)
@@ -608,18 +661,6 @@ trait Definitions extends reflect.api.StandardDefinitions {
/** returns true if this type is exactly ProductN[T1,...,Tn], not some subclass */
def isExactProductType(tp: Type): Boolean = isProductNClass(tp.typeSymbol)
- def productType(elems: List[Type]) = {
- if (elems.isEmpty) UnitClass.tpe
- else {
- val len = elems.length
- if (len <= MaxProductArity) {
- val sym = ProductClass(len)
- typeRef(sym.typeConstructor.prefix, sym, elems)
- }
- else NoType
- }
- }
-
/** if tpe <: ProductN[T1,...,TN], returns List(T1,...,TN) else Nil */
def getProductArgs(tpe: Type): List[Type] = tpe.baseClasses find isProductNClass match {
case Some(x) => tpe.baseType(x).typeArgs
@@ -632,21 +673,10 @@ trait Definitions extends reflect.api.StandardDefinitions {
}
def functionApply(n: Int) = getMember(FunctionClass(n), nme.apply)
- def functionType(formals: List[Type], restpe: Type) = {
- val len = formals.length
- if (len <= MaxFunctionArity) {
- val sym = FunctionClass(len)
- typeRef(sym.typeConstructor.prefix, sym, formals :+ restpe)
- } else NoType
- }
- def abstractFunctionForFunctionType(tp: Type) = tp.normalize match {
- case tr @ TypeRef(_, _, args) if isFunctionType(tr) =>
- val sym = AbstractFunctionClass(args.length - 1)
- typeRef(sym.typeConstructor.prefix, sym, args)
- case _ =>
- NoType
- }
+ def abstractFunctionForFunctionType(tp: Type) =
+ if (isFunctionType(tp)) abstractFunctionType(tp.typeArgs.init, tp.typeArgs.last)
+ else NoType
def isFunctionType(tp: Type): Boolean = tp.normalize match {
case TypeRef(_, sym, args) if args.nonEmpty =>
@@ -656,6 +686,11 @@ trait Definitions extends reflect.api.StandardDefinitions {
false
}
+ def isPartialFunctionType(tp: Type): Boolean = {
+ val sym = tp.typeSymbol
+ (sym eq PartialFunctionClass) || (sym eq AbstractPartialFunctionClass)
+ }
+
def isSeqType(tp: Type) = elementType(SeqClass, tp.normalize) != NoType
def elementType(container: Symbol, tp: Type): Type = tp match {
@@ -663,17 +698,21 @@ trait Definitions extends reflect.api.StandardDefinitions {
case _ => NoType
}
- def seqType(arg: Type) = appliedType(SeqClass.typeConstructor, List(arg))
- def arrayType(arg: Type) = appliedType(ArrayClass.typeConstructor, List(arg))
- def byNameType(arg: Type) = appliedType(ByNameParamClass.typeConstructor, List(arg))
- def iteratorOfType(tp: Type) = appliedType(IteratorClass.typeConstructor, List(tp))
+ def arrayType(arg: Type) = appliedType(ArrayClass, arg)
+ def byNameType(arg: Type) = appliedType(ByNameParamClass, arg)
+ def iteratorOfType(tp: Type) = appliedType(IteratorClass, tp)
+ def javaRepeatedType(arg: Type) = appliedType(JavaRepeatedParamClass, arg)
+ def optionType(tp: Type) = appliedType(OptionClass, tp)
+ def scalaRepeatedType(arg: Type) = appliedType(RepeatedParamClass, arg)
+ def seqType(arg: Type) = appliedType(SeqClass, arg)
+ def someType(tp: Type) = appliedType(SomeClass, tp)
- lazy val StringArray = arrayType(StringClass.tpe)
+ def StringArray = arrayType(StringClass.tpe)
lazy val ObjectArray = arrayType(ObjectClass.tpe)
def ClassType(arg: Type) =
if (phase.erasedTypes || forMSIL) ClassClass.tpe
- else appliedType(ClassClass.typeConstructor, List(arg))
+ else appliedType(ClassClass, arg)
def vmClassType(arg: Type): Type = ClassType(arg)
def vmSignature(sym: Symbol, info: Type): String = signature(info) // !!!
@@ -855,80 +894,98 @@ trait Definitions extends reflect.api.StandardDefinitions {
def Object_toString = getMember(ObjectClass, nme.toString_)
// boxed classes
- lazy val ObjectRefClass = getRequiredClass("scala.runtime.ObjectRef")
- lazy val VolatileObjectRefClass = getRequiredClass("scala.runtime.VolatileObjectRef")
- lazy val BoxesRunTimeClass = getRequiredModule("scala.runtime.BoxesRunTime")
+ lazy val ObjectRefClass = requiredClass[scala.runtime.ObjectRef[_]]
+ lazy val VolatileObjectRefClass = requiredClass[scala.runtime.VolatileObjectRef[_]]
+ lazy val BoxesRunTimeModule = getRequiredModule("scala.runtime.BoxesRunTime")
+ lazy val BoxesRunTimeClass = BoxesRunTimeModule.moduleClass
lazy val BoxedNumberClass = getClass(sn.BoxedNumber)
lazy val BoxedCharacterClass = getClass(sn.BoxedCharacter)
lazy val BoxedBooleanClass = getClass(sn.BoxedBoolean)
- lazy val BoxedByteClass = getRequiredClass("java.lang.Byte")
- lazy val BoxedShortClass = getRequiredClass("java.lang.Short")
- lazy val BoxedIntClass = getRequiredClass("java.lang.Integer")
- lazy val BoxedLongClass = getRequiredClass("java.lang.Long")
- lazy val BoxedFloatClass = getRequiredClass("java.lang.Float")
- lazy val BoxedDoubleClass = getRequiredClass("java.lang.Double")
-
- lazy val BoxedUnitClass = getRequiredClass("scala.runtime.BoxedUnit")
+ lazy val BoxedByteClass = requiredClass[java.lang.Byte]
+ lazy val BoxedShortClass = requiredClass[java.lang.Short]
+ lazy val BoxedIntClass = requiredClass[java.lang.Integer]
+ lazy val BoxedLongClass = requiredClass[java.lang.Long]
+ lazy val BoxedFloatClass = requiredClass[java.lang.Float]
+ lazy val BoxedDoubleClass = requiredClass[java.lang.Double]
+
+ lazy val Boxes_isNumberOrBool = getDecl(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean)
+ lazy val Boxes_isNumber = getDecl(BoxesRunTimeClass, nme.isBoxedNumber)
+
+ lazy val BoxedUnitClass = requiredClass[scala.runtime.BoxedUnit]
lazy val BoxedUnitModule = getRequiredModule("scala.runtime.BoxedUnit")
def BoxedUnit_UNIT = getMember(BoxedUnitModule, nme.UNIT)
def BoxedUnit_TYPE = getMember(BoxedUnitModule, nme.TYPE_)
// Annotation base classes
- lazy val AnnotationClass = getRequiredClass("scala.annotation.Annotation")
- lazy val ClassfileAnnotationClass = getRequiredClass("scala.annotation.ClassfileAnnotation")
- lazy val StaticAnnotationClass = getRequiredClass("scala.annotation.StaticAnnotation")
+ lazy val AnnotationClass = requiredClass[scala.annotation.Annotation]
+ lazy val ClassfileAnnotationClass = requiredClass[scala.annotation.ClassfileAnnotation]
+ lazy val StaticAnnotationClass = requiredClass[scala.annotation.StaticAnnotation]
// Annotations
- lazy val BridgeClass = getRequiredClass("scala.annotation.bridge")
- lazy val ElidableMethodClass = getRequiredClass("scala.annotation.elidable")
- lazy val ImplicitNotFoundClass = getRequiredClass("scala.annotation.implicitNotFound")
- lazy val MigrationAnnotationClass = getRequiredClass("scala.annotation.migration")
- lazy val ScalaStrictFPAttr = getRequiredClass("scala.annotation.strictfp")
- lazy val SerializableAttr = getRequiredClass("scala.annotation.serializable") // @serializable is deprecated
- lazy val SwitchClass = getRequiredClass("scala.annotation.switch")
- lazy val TailrecClass = getRequiredClass("scala.annotation.tailrec")
- lazy val VarargsClass = getRequiredClass("scala.annotation.varargs")
- lazy val uncheckedStableClass = getRequiredClass("scala.annotation.unchecked.uncheckedStable")
- lazy val uncheckedVarianceClass = getRequiredClass("scala.annotation.unchecked.uncheckedVariance")
-
- lazy val BeanPropertyAttr = getRequiredClass("scala.beans.BeanProperty")
- lazy val BooleanBeanPropertyAttr = getRequiredClass("scala.beans.BooleanBeanProperty")
- lazy val CloneableAttr = getRequiredClass("scala.cloneable")
- lazy val DeprecatedAttr = getRequiredClass("scala.deprecated")
- lazy val DeprecatedNameAttr = getRequiredClass("scala.deprecatedName")
- lazy val NativeAttr = getRequiredClass("scala.native")
- lazy val RemoteAttr = getRequiredClass("scala.remote")
- lazy val ScalaInlineClass = getRequiredClass("scala.inline")
- lazy val ScalaNoInlineClass = getRequiredClass("scala.noinline")
- lazy val SerialVersionUIDAttr = getRequiredClass("scala.SerialVersionUID")
- lazy val SpecializedClass = getRequiredClass("scala.specialized")
- lazy val ThrowsClass = getRequiredClass("scala.throws")
- lazy val TransientAttr = getRequiredClass("scala.transient")
- lazy val UncheckedClass = getRequiredClass("scala.unchecked")
- lazy val VolatileAttr = getRequiredClass("scala.volatile")
+ lazy val BridgeClass = requiredClass[scala.annotation.bridge]
+ lazy val ElidableMethodClass = requiredClass[scala.annotation.elidable]
+ lazy val ImplicitNotFoundClass = requiredClass[scala.annotation.implicitNotFound]
+ lazy val MigrationAnnotationClass = requiredClass[scala.annotation.migration]
+ lazy val ScalaStrictFPAttr = requiredClass[scala.annotation.strictfp]
+ lazy val SerializableAttr = requiredClass[scala.annotation.serializable] // @serializable is deprecated
+ lazy val SwitchClass = requiredClass[scala.annotation.switch]
+ lazy val TailrecClass = requiredClass[scala.annotation.tailrec]
+ lazy val VarargsClass = requiredClass[scala.annotation.varargs]
+ lazy val uncheckedStableClass = requiredClass[scala.annotation.unchecked.uncheckedStable]
+ lazy val uncheckedVarianceClass = requiredClass[scala.annotation.unchecked.uncheckedVariance]
+
+ lazy val BeanPropertyAttr = requiredClass[scala.beans.BeanProperty]
+ lazy val BooleanBeanPropertyAttr = requiredClass[scala.beans.BooleanBeanProperty]
+ lazy val CloneableAttr = requiredClass[scala.cloneable]
+ lazy val DeprecatedAttr = requiredClass[scala.deprecated]
+ lazy val DeprecatedNameAttr = requiredClass[scala.deprecatedName]
+ lazy val NativeAttr = requiredClass[scala.native]
+ lazy val RemoteAttr = requiredClass[scala.remote]
+ lazy val ScalaInlineClass = requiredClass[scala.inline]
+ lazy val ScalaNoInlineClass = requiredClass[scala.noinline]
+ lazy val SerialVersionUIDAttr = requiredClass[scala.SerialVersionUID]
+ lazy val SpecializedClass = requiredClass[scala.specialized]
+ lazy val ThrowsClass = requiredClass[scala.throws]
+ lazy val TransientAttr = requiredClass[scala.transient]
+ lazy val UncheckedClass = requiredClass[scala.unchecked]
+ lazy val UnspecializedClass = requiredClass[scala.annotation.unspecialized]
+ lazy val VolatileAttr = requiredClass[scala.volatile]
// Meta-annotations
- lazy val BeanGetterTargetClass = getMetaAnnotation("beanGetter")
- lazy val BeanSetterTargetClass = getMetaAnnotation("beanSetter")
- lazy val FieldTargetClass = getMetaAnnotation("field")
- lazy val GetterTargetClass = getMetaAnnotation("getter")
- lazy val ParamTargetClass = getMetaAnnotation("param")
- lazy val SetterTargetClass = getMetaAnnotation("setter")
- // TODO: module, moduleClass? package, packageObject?
-
- private def getMetaAnnotation(name: String) = getRequiredClass("scala.annotation.meta." + name)
+ lazy val BeanGetterTargetClass = requiredClass[meta.beanGetter]
+ lazy val BeanSetterTargetClass = requiredClass[meta.beanSetter]
+ lazy val FieldTargetClass = requiredClass[meta.field]
+ lazy val GetterTargetClass = requiredClass[meta.getter]
+ lazy val ParamTargetClass = requiredClass[meta.param]
+ lazy val SetterTargetClass = requiredClass[meta.setter]
+ lazy val ClassTargetClass = requiredClass[meta.companionClass]
+ lazy val ObjectTargetClass = requiredClass[meta.companionObject]
+ lazy val MethodTargetClass = requiredClass[meta.companionMethod] // TODO: module, moduleClass? package, packageObject?
+ lazy val LanguageFeatureAnnot = requiredClass[meta.languageFeature]
+
+ // Language features
+ lazy val languageFeatureModule = getRequiredModule("scala.languageFeature")
+ lazy val experimentalModule = getMember(languageFeatureModule, nme.experimental)
+ lazy val MacrosFeature = getLanguageFeature("macros", experimentalModule)
+ lazy val DynamicsFeature = getLanguageFeature("dynamics")
+ lazy val PostfixOpsFeature = getLanguageFeature("postfixOps")
+ lazy val ReflectiveCallsFeature = getLanguageFeature("reflectiveCalls")
+ lazy val ImplicitConversionsFeature = getLanguageFeature("implicitConversions")
+ lazy val HigherKindsFeature = getLanguageFeature("higherKinds")
+ lazy val ExistentialsFeature = getLanguageFeature("existentials")
+
def isMetaAnnotation(sym: Symbol): Boolean = metaAnnotations(sym) || (
// Trying to allow for deprecated locations
sym.isAliasType && isMetaAnnotation(sym.info.typeSymbol)
)
- lazy val metaAnnotations = Set(
+ lazy val metaAnnotations = Set[Symbol](
FieldTargetClass, ParamTargetClass,
GetterTargetClass, SetterTargetClass,
BeanGetterTargetClass, BeanSetterTargetClass
)
lazy val AnnotationDefaultAttr: Symbol = {
- val attr = enterNewClass(RuntimePackageClass, tpnme.AnnotationDefaultATTR, List(AnnotationClass.typeConstructor))
+ val attr = enterNewClass(RuntimePackageClass, tpnme.AnnotationDefaultATTR, List(AnnotationClass.tpe))
// This attribute needs a constructor so that modifiers in parsed Java code make sense
attr.info.decls enter attr.newClassConstructor(NoPosition)
attr
@@ -940,31 +997,77 @@ trait Definitions extends reflect.api.StandardDefinitions {
def getPackageObject(fullname: String): Symbol =
getModule(newTermName(fullname)).info member nme.PACKAGE
- def getModule(fullname: Name): Symbol =
- getModuleOrClass(fullname.toTermName)
+ def getModule(fullname: Name): ModuleSymbol =
+ getModuleOrClass(fullname.toTermName) match {
+ case x: ModuleSymbol => x
+ case _ => MissingRequirementError.notFound("object " + fullname)
+ }
- def getClass(fullname: Name): Symbol = {
- var result = getModuleOrClass(fullname.toTypeName)
- while (result.isAliasType) result = result.info.typeSymbol
- result
+ def getPackage(fullname: Name): PackageSymbol =
+ getModuleOrClass(fullname.toTermName) match {
+ case x: PackageSymbol => x
+ case _ => MissingRequirementError.notFound("package " + fullname)
+ }
+ @inline private def wrapMissing(body: => Symbol): Symbol =
+ try body
+ catch { case _: MissingRequirementError => NoSymbol }
+
+ private def fatalMissingSymbol(owner: Symbol, name: Name, what: String = "member") = {
+ throw new FatalError(owner + " does not have a " + what + " " + name)
}
- def getRequiredModule(fullname: String): Symbol =
+ @deprecated("Use getClassByName", "2.10.0")
+ def getClass(fullname: Name): Symbol = getClassByName(fullname)
+
+ def getRequiredPackage(fullname: String): PackageSymbol =
+ getPackage(newTermNameCached(fullname))
+
+ def getRequiredModule(fullname: String): ModuleSymbol =
getModule(newTermNameCached(fullname))
- def getRequiredClass(fullname: String): Symbol =
- getClass(newTypeNameCached(fullname))
+
+ def erasureName[T: ErasureTag] : String = {
+ /** We'd like the String representation to be a valid
+ * scala type, so we have to decode the jvm's secret language.
+ */
+ def erasureString(clazz: Class[_]): String = {
+ if (clazz.isArray) "Array[" + erasureString(clazz.getComponentType) + "]"
+ else clazz.getName
+ }
+ erasureString(implicitly[ErasureTag[T]].erasure)
+ }
+
+ def requiredClass[T: ClassTag] : ClassSymbol = getRequiredClass(erasureName[T])
+
+ // TODO: What syntax do we think should work here? Say you have an object
+ // like scala.Predef. You can't say requiredModule[scala.Predef] since there's
+ // no accompanying Predef class, and if you say requiredModule[scala.Predef.type]
+ // the name found via the erasure is scala.Predef$. For now I am
+ // removing the trailing $, but I think that classTag should have
+ // a method which returns a usable name, one which doesn't expose this
+ // detail of the backend.
+ def requiredModule[T: ClassTag] : ModuleSymbol =
+ getRequiredModule(erasureName[T] stripSuffix "$")
+
+ def getRequiredClass(fullname: String): ClassSymbol =
+ getClassByName(newTypeNameCached(fullname)) match {
+ case x: ClassSymbol => x
+ case _ => MissingRequirementError.notFound("class " + fullname)
+ }
def getClassIfDefined(fullname: String): Symbol =
getClassIfDefined(newTypeName(fullname))
+
def getClassIfDefined(fullname: Name): Symbol =
- try getClass(fullname.toTypeName)
- catch { case _: MissingRequirementError => NoSymbol }
+ wrapMissing(getClass(fullname.toTypeName))
def getModuleIfDefined(fullname: String): Symbol =
getModuleIfDefined(newTermName(fullname))
+
def getModuleIfDefined(fullname: Name): Symbol =
- try getModule(fullname.toTermName)
- catch { case _: MissingRequirementError => NoSymbol }
+ wrapMissing(getModule(fullname.toTermName))
+
+ def getLanguageFeature(name: String, owner: Symbol = languageFeatureModule) =
+ getMember(owner, newTypeName(name))
def termMember(owner: Symbol, name: String): Symbol = owner.info.member(newTermName(name))
def typeMember(owner: Symbol, name: String): Symbol = owner.info.member(newTypeName(name))
@@ -984,13 +1087,47 @@ trait Definitions extends reflect.api.StandardDefinitions {
else findNamedMember(segs.tail, root.info member segs.head)
def getMember(owner: Symbol, name: Name): Symbol = {
- if (owner == NoSymbol) NoSymbol
- else owner.info.nonPrivateMember(name) match {
- case NoSymbol => throw new FatalError(owner + " does not have a member " + name)
- case result => result
+ getMemberIfDefined(owner, name) orElse {
+ if (phase.flatClasses && name.isTypeName && !owner.isPackageObjectOrClass) {
+ val pkg = owner.owner
+ val flatname = nme.flattenedName(owner.name, name)
+ getMember(pkg, flatname)
+ }
+ else fatalMissingSymbol(owner, name)
+ }
+ }
+ def getMemberModule(owner: Symbol, name: Name): ModuleSymbol = {
+ getMember(owner, name.toTermName) match {
+ case x: ModuleSymbol => x
+ case _ => fatalMissingSymbol(owner, name, "member object")
}
}
-
+ def getMemberClass(owner: Symbol, name: Name): ClassSymbol = {
+ getMember(owner, name.toTypeName) match {
+ case x: ClassSymbol => x
+ case _ => fatalMissingSymbol(owner, name, "member class")
+ }
+ }
+ def getMemberMethod(owner: Symbol, name: Name): MethodSymbol = {
+ getMember(owner, name.toTermName) match {
+ case x: MethodSymbol => x
+ case _ => fatalMissingSymbol(owner, name, "method")
+ }
+ }
+
+ def getMemberIfDefined(owner: Symbol, name: Name): Symbol =
+ owner.info.nonPrivateMember(name)
+
+ /** Using getDecl rather than getMember may avoid issues with
+ * OverloadedTypes turning up when you don't want them, if you
+ * know the method in question is uniquely declared in the given owner.
+ */
+ def getDecl(owner: Symbol, name: Name): Symbol = {
+ getDeclIfDefined(owner, name) orElse fatalMissingSymbol(owner, name, "decl")
+ }
+ def getDeclIfDefined(owner: Symbol, name: Name): Symbol =
+ owner.info.nonPrivateDecl(name)
+
def packageExists(packageName: String): Boolean =
getModuleIfDefined(packageName).isPackage
@@ -1016,10 +1153,16 @@ trait Definitions extends reflect.api.StandardDefinitions {
*/
private def getModuleOrClass(path: Name): Symbol = getModuleOrClass(path, path.length)
- private def newAlias(owner: Symbol, name: TypeName, alias: Type): Symbol =
+ def getClassByName(fullname: Name): Symbol = {
+ var result = getModuleOrClass(fullname.toTypeName)
+ while (result.isAliasType) result = result.info.typeSymbol
+ result
+ }
+
+ private def newAlias(owner: Symbol, name: TypeName, alias: Type): AliasTypeSymbol =
owner.newAliasType(name) setInfoAndEnter alias
- private def specialPolyClass(name: TypeName, flags: Long)(parentFn: Symbol => Type): Symbol = {
+ private def specialPolyClass(name: TypeName, flags: Long)(parentFn: Symbol => Type): ClassSymbol = {
val clazz = enterNewClass(ScalaPackageClass, name, Nil)
val tparam = clazz.newSyntheticTypeParam("T0", flags)
val parents = List(AnyRefClass.tpe, parentFn(tparam))
@@ -1027,7 +1170,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
clazz setInfo GenPolyType(List(tparam), ClassInfoType(parents, newScope, clazz))
}
- def newPolyMethod(typeParamCount: Int, owner: Symbol, name: TermName, flags: Long)(createFn: PolyMethodCreator): Symbol = {
+ def newPolyMethod(typeParamCount: Int, owner: Symbol, name: TermName, flags: Long)(createFn: PolyMethodCreator): MethodSymbol = {
val msym = owner.newMethod(name.encode, NoPosition, flags)
val tparams = msym.newSyntheticTypeParams(typeParamCount)
val mtpe = createFn(tparams) match {
@@ -1040,16 +1183,16 @@ trait Definitions extends reflect.api.StandardDefinitions {
/** T1 means one type parameter.
*/
- def newT1NullaryMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): Symbol = {
+ def newT1NullaryMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): MethodSymbol = {
newPolyMethod(1, owner, name, flags)(tparams => (None, createFn(tparams.head)))
}
- def newT1NoParamsMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): Symbol = {
+ def newT1NoParamsMethod(owner: Symbol, name: TermName, flags: Long)(createFn: Symbol => Type): MethodSymbol = {
newPolyMethod(1, owner, name, flags)(tparams => (Some(Nil), createFn(tparams.head)))
}
- lazy val boxedClassValues = boxedClass.values.toSet
- lazy val isUnbox = unboxMethod.values.toSet
- lazy val isBox = boxMethod.values.toSet
+ lazy val boxedClassValues = boxedClass.values.toSet[Symbol]
+ lazy val isUnbox = unboxMethod.values.toSet[Symbol]
+ lazy val isBox = boxMethod.values.toSet[Symbol]
/** Is symbol a phantom class for which no runtime representation exists? */
lazy val isPhantomClass = Set[Symbol](AnyClass, AnyValClass, NullClass, NothingClass)
@@ -1057,14 +1200,13 @@ trait Definitions extends reflect.api.StandardDefinitions {
/** Is the symbol that of a parent which is added during parsing? */
lazy val isPossibleSyntheticParent = ProductClass.toSet[Symbol] + ProductRootClass + SerializableClass
- lazy val scalaValueClassesSet = ScalaValueClasses.toSet
- private lazy val boxedValueClassesSet = boxedClass.values.toSet + BoxedUnitClass
+ private lazy val boxedValueClassesSet = boxedClass.values.toSet[Symbol] + BoxedUnitClass
/** Is symbol a value class? */
- def isPrimitiveValueClass(sym: Symbol) = scalaValueClassesSet(sym)
+ def isPrimitiveValueClass(sym: Symbol) = ScalaValueClasses contains sym
def isNonUnitValueClass(sym: Symbol) = isPrimitiveValueClass(sym) && (sym != UnitClass)
def isSpecializableClass(sym: Symbol) = isPrimitiveValueClass(sym) || (sym == AnyRefClass)
- def isScalaValueType(tp: Type) = scalaValueClassesSet(tp.typeSymbol)
+ def isScalaValueType(tp: Type) = ScalaValueClasses contains tp.typeSymbol
/** Is symbol a boxed value class, e.g. java.lang.Integer? */
def isBoxedValueClass(sym: Symbol) = boxedValueClassesSet(sym)
diff --git a/src/compiler/scala/reflect/internal/Flags.scala b/src/compiler/scala/reflect/internal/Flags.scala
index ce1c8d0908..e6820cf78a 100644
--- a/src/compiler/scala/reflect/internal/Flags.scala
+++ b/src/compiler/scala/reflect/internal/Flags.scala
@@ -83,89 +83,89 @@ import scala.collection.{ mutable, immutable }
/** Flags set on Modifiers instances in the parsing stage.
*/
class ModifierFlags {
- final val IMPLICIT = 0x00000200
- final val FINAL = 0x00000020 // May not be overridden. Note that java final implies much more than scala final.
- final val PRIVATE = 0x00000004
- final val PROTECTED = 0x00000001
-
- final val SEALED = 0x00000400
- final val OVERRIDE = 0x00000002
- final val CASE = 0x00000800
- final val ABSTRACT = 0x00000008 // abstract class, or used in conjunction with abstract override.
+ final val IMPLICIT = 1 << 9
+ final val FINAL = 1 << 5 // May not be overridden. Note that java final implies much more than scala final.
+ final val PRIVATE = 1 << 2
+ final val PROTECTED = 1 << 0
+
+ final val SEALED = 1 << 10
+ final val OVERRIDE = 1 << 1
+ final val CASE = 1 << 11
+ final val ABSTRACT = 1 << 3 // abstract class, or used in conjunction with abstract override.
// Note difference to DEFERRED!
- final val DEFERRED = 0x00000010 // was `abstract' for members | trait is virtual
- final val INTERFACE = 0x00000080 // symbol is an interface (i.e. a trait which defines only abstract methods)
- final val MUTABLE = 0x00001000 // symbol is a mutable variable.
- final val PARAM = 0x00002000 // symbol is a (value or type) parameter to a method
- final val MACRO = 0x00008000 // symbol is a macro definition
-
- final val COVARIANT = 0x00010000 // symbol is a covariant type variable
- final val BYNAMEPARAM = 0x00010000 // parameter is by name
- final val CONTRAVARIANT = 0x00020000 // symbol is a contravariant type variable
- final val ABSOVERRIDE = 0x00040000 // combination of abstract & override
- final val LOCAL = 0x00080000 // symbol is local to current class (i.e. private[this] or protected[this]
+ final val DEFERRED = 1 << 4 // was `abstract' for members | trait is virtual
+ final val INTERFACE = 1 << 7 // symbol is an interface (i.e. a trait which defines only abstract methods)
+ final val MUTABLE = 1 << 12 // symbol is a mutable variable.
+ final val PARAM = 1 << 13 // symbol is a (value or type) parameter to a method
+ final val MACRO = 1 << 15 // symbol is a macro definition
+
+ final val COVARIANT = 1 << 16 // symbol is a covariant type variable
+ final val BYNAMEPARAM = 1 << 16 // parameter is by name
+ final val CONTRAVARIANT = 1 << 17 // symbol is a contravariant type variable
+ final val ABSOVERRIDE = 1 << 18 // combination of abstract & override
+ final val LOCAL = 1 << 19 // symbol is local to current class (i.e. private[this] or protected[this]
// pre: PRIVATE or PROTECTED are also set
- final val JAVA = 0x00100000 // symbol was defined by a Java class
- final val STATIC = 0x00800000 // static field, method or class
- final val CASEACCESSOR = 0x01000000 // symbol is a case parameter (or its accessor, or a GADT skolem)
- final val TRAIT = 0x02000000 // symbol is a trait
- final val DEFAULTPARAM = 0x02000000 // the parameter has a default value
- final val PARAMACCESSOR = 0x20000000 // for field definitions generated for primary constructor
+ final val JAVA = 1 << 20 // symbol was defined by a Java class
+ final val STATIC = 1 << 23 // static field, method or class
+ final val CASEACCESSOR = 1 << 24 // symbol is a case parameter (or its accessor, or a GADT skolem)
+ final val TRAIT = 1 << 25 // symbol is a trait
+ final val DEFAULTPARAM = 1 << 25 // the parameter has a default value
+ final val PARAMACCESSOR = 1 << 29 // for field definitions generated for primary constructor
// parameters (no matter if it's a 'val' parameter or not)
// for parameters of a primary constructor ('val' or not)
// for the accessor methods generated for 'val' or 'var' parameters
- final val LAZY = 0x80000000L // symbol is a lazy val. can't have MUTABLE unless transformed by typer
- final val PRESUPER = 0x2000000000L // value is evaluated before super call
- final val DEFAULTINIT = 0x20000000000L// symbol is initialized to the default value: used by -Xcheckinit
+ final val LAZY = 1L << 31 // symbol is a lazy val. can't have MUTABLE unless transformed by typer
+ final val PRESUPER = 1L << 37 // value is evaluated before super call
+ final val DEFAULTINIT = 1L << 41 // symbol is initialized to the default value: used by -Xcheckinit
// Overridden.
def flagToString(flag: Long): String = ""
- final val PrivateLocal: Long = PRIVATE | LOCAL
- final val ProtectedLocal: Long = PROTECTED | LOCAL
- final val AccessFlags: Long = PRIVATE | PROTECTED | LOCAL
+ final val PrivateLocal = PRIVATE | LOCAL
+ final val ProtectedLocal = PROTECTED | LOCAL
+ final val AccessFlags = PRIVATE | PROTECTED | LOCAL
}
object ModifierFlags extends ModifierFlags
/** All flags and associated operatins */
class Flags extends ModifierFlags {
- final val METHOD = 0x00000040 // a method
- final val MODULE = 0x00000100 // symbol is module or class implementing a module
- final val PACKAGE = 0x00004000 // symbol is a java package
-
- final val CAPTURED = 0x00010000 // variable is accessed from nested function. Set by LambdaLift.
- final val LABEL = 0x00020000 // method symbol is a label. Set by TailCall
- final val INCONSTRUCTOR = 0x00020000 // class symbol is defined in this/superclass constructor.
- final val SYNTHETIC = 0x00200000 // symbol is compiler-generated
- final val STABLE = 0x00400000 // functions that are assumed to be stable
+ final val METHOD = 1 << 6 // a method
+ final val MODULE = 1 << 8 // symbol is module or class implementing a module
+ final val PACKAGE = 1 << 14 // symbol is a java package
+
+ final val CAPTURED = 1 << 16 // variable is accessed from nested function. Set by LambdaLift.
+ final val LABEL = 1 << 17 // method symbol is a label. Set by TailCall
+ final val INCONSTRUCTOR = 1 << 17 // class symbol is defined in this/superclass constructor.
+ final val SYNTHETIC = 1 << 21 // symbol is compiler-generated
+ final val STABLE = 1 << 22 // functions that are assumed to be stable
// (typically, access methods for valdefs)
// or classes that do not contain abstract types.
- final val BRIDGE = 0x04000000 // function is a bridge method. Set by Erasure
- final val ACCESSOR = 0x08000000 // a value or variable accessor (getter or setter)
+ final val BRIDGE = 1 << 26 // function is a bridge method. Set by Erasure
+ final val ACCESSOR = 1 << 27 // a value or variable accessor (getter or setter)
- final val SUPERACCESSOR = 0x10000000 // a super accessor
- final val MODULEVAR = 0x40000000 // for variables: is the variable caching a module value
+ final val SUPERACCESSOR = 1 << 28 // a super accessor
+ final val MODULEVAR = 1 << 30 // for variables: is the variable caching a module value
- final val IS_ERROR = 0x100000000L // symbol is an error symbol
- final val OVERLOADED = 0x200000000L // symbol is overloaded
- final val LIFTED = 0x400000000L // class has been lifted out to package level
+ final val IS_ERROR = 1L << 32 // symbol is an error symbol
+ final val OVERLOADED = 1L << 33 // symbol is overloaded
+ final val LIFTED = 1L << 34 // class has been lifted out to package level
// local value has been lifted out to class level
// todo: make LIFTED = latePRIVATE?
- final val MIXEDIN = 0x800000000L // term member has been mixed in
- final val EXISTENTIAL = 0x800000000L // type is an existential parameter or skolem
- final val EXPANDEDNAME = 0x1000000000L // name has been expanded with class suffix
- final val IMPLCLASS = 0x2000000000L // symbol is an implementation class
- final val TRANS_FLAG = 0x4000000000L // transient flag guaranteed to be reset after each phase.
+ final val MIXEDIN = 1L << 35 // term member has been mixed in
+ final val EXISTENTIAL = 1L << 35 // type is an existential parameter or skolem
+ final val EXPANDEDNAME = 1L << 36 // name has been expanded with class suffix
+ final val IMPLCLASS = 1L << 37 // symbol is an implementation class
+ final val TRANS_FLAG = 1L << 38 // transient flag guaranteed to be reset after each phase.
- final val LOCKED = 0x8000000000L // temporary flag to catch cyclic dependencies
- final val SPECIALIZED = 0x10000000000L// symbol is a generated specialized member
- final val VBRIDGE = 0x40000000000L// symbol is a varargs bridge
+ final val LOCKED = 1L << 39 // temporary flag to catch cyclic dependencies
+ final val SPECIALIZED = 1L << 40 // symbol is a generated specialized member
+ final val VBRIDGE = 1L << 42 // symbol is a varargs bridge
- final val VARARGS = 0x80000000000L// symbol is a Java-style varargs method
- final val TRIEDCOOKING = 0x100000000000L // ``Cooking'' has been tried on this symbol
- // A Java method's type is ``cooked'' by transforming raw types to existentials
+ final val VARARGS = 1L << 43 // symbol is a Java-style varargs method
+ final val TRIEDCOOKING = 1L << 44 // ``Cooking'' has been tried on this symbol
+ // A Java method's type is ``cooked'' by transforming raw types to existentials
- final val SYNCHRONIZED = 0x200000000000L // symbol is a method which should be marked ACC_SYNCHRONIZED
+ final val SYNCHRONIZED = 1L << 45 // symbol is a method which should be marked ACC_SYNCHRONIZED
// ------- shift definitions -------------------------------------------------------
final val InitialFlags = 0x0001FFFFFFFFFFFFL // flags that are enabled from phase 1.
@@ -174,6 +174,9 @@ class Flags extends ModifierFlags {
final val LateShift = 47L
final val AntiShift = 56L
+ // Flags which sketchily share the same slot
+ val OverloadedFlagsMask = 0L | BYNAMEPARAM | CONTRAVARIANT | DEFAULTPARAM | EXISTENTIAL | IMPLCLASS
+
// ------- late flags (set by a transformer phase) ---------------------------------
//
// Summary of when these are claimed to be first used.
@@ -206,34 +209,46 @@ class Flags extends ModifierFlags {
// ------- masks -----------------------------------------------------------------------
+ /** To be a little clearer to people who aren't habitual bit twiddlers.
+ */
+ final val AllFlags = -1L
+
/** These flags can be set when class or module symbol is first created.
* They are the only flags to survive a call to resetFlags().
*/
- final val TopLevelCreationFlags: Long =
+ final val TopLevelCreationFlags =
MODULE | PACKAGE | FINAL | JAVA
+ // TODO - there's no call to slap four flags onto every package.
+ final val PackageFlags = TopLevelCreationFlags
+
+ // FINAL not included here due to possibility of object overriding.
+ // In fact, FINAL should not be attached regardless. We should be able
+ // to reconstruct whether an object was marked final in source.
+ final val ModuleFlags = MODULE
+
/** These modifiers can be set explicitly in source programs. This is
* used only as the basis for the default flag mask (which ones to display
* when printing a normal message.)
*/
- final val ExplicitFlags: Long =
+ final val ExplicitFlags =
PRIVATE | PROTECTED | ABSTRACT | FINAL | SEALED |
OVERRIDE | CASE | IMPLICIT | ABSOVERRIDE | LAZY
- /** These modifiers appear in TreePrinter output. */
- final val PrintableFlags: Long =
- ExplicitFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO |
- ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | BRIDGE | STATIC | VBRIDGE | SPECIALIZED | SYNCHRONIZED
-
/** The two bridge flags */
final val BridgeFlags = BRIDGE | VBRIDGE
final val BridgeAndPrivateFlags = BridgeFlags | PRIVATE
+ /** These modifiers appear in TreePrinter output. */
+ final val PrintableFlags =
+ ExplicitFlags | BridgeFlags | LOCAL | SYNTHETIC | STABLE | CASEACCESSOR | MACRO |
+ ACCESSOR | SUPERACCESSOR | PARAMACCESSOR | STATIC | SPECIALIZED | SYNCHRONIZED
+
/** When a symbol for a field is created, only these flags survive
* from Modifiers. Others which may be applied at creation time are:
* PRIVATE, LOCAL.
*/
- final val FieldFlags: Long =
+ final val FieldFlags =
MUTABLE | CASEACCESSOR | PARAMACCESSOR | STATIC | FINAL | PRESUPER | LAZY
/** Masks for getters and setters, where the flags are derived from those
@@ -245,26 +260,25 @@ class Flags extends ModifierFlags {
/** When a symbol for a default getter is created, it inherits these
* flags from the method with the default. Other flags applied at creation
- * time are SYNTHETIC, DEFAULTPARAM, and possibly OVERRIDE.
+ * time are SYNTHETIC, DEFAULTPARAM, and possibly OVERRIDE, and maybe PRESUPER.
*/
- final val DefaultGetterFlags: Long =
- PRIVATE | PROTECTED | FINAL
+ final val DefaultGetterFlags = PRIVATE | PROTECTED | FINAL
/** When a symbol for a method parameter is created, only these flags survive
* from Modifiers. Others which may be applied at creation time are:
* SYNTHETIC.
*/
- final val ValueParameterFlags: Long = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM
- final val BeanPropertyFlags = DEFERRED | OVERRIDE | STATIC
- final val VarianceFlags = COVARIANT | CONTRAVARIANT
+ final val ValueParameterFlags = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM
+ final val BeanPropertyFlags = DEFERRED | OVERRIDE | STATIC
+ final val VarianceFlags = COVARIANT | CONTRAVARIANT
/** These appear to be flags which should be transferred from owner symbol
* to a newly created constructor symbol.
*/
- final val ConstrFlags: Long = JAVA
+ final val ConstrFlags = JAVA
/** Module flags inherited by their module-class */
- final val ModuleToClassFlags: Long = AccessFlags | MODULE | PACKAGE | CASE | SYNTHETIC | JAVA | FINAL
+ final val ModuleToClassFlags = AccessFlags | TopLevelCreationFlags | CASE | SYNTHETIC
def getterFlags(fieldFlags: Long): Long = ACCESSOR + (
if ((fieldFlags & MUTABLE) != 0) fieldFlags & ~MUTABLE & ~PRESUPER
@@ -294,7 +308,7 @@ class Flags extends ModifierFlags {
private final val PKL_MASK = 0x00000FFF
- final val PickledFlags: Long = 0xFFFFFFFFL
+ final val PickledFlags = 0xFFFFFFFFL
private def rawPickledCorrespondence = Array(
(IMPLICIT, IMPLICIT_PKL),
@@ -406,32 +420,28 @@ class Flags extends ModifierFlags {
case 0x8000000000000000L => "" // (1L << 63)
case _ => ""
}
-
+
+ private def accessString(flags: Long, privateWithin: String)= (
+ if (privateWithin == "") {
+ if ((flags & PrivateLocal) == PrivateLocal) "private[this]"
+ else if ((flags & ProtectedLocal) == ProtectedLocal) "protected[this]"
+ else if ((flags & PRIVATE) != 0) "private"
+ else if ((flags & PROTECTED) != 0) "protected"
+ else ""
+ }
+ else if ((flags & PROTECTED) != 0) "protected[" + privateWithin + "]"
+ else "private[" + privateWithin + "]"
+ )
+
+ @deprecated("Use flagString on the flag-carrying member", "2.10.0")
def flagsToString(flags: Long, privateWithin: String): String = {
- var f = flags
- val pw =
- if (privateWithin == "") {
- if ((flags & PrivateLocal) == PrivateLocal) {
- f &= ~PrivateLocal
- "private[this]"
- } else if ((flags & ProtectedLocal) == ProtectedLocal) {
- f &= ~ProtectedLocal
- "protected[this]"
- } else {
- ""
- }
- } else if ((f & PROTECTED) != 0L) {
- f &= ~PROTECTED
- "protected[" + privateWithin + "]"
- } else {
- "private[" + privateWithin + "]"
- }
- List(flagsToString(f), pw) filterNot (_ == "") mkString " "
- }
+ val access = accessString(flags, privateWithin)
+ val nonAccess = flagsToString(flags & ~AccessFlags)
- // List of the raw flags, in pickled order
- protected final val MaxBitPosition = 62
+ List(nonAccess, access) filterNot (_ == "") mkString " "
+ }
+ @deprecated("Use flagString on the flag-carrying member", "2.10.0")
def flagsToString(flags: Long): String = {
// Fast path for common case
if (flags == 0L) "" else {
@@ -459,13 +469,16 @@ class Flags extends ModifierFlags {
def pickledToRawFlags(pflags: Long): Long =
(pflags & ~PKL_MASK) | p2r(pflags.toInt & PKL_MASK)
- protected final val pickledListOrder: List[Long] = {
+ // List of the raw flags, in pickled order
+ final val MaxBitPosition = 62
+
+ final val pickledListOrder: List[Long] = {
val all = 0 to MaxBitPosition map (1L << _)
val front = rawFlags map (_.toLong)
front.toList ++ (all filterNot (front contains _))
}
- protected final val rawFlagPickledOrder: Array[Long] = pickledListOrder.toArray
+ final val rawFlagPickledOrder: Array[Long] = pickledListOrder.toArray
def flagOfModifier(mod: Modifier): Long = mod match {
case Modifier.`protected` => PROTECTED
diff --git a/src/compiler/scala/reflect/internal/FreeVars.scala b/src/compiler/scala/reflect/internal/FreeVars.scala
new file mode 100644
index 0000000000..8b6e8b61f3
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/FreeVars.scala
@@ -0,0 +1,60 @@
+package scala.reflect
+package internal
+
+trait FreeVars extends api.FreeVars {
+ self: SymbolTable =>
+
+ object FreeTerm extends FreeTermExtractor {
+ def unapply(freeTerm: FreeTerm): Option[(TermName, Type, Any, String)] =
+ Some(freeTerm.name, freeTerm.info, freeTerm.value, freeTerm.origin)
+ }
+
+ object FreeType extends FreeTypeExtractor {
+ def unapply(freeType: FreeType): Option[(TypeName, Type, String)] =
+ Some(freeType.name, freeType.info, freeType.origin)
+ }
+
+ // [Eugene] am I doing this right?
+ def freeTerms(tree: Tree): List[FreeTerm] = {
+ def isFreeTermSym(sym: Symbol) = sym != null && sym.isFreeTerm
+ def isFreeTermTpe(t: Type) = t != null && isFreeTermSym(t.termSymbol)
+
+ val buf = collection.mutable.Set[Symbol]()
+ tree foreach (sub => {
+ if (sub.tpe != null) buf ++= (sub.tpe collect { case tpe if isFreeTermTpe(tpe) => tpe.typeSymbol })
+ if (sub.symbol != null && isFreeTermSym(sub.symbol)) buf += sub.symbol
+ })
+
+ buf.toList.collect{ case fty: FreeTerm => fty }
+ }
+
+ // [Eugene] am I doing this right?
+ def freeTypes(tree: Tree): List[FreeType] = {
+ def isFreeTypeSym(sym: Symbol) = sym != null && sym.isFreeType
+ def isFreeTypeTpe(t: Type) = t != null && isFreeTypeSym(t.typeSymbol)
+
+ val buf = collection.mutable.Set[Symbol]()
+ tree foreach (sub => {
+ if (sub.tpe != null) buf ++= (sub.tpe collect { case tpe if isFreeTypeTpe(tpe) => tpe.typeSymbol })
+ if (sub.symbol != null && isFreeTypeSym(sub.symbol)) buf += sub.symbol
+ })
+
+ buf.toList.collect{ case fty: FreeType => fty }
+ }
+
+ // todo. also update tpe's of dependent free vars
+ // e.g. if we substitute free$C, then free$C$this should have its info updated
+ // todo. should also transform typetags of types dependent on that free type?
+ // [Eugene] how do I check that the substitution is legal w.r.t fty.info?
+ def substituteFreeTypes(tree0: Tree, subs: Map[FreeType, Type]): Tree = {
+ val tree = tree0.duplicate
+ new TreeTypeSubstituter(subs.keys.toList, subs.values.toList).traverse(tree)
+ tree
+ }
+
+ // [Eugene] how do I check that the substitution is legal w.r.t fty.info?
+ def substituteFreeTypes(tpe0: Type, subs: Map[FreeType, Type]): Type = {
+ val tpe = tpe0 // [Eugene] tpe0.duplicate?
+ tpe.subst(subs.keys.toList, subs.values.toList)
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/internal/FrontEnds.scala b/src/compiler/scala/reflect/internal/FrontEnds.scala
new file mode 100644
index 0000000000..74501c7686
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/FrontEnds.scala
@@ -0,0 +1,75 @@
+package scala.reflect
+package internal
+
+trait FrontEnds { self: SymbolTable =>
+
+ import scala.tools.nsc.reporters._
+ import scala.tools.nsc.Settings
+
+ def mkConsoleFrontEnd(minSeverity: Int = 1): FrontEnd = {
+ val settings = new Settings()
+ if (minSeverity <= 0) settings.verbose.value = true
+ if (minSeverity > 1) settings.nowarn.value = true
+ wrapReporter(new ConsoleReporter(settings))
+ }
+
+ abstract class FrontEndToReporterProxy(val frontEnd: FrontEnd) extends AbstractReporter {
+ import frontEnd.{Severity => ApiSeverity}
+ val API_INFO = frontEnd.INFO
+ val API_WARNING = frontEnd.WARNING
+ val API_ERROR = frontEnd.ERROR
+
+ type NscSeverity = Severity
+ val NSC_INFO = INFO
+ val NSC_WARNING = WARNING
+ val NSC_ERROR = ERROR
+
+ def display(pos: Position, msg: String, nscSeverity: NscSeverity): Unit =
+ frontEnd.log(pos, msg, nscSeverity match {
+ case NSC_INFO => API_INFO
+ case NSC_WARNING => API_WARNING
+ case NSC_ERROR => API_ERROR
+ })
+
+ def displayPrompt(): Unit =
+ frontEnd.interactive()
+ }
+
+ def wrapFrontEnd(frontEnd: FrontEnd): Reporter = new FrontEndToReporterProxy(frontEnd) {
+ val settings = new Settings()
+ settings.verbose.value = true
+ settings.nowarn.value = false
+ }
+
+ class ReporterToFrontEndProxy(val reporter: Reporter) extends FrontEnd {
+ val API_INFO = INFO
+ val API_WARNING = WARNING
+ val API_ERROR = ERROR
+
+ override def hasErrors = reporter.hasErrors
+ override def hasWarnings = reporter.hasWarnings
+
+ def display(info: Info): Unit = info.severity match {
+ case API_INFO => reporter.info(info.pos, info.msg, false)
+ case API_WARNING => reporter.warning(info.pos, info.msg)
+ case API_ERROR => reporter.error(info.pos, info.msg)
+ }
+
+ def interactive(): Unit = reporter match {
+ case reporter: AbstractReporter => reporter.displayPrompt()
+ case _ => // do nothing
+ }
+
+ override def flush(): Unit = {
+ super.flush()
+ reporter.flush()
+ }
+
+ override def reset(): Unit = {
+ super.reset()
+ reporter.reset()
+ }
+ }
+
+ def wrapReporter(reporter: Reporter): FrontEnd = new ReporterToFrontEndProxy(reporter)
+}
diff --git a/src/compiler/scala/reflect/internal/HasFlags.scala b/src/compiler/scala/reflect/internal/HasFlags.scala
index 8affd66cd5..348f81c51d 100644
--- a/src/compiler/scala/reflect/internal/HasFlags.scala
+++ b/src/compiler/scala/reflect/internal/HasFlags.scala
@@ -1,83 +1,12 @@
package scala.reflect
package internal
-/** ISSUE #1: Flag names vs. Test method names
- *
- * The following methods from Symbol have a name of
- * the form isFoo where FOO is the name of a flag, but where the method
- * body tests for more than whether the flag is set.
- *
- * There are two possibilities with such methods. Either the extra
- * tests are strictly to partition among overloaded flags (which is
- * the case we can live with in the short term, if each such flag's
- * partitioning assumptions are documented) or they aren't.
- *
- * The second case implies that "x hasFlag FOO" and "x.isFoo" have
- * different semantics, and this we can't live with, because even if
- * we're smart enough to avoid being tripped up by that, the next guy isn't.
- *
- * No extreme measures necessary, only renaming isFoo to something
- * which hews more closely to its implementation. (Or renaming the flag.)
- *
- // Defined in the compiler Symbol
- //
- final def isLabel = isMethod && !hasAccessorFlag && hasFlag(LABEL)
- final def isLocal: Boolean = owner.isTerm
- final def isModuleVar: Boolean = isVariable && hasFlag(MODULEVAR)
- final def isStable =
- isTerm &&
- !hasTraitFlag &&
- (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) &&
- !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
- final def isStatic: Boolean =
- hasFlag(STATIC) || isRoot || owner.isStaticOwner
- override final def isTrait: Boolean =
- isClass && hasFlag(TRAIT | notDEFERRED) // A virtual class becomes a trait (part of DEVIRTUALIZE)
-
- // Defined in the library Symbol
- //
- def isTrait: Boolean = isClass && hasFlag(TRAIT) // refined later for virtual classes.
- final def isContravariant = isType && hasFlag(CONTRAVARIANT)
- final def isCovariant = isType && hasFlag(COVARIANT)
- final def isMethod = isTerm && hasFlag(METHOD)
- final def isModule = isTerm && hasFlag(MODULE)
- final def isPackage = isModule && hasFlag(PACKAGE)
- *
- */
-
-/** ISSUE #2: Implicit flag relationships must be made explicit.
- *
- * For instance, every time the MODULE flag is set, the FINAL flag is
- * set along with it:
- *
- .setFlag(FINAL | MODULE | PACKAGE | JAVA)
- .setFlag(FINAL | MODULE | PACKAGE | JAVA).setInfo(rootLoader)
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- val m = new ModuleSymbol(this, pos, name).setFlag(MODULE | FINAL)
- setFlag(module.getFlag(ModuleToClassFlags) | MODULE | FINAL)
- sourceModule.flags = MODULE | FINAL
-
- * However the same is not true of when the MODULE flag is cleared:
-
- sym.resetFlag(MODULE)
- .setFlag(sym.flags | STABLE).resetFlag(MODULE)
- sym.resetFlag(MODULE | FINAL | CASE)
-
- * It's not relevant whether this example poses any issues: we must
- * not tolerate these uncertainties. If the flags are to move together
- * then both setting and clearing have to be encapsulated. If there
- * is a useful and used distinction between the various permutations
- * of on and off, then it must be documented. It's the only way!
- */
-
import Flags._
/** Common code utilized by Modifiers (which carry the flags associated
* with Trees) and Symbol.
*/
trait HasFlags {
- type FlagsType
type AccessBoundaryType
type AnnotationType
@@ -86,12 +15,7 @@ trait HasFlags {
* flag methods through accessors and disallow raw flag manipulation.
* And after that, perhaps, on some magical day: a typesafe enumeration.
*/
- protected def flags: FlagsType
-
- /** The printable representation of this entity's flags and access boundary,
- * restricted to flags in the given mask.
- */
- def hasFlagsToString(mask: FlagsType): String
+ protected def flags: Long
/** Access level encoding: there are three scala flags (PRIVATE, PROTECTED,
* and LOCAL) which combine with value privateWithin (the "foo" in private[foo])
@@ -137,6 +61,23 @@ trait HasFlags {
*/
def hasNoFlags(mask: Long): Boolean = !hasFlag(mask)
+ /** The printable representation of this entity's flags and access boundary,
+ * restricted to flags in the given mask.
+ */
+ def flagString: String = flagString(flagMask)
+ def flagString(mask: Long): String = calculateFlagString(flags & mask)
+
+ /** The default mask determining which flags to display.
+ */
+ def flagMask: Long = AllFlags
+
+ /** The string representation of a single bit, seen from this
+ * flag carrying entity.
+ */
+ def resolveOverloadedFlag(flag: Long): String = Flags.flagToString(flag)
+
+ def privateWithinString = if (hasAccessBoundary) privateWithin.toString else ""
+
protected def isSetting(f: Long, mask: Long) = !hasFlag(f) && ((mask & f) != 0L)
protected def isClearing(f: Long, mask: Long) = hasFlag(f) && ((mask & f) != 0L)
@@ -165,26 +106,20 @@ trait HasFlags {
// which must have been a bug.
def isPublic = hasNoFlags(PRIVATE | PROTECTED) && !hasAccessBoundary
- // Renamed the Modifiers impl from isArgument.
- def isParameter = hasFlag(PARAM)
-
// Removed isClass qualification since the flag isn't overloaded and
// sym.isClass is enforced in Namers#validate.
def isSealed = hasFlag(SEALED)
// Removed !isClass qualification since the flag isn't overloaded.
- def isDeferred = hasFlag(DEFERRED )
+ def isDeferred = hasFlag(DEFERRED)
// Dropped isTerm condition because flag isn't overloaded.
def isAbstractOverride = hasFlag(ABSOVERRIDE)
def isAnyOverride = hasFlag(OVERRIDE | ABSOVERRIDE)
- def isDefaultInit = hasFlag(DEFAULTINIT)
// Disambiguating: DEFAULTPARAM, TRAIT
def hasDefault = hasAllFlags(DEFAULTPARAM | PARAM)
def isTrait = hasFlag(TRAIT) && !hasFlag(PARAM)
- def hasTraitFlag = hasFlag(TRAIT)
- def hasDefaultFlag = hasFlag(DEFAULTPARAM)
// Straightforwardly named accessors already being used differently.
// These names are most likely temporary.
@@ -193,16 +128,9 @@ trait HasFlags {
def hasLocalFlag = hasFlag(LOCAL)
def hasModuleFlag = hasFlag(MODULE)
def hasPackageFlag = hasFlag(PACKAGE)
- def hasPreSuperFlag = hasFlag(PRESUPER)
def hasStableFlag = hasFlag(STABLE)
def hasStaticFlag = hasFlag(STATIC)
- // Disambiguating: BYNAMEPARAM, CAPTURED, COVARIANT.
- def isByNameParam = hasAllFlags(BYNAMEPARAM | PARAM)
- // Nope, these aren't going to fly:
- // def isCapturedVariable = hasAllFlags(CAPTURED | MUTABLE)
- // def isCovariant = hasFlag(COVARIANT) && hasNoFlags(PARAM | MUTABLE)
-
// Disambiguating: LABEL, CONTRAVARIANT, INCONSTRUCTOR
def isLabel = hasAllFlags(LABEL | METHOD) && !hasAccessorFlag
// Cannot effectively disambiguate the others at this level.
@@ -212,23 +140,60 @@ trait HasFlags {
// Name
def isJavaDefined = hasFlag(JAVA)
- // Keeping some potentially ambiguous names around so as not to break
- // the rest of the world
+ def flagBitsToString(bits: Long): String = {
+ // Fast path for common case
+ if (bits == 0L) "" else {
+ var sb: StringBuilder = null
+ var i = 0
+ while (i <= MaxBitPosition) {
+ val flag = Flags.rawFlagPickledOrder(i)
+ if ((bits & flag) != 0L) {
+ val s = resolveOverloadedFlag(flag)
+ if (s.length > 0) {
+ if (sb eq null) sb = new StringBuilder append s
+ else if (sb.length == 0) sb append s
+ else sb append " " append s
+ }
+ }
+ i += 1
+ }
+ if (sb eq null) "" else sb.toString
+ }
+ }
+
+ def accessString: String = {
+ val pw = privateWithinString
+
+ if (pw == "") {
+ if (hasAllFlags(PrivateLocal)) "private[this]"
+ else if (hasAllFlags(ProtectedLocal)) "protected[this]"
+ else if (hasFlag(PRIVATE)) "private"
+ else if (hasFlag(PROTECTED)) "protected"
+ else ""
+ }
+ else if (hasFlag(PROTECTED)) "protected[" + pw + "]"
+ else "private[" + pw + "]"
+ }
+ protected def calculateFlagString(basis: Long): String = {
+ val access = accessString
+ val nonAccess = flagBitsToString(basis & ~AccessFlags)
+
+ if (access == "") nonAccess
+ else if (nonAccess == "") access
+ else nonAccess + " " + access
+ }
+
+ // Backward compat section
+ @deprecated( "Use isTrait", "2.10.0")
+ def hasTraitFlag = hasFlag(TRAIT)
+ @deprecated("Use hasDefault", "2.10.0")
+ def hasDefaultFlag = hasFlag(DEFAULTPARAM)
@deprecated("", "2.9.0")
def isAbstract = hasFlag(ABSTRACT)
- // Problematic:
- // ABSTRACT and DEFERRED too easy to confuse, and
- // ABSTRACT + OVERRIDE ==> ABSOVERRIDE adds to it.
- //
- // final def isAbstractClass = isClass && hasFlag(ABSTRACT)
- // def isAbstractType = false // to be overridden
-
- // Question:
- // Which name? All other flags are isFlag so it's probably a mistake to
- // vary from that, but isAccessor does sound like it includes the other
- // *ACCESSOR flags. Perhaps something like isSimpleAccessor.
- //
- // def isAccessor = hasFlag(ACCESSOR )
- // final def isGetterOrSetter = hasAccessorFlag
+ @deprecated("Use isValueParameter or isTypeParameter", "2.10.0")
+ def isParameter = hasFlag(PARAM)
+ @deprecated("Use flagString", "2.10.0")
+ def defaultFlagString = flagString
+ @deprecated("Use flagString(mask)", "2.10.0")
+ def hasFlagsToString(mask: Long): String = flagString(mask)
}
-
diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala
index 04381937d1..6d6a0ec317 100644
--- a/src/compiler/scala/reflect/internal/Importers.scala
+++ b/src/compiler/scala/reflect/internal/Importers.scala
@@ -4,7 +4,24 @@ import scala.collection.mutable.WeakHashMap
trait Importers { self: SymbolTable =>
- abstract class Importer {
+ // [Eugene] possible to make this less cast-heavy?
+ def mkImporter(from0: api.Universe): Importer { val from: from0.type } = (
+ if (self eq from0) {
+ new Importer {
+ val from = from0
+ val reverse = this.asInstanceOf[from.Importer{ val from: self.type }]
+ def importSymbol(sym: from.Symbol) = sym.asInstanceOf[self.Symbol]
+ def importType(tpe: from.Type) = tpe.asInstanceOf[self.Type]
+ def importTree(tree: from.Tree) = tree.asInstanceOf[self.Tree]
+ }
+ } else {
+ // todo. fix this loophole
+ assert(from0.isInstanceOf[SymbolTable], "`from` should be an instance of scala.reflect.internal.SymbolTable")
+ new StandardImporter { val from = from0.asInstanceOf[SymbolTable] }
+ }
+ ).asInstanceOf[Importer { val from: from0.type }]
+
+ abstract class StandardImporter extends Importer {
val from: SymbolTable
@@ -24,13 +41,15 @@ trait Importers { self: SymbolTable =>
}
}
- object reverse extends from.Importer {
+ object reverse extends from.StandardImporter {
val from: self.type = self
- for ((fromsym, mysym) <- Importer.this.symMap) symMap += ((mysym, fromsym))
- for ((fromtpe, mytpe) <- Importer.this.tpeMap) tpeMap += ((mytpe, fromtpe))
+ for ((fromsym, mysym) <- StandardImporter.this.symMap) symMap += ((mysym, fromsym))
+ for ((fromtpe, mytpe) <- StandardImporter.this.tpeMap) tpeMap += ((mytpe, fromtpe))
}
- def importPosition(pos: from.Position): Position = NoPosition
+ // todo. careful import of positions
+ def importPosition(pos: from.Position): Position =
+ pos.asInstanceOf[Position]
def importSymbol(sym0: from.Symbol): Symbol = {
def doImport(sym: from.Symbol): Symbol = {
@@ -51,8 +70,10 @@ trait Importers { self: SymbolTable =>
linkReferenced(myowner.newMethod(myname, mypos, myflags), x, importSymbol)
case x: from.ModuleSymbol =>
linkReferenced(myowner.newModuleSymbol(myname, mypos, myflags), x, importSymbol)
- case x: from.FreeVar =>
- newFreeVar(importName(x.name).toTermName, importType(x.tpe), x.value, myflags)
+ case x: from.FreeTerm =>
+ newFreeTermSymbol(importName(x.name).toTermName, importType(x.info), x.value, x.flags, x.origin)
+ case x: from.FreeType =>
+ newFreeTypeSymbol(importName(x.name).toTypeName, importType(x.info), x.value, x.flags, x.origin)
case x: from.TermSymbol =>
linkReferenced(myowner.newValue(myname, mypos, myflags), x, importSymbol)
case x: from.TypeSkolem =>
@@ -63,7 +84,7 @@ trait Importers { self: SymbolTable =>
}
myowner.newTypeSkolemSymbol(myname.toTypeName, origin, mypos, myflags)
case x: from.ModuleClassSymbol =>
- val mysym = myowner.newModuleClassSymbol(myname.toTypeName, mypos, myflags)
+ val mysym = myowner.newModuleClass(myname.toTypeName, mypos, myflags)
symMap(x) = mysym
mysym.sourceModule = importSymbol(x.sourceModule)
mysym
@@ -72,7 +93,7 @@ trait Importers { self: SymbolTable =>
symMap(x) = mysym
if (sym.thisSym != sym) {
mysym.typeOfThis = importType(sym.typeOfThis)
- mysym.thisSym.name = importName(sym.thisSym.name)
+ mysym.thisSym setName importName(sym.thisSym.name)
}
mysym
case x: from.TypeSymbol =>
@@ -109,14 +130,18 @@ trait Importers { self: SymbolTable =>
val owner = sym.owner
var scope = if (owner.isClass && !owner.isRefinementClass) owner.info else from.NoType
var existing = scope.decl(name)
- if (sym.isPackageClass || sym.isModuleClass) existing = existing.moduleClass
+ if (sym.isModuleClass)
+ existing = existing.moduleClass
+
if (!existing.exists) scope = from.NoType
val myname = importName(name)
val myowner = importSymbol(owner)
val myscope = if (scope != from.NoType && !(myowner hasFlag Flags.LOCKED)) myowner.info else NoType
var myexisting = if (myscope != NoType) myowner.info.decl(myname) else NoSymbol // cannot load myexisting in general case, because it creates cycles for methods
- if (sym.isPackageClass || sym.isModuleClass) myexisting = importSymbol(sym.sourceModule).moduleClass
+ if (sym.isModuleClass)
+ myexisting = importSymbol(sym.sourceModule).moduleClass
+
if (!sym.isOverloaded && myexisting.isOverloaded) {
myexisting =
if (sym.isMethod) {
@@ -301,7 +326,7 @@ trait Importers { self: SymbolTable =>
case from.ValDef(mods, name, tpt, rhs) =>
new ValDef(importModifiers(mods), importName(name).toTermName, importTree(tpt), importTree(rhs))
case from.DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- new DefDef(importModifiers(mods), importName(name).toTermName, tparams map importTypeDef, vparamss map (_ map importValDef), importTree(tpt), importTree(rhs))
+ new DefDef(importModifiers(mods), importName(name).toTermName, tparams map importTypeDef, mmap(vparamss)(importValDef), importTree(tpt), importTree(rhs))
case from.TypeDef(mods, name, tparams, rhs) =>
new TypeDef(importModifiers(mods), importName(name).toTypeName, tparams map importTypeDef, importTree(rhs))
case from.LabelDef(name, params, rhs) =>
@@ -364,12 +389,10 @@ trait Importers { self: SymbolTable =>
new This(importName(qual).toTypeName)
case from.Select(qual, name) =>
new Select(importTree(qual), importName(name))
- case from.Ident(name) => tree match {
- case _: from.BackQuotedIdent =>
- new BackQuotedIdent(importName(name))
- case _ =>
- new Ident(importName(name))
- }
+ case from.Ident(name) =>
+ new Ident(importName(name))
+ case from.ReferenceToBoxed(ident) =>
+ new ReferenceToBoxed(importTree(ident) match { case ident: Ident => ident })
case from.Literal(constant @ from.Constant(_)) =>
new Literal(importConstant(constant))
case from.TypeTree() =>
@@ -421,7 +444,7 @@ trait Importers { self: SymbolTable =>
def importIdent(tree: from.Ident): Ident = importTree(tree).asInstanceOf[Ident]
def importCaseDef(tree: from.CaseDef): CaseDef = importTree(tree).asInstanceOf[CaseDef]
def importConstant(constant: from.Constant): Constant = new Constant(constant.tag match {
- case ClassTag => importType(constant.value.asInstanceOf[from.Type])
+ case ClazzTag => importType(constant.value.asInstanceOf[from.Type])
case EnumTag => importSymbol(constant.value.asInstanceOf[from.Symbol])
case _ => constant.value
})
diff --git a/src/compiler/scala/reflect/internal/JvmClassInfo.scala b/src/compiler/scala/reflect/internal/JvmClassInfo.scala
new file mode 100644
index 0000000000..80d868f666
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/JvmClassInfo.scala
@@ -0,0 +1,220 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect.internal
+
+import java.io.{ DataInput, InputStream, DataInputStream, ByteArrayInputStream, BufferedInputStream, FileInputStream }
+import scala.tools.nsc.io.{ Directory }
+import scala.reflect.NameTransformer.decode
+import scala.tools.util.StringOps.trimTrailingSpace
+import ConstantPool._
+import ClassfileConstants._
+
+abstract class JvmInfo(attributes: Array[JvmAttributeInfo]) {
+ // def flags: Short
+ def name: String
+
+ val signature = attributes collectFirst { case x: SignatureAttr => x.value } getOrElse ""
+ val innerClasses = attributes collectFirst { case x: InnerClassesAttr => x.value } getOrElse Array()
+}
+abstract class JvmAttributeInfo {
+ // attribute_info {
+ // u2 attribute_name_index;
+ // u4 attribute_length;
+ // u1 info[attribute_length];
+ // }
+ def name: String
+ def value: Any
+}
+
+class JvmClassInfo(
+ val name: String,
+ val superName: String,
+ val interfaces: Array[String],
+ val fields: Array[JvmMemberInfo],
+ val methods: Array[JvmMemberInfo],
+ attributes: Array[JvmAttributeInfo]
+) extends JvmInfo(attributes) {
+
+ def members = fields ++ methods sortBy (_.decodedName)
+ def memberDescriptors = members map (_.toErasedString)
+ def memberSignatures = members filter (_.hasSignature) map (_.toGenericString)
+ def descriptorsString = if (memberDescriptors.nonEmpty) memberDescriptors.mkString("\n-- Member Descriptors --\n", "\n", "\n") else ""
+ def signaturesString = if (memberSignatures.nonEmpty) memberSignatures.mkString("\n-- Member Signatures --\n", "\n", "\n") else ""
+ def innersString = if (innerClasses.isEmpty) "" else innerClasses.mkString("\n-- Inner Classes --\n", "\n", "\n")
+ def membersString = descriptorsString + signaturesString
+ def extendsString = if (superName == "") "" else " extends " + superName
+ def implementsString = if (interfaces.isEmpty) "" else interfaces.mkString("Implements: ", ", ", "")
+
+ private def group(label: String, xs: Traversable[(String, String)]) =
+ xs map { case (name, value) => line(label, name, value) } mkString "\n"
+
+ private def line(label: String, name: String, data: String) =
+ trimTrailingSpace(" %-15s %30s %s".format(label, name, data))
+
+ override def toString = (
+ List(
+ "class " + name + extendsString,
+ if (signature == "") "" else line("class sig", "", signature),
+ group("interface", interfaces map (x => (("", x)))),
+ (innerClasses map (ic => line(ic.kind, ic.innerName, ic.nestString))).sorted.mkString("\n"),
+ group("descriptor", members map (x => (x.name, x.descriptor))),
+ group("signature", members filter (_.hasSignature) map (x => (x.name, x.signature)))
+ ) map trimTrailingSpace filterNot (_ == "") mkString ("", "\n", "\n")
+ )
+}
+
+// method_info or field_info {
+// u2 access_flags;
+// u2 name_index;
+// u2 descriptor_index;
+// u2 attributes_count;
+// attribute_info attributes[attributes_count];
+// }
+class JvmMemberInfo(
+ val flags: Short,
+ val name: String,
+ val descriptor: String,
+ attributes: Array[JvmAttributeInfo]
+) extends JvmInfo(attributes) {
+
+ final def isAbstract = (flags & JAVA_ACC_ABSTRACT) != 0
+ final def isAnnotated = (flags & JAVA_ACC_ANNOTATION) != 0
+ final def isFinal = (flags & JAVA_ACC_FINAL) != 0
+ final def isPrivate = (flags & JAVA_ACC_PRIVATE) != 0
+ final def isProtected = (flags & JAVA_ACC_PROTECTED) != 0
+ final def isPublic = (flags & JAVA_ACC_PUBLIC) != 0
+ final def isStatic = (flags & JAVA_ACC_STATIC) != 0
+ final def isSynthetic = (flags & JAVA_ACC_SYNTHETIC) != 0
+ final def isVarargs = (flags & JAVA_ACC_VARARGS) != 0
+
+ // method only
+ final def isBridge = (flags & JAVA_ACC_BRIDGE) != 0
+
+ // field only
+ final def isEnum = (flags & JAVA_ACC_ENUM) != 0
+ final def isTransient = (flags & JAVA_ACC_TRANSIENT) != 0
+
+ def isMethod = descriptor startsWith "(" // )
+ def isField = !isMethod
+ def scalaFlags = toScalaMethodFlags(flags)
+ def decodedName = decode(name)
+ def hasSignature = signature != ""
+ def toErasedString = "%-30s %s".format(decodedName, descriptor)
+ def toGenericString = "%-30s %s".format(decodedName, signature)
+
+ override def toString = (
+ if (hasSignature) toGenericString else toErasedString
+ )
+}
+class GenericAttr(val name: String, val value: Array[Byte]) extends JvmAttributeInfo { }
+class SignatureAttr(val value: String) extends JvmAttributeInfo { def name = "Signature" }
+class InnerClassesAttr(val value: Array[JvmInnerClassInfo]) extends JvmAttributeInfo { def name = "InnerClasses" }
+
+// package foo { class Foo { class Bar } }
+//
+// javap would say
+// Bar = class foo.Foo$Bar of class foo.Foo
+// which is translated as
+// innerClass = foo.Foo$Bar
+// outerClass = foo.Foo
+// innerName = Bar
+
+class JvmInnerClassInfo(
+ thisClass: String, // classfile which is being parsed
+ val innerClass: String, // the full name of the inner/nested class
+ val outerClass: String, // the full name of the outer class - must be a prefix of innerClass
+ val innerName: String, // the simple name of the inner class - should (?) be a suffix of innerClass
+ val flags: Short // flags
+) {
+ val isEntryOfEnclosingClass = !isAnonymousClass && (innerClass == thisClass)
+ val isEntryOfNestedClass = !isAnonymousClass && (outerClass == thisClass)
+
+ def isTopLevelClass = outerClass == ""
+ def isAnonymousClass = innerName == ""
+ def isMemberClass = !isTopLevelClass
+
+ def kind = (
+ if (isEntryOfEnclosingClass) "inner/enclosing"
+ else if (isEntryOfNestedClass) "inner/nested"
+ else if (isAnonymousClass) "inner/anon"
+ else "inner"
+ )
+ def nestString = (
+ if (isEntryOfEnclosingClass) "enclosing class: " + outerClass
+ else if (isEntryOfNestedClass) "member class: " + innerClass
+ else if (isAnonymousClass) "anonymous class: " + innerClass
+ else innerClass + " in " + outerClass
+ )
+ override def toString = innerName + "=" + nestString
+}
+
+object JvmClassInfo {
+ class Builder(protected[this] val in: DataInput) extends ScalacClassfileModel {
+ def readInterface(): InterfaceInfo = nameAt(u2)
+ def readMember(): JvmMemberInfo = new JvmMemberInfo(u2.toShort, stringAt(u2), stringAt(u2), readAttributes())
+ def readInnerClass(): JvmInnerClassInfo = new JvmInnerClassInfo(thisClass, nameAt(u2), nameAt(u2), stringAt(u2), u2.toShort)
+
+ def readConstantPoolEntry(): Entry = (u1: @annotation.switch) match {
+ case CONSTANT_Utf8 => new Utf8_info(in.readUTF)
+ case CONSTANT_Integer => new Integer_info(in.readInt)
+ case CONSTANT_Float => new Float_info(in.readFloat)
+ case CONSTANT_Long => new Long_info(in.readLong)
+ case CONSTANT_Double => new Double_info(in.readDouble)
+ case CONSTANT_Class => new Class_info(u2)
+ case CONSTANT_String => new String_info(u2)
+ case CONSTANT_Fieldref => new Fieldref_info(u2, u2)
+ case CONSTANT_Methodref => new Methodref_info(u2, u2)
+ case CONSTANT_InterfaceMethodref => new InterfaceMethodref_info(u2, u2)
+ case CONSTANT_NameAndType => new NameAndType_info(u2, u2)
+ }
+
+ // field_info attributes:
+ // ConstantValue (§4.7.2), Synthetic (§4.7.8), Signature (§4.7.9), Deprecated (§4.7.15),
+ // RuntimeVisibleAnnotations (§4.7.16) and RuntimeInvisibleAnnotations (§4.7.17).
+ //
+ // method_info attributes:
+ // Code (§4.7.3), Exceptions (§4.7.5), Synthetic (§4.7.8), Signature (§4.7.9), Deprecated (§4.7.15),
+ // RuntimeVisibleAnnotations (§4.7.16), RuntimeInvisibleAnnotations (§4.7.17), RuntimeVisibleParameterAnnotations (§4.7.18),
+ // RuntimeInvisibleParameterAnnotations (§4.7.19) and AnnotationDefault (§4.7.20).
+ def readAttribute(): AttributeInfo = {
+ val name = stringAt(u2)
+ val len = u4
+ name match {
+ case "Signature" => new SignatureAttr(stringAt(u2))
+ case "InnerClasses" => new InnerClassesAttr(readInnerClasses())
+ case name => val bytes = new Array[Byte](len) ; in.readFully(bytes) ; new GenericAttr(name, bytes)
+ }
+ }
+ }
+
+ private def classFiles(path: String) =
+ Directory(path).deepFiles filter (_ hasExtension "class")
+
+ def classInfoMap(path: String): Map[String, JvmClassInfo] = {
+ classFiles(path) map (f => (f.path, JvmClassInfo fromFile f.jfile)) toMap
+ }
+ def classInfoList(path: String): List[(String, JvmClassInfo)] = {
+ classInfoMap(path).toList sortBy (_._1)
+ }
+
+ def fromFile(file: java.io.File) =
+ fromStream(new BufferedInputStream(new FileInputStream(file)))
+
+ def fromBytes(bytes: Array[Byte]) =
+ fromStream(new ByteArrayInputStream(bytes))
+
+ def fromPath(path: String) =
+ fromStream(new BufferedInputStream(new FileInputStream(path)))
+
+ def fromStream(in0: InputStream) = {
+ val in = new DataInputStream(in0)
+ try fromDataInput(in) finally in.close()
+ }
+
+ def fromDataInput(in: DataInput): JvmClassInfo = {
+ new Builder(in) parse
+ }
+}
diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala
deleted file mode 100644
index 48f21721da..0000000000
--- a/src/compiler/scala/reflect/internal/NameManglers.scala
+++ /dev/null
@@ -1,212 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.reflect
-package internal
-
-import java.security.MessageDigest
-import scala.io.Codec
-import Chars.isOperatorPart
-
-/** A trait to encapsulate name mangling. It's intended for the
- * values and methods involved in assembling names out of other names,
- * and not for simple synthetically named locals.
- */
-trait NameManglers {
- self: SymbolTable =>
-
- trait NameManglingCommon {
- self: CommonNames =>
-
- val MODULE_SUFFIX_STRING = NameTransformer.MODULE_SUFFIX_STRING
- val NAME_JOIN_STRING = NameTransformer.NAME_JOIN_STRING
-
- val MODULE_SUFFIX_NAME: TermName = newTermName(MODULE_SUFFIX_STRING)
- val NAME_JOIN_NAME: TermName = newTermName(NAME_JOIN_STRING)
-
- def flattenedName(segments: Name*): NameType = compactedString(segments mkString NAME_JOIN_STRING)
-
- /**
- * COMPACTIFY
- *
- * The hashed name has the form (prefix + marker + md5 + marker + suffix), where
- * - prefix/suffix.length = MaxNameLength / 4
- * - md5.length = 32
- *
- * We obtain the formula:
- *
- * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6
- *
- * (+6 for ".class"). MaxNameLength can therefore be computed as follows:
- */
- private final val marker = "$$$$"
- private final val MaxNameLength = math.min(
- settings.maxClassfileName.value - 6,
- 2 * (settings.maxClassfileName.value - 6 - 2*marker.length - 32)
- )
- private lazy val md5 = MessageDigest.getInstance("MD5")
- private def toMD5(s: String, edge: Int) = {
- val prefix = s take edge
- val suffix = s takeRight edge
-
- val cs = s.toArray
- val bytes = Codec toUTF8 cs
- md5 update bytes
- val md5chars = md5.digest() map (b => (b & 0xFF).toHexString) mkString
-
- prefix + marker + md5chars + marker + suffix
- }
- private def compactedString(s: String) =
- if (s.length <= MaxNameLength) s
- else toMD5(s, MaxNameLength / 4)
- }
-
- trait TypeNameMangling extends NameManglingCommon {
- self: tpnme.type =>
-
- }
-
- trait TermNameMangling extends NameManglingCommon {
- self: nme.type =>
-
- val IMPL_CLASS_SUFFIX = "$class"
- val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
- val PROTECTED_PREFIX = "protected$"
- val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set"
- val SINGLETON_SUFFIX = ".type"
- val SUPER_PREFIX_STRING = "super$"
- val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
- val SETTER_SUFFIX: TermName = encode("_=")
-
- @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
- def SPECIALIZED_SUFFIX_STRING = SPECIALIZED_SUFFIX.toString
- @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
- def SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX.toTermName
-
- def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR
- def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX
- def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX
- def isLocalDummyName(name: Name) = name startsWith LOCALDUMMY_PREFIX
- def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING
- def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
- def isProtectedAccessorName(name: Name) = name startsWith PROTECTED_PREFIX
- def isSuperAccessorName(name: Name) = name startsWith SUPER_PREFIX_STRING
- def isReplWrapperName(name: Name) = name containsName INTERPRETER_IMPORT_WRAPPER
- def isSetterName(name: Name) = name endsWith SETTER_SUFFIX
- def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING)
- def isSingletonName(name: Name) = name endsWith SINGLETON_SUFFIX
- def isModuleName(name: Name) = name endsWith MODULE_SUFFIX_NAME
-
- def isOpAssignmentName(name: Name) = name match {
- case raw.NE | raw.LE | raw.GE | EMPTY => false
- case _ =>
- name.endChar == '=' && name.startChar != '=' && isOperatorPart(name.startChar)
- }
-
- /** The expanded setter name of `name` relative to this class `base`
- */
- def expandedSetterName(name: TermName, base: Symbol): TermName =
- expandedName(name, base, separator = TRAIT_SETTER_SEPARATOR_STRING)
-
- /** If `name` is an expandedName name, the original name.
- * Otherwise `name` itself.
- */
- def originalName(name: Name): Name = {
- var i = name.length
- while (i >= 2 && !(name(i - 1) == '$' && name(i - 2) == '$')) i -= 1
- if (i >= 2) {
- while (i >= 3 && name(i - 3) == '$') i -= 1
- name.subName(i, name.length)
- } else name
- }
-
- def unspecializedName(name: Name): Name = (
- if (name endsWith SPECIALIZED_SUFFIX)
- name.subName(0, name.lastIndexOf('m') - 1)
- else name
- )
-
- def macroMethodName(name: Name) = {
- val base = if (name.isTypeName) nme.TYPEkw else nme.DEFkw
- base append nme.MACRO append name
- }
-
- /** Return the original name and the types on which this name
- * is specialized. For example,
- * {{{
- * splitSpecializedName("foo$mIcD$sp") == ('foo', "I", "D")
- * }}}
- * `foo$mIcD$sp` is the name of a method specialized on two type
- * parameters, the first one belonging to the method itself, on Int,
- * and another one belonging to the enclosing class, on Double.
- */
- def splitSpecializedName(name: Name): (Name, String, String) =
- if (name endsWith SPECIALIZED_SUFFIX) {
- val name1 = name dropRight SPECIALIZED_SUFFIX.length
- val idxC = name1 lastIndexOf 'c'
- val idxM = name1 lastIndexOf 'm'
-
- (name1.subName(0, idxM - 1),
- name1.subName(idxC + 1, name1.length).toString,
- name1.subName(idxM + 1, idxC).toString)
- } else
- (name, "", "")
-
- def getterName(name: TermName): TermName = if (isLocalName(name)) localToGetter(name) else name
- def getterToLocal(name: TermName): TermName = name append LOCAL_SUFFIX_STRING
- def getterToSetter(name: TermName): TermName = name append SETTER_SUFFIX
- def localToGetter(name: TermName): TermName = name dropRight LOCAL_SUFFIX_STRING.length
-
- def dropLocalSuffix(name: Name): Name = if (name endsWith ' ') name dropRight 1 else name
-
- def setterToGetter(name: TermName): TermName = {
- val p = name.pos(TRAIT_SETTER_SEPARATOR_STRING)
- if (p < name.length)
- setterToGetter(name drop (p + TRAIT_SETTER_SEPARATOR_STRING.length))
- else
- name.subName(0, name.length - SETTER_SUFFIX.length)
- }
-
- def defaultGetterName(name: Name, pos: Int): TermName = {
- val prefix = if (isConstructorName(name)) "init" else name
- newTermName(prefix + DEFAULT_GETTER_STRING + pos)
- }
- def defaultGetterToMethod(name: Name): TermName = {
- val p = name.pos(DEFAULT_GETTER_STRING)
- if (p < name.length) name.toTermName.subName(0, p)
- else name.toTermName
- }
-
- // This isn't needed at the moment since I fixed $class$1 but
- // I expect it will be at some point.
- //
- // def anonNumberSuffix(name: Name): Name = {
- // ("" + name) lastIndexOf '$' match {
- // case -1 => nme.EMPTY
- // case idx =>
- // val s = name drop idx
- // if (s.toString forall (_.isDigit)) s
- // else nme.EMPTY
- // }
- // }
-
- def stripModuleSuffix(name: Name): Name = (
- if (isModuleName(name)) name dropRight MODULE_SUFFIX_STRING.length else name
- )
-
- def dropSingletonName(name: Name): TypeName = name dropRight SINGLETON_SUFFIX.length toTypeName
- def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName
- def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName
- def interfaceName(implname: Name): TypeName = implname dropRight IMPL_CLASS_SUFFIX.length toTypeName
- def localDummyName(clazz: Symbol): TermName = newTermName(LOCALDUMMY_PREFIX + clazz.name + ">")
- def superName(name: Name): TermName = newTermName(SUPER_PREFIX_STRING + name)
-
- /** The name of an accessor for protected symbols. */
- def protName(name: Name): TermName = newTermName(PROTECTED_PREFIX + name)
-
- /** The name of a setter for protected symbols. Used for inherited Java fields. */
- def protSetterName(name: Name): TermName = newTermName(PROTECTED_SET_PREFIX + name)
- }
-}
diff --git a/src/compiler/scala/reflect/internal/Names.scala b/src/compiler/scala/reflect/internal/Names.scala
index 5f38374f20..23eaa1088c 100644
--- a/src/compiler/scala/reflect/internal/Names.scala
+++ b/src/compiler/scala/reflect/internal/Names.scala
@@ -8,6 +8,7 @@ package internal
import scala.io.Codec
import java.security.MessageDigest
+import language.implicitConversions
/** The class Names ...
*
@@ -355,8 +356,10 @@ trait Names extends api.Names {
final def endsWith(char: Char): Boolean = len > 0 && endChar == char
final def endsWith(name: String): Boolean = endsWith(newTermName(name))
- def dropRight(n: Int) = subName(0, len - n)
- def drop(n: Int) = subName(n, len)
+ def dropRight(n: Int): ThisNameType = subName(0, len - n)
+ def drop(n: Int): ThisNameType = subName(n, len)
+ def stripSuffix(suffix: Name): ThisNameType =
+ if (this endsWith suffix) dropRight(suffix.length) else thisName
def indexOf(ch: Char) = {
val idx = pos(ch)
@@ -394,14 +397,14 @@ trait Names extends api.Names {
// def decodedName: ThisNameType = newName(decoded)
def encodedName: ThisNameType = encode
- /** Replace operator symbols by corresponding $op_name. */
+ /** Replace operator symbols by corresponding \$op_name. */
def encode: ThisNameType = {
val str = toString
val res = NameTransformer.encode(str)
if (res == str) thisName else newName(res)
}
- /** Replace $op_name by corresponding operator symbol. */
+ /** Replace \$op_name by corresponding operator symbol. */
def decode: String = {
if (this containsChar '$') {
val str = toString
diff --git a/src/compiler/scala/reflect/internal/Positions.scala b/src/compiler/scala/reflect/internal/Positions.scala
index 78de8d0ff2..5ec2659098 100644
--- a/src/compiler/scala/reflect/internal/Positions.scala
+++ b/src/compiler/scala/reflect/internal/Positions.scala
@@ -3,9 +3,8 @@ package internal
trait Positions extends api.Positions { self: SymbolTable =>
- def focusPos(pos: Position): Position
- def isRangePos(pos: Position): Boolean
- def showPos(pos: Position): String
+ type Position = scala.tools.nsc.util.Position
+ val NoPosition = scala.tools.nsc.util.NoPosition
/** A position that wraps a set of trees.
* The point of the wrapping position is the point of the default position.
@@ -27,4 +26,37 @@ trait Positions extends api.Positions { self: SymbolTable =>
* to some of the nodes in `tree`.
*/
def ensureNonOverlapping(tree: Tree, others: List[Tree]) {}
+
+ trait PosAssigner extends Traverser {
+ var pos: Position
+ }
+ protected[this] lazy val posAssigner: PosAssigner = new DefaultPosAssigner
+
+ protected class DefaultPosAssigner extends PosAssigner {
+ var pos: Position = _
+ override def traverse(t: Tree) {
+ if (t eq EmptyTree) ()
+ else if (t.pos == NoPosition) {
+ t.setPos(pos)
+ super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if?
+ // @PP: it's pruning whenever it encounters a node with a
+ // position, which I interpret to mean that (in the author's
+ // mind at least) either the children of a positioned node will
+ // already be positioned, or the children of a positioned node
+ // do not merit positioning.
+ //
+ // Whatever the author's rationale, it does seem like a bad idea
+ // to press on through a positioned node to find unpositioned
+ // children beneath it and then to assign whatever happens to
+ // be in `pos` to such nodes. There are supposed to be some
+ // position invariants which I can't imagine surviving that.
+ }
+ }
+ }
+
+ def atPos[T <: Tree](pos: Position)(tree: T): T = {
+ posAssigner.pos = pos
+ posAssigner.traverse(tree)
+ tree
+ }
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/internal/Required.scala b/src/compiler/scala/reflect/internal/Required.scala
index 1bf1a2e97e..6d146354a3 100644
--- a/src/compiler/scala/reflect/internal/Required.scala
+++ b/src/compiler/scala/reflect/internal/Required.scala
@@ -5,15 +5,10 @@ import settings.MutableSettings
trait Required { self: SymbolTable =>
- type AbstractFileType >: Null <: {
- def path: String
- def canonicalPath: String
- }
+ type AbstractFileType >: Null <: api.RequiredFile
def picklerPhase: Phase
- val gen: TreeGen { val global: Required.this.type }
-
def settings: MutableSettings
def forInteractive: Boolean
diff --git a/src/compiler/scala/reflect/internal/Scopes.scala b/src/compiler/scala/reflect/internal/Scopes.scala
index ef48d6102f..36e8ebb212 100644
--- a/src/compiler/scala/reflect/internal/Scopes.scala
+++ b/src/compiler/scala/reflect/internal/Scopes.scala
@@ -113,7 +113,7 @@ trait Scopes extends api.Scopes { self: SymbolTable =>
*
* @param sym ...
*/
- def enter(sym: Symbol): Symbol = { enter(newScopeEntry(sym, this)); sym }
+ def enter[T <: Symbol](sym: T): T = { enter(newScopeEntry(sym, this)); sym }
/** enter a symbol, asserting that no symbol with same name exists in scope
*
diff --git a/src/compiler/scala/reflect/internal/StdAttachments.scala b/src/compiler/scala/reflect/internal/StdAttachments.scala
new file mode 100644
index 0000000000..ae2ad87deb
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/StdAttachments.scala
@@ -0,0 +1,10 @@
+package scala.reflect
+package internal
+
+import scala.reflect.makro.runtime.{Context => MacroContext}
+
+trait StdAttachments {
+ self: SymbolTable =>
+
+ case class ReifyAttachment(original: Symbol)
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index e2c253628c..0cdf65bd8f 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -6,26 +6,141 @@
package scala.reflect
package internal
-import scala.collection.immutable
-import NameTransformer.MODULE_SUFFIX_STRING
+import java.security.MessageDigest
+import Chars.isOperatorPart
import annotation.switch
+import language.implicitConversions
+import scala.collection.immutable
+import scala.io.Codec
-trait StdNames extends NameManglers { self: SymbolTable =>
+trait StdNames {
+ self: SymbolTable =>
def encode(str: String): TermName = newTermNameCached(NameTransformer.encode(str))
- implicit def lowerTermNames(n: TermName): String = "" + n
-
- // implicit def stringToTermName(s: String): TermName = newTermName(s)
-
- /** This should be the first trait in the linearization. */
- trait Keywords {
+ implicit def lowerTermNames(n: TermName): String = n.toString
+
+ /** Tensions: would like the keywords to be the very first names entered into the names
+ * storage so their ids count from 0, which simplifies the parser. Switched to abstract
+ * classes to avoid all the indirection which is generated with implementation-containing
+ * traits. Since all these classes use eager vals, that means the constructor with the
+ * keywords must run first. If it's the top in the superclass chain, then CommonNames
+ * must inherit from it, which means TypeNames would inherit keywords as well.
+ *
+ * Solution: Keywords extends CommonNames and uses early defs to beat the
+ * CommonNames constructor out of the starting gate. This is its builder.
+ */
+ private class KeywordSetBuilder {
private var kws: Set[TermName] = Set()
- private def kw(s: String): TermName = {
+ def apply(s: String): TermName = {
val result = newTermNameCached(s)
kws = kws + result
result
}
+ def result: Set[TermName] = {
+ val result = kws
+ kws = null
+ result
+ }
+ }
+
+ private final object compactify extends (String => String) {
+ val md5 = MessageDigest.getInstance("MD5")
+
+ /**
+ * COMPACTIFY
+ *
+ * The hashed name has the form (prefix + marker + md5 + marker + suffix), where
+ * - prefix/suffix.length = MaxNameLength / 4
+ * - md5.length = 32
+ *
+ * We obtain the formula:
+ *
+ * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6
+ *
+ * (+6 for ".class"). MaxNameLength can therefore be computed as follows:
+ */
+ val marker = "$$$$"
+ val MaxNameLength = math.min(
+ settings.maxClassfileName.value - 6,
+ 2 * (settings.maxClassfileName.value - 6 - 2*marker.length - 32)
+ )
+ def toMD5(s: String, edge: Int): String = {
+ val prefix = s take edge
+ val suffix = s takeRight edge
+
+ val cs = s.toArray
+ val bytes = Codec toUTF8 cs
+ md5 update bytes
+ val md5chars = md5.digest() map (b => (b & 0xFF).toHexString) mkString
+
+ prefix + marker + md5chars + marker + suffix
+ }
+ def apply(s: String): String = (
+ if (s.length <= MaxNameLength) s
+ else toMD5(s, MaxNameLength / 4)
+ )
+ }
+
+ abstract class CommonNames {
+ type NameType <: Name
+ protected implicit def createNameType(name: String): NameType
+
+ def flattenedName(segments: Name*): NameType =
+ compactify(segments mkString NAME_JOIN_STRING)
+
+ val MODULE_SUFFIX_STRING: String = NameTransformer.MODULE_SUFFIX_STRING
+ val NAME_JOIN_STRING: String = NameTransformer.NAME_JOIN_STRING
+ val SINGLETON_SUFFIX: String = ".type"
+
+ val ANON_CLASS_NAME: NameType = "$anon"
+ val ANON_FUN_NAME: NameType = "$anonfun"
+ val EMPTY: NameType = ""
+ val EMPTY_PACKAGE_NAME: NameType = "<empty>"
+ val IMPL_CLASS_SUFFIX = "$class"
+ val IMPORT: NameType = "<import>"
+ val MODULE_SUFFIX_NAME: NameType = MODULE_SUFFIX_STRING
+ val MODULE_VAR_SUFFIX: NameType = "$module"
+ val NAME_JOIN_NAME: NameType = NAME_JOIN_STRING
+ val PACKAGE: NameType = "package"
+ val ROOT: NameType = "<root>"
+ val SPECIALIZED_SUFFIX: NameType = "$sp"
+
+ // value types (and AnyRef) are all used as terms as well
+ // as (at least) arguments to the @specialize annotation.
+ final val Boolean: NameType = "Boolean"
+ final val Byte: NameType = "Byte"
+ final val Char: NameType = "Char"
+ final val Double: NameType = "Double"
+ final val Float: NameType = "Float"
+ final val Int: NameType = "Int"
+ final val Long: NameType = "Long"
+ final val Short: NameType = "Short"
+ final val Unit: NameType = "Unit"
+
+ final val ScalaValueNames: scala.List[NameType] =
+ scala.List(Byte, Char, Short, Int, Long, Float, Double, Boolean, Unit)
+
+ // some types whose companions we utilize
+ final val AnyRef: NameType = "AnyRef"
+ final val Array: NameType = "Array"
+ final val List: NameType = "List"
+ final val Seq: NameType = "Seq"
+ final val Symbol: NameType = "Symbol"
+ final val ClassTag: NameType = "ClassTag"
+ final val TypeTag : NameType = "TypeTag"
+ final val ConcreteTypeTag: NameType = "ConcreteTypeTag"
+
+ // fictions we use as both types and terms
+ final val ERROR: NameType = "<error>"
+ final val NO_NAME: NameType = "<none>" // formerly NOSYMBOL
+ final val WILDCARD: NameType = "_"
+ }
+
+ /** This should be the first trait in the linearization. */
+ // abstract class Keywords extends CommonNames {
+ abstract class Keywords extends {
+ private val kw = new KeywordSetBuilder
final val ABSTRACTkw: TermName = kw("abstract")
final val CASEkw: TermName = kw("case")
@@ -44,6 +159,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val IMPLICITkw: TermName = kw("implicit")
final val IMPORTkw: TermName = kw("import")
final val LAZYkw: TermName = kw("lazy")
+ final val MACROkw: TermName = kw("macro")
final val MATCHkw: TermName = kw("match")
final val NEWkw: TermName = kw("new")
final val NULLkw: TermName = kw("null")
@@ -55,6 +171,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val RETURNkw: TermName = kw("return")
final val SEALEDkw: TermName = kw("sealed")
final val SUPERkw: TermName = kw("super")
+ final val THENkw: TermName = kw("then")
final val THISkw: TermName = kw("this")
final val THROWkw: TermName = kw("throw")
final val TRAITkw: TermName = kw("trait")
@@ -78,72 +195,31 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val HASHkw: TermName = kw("#")
final val ATkw: TermName = kw("@")
- final val keywords = {
- val result = kws.toSet
- kws = null
- result
- }
-
+ final val keywords = kw.result
+ } with CommonNames {
final val javaKeywords = new JavaKeywords()
}
- trait CommonNames /*extends LibraryCommonNames*/ {
-
- type NameType <: Name
- protected implicit def createNameType(name: String): NameType
-
- val EMPTY: NameType = ""
- val ANON_FUN_NAME: NameType = "$anonfun"
- val ANON_CLASS_NAME: NameType = "$anon"
- val EMPTY_PACKAGE_NAME: NameType = "<empty>"
- val IMPORT: NameType = "<import>"
- val MODULE_VAR_SUFFIX: NameType = "$module"
- val ROOT: NameType = "<root>"
- val PACKAGE: NameType = "package"
- val SPECIALIZED_SUFFIX: NameType = "$sp"
-
- // value types (and AnyRef) are all used as terms as well
- // as (at least) arguments to the @specialize annotation.
- final val Boolean: NameType = "Boolean"
- final val Byte: NameType = "Byte"
- final val Char: NameType = "Char"
- final val Double: NameType = "Double"
- final val Float: NameType = "Float"
- final val Int: NameType = "Int"
- final val Long: NameType = "Long"
- final val Short: NameType = "Short"
- final val Unit: NameType = "Unit"
-
- final val ScalaValueNames: scala.List[NameType] =
- scala.List(Byte, Char, Short, Int, Long, Float, Double, Boolean, Unit)
-
- // some types whose companions we utilize
- final val AnyRef: NameType = "AnyRef"
- final val Array: NameType = "Array"
- final val List: NameType = "List"
- final val Seq: NameType = "Seq"
- final val Symbol: NameType = "Symbol"
-
- // fictions we use as both types and terms
- final val ERROR: NameType = "<error>"
- final val NO_NAME: NameType = "<none>" // formerly NOSYMBOL
- final val WILDCARD: NameType = "_"
- }
+ abstract class TypeNames extends Keywords {
+ type NameType = TypeName
+ protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name)
- trait TypeNames extends CommonNames {
final val BYNAME_PARAM_CLASS_NAME: NameType = "<byname>"
final val EQUALS_PATTERN_NAME: NameType = "<equals>"
final val JAVA_REPEATED_PARAM_CLASS_NAME: NameType = "<repeated...>"
final val LOCAL_CHILD: NameType = "<local child>"
+ final val REFINE_CLASS_NAME: NameType = "<refinement>"
final val REPEATED_PARAM_CLASS_NAME: NameType = "<repeated>"
final val WILDCARD_STAR: NameType = "_*"
final val Any: NameType = "Any"
final val AnyVal: NameType = "AnyVal"
+ final val Expr: NameType = "Expr"
final val Nothing: NameType = "Nothing"
final val Null: NameType = "Null"
final val Object: NameType = "Object"
final val PartialFunction: NameType = "PartialFunction"
+ final val PrefixType: NameType = "PrefixType"
final val Product: NameType = "Product"
final val Serializable: NameType = "Serializable"
final val Singleton: NameType = "Singleton"
@@ -153,7 +229,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val Annotation: NameType = "Annotation"
final val ClassfileAnnotation: NameType = "ClassfileAnnotation"
final val Enum: NameType = "Enum"
-
+ final val Group: NameType = "Group"
final val Tree: NameType = "Tree"
final val TypeTree: NameType = "TypeTree"
@@ -171,7 +247,6 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val DeprecatedATTR: NameType = "Deprecated"
final val ExceptionsATTR: NameType = "Exceptions"
final val InnerClassesATTR: NameType = "InnerClasses"
- final val JacoMetaATTR: NameType = "JacoMeta"
final val LineNumberTableATTR: NameType = "LineNumberTable"
final val LocalVariableTableATTR: NameType = "LocalVariableTable"
final val RuntimeAnnotationATTR: NameType = "RuntimeVisibleAnnotations" // RetentionPolicy.RUNTIME
@@ -181,36 +256,212 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val SignatureATTR: NameType = "Signature"
final val SourceFileATTR: NameType = "SourceFile"
final val SyntheticATTR: NameType = "Synthetic"
+
+ def dropSingletonName(name: Name): TypeName = name dropRight SINGLETON_SUFFIX.length toTypeName
+ def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName
+ def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName
+ def interfaceName(implname: Name): TypeName = implname dropRight IMPL_CLASS_SUFFIX.length toTypeName
}
- trait TermNames extends Keywords with CommonNames {
+ abstract class TermNames extends Keywords {
+ type NameType = TermName
+ protected implicit def createNameType(name: String): TermName = newTermNameCached(name)
+
+ /** Base strings from which synthetic names are derived. */
+ val BITMAP_PREFIX = "bitmap$"
+ val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
+ val DEFAULT_GETTER_STRING = "$default$"
+ val DEFAULT_GETTER_INIT_STRING = "$lessinit$greater" // CONSTRUCTOR.encoded, less is more
+ val DO_WHILE_PREFIX = "doWhile$"
+ val EVIDENCE_PARAM_PREFIX = "evidence$"
+ val EXCEPTION_RESULT_PREFIX = "exceptionResult"
+ val EXPAND_SEPARATOR_STRING = "$$"
+ val INTERPRETER_IMPORT_WRAPPER = "$iw"
+ val INTERPRETER_LINE_PREFIX = "line"
+ val INTERPRETER_VAR_PREFIX = "res"
+ val INTERPRETER_WRAPPER_SUFFIX = "$object"
+ val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
+ val PROTECTED_PREFIX = "protected$"
+ val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set"
+ val SUPER_PREFIX_STRING = "super$"
+ val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
+ val WHILE_PREFIX = "while$"
+
// Compiler internal names
- val EXPAND_SEPARATOR_STRING = "$$"
-
- val ANYNAME: NameType = "<anyname>"
- val CONSTRUCTOR: NameType = "<init>"
- val FAKE_LOCAL_THIS: NameType = "this$"
- val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something?
- val LAZY_LOCAL: NameType = "$lzy"
- val LOCAL_SUFFIX_STRING = " "
- val MACRO: NameType = "macro$"
- val MIRROR_PREFIX: NameType = "$mr."
- val MIRROR_SHORT: NameType = "$mr"
- val MIXIN_CONSTRUCTOR: NameType = "$init$"
- val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
- val OUTER: NameType = "$outer"
- val OUTER_LOCAL: NameType = OUTER + LOCAL_SUFFIX_STRING // "$outer ", note the space
- val OUTER_SYNTH: NameType = "<outer>" // emitted by virtual pattern matcher, replaced by outer accessor in explicitouter
- val SELECTOR_DUMMY: NameType = "<unapply-selector>"
- val SELF: NameType = "$this"
- val SPECIALIZED_INSTANCE: NameType = "specInstance$"
- val STAR: NameType = "*"
- val THIS: NameType = "_$this"
-
- final val Nil: NameType = "Nil"
- final val Predef: NameType = "Predef"
- final val ScalaRunTime: NameType = "ScalaRunTime"
- final val Some: NameType = "Some"
+ val ANYNAME: NameType = "<anyname>"
+ val CONSTRUCTOR: NameType = "<init>"
+ val FAKE_LOCAL_THIS: NameType = "this$"
+ val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something?
+ val LAZY_LOCAL: NameType = "$lzy"
+ val LAZY_SLOW_SUFFIX: NameType = "$lzycompute"
+ val LOCAL_SUFFIX_STRING = " "
+ val MIRROR_FREE_PREFIX: NameType = "free$"
+ val MIRROR_FREE_THIS_SUFFIX: NameType = "$this"
+ val MIRROR_FREE_VALUE_SUFFIX: NameType = "$value"
+ val MIRROR_PREFIX: NameType = "$mr."
+ val MIRROR_SHORT: NameType = "$mr"
+ val MIRROR_SYMDEF_PREFIX: NameType = "symdef$"
+ val MIXIN_CONSTRUCTOR: NameType = "$init$"
+ val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
+ val OUTER: NameType = "$outer"
+ val OUTER_LOCAL: NameType = OUTER + LOCAL_SUFFIX_STRING // "$outer ", note the space
+ val OUTER_SYNTH: NameType = "<outer>" // emitted by virtual pattern matcher, replaced by outer accessor in explicitouter
+ val SELECTOR_DUMMY: NameType = "<unapply-selector>"
+ val SELF: NameType = "$this"
+ val SETTER_SUFFIX: NameType = encode("_=")
+ val SPECIALIZED_INSTANCE: NameType = "specInstance$"
+ val STAR: NameType = "*"
+ val THIS: NameType = "_$this"
+
+ @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
+ def SPECIALIZED_SUFFIX_STRING = SPECIALIZED_SUFFIX.toString
+ @deprecated("Use SPECIALIZED_SUFFIX", "2.10.0")
+ def SPECIALIZED_SUFFIX_NAME: TermName = SPECIALIZED_SUFFIX.toTermName
+
+ def isConstructorName(name: Name) = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR
+ def isExceptionResultName(name: Name) = name startsWith EXCEPTION_RESULT_PREFIX
+ def isImplClassName(name: Name) = name endsWith IMPL_CLASS_SUFFIX
+ def isLocalDummyName(name: Name) = name startsWith LOCALDUMMY_PREFIX
+ def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING
+ def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX)
+ def isProtectedAccessorName(name: Name) = name startsWith PROTECTED_PREFIX
+ def isSuperAccessorName(name: Name) = name startsWith SUPER_PREFIX_STRING
+ def isReplWrapperName(name: Name) = name containsName INTERPRETER_IMPORT_WRAPPER
+ def isSetterName(name: Name) = name endsWith SETTER_SUFFIX
+ def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING)
+ def isSingletonName(name: Name) = name endsWith SINGLETON_SUFFIX
+ def isModuleName(name: Name) = name endsWith MODULE_SUFFIX_NAME
+
+ def isDeprecatedIdentifierName(name: Name) = name.toTermName match {
+ case nme.`then` | nme.`macro` => true
+ case _ => false
+ }
+
+ def isOpAssignmentName(name: Name) = name match {
+ case raw.NE | raw.LE | raw.GE | EMPTY => false
+ case _ =>
+ name.endChar == '=' && name.startChar != '=' && isOperatorPart(name.startChar)
+ }
+
+ /** The expanded name of `name` relative to this class `base` with given `separator`
+ */
+ def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName =
+ newTermNameCached(base.fullName('$') + separator + name)
+
+ /** The expanded setter name of `name` relative to this class `base`
+ */
+ def expandedSetterName(name: TermName, base: Symbol): TermName =
+ expandedName(name, base, separator = TRAIT_SETTER_SEPARATOR_STRING)
+
+ /** If `name` is an expandedName name, the original name.
+ * Otherwise `name` itself.
+ */
+ def originalName(name: Name): Name = {
+ var i = name.length
+ while (i >= 2 && !(name(i - 1) == '$' && name(i - 2) == '$')) i -= 1
+ if (i >= 2) {
+ while (i >= 3 && name(i - 3) == '$') i -= 1
+ name.subName(i, name.length)
+ } else name
+ }
+
+ def unspecializedName(name: Name): Name = (
+ if (name endsWith SPECIALIZED_SUFFIX)
+ name.subName(0, name.lastIndexOf('m') - 1)
+ else name
+ )
+
+ /*
+ def anonNumberSuffix(name: Name): Name = {
+ ("" + name) lastIndexOf '$' match {
+ case -1 => nme.EMPTY
+ case idx =>
+ val s = name drop idx
+ if (s.toString forall (_.isDigit)) s
+ else nme.EMPTY
+ }
+ }
+ */
+
+ /** Return the original name and the types on which this name
+ * is specialized. For example,
+ * {{{
+ * splitSpecializedName("foo$mIcD$sp") == ('foo', "I", "D")
+ * }}}
+ * `foo$mIcD$sp` is the name of a method specialized on two type
+ * parameters, the first one belonging to the method itself, on Int,
+ * and another one belonging to the enclosing class, on Double.
+ */
+ def splitSpecializedName(name: Name): (Name, String, String) =
+ if (name endsWith SPECIALIZED_SUFFIX) {
+ val name1 = name dropRight SPECIALIZED_SUFFIX.length
+ val idxC = name1 lastIndexOf 'c'
+ val idxM = name1 lastIndexOf 'm'
+
+ (name1.subName(0, idxM - 1),
+ name1.subName(idxC + 1, name1.length).toString,
+ name1.subName(idxM + 1, idxC).toString)
+ } else
+ (name, "", "")
+
+ def getterName(name: TermName): TermName = if (isLocalName(name)) localToGetter(name) else name
+ def getterToLocal(name: TermName): TermName = name append LOCAL_SUFFIX_STRING
+ def getterToSetter(name: TermName): TermName = name append SETTER_SUFFIX
+ def localToGetter(name: TermName): TermName = name dropRight LOCAL_SUFFIX_STRING.length
+
+ def dropLocalSuffix(name: Name): Name = if (name endsWith ' ') name dropRight 1 else name
+
+ def setterToGetter(name: TermName): TermName = {
+ val p = name.pos(TRAIT_SETTER_SEPARATOR_STRING)
+ if (p < name.length)
+ setterToGetter(name drop (p + TRAIT_SETTER_SEPARATOR_STRING.length))
+ else
+ name.subName(0, name.length - SETTER_SUFFIX.length)
+ }
+
+ // Nominally, name$default$N, encoded for <init>
+ def defaultGetterName(name: Name, pos: Int): TermName = {
+ val prefix = if (isConstructorName(name)) DEFAULT_GETTER_INIT_STRING else name
+ newTermName(prefix + DEFAULT_GETTER_STRING + pos)
+ }
+ // Nominally, name from name$default$N, CONSTRUCTOR for <init>
+ def defaultGetterToMethod(name: Name): TermName = {
+ val p = name.pos(DEFAULT_GETTER_STRING)
+ if (p < name.length) {
+ val q = name.toTermName.subName(0, p)
+ // i.e., if (q.decoded == CONSTRUCTOR.toString) CONSTRUCTOR else q
+ if (q.toString == DEFAULT_GETTER_INIT_STRING) CONSTRUCTOR else q
+ } else name.toTermName
+ }
+
+ // If the name ends with $nn where nn are
+ // all digits, strip the $ and the digits.
+ // Otherwise return the argument.
+ def stripAnonNumberSuffix(name: Name): Name = {
+ var pos = name.length
+ while (pos > 0 && name(pos - 1).isDigit)
+ pos -= 1
+
+ if (pos <= 0 || pos == name.length || name(pos - 1) != '$') name
+ else name.subName(0, pos - 1)
+ }
+
+ def stripModuleSuffix(name: Name): Name = (
+ if (isModuleName(name)) name dropRight MODULE_SUFFIX_STRING.length else name
+ )
+ def localDummyName(clazz: Symbol): TermName = newTermName(LOCALDUMMY_PREFIX + clazz.name + ">")
+ def superName(name: Name): TermName = newTermName(SUPER_PREFIX_STRING + name)
+
+ /** The name of an accessor for protected symbols. */
+ def protName(name: Name): TermName = newTermName(PROTECTED_PREFIX + name)
+
+ /** The name of a setter for protected symbols. Used for inherited Java fields. */
+ def protSetterName(name: Name): TermName = newTermName(PROTECTED_SET_PREFIX + name)
+
+ final val Nil: NameType = "Nil"
+ final val Predef: NameType = "Predef"
+ final val ScalaRunTime: NameType = "ScalaRunTime"
+ final val Some: NameType = "Some"
val _1 : NameType = "_1"
val _2 : NameType = "_2"
@@ -275,12 +526,41 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val genericWrapArray: NameType = "genericWrapArray"
// Compiler utilized names
- // val productElementName: NameType = "productElementName"
+
+ val AnnotatedType: NameType = "AnnotatedType"
+ val AnnotationInfo: NameType = "AnnotationInfo"
+ val Any: NameType = "Any"
+ val AnyVal: NameType = "AnyVal"
+ val AppliedTypeTree: NameType = "AppliedTypeTree"
+ val Apply: NameType = "Apply"
+ val ArrayAnnotArg: NameType = "ArrayAnnotArg"
+ val Constant: NameType = "Constant"
+ val ConstantType: NameType = "ConstantType"
+ val EmptyPackage: NameType = "EmptyPackage"
+ val EmptyPackageClass: NameType = "EmptyPackageClass"
+ val ExistentialTypeTree: NameType = "ExistentialTypeTree"
+ val Expr: NameType = "Expr"
val Ident: NameType = "Ident"
+ val Import: NameType = "Import"
+ val Literal: NameType = "Literal"
+ val LiteralAnnotArg: NameType = "LiteralAnnotArg"
+ val NestedAnnotArg: NameType = "NestedAnnotArg"
+ val NoPrefix: NameType = "NoPrefix"
+ val NoSymbol: NameType = "NoSymbol"
+ val Nothing: NameType = "Nothing"
+ val NoType: NameType = "NoType"
+ val Null: NameType = "Null"
+ val Object: NameType = "Object"
+ val RootPackage: NameType = "RootPackage"
+ val RootClass: NameType = "RootClass"
+ val Select: NameType = "Select"
val StringContext: NameType = "StringContext"
val This: NameType = "This"
val Tree : NameType = "Tree"
+ val Tuple2: NameType = "Tuple2"
val TYPE_ : NameType = "TYPE"
+ val TypeApply: NameType = "TypeApply"
+ val TypeRef: NameType = "TypeRef"
val TypeTree: NameType = "TypeTree"
val UNIT : NameType = "UNIT"
val add_ : NameType = "add"
@@ -289,9 +569,13 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val append: NameType = "append"
val apply: NameType = "apply"
val applyDynamic: NameType = "applyDynamic"
+ val applyDynamicNamed: NameType = "applyDynamicNamed"
val applyOrElse: NameType = "applyOrElse"
val args : NameType = "args"
val argv : NameType = "argv"
+ val arrayClass: NameType = "arrayClass"
+ val arrayElementClass: NameType = "arrayElementClass"
+ val arrayTagToClassManifest: NameType = "arrayTagToClassManifest"
val arrayValue: NameType = "arrayValue"
val array_apply : NameType = "array_apply"
val array_clone : NameType = "array_clone"
@@ -309,8 +593,10 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val checkInitialized: NameType = "checkInitialized"
val classOf: NameType = "classOf"
val clone_ : NameType = if (forMSIL) "MemberwiseClone" else "clone" // sn.OClone causes checkinit failure
+ val concreteTypeTagToManifest: NameType = "concreteTypeTagToManifest"
val conforms: NameType = "conforms"
val copy: NameType = "copy"
+ val definitions: NameType = "definitions"
val delayedInit: NameType = "delayedInit"
val delayedInitArg: NameType = "delayedInit$body"
val drop: NameType = "drop"
@@ -322,15 +608,17 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val equalsNumNum : NameType = "equalsNumNum"
val equalsNumObject : NameType = "equalsNumObject"
val equals_ : NameType = if (forMSIL) "Equals" else "equals"
+ val erasure: NameType = "erasure"
val error: NameType = "error"
+ val eval: NameType = "eval"
val ex: NameType = "ex"
+ val experimental: NameType = "experimental"
val false_ : NameType = "false"
val filter: NameType = "filter"
val finalize_ : NameType = if (forMSIL) "Finalize" else "finalize"
val find_ : NameType = "find"
val flatMap: NameType = "flatMap"
val foreach: NameType = "foreach"
- val freeValue : NameType = "freeValue"
val genericArrayOps: NameType = "genericArrayOps"
val get: NameType = "get"
val getOrElse: NameType = "getOrElse"
@@ -339,6 +627,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val hash_ : NameType = "hash"
val head: NameType = "head"
val identity: NameType = "identity"
+ val info: NameType = "info"
val inlinedEquals: NameType = "inlinedEquals"
val isArray: NameType = "isArray"
val isDefinedAt: NameType = "isDefinedAt"
@@ -350,38 +639,65 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val lang: NameType = "lang"
val length: NameType = "length"
val lengthCompare: NameType = "lengthCompare"
- val lift_ : NameType = "lift"
- val macro_ : NameType = "macro"
+ val liftedTree: NameType = "liftedTree"
+ val `macro` : NameType = "macro"
val macroThis : NameType = "_this"
- val macroContext : NameType = "_context"
+ val macroContext : NameType = "c"
val main: NameType = "main"
+ val manifest: NameType = "manifest"
+ val manifestToConcreteTypeTag: NameType = "manifestToConcreteTypeTag"
val map: NameType = "map"
+ val materializeArrayTag: NameType = "materializeArrayTag"
+ val materializeClassTag: NameType = "materializeClassTag"
+ val materializeConcreteTypeTag: NameType = "materializeConcreteTypeTag"
+ val materializeErasureTag: NameType= "materializeErasureTag"
+ val materializeTypeTag: NameType = "materializeTypeTag"
val mirror : NameType = "mirror"
+ val moduleClass : NameType = "moduleClass"
+ val name: NameType = "name"
val ne: NameType = "ne"
val newArray: NameType = "newArray"
+ val newFreeExistential: NameType = "newFreeExistential"
+ val newFreeTerm: NameType = "newFreeTerm"
+ val newFreeType: NameType = "newFreeType"
+ val newNestedSymbol: NameType = "newNestedSymbol"
val newScopeWith: NameType = "newScopeWith"
val next: NameType = "next"
+ val nmeNewTermName: NameType = "newTermName"
+ val nmeNewTypeName: NameType = "newTypeName"
+ val normalize: NameType = "normalize"
val notifyAll_ : NameType = "notifyAll"
val notify_ : NameType = "notify"
val null_ : NameType = "null"
val ofDim: NameType = "ofDim"
+ val origin: NameType = "origin"
+ val prefix : NameType = "prefix"
val productArity: NameType = "productArity"
val productElement: NameType = "productElement"
val productIterator: NameType = "productIterator"
val productPrefix: NameType = "productPrefix"
val readResolve: NameType = "readResolve"
+ val reflect : NameType = "reflect"
+ val reify : NameType = "reify"
val runOrElse: NameType = "runOrElse"
val runtime: NameType = "runtime"
val sameElements: NameType = "sameElements"
val scala_ : NameType = "scala"
+ val selectDynamic: NameType = "selectDynamic"
+ val selectOverloadedMethod: NameType = "selectOverloadedMethod"
+ val selectTerm: NameType = "selectTerm"
+ val selectType: NameType = "selectType"
val self: NameType = "self"
val setAccessible: NameType = "setAccessible"
val setAnnotations: NameType = "setAnnotations"
val setSymbol: NameType = "setSymbol"
val setType: NameType = "setType"
val setTypeSignature: NameType = "setTypeSignature"
+ val staticClass : NameType = "staticClass"
+ val staticModule : NameType = "staticModule"
val synchronized_ : NameType = "synchronized"
val tail: NameType = "tail"
+ val `then` : NameType = "then"
val thisModuleType: NameType = "thisModuleType"
val this_ : NameType = "this"
val throw_ : NameType = "throw"
@@ -390,18 +706,22 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val toObjectArray : NameType = "toObjectArray"
val toSeq: NameType = "toSeq"
val toString_ : NameType = if (forMSIL) "ToString" else "toString"
+ val tpe : NameType = "tpe"
+ val tree : NameType = "tree"
val true_ : NameType = "true"
val typedProductIterator: NameType = "typedProductIterator"
val unapply: NameType = "unapply"
val unapplySeq: NameType = "unapplySeq"
val unbox: NameType = "unbox"
val update: NameType = "update"
+ val updateDynamic: NameType = "updateDynamic"
val value: NameType = "value"
val valueOf : NameType = "valueOf"
val values : NameType = "values"
val view_ : NameType = "view"
val wait_ : NameType = "wait"
val withFilter: NameType = "withFilter"
+ val wrap: NameType = "wrap"
val zip: NameType = "zip"
val synthSwitch: NameType = "$synthSwitch"
@@ -439,19 +759,11 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val toInteger: NameType = "toInteger"
}
- object tpnme extends AbsTypeNames with TypeNames /*with LibraryTypeNames*/ with TypeNameMangling {
- type NameType = TypeName
- protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name)
-
- val REFINE_CLASS_NAME: NameType = "<refinement>"
- }
+ object tpnme extends TypeNames with AbsTypeNames { }
/** For fully qualified type names.
*/
object fulltpnme extends TypeNames {
- type NameType = TypeName
- protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name)
-
val RuntimeNothing: NameType = "scala.runtime.Nothing$"
val RuntimeNull: NameType = "scala.runtime.Null$"
val JavaLangEnum: NameType = "java.lang.Enum"
@@ -466,18 +778,9 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val RuntimeNull = toBinary(fulltpnme.RuntimeNull).toTypeName
}
- object fullnme extends TermNames {
- type NameType = TermName
- protected implicit def createNameType(name: String): TermName = newTermNameCached(name)
-
- val MirrorPackage: NameType = "scala.reflect.mirror"
- }
-
val javanme = nme.javaKeywords
- object nme extends AbsTermNames with TermNames /*with LibraryTermNames*/ with TermNameMangling {
- type NameType = TermName
- protected implicit def createNameType(name: String): TermName = newTermNameCached(name)
+ object nme extends TermNames with AbsTermNames {
/** Translate a String into a list of simple TypeNames and TermNames.
* In all segments before the last, type/term is determined by whether
@@ -517,42 +820,27 @@ trait StdNames extends NameManglers { self: SymbolTable =>
def newBitmapName(bitmapPrefix: Name, n: Int) = bitmapPrefix append ("" + n)
- val BITMAP_PREFIX: String = "bitmap$"
val BITMAP_NORMAL: NameType = BITMAP_PREFIX + "" // initialization bitmap for public/protected lazy vals
val BITMAP_TRANSIENT: NameType = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals
- val BITMAP_PRIVATE: NameType = BITMAP_PREFIX + "priv$" // initialization bitmap for private lazy vals
val BITMAP_CHECKINIT: NameType = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values
val BITMAP_CHECKINIT_TRANSIENT: NameType = BITMAP_PREFIX + "inittrans$" // initialization bitmap for transient checkinit values
- /** The expanded name of `name` relative to this class `base` with given `separator`
- */
- def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName =
- newTermNameCached(base.fullName('$') + separator + name)
+ def newLazyValSlowComputeName(lzyValName: Name) = lzyValName append LAZY_SLOW_SUFFIX
+
+ def isModuleVarName(name: Name): Boolean =
+ stripAnonNumberSuffix(name) endsWith MODULE_VAR_SUFFIX
def moduleVarName(name: TermName): TermName =
newTermNameCached("" + name + MODULE_VAR_SUFFIX)
- val ROOTPKG: TermName = "_root_"
+ val ROOTPKG: TermName = "_root_"
+ val EQEQ_LOCAL_VAR: TermName = "eqEqTemp$"
- /** Base strings from which synthetic names are derived. */
- val CHECK_IF_REFUTABLE_STRING = "check$ifrefutable$"
- val DEFAULT_GETTER_STRING = "$default$"
- val DO_WHILE_PREFIX = "doWhile$"
- val EQEQ_LOCAL_VAR_STRING = "eqEqTemp$"
- val EVIDENCE_PARAM_PREFIX = "evidence$"
- val EXCEPTION_RESULT_PREFIX = "exceptionResult"
- val INTERPRETER_IMPORT_WRAPPER = "$iw"
- val INTERPRETER_LINE_PREFIX = "line"
- val INTERPRETER_VAR_PREFIX = "res"
- val INTERPRETER_WRAPPER_SUFFIX = "$object"
- val WHILE_PREFIX = "while$"
-
- val EQEQ_LOCAL_VAR: TermName = newTermName(EQEQ_LOCAL_VAR_STRING)
-
- def getCause = sn.GetCause
- def getClass_ = sn.GetClass
- def getMethod_ = sn.GetMethod
- def invoke_ = sn.Invoke
+ def getCause = sn.GetCause
+ def getClass_ = sn.GetClass
+ def getComponentType = sn.GetComponentType
+ def getMethod_ = sn.GetMethod
+ def invoke_ = sn.Invoke
val ADD = encode("+")
val AND = encode("&")
@@ -711,6 +999,11 @@ trait StdNames extends NameManglers { self: SymbolTable =>
case 22 => nme._22
case _ => newTermName("_" + j)
}
+
+ @deprecated("Use a method in tpnme", "2.10.0") def dropSingletonName(name: Name): TypeName = tpnme.dropSingletonName(name)
+ @deprecated("Use a method in tpnme", "2.10.0") def singletonName(name: Name): TypeName = tpnme.singletonName(name)
+ @deprecated("Use a method in tpnme", "2.10.0") def implClassName(name: Name): TypeName = tpnme.implClassName(name)
+ @deprecated("Use a method in tpnme", "2.10.0") def interfaceName(implname: Name): TypeName = tpnme.interfaceName(implname)
}
abstract class SymbolNames {
@@ -736,6 +1029,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
val ForName : TermName
val GetCause : TermName
val GetClass : TermName
+ val GetComponentType : TermName
val GetMethod : TermName
val Invoke : TermName
val JavaLang : TermName
@@ -744,12 +1038,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
}
class JavaKeywords {
- private var kws: Set[TermName] = Set()
- private def kw(s: String): TermName = {
- val result = newTermNameCached(s)
- kws = kws + result
- result
- }
+ private val kw = new KeywordSetBuilder
final val ABSTRACTkw: TermName = kw("abstract")
final val ASSERTkw: TermName = kw("assert")
@@ -802,11 +1091,7 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val VOLATILEkw: TermName = kw("volatile")
final val WHILEkw: TermName = kw("while")
- final val keywords = {
- val result = kws.toSet
- kws = null
- result
- }
+ final val keywords = kw.result
}
private abstract class JavaNames extends SymbolNames {
@@ -830,12 +1115,13 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val Throwable: TypeName = "java.lang.Throwable"
final val ValueType: TypeName = tpnme.NO_NAME
- final val ForName: TermName = newTermName("forName")
- final val GetCause: TermName = newTermName("getCause")
- final val GetClass: TermName = newTermName("getClass")
- final val GetMethod: TermName = newTermName("getMethod")
- final val Invoke: TermName = newTermName("invoke")
- final val JavaLang: TermName = newTermName("java.lang")
+ final val ForName: TermName = newTermName("forName")
+ final val GetCause: TermName = newTermName("getCause")
+ final val GetClass: TermName = newTermName("getClass")
+ final val GetComponentType: TermName = newTermName("getComponentType")
+ final val GetMethod: TermName = newTermName("getMethod")
+ final val Invoke: TermName = newTermName("invoke")
+ final val JavaLang: TermName = newTermName("java.lang")
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> BoxedBoolean,
@@ -867,12 +1153,13 @@ trait StdNames extends NameManglers { self: SymbolTable =>
final val Throwable: TypeName = "System.Exception"
final val ValueType: TypeName = "System.ValueType"
- final val ForName: TermName = newTermName("GetType")
- final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */
- final val GetClass: TermName = newTermName("GetType")
- final val GetMethod: TermName = newTermName("GetMethod")
- final val Invoke: TermName = newTermName("Invoke")
- final val JavaLang: TermName = newTermName("System")
+ final val ForName: TermName = newTermName("GetType")
+ final val GetCause: TermName = newTermName("InnerException") /* System.Reflection.TargetInvocationException.InnerException */
+ final val GetClass: TermName = newTermName("GetType")
+ final val GetComponentType: TermName = newTermName("GetElementType")
+ final val GetMethod: TermName = newTermName("GetMethod")
+ final val Invoke: TermName = newTermName("Invoke")
+ final val JavaLang: TermName = newTermName("System")
val Boxed = immutable.Map[TypeName, TypeName](
tpnme.Boolean -> "System.Boolean",
diff --git a/src/compiler/scala/reflect/internal/SymbolCreations.scala b/src/compiler/scala/reflect/internal/SymbolCreations.scala
new file mode 100644
index 0000000000..ac82ffe62a
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/SymbolCreations.scala
@@ -0,0 +1,112 @@
+ /* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect
+package internal
+
+import scala.collection.{ mutable, immutable }
+import scala.collection.mutable.ListBuffer
+import util.Statistics._
+import Flags._
+import api.Modifier
+
+trait SymbolCreations {
+ self: SymbolTable =>
+
+ import definitions._
+
+ /** Symbol creation interface, possibly better moved somewhere else.
+ * It'd be nice if we had virtual classes, but since we
+ * don't: these methods insulate the direct instantiation of the symbols
+ * (which may be overridden, e.g. in SynchronizedSymbols) from the
+ * enforcement of preconditions and choice of symbol constructor based
+ * on flags, which are (or should be) final so they can be reasoned about
+ * without lots of surprises.
+ */
+ trait SymbolCreatorInterface {
+ // Fallbacks; more precise creators should normally be called.
+ protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol
+ // This in fact does not exist anymore in the interests of better typed TypeSymbols.
+ // protected def createTypeSymbol(name: TypeName, pos: Position, newFlags: Long): TypeSymbol
+
+ // I believe all but rogue TypeSymbols are one of: ClassSymbol, AbstractTypeSymbol, AliasTypeSymbol, or TypeSkolem.
+ protected def createAbstractTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AbstractTypeSymbol
+ protected def createAliasTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AliasTypeSymbol
+ protected def createTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position, newFlags: Long): TypeSkolem
+ protected def createClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol
+
+ // More specific ClassSymbols.
+ // TODO - AnonymousClassSymbol.
+ // TODO maybe - PackageObjects, but that one cost me a lot of time when I tried it before
+ // because it broke reification some way I couldn't see.
+ protected def createModuleClassSymbol(name: TypeName, pos: Position, newFlags: Long): ModuleClassSymbol
+ protected def createPackageClassSymbol(name: TypeName, pos: Position, newFlags: Long): PackageClassSymbol
+ protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol
+ protected def createImplClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol
+ protected def createPackageObjectClassSymbol(pos: Position, newFlags: Long): PackageObjectClassSymbol
+
+ // Distinguished term categories include methods, modules, packages, package objects,
+ // value parameters, and values (including vals, vars, and lazy vals.)
+ protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol
+ protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol
+ protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol
+
+ // TODO
+ // protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol
+ // protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol
+ }
+
+ trait SymbolCreator extends SymbolCreatorInterface {
+ self: Symbol =>
+
+ /*** Predictable symbol creation.
+ *
+ * newTermSymbol, newClassSymbol, and newNonClassSymbol all create symbols based
+ * only on the flags (for reconstruction after reification.) It would be nice to
+ * combine the last two into newTypeSymbol, but this requires some flag which allows us
+ * to distinguish classes and type aliases, which as yet does not exist.
+ *
+ * The fundamental flags used to determine which Symbol subclass to instantiate are:
+ * METHOD, PACKAGE, MODULE, PARAM, DEFERRED.
+ */
+ final def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol = {
+ if ((newFlags & METHOD) != 0)
+ createMethodSymbol(name, pos, newFlags)
+ else if ((newFlags & PACKAGE) != 0)
+ createPackageSymbol(name, pos, newFlags | PackageFlags)
+ else if ((newFlags & MODULE) != 0)
+ createModuleSymbol(name, pos, newFlags)
+ else if ((newFlags & PARAM) != 0)
+ createValueParameterSymbol(name, pos, newFlags)
+ else
+ createValueMemberSymbol(name, pos, newFlags)
+ }
+
+ final def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = {
+ if (name == tpnme.REFINE_CLASS_NAME)
+ createRefinementClassSymbol(pos, newFlags)
+ else if ((newFlags & PACKAGE) != 0)
+ createPackageClassSymbol(name, pos, newFlags | PackageFlags)
+ else if (name == tpnme.PACKAGE)
+ createPackageObjectClassSymbol(pos, newFlags)
+ else if ((newFlags & MODULE) != 0)
+ createModuleClassSymbol(name, pos, newFlags)
+ else if ((newFlags & IMPLCLASS) != 0)
+ createImplClassSymbol(name, pos, newFlags)
+ else
+ createClassSymbol(name, pos, newFlags)
+ }
+
+ final def newNonClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol = {
+ if ((newFlags & DEFERRED) != 0)
+ createAbstractTypeSymbol(name, pos, newFlags)
+ else
+ createAliasTypeSymbol(name, pos, newFlags)
+ }
+
+ def newTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
+ newNonClassSymbol(name, pos, newFlags)
+ }
+}
diff --git a/src/compiler/scala/reflect/internal/SymbolFlags.scala b/src/compiler/scala/reflect/internal/SymbolFlags.scala
new file mode 100644
index 0000000000..4ce8ac40df
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/SymbolFlags.scala
@@ -0,0 +1,175 @@
+ /* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.reflect
+package internal
+
+import scala.collection.{ mutable, immutable }
+import scala.collection.mutable.ListBuffer
+import util.Statistics._
+import Flags._
+import api.Modifier
+
+trait SymbolFlags {
+ self: SymbolTable =>
+
+ import definitions._
+
+ /** Not mixed in under normal conditions; a powerful debugging aid.
+ */
+ trait FlagVerifier extends Symbol {
+ private def assert0(cond: Boolean, message: => Any) {
+ if (!cond) {
+ Console.err.println("[flag verification failure]\n%s\n%s\n".format(atPhaseStackMessage, message))
+ (new Throwable).getStackTrace.take(13).drop(3).foreach(println)
+ println("")
+ }
+ }
+
+ protected def verifyChange(isAdd: Boolean, mask: Long, before: Long) {
+ val after = if (isAdd) before | mask else before & ~mask
+ val added = after & ~before
+ val removed = before & ~after
+ val ignored = mask & ~added & ~removed
+ val error = (
+ (added & OverloadedFlagsMask) != 0 || (removed & OverloadedFlagsMask) != 0
+ // || (ignored != 0)
+ )
+ val addString = if (added == 0) "" else "+(" + flagsToString(added) + ")"
+ val removeString = if (removed == 0) "" else "-(" + flagsToString(removed) + ")"
+ val changeString = if (added == 0 && removed == 0) "no change" else addString + " " + removeString
+
+ if (error) {
+ val templ = (
+ """| symbol: %s %s in %s
+ | call: %s(%s)
+ | flags: %s
+ | result: %s""".stripMargin
+ )
+
+ assert0(false, templ.format(
+ shortSymbolClass,
+ name.decode,
+ owner,
+ if (isAdd) "+" else "-",
+ flagsToString(mask),
+ flagsToString(before),
+ changeString
+ ))
+ }
+ }
+
+ protected def verifyFlags(what: String) {
+ assert0(this hasAllFlags alwaysHasFlags, symbolCreationString + "\n always=%s, what=%s\n".format(flagsToString(alwaysHasFlags), what))
+ if (this hasFlag neverHasFlags) {
+ val hasRaw = (rawflags & neverHasFlags) != 0
+ assert0(!hasRaw, symbolCreationString + "\n never=%s, what=%s".format(flagsToString(neverHasFlags), what))
+ }
+ }
+ abstract override def initFlags(mask: Long): this.type = {
+ super.initFlags(mask)
+ verifyFlags("initFlags(" + flagsToString(mask) + ")")
+ this
+ }
+ abstract override def setFlag(mask: Long): this.type = {
+ verifyChange(true, mask, rawflags)
+ super.setFlag(mask)
+ verifyFlags("setFlag(" + flagsToString(mask) + ")")
+ this
+ }
+ abstract override def resetFlag(mask: Long): this.type = {
+ verifyChange(false, mask, rawflags)
+ super.resetFlag(mask)
+ verifyFlags("resetFlag(" + flagsToString(mask) + ")")
+ this
+ }
+ abstract override def flags_=(fs: Long) {
+ if ((fs & ~rawflags) != 0)
+ verifyChange(true, fs & ~rawflags, rawflags)
+ if ((rawflags & ~fs) != 0)
+ verifyChange(false, rawflags & ~fs, rawflags)
+
+ super.flags_=(fs)
+ verifyFlags("flags_=(" + flagsToString(fs) + ")")
+ }
+ }
+
+ /** Flags which should always be present on a particular class of
+ * Symbol, and never be present on any others.
+ */
+ def AllDistinguishingFlags: Long = METHOD | MODULE | IMPLCLASS
+
+ /** A distinguishing flag is one which the mixing class must always
+ * have, and which no other symbol class is allowed to have.
+ */
+ trait DistinguishingFlag extends SymbolFlagLogic {
+ this: Symbol =>
+
+ def distinguishingFlag: Long
+ override protected def alwaysHasFlags = super.alwaysHasFlags | distinguishingFlag
+ override protected def neverHasFlags = super.neverHasFlags & ~distinguishingFlag
+ }
+
+ trait SymbolFlagLogic {
+ this: Symbol =>
+
+ // Forced for performance reasons to define all the flag manipulation
+ // methods alongside the field being manipulated.
+ def getFlag(mask: Long): Long
+ def hasFlag(mask: Long): Boolean
+ def hasAllFlags(mask: Long): Boolean
+ def setFlag(mask: Long): this.type
+ def resetFlag(mask: Long): this.type
+ def initFlags(mask: Long): this.type
+ def resetFlags(): Unit
+
+ protected def resolveOverloadedFlag(flag: Long): String
+ protected def calculateFlagString(basis: Long): String
+
+ protected def alwaysHasFlags: Long = 0L
+ protected def neverHasFlags: Long = AllDistinguishingFlags
+
+ def rawFlagString(mask: Long): String = calculateFlagString(rawflags & mask)
+ def rawFlagString: String = rawFlagString(flagMask)
+ def debugFlagString: String = flagString(AllFlags)
+
+ /** String representation of symbol's variance */
+ def varianceString: String =
+ if (variance == 1) "+"
+ else if (variance == -1) "-"
+ else ""
+
+ override def flagMask =
+ if (settings.debug.value && !isAbstractType) AllFlags
+ else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE
+ else ExplicitFlags
+
+ // make the error message more googlable
+ def flagsExplanationString =
+ if (isGADTSkolem) " (this is a GADT skolem)"
+ else ""
+
+ /** If the given flag is set on this symbol, also set the corresponding
+ * notFLAG. For instance if flag is PRIVATE, the notPRIVATE flag will
+ * be set if PRIVATE is currently set.
+ */
+ final def setNotFlag(flag: Int) = if (hasFlag(flag)) setFlag((flag: @annotation.switch) match {
+ case PRIVATE => notPRIVATE
+ case PROTECTED => notPROTECTED
+ case OVERRIDE => notOVERRIDE
+ case _ => abort("setNotFlag on invalid flag: " + flag)
+ })
+
+ def shortSymbolClass = getClass.getName.split('.').last.stripPrefix("Symbols$")
+ def symbolCreationString: String = (
+ "%s%25s | %-40s | %s".format(
+ if (settings.uniqid.value) "%06d | ".format(id) else "",
+ shortSymbolClass,
+ name.decode + " in " + owner,
+ rawFlagString
+ )
+ )
+ }
+}
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index bb11ca634a..76b4f5f53e 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -13,7 +13,10 @@ import scala.tools.nsc.util.WeakHashSet
abstract class SymbolTable extends api.Universe
with Collections
with Names
+ with SymbolCreations
with Symbols
+ with SymbolFlags
+ with FreeVars
with Types
with Kinds
with ExistentialsAndSkolems
@@ -32,6 +35,10 @@ abstract class SymbolTable extends api.Universe
with TypeDebugging
with Importers
with Required
+ with TreeBuildUtil
+ with FrontEnds
+ with CapturedVariables
+ with StdAttachments
{
def rootLoader: LazyType
def log(msg: => AnyRef): Unit
@@ -43,10 +50,21 @@ abstract class SymbolTable extends api.Universe
/** Override with final implementation for inlining. */
def debuglog(msg: => String): Unit = if (settings.debug.value) log(msg)
def debugwarn(msg: => String): Unit = if (settings.debug.value) Console.err.println(msg)
+ def throwableAsString(t: Throwable): String = "" + t
+
+ /** Prints a stack trace if -Ydebug or equivalent was given, otherwise does nothing. */
+ def debugStack(t: Throwable): Unit = debugwarn(throwableAsString(t))
/** Overridden when we know more about what was happening during a failure. */
def supplementErrorMessage(msg: String): String = msg
+ private[scala] def printCaller[T](msg: String)(result: T) = {
+ Console.err.println("%s: %s\nCalled from: %s".format(msg, result,
+ (new Throwable).getStackTrace.drop(2).take(15).mkString("\n")))
+
+ result
+ }
+
private[scala] def printResult[T](msg: String)(result: T) = {
Console.err.println(msg + ": " + result)
result
@@ -62,6 +80,26 @@ abstract class SymbolTable extends api.Universe
result
}
+ // For too long have we suffered in order to sort NAMES.
+ // I'm pretty sure there's a reasonable default for that.
+ // Notice challenge created by Ordering's invariance.
+ implicit def lowPriorityNameOrdering[T <: Names#Name]: Ordering[T] =
+ SimpleNameOrdering.asInstanceOf[Ordering[T]]
+
+ private object SimpleNameOrdering extends Ordering[Names#Name] {
+ def compare(n1: Names#Name, n2: Names#Name) = (
+ if (n1 eq n2) 0
+ else n1.toString compareTo n2.toString
+ )
+ }
+
+ /** Dump each symbol to stdout after shutdown.
+ */
+ final val traceSymbolActivity = sys.props contains "scalac.debug.syms"
+ object traceSymbols extends {
+ val global: SymbolTable.this.type = SymbolTable.this
+ } with util.TraceSymbolActivity
+
/** Are we compiling for Java SE? */
// def forJVM: Boolean
@@ -93,6 +131,11 @@ abstract class SymbolTable extends api.Universe
final def atPhaseStack: List[Phase] = phStack
final def phase: Phase = ph
+ def atPhaseStackMessage = atPhaseStack match {
+ case Nil => ""
+ case ps => ps.reverseMap("->" + _).mkString("(", " ", ")")
+ }
+
final def phase_=(p: Phase) {
//System.out.println("setting phase to " + p)
assert((p ne null) && p != NoPhase, p)
@@ -144,7 +187,7 @@ abstract class SymbolTable extends api.Universe
try op
finally popPhase(saved)
}
-
+
/** Since when it is to be "at" a phase is inherently ambiguous,
* a couple unambiguously named methods.
@@ -206,7 +249,7 @@ abstract class SymbolTable extends api.Universe
def arrayToRepeated(tp: Type): Type = tp match {
case MethodType(params, rtpe) =>
val formals = tp.paramTypes
- assert(formals.last.typeSymbol == definitions.ArrayClass)
+ assert(formals.last.typeSymbol == definitions.ArrayClass, formals)
val method = params.last.owner
val elemtp = formals.last.typeArgs.head match {
case RefinedType(List(t1, t2), _) if (t1.typeSymbol.isAbstractType && t2.typeSymbol == definitions.ObjectClass) =>
@@ -214,8 +257,7 @@ abstract class SymbolTable extends api.Universe
case t =>
t
}
- val newParams = method.newSyntheticValueParams(
- formals.init :+ appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(elemtp)))
+ val newParams = method.newSyntheticValueParams(formals.init :+ definitions.javaRepeatedType(elemtp))
MethodType(newParams, rtpe)
case PolyType(tparams, rtpe) =>
PolyType(tparams, arrayToRepeated(rtpe))
@@ -242,14 +284,8 @@ abstract class SymbolTable extends api.Universe
object perRunCaches {
import java.lang.ref.WeakReference
import scala.runtime.ScalaRunTime.stringOf
+ import scala.collection.generic.Clearable
- // We can allow ourselves a structural type, these methods
- // amount to a few calls per run at most. This does suggest
- // a "Clearable" trait may be useful.
- private type Clearable = {
- def size: Int
- def clear(): Unit
- }
// Weak references so the garbage collector will take care of
// letting us know when a cache is really out of commission.
private val caches = mutable.HashSet[WeakReference[Clearable]]()
@@ -258,10 +294,14 @@ abstract class SymbolTable extends api.Universe
println(caches.size + " structures are in perRunCaches.")
caches.zipWithIndex foreach { case (ref, index) =>
val cache = ref.get()
- println("(" + index + ")" + (
- if (cache == null) " has been collected."
- else " has " + cache.size + " entries:\n" + stringOf(cache)
- ))
+ cache match {
+ case xs: Traversable[_] =>
+ println("(" + index + ")" + (
+ if (cache == null) " has been collected."
+ else " has " + xs.size + " entries:\n" + stringOf(xs)
+ ))
+ case _ =>
+ }
}
}
// if (settings.debug.value) {
@@ -275,8 +315,9 @@ abstract class SymbolTable extends api.Universe
def clearAll() = {
if (settings.debug.value) {
- val size = caches flatMap (ref => Option(ref.get)) map (_.size) sum;
- log("Clearing " + caches.size + " caches totalling " + size + " entries.")
+ // val size = caches flatMap (ref => Option(ref.get)) map (_.size) sum;
+ log("Clearing " + caches.size + " caches.")
+ // totalling " + size + " entries.")
}
caches foreach { ref =>
val cache = ref.get()
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 4473d63f5f..2a5b759f94 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -3,7 +3,6 @@
* @author Martin Odersky
*/
-
package scala.reflect
package internal
@@ -46,21 +45,32 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
m
}
- /** Create a new free variable. Its owner is NoSymbol.
+ /** Create a new free term. Its owner is NoSymbol.
+ */
+ def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeTerm =
+ new FreeTerm(name, value, origin) initFlags flags setInfo info
+
+ /** Create a new free type. Its owner is NoSymbol.
*/
- def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar =
- new FreeVar(name, value) initFlags newFlags setInfo tpe
+ def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String): FreeType =
+ new FreeType(name, value, origin) initFlags flags setInfo info
/** The original owner of a class. Used by the backend to generate
* EnclosingMethod attributes.
*/
val originalOwner = perRunCaches.newMap[Symbol, Symbol]()
- abstract class AbsSymbolImpl extends AbsSymbol { this: Symbol =>
- def newNestedSymbol(name: Name, pos: Position, newFlags: Long) = name match {
+ abstract class AbsSymbolImpl extends AbsSymbol {
+ this: Symbol =>
+
+ def kind: String = kindString
+ def isExistential: Boolean = this.isExistentiallyBound
+
+ def newNestedSymbol(name: Name, pos: Position, newFlags: Long, isClass: Boolean): Symbol = name match {
case n: TermName => newTermSymbol(n, pos, newFlags)
- case n: TypeName => newTypeSymbol(n, pos, newFlags)
+ case n: TypeName => if (isClass) newClassSymbol(n, pos, newFlags) else newNonClassSymbol(n, pos, newFlags)
}
+
def enclosingClass: Symbol = enclClass
def enclosingMethod: Symbol = enclMethod
def thisPrefix: Type = thisType
@@ -74,39 +84,130 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def setInternalFlags(flag: Long): this.type = { setFlag(flag); this }
def setTypeSignature(tpe: Type): this.type = { setInfo(tpe); this }
def setAnnotations(annots: AnnotationInfo*): this.type = { setAnnotations(annots.toList); this }
+
+ private def lastElemType(ts: Seq[Type]): Type = ts.last.normalize.typeArgs.head
+
+ private def formalTypes(formals: List[Type], nargs: Int): List[Type] = {
+ val formals1 = formals mapConserve {
+ case TypeRef(_, ByNameParamClass, List(arg)) => arg
+ case formal => formal
+ }
+ if (isVarArgTypes(formals1)) {
+ val ft = lastElemType(formals)
+ formals1.init ::: List.fill(nargs - (formals1.length - 1))(ft)
+ } else formals1
+ }
+
+ def resolveOverloaded(pre: Type, targs: Seq[Type], actuals: Seq[Type]): Symbol = {
+ def firstParams(tpe: Type): (List[Symbol], List[Type]) = tpe match {
+ case PolyType(tparams, restpe) =>
+ val (Nil, formals) = firstParams(restpe)
+ (tparams, formals)
+ case MethodType(params, _) =>
+ (Nil, params map (_.tpe))
+ case _ =>
+ (Nil, Nil)
+ }
+ def isApplicable(alt: Symbol, targs: List[Type], actuals: Seq[Type]) = {
+ def isApplicableType(tparams: List[Symbol], tpe: Type): Boolean = {
+ val (tparams, formals) = firstParams(pre memberType alt)
+ val formals1 = formalTypes(formals, actuals.length)
+ val actuals1 =
+ if (isVarArgTypes(actuals)) {
+ if (!isVarArgTypes(formals)) return false
+ actuals.init :+ lastElemType(actuals)
+ } else actuals
+ if (formals1.length != actuals1.length) return false
+
+ if (tparams.isEmpty) return (actuals1 corresponds formals1)(_ <:< _)
+
+ if (targs.length == tparams.length)
+ isApplicableType(List(), tpe.instantiateTypeParams(tparams, targs))
+ else if (targs.nonEmpty)
+ false
+ else {
+ val tvars = tparams map (TypeVar(_))
+ (actuals1 corresponds formals1) { (actual, formal) =>
+ val tp1 = actual.deconst.instantiateTypeParams(tparams, tvars)
+ val pt1 = actual.instantiateTypeParams(tparams, tvars)
+ tp1 <:< pt1
+ } &&
+ solve(tvars, tparams, List.fill(tparams.length)(COVARIANT), upper = false)
+ }
+ }
+ isApplicableType(List(), pre.memberType(alt))
+ }
+ def isAsGood(alt1: Symbol, alt2: Symbol): Boolean = {
+ alt1 == alt2 ||
+ alt2 == NoSymbol || {
+ val (tparams, formals) = firstParams(pre memberType alt1)
+ isApplicable(alt2, tparams map (_.tpe), formals)
+ }
+ }
+ assert(isOverloaded)
+ val applicables = alternatives filter (isApplicable(_, targs.toList, actuals))
+ def winner(alts: List[Symbol]) =
+ ((NoSymbol: Symbol) /: alts)((best, alt) => if (isAsGood(alt, best)) alt else best)
+ val best = winner(applicables)
+ if (best == winner(applicables.reverse)) best else NoSymbol
+ }
}
/** The class for all symbols */
abstract class Symbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: Name)
extends AbsSymbolImpl
with HasFlags
+ with SymbolFlagLogic
+ with SymbolCreator
+ // with FlagVerifier // DEBUG
with Annotatable[Symbol] {
- type FlagsType = Long
type AccessBoundaryType = Symbol
type AnnotationType = AnnotationInfo
+ // TODO - don't allow names to be renamed in this unstructured a fashion.
+ // Rename as little as possible. Enforce invariants on all renames.
+ type NameType >: Null <: Name
+ type TypeOfClonedSymbol >: Null <: Symbol { type NameType = Symbol.this.NameType }
+
+ // Abstract here so TypeSymbol and TermSymbol can have a private[this] field
+ // with the proper specific type.
+ def rawname: NameType
+ def name: NameType
+ def name_=(n: Name): Unit
+ def asNameType(n: Name): NameType
+
private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api
- private[this] var _rawname = initName
- private[this] var _rawflags = 0L
+ private[this] var _rawflags: Long = _
def rawowner = _rawowner
- def rawname = _rawname
def rawflags = _rawflags
- protected def rawflags_=(x: FlagsType) { _rawflags = x }
-
private var rawpos = initPos
val id = nextId() // identity displayed when -uniqid
-
private[this] var _validTo: Period = NoPeriod
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbol(this)
+
def validTo = _validTo
def validTo_=(x: Period) { _validTo = x}
def pos = rawpos
def setPos(pos: Position): this.type = { this.rawpos = pos; this }
+ def setName(name: Name): this.type = { this.name = asNameType(name) ; this }
+
+ // Update the surrounding scopes
+ protected[this] def changeNameInOwners(name: Name) {
+ if (owner.isClass) {
+ var ifs = owner.infos
+ while (ifs != null) {
+ ifs.info.decls.rehash(this, name)
+ ifs = ifs.prev
+ }
+ }
+ }
/** !!! The logic after "hasFlag" is far too opaque to be unexplained.
* I'm guessing it's attempting to compensate for flag overloading,
@@ -131,87 +232,54 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
newTermSymbol(name, pos, PARAM | newFlags)
/** Create local dummy for template (owner of local blocks) */
- final def newLocalDummy(pos: Position) =
+ final def newLocalDummy(pos: Position): TermSymbol =
newTermSymbol(nme.localDummyName(this), pos) setInfo NoType
final def newMethod(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
- newMethodSymbol(name, pos, METHOD | newFlags)
+ createMethodSymbol(name, pos, METHOD | newFlags)
final def newLabel(name: TermName, pos: Position = NoPosition): MethodSymbol =
newMethod(name, pos, LABEL)
/** Propagates ConstrFlags (JAVA, specifically) from owner to constructor. */
- final def newConstructor(pos: Position, newFlags: Long = 0L) =
+ final def newConstructor(pos: Position, newFlags: Long = 0L): MethodSymbol =
newMethod(nme.CONSTRUCTOR, pos, getFlag(ConstrFlags) | newFlags)
/** Static constructor with info set. */
- def newStaticConstructor(pos: Position) =
+ def newStaticConstructor(pos: Position): MethodSymbol =
newConstructor(pos, STATIC) setInfo UnitClass.tpe
+
/** Instance constructor with info set. */
- def newClassConstructor(pos: Position) =
+ def newClassConstructor(pos: Position): MethodSymbol =
newConstructor(pos) setInfo MethodType(Nil, this.tpe)
- // Top-level objects can be automatically marked final, but others
- // must be explicitly marked final if overridable objects are enabled.
- private def ModuleFlags = (
- if (isPackage || !settings.overrideObjects.value) MODULE | FINAL
- else MODULE
- )
def newLinkedModule(clazz: Symbol, newFlags: Long = 0L): ModuleSymbol = {
- val m = newModuleSymbol(clazz.name.toTermName, clazz.pos, ModuleFlags | newFlags)
+ val m = newModuleSymbol(clazz.name.toTermName, clazz.pos, MODULE | newFlags)
connectModuleToClass(m, clazz.asInstanceOf[ClassSymbol])
}
final def newModule(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = {
- val m = newModuleSymbol(name, pos, newFlags | ModuleFlags)
- val clazz = newModuleClassSymbol(name.toTypeName, pos, (m getFlag ModuleToClassFlags) | MODULE)
+ val m = newModuleSymbol(name, pos, newFlags | MODULE)
+ val clazz = newModuleClass(name.toTypeName, pos, m getFlag ModuleToClassFlags)
connectModuleToClass(m, clazz)
}
final def newPackage(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol = {
assert(name == nme.ROOT || isPackageClass, this)
- newModule(name, pos, JAVA | PACKAGE | newFlags)
+ newModule(name, pos, PackageFlags | newFlags)
}
- final def newThisSym(pos: Position) =
- newTermSymbol(nme.this_, pos, SYNTHETIC)
- final def newImport(pos: Position) =
- newTermSymbol(nme.IMPORT, pos)
-
- /** Direct symbol factories.
- * For internal use; these are unlikely to be what you want.
- */
- def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
- new TermSymbol(this, pos, name) initFlags newFlags
-
- def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol =
- new AbstractTypeSymbol(this, pos, name) initFlags newFlags
-
- def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol =
- new AliasTypeSymbol(this, pos, name) initFlags newFlags
- def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
- new ModuleSymbol(this, pos, name) initFlags newFlags
+ final def newThisSym(name: TermName = nme.this_, pos: Position = NoPosition): TermSymbol =
+ newTermSymbol(name, pos, SYNTHETIC)
- def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
- new MethodSymbol(this, pos, name) initFlags newFlags
+ final def newImport(pos: Position): TermSymbol =
+ newTermSymbol(nme.IMPORT, pos)
- def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
- new ClassSymbol(this, pos, name) initFlags newFlags
+ final def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
+ newTermSymbol(name, pos, newFlags).asInstanceOf[ModuleSymbol]
- def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
- new ModuleClassSymbol(this, pos, name) initFlags newFlags
+ final def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
+ newClassSymbol(name, pos, newFlags).asInstanceOf[ModuleClassSymbol]
- /** Derive whether it is an abstract type from the flags; after creation
- * the DEFERRED flag will be ignored.
- */
- def newTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
- if ((newFlags & DEFERRED) == 0L)
- newAliasTypeSymbol(name, pos, newFlags)
- else
- newAbstractTypeSymbol(name, pos, newFlags)
-
- def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem =
- if ((newFlags & DEFERRED) == 0L)
- new TypeSkolem(this, pos, name, origin) initFlags newFlags
- else
- new TypeSkolem(this, pos, name, origin) with AbstractTypeMixin initFlags newFlags
+ final def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem =
+ createTypeSkolemSymbol(name, origin, pos, newFlags)
/** @param pre type relative to which alternatives are seen.
* for instance:
@@ -231,40 +299,45 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*
* pre.memberType(m)
*/
- final def newOverloaded(pre: Type, alternatives: List[Symbol]): Symbol = (
+ final def newOverloaded(pre: Type, alternatives: List[Symbol]): TermSymbol = (
newTermSymbol(alternatives.head.name.toTermName, alternatives.head.pos, OVERLOADED)
setInfo OverloadedType(pre, alternatives)
)
- final def newErrorValue(name: TermName) =
+ final def newErrorValue(name: TermName): TermSymbol =
newTermSymbol(name, pos, SYNTHETIC | IS_ERROR) setInfo ErrorType
/** Symbol of a type definition type T = ...
*/
- final def newAliasType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol =
- newAliasTypeSymbol(name, pos, newFlags)
+ final def newAliasType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol =
+ createAliasTypeSymbol(name, pos, newFlags)
/** Symbol of an abstract type type T >: ... <: ...
*/
- final def newAbstractType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol =
- newAbstractTypeSymbol(name, pos, DEFERRED | newFlags)
+ final def newAbstractType(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol =
+ createAbstractTypeSymbol(name, pos, DEFERRED | newFlags)
/** Symbol of a type parameter
*/
- final def newTypeParameter(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) =
+ final def newTypeParameter(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
newAbstractType(name, pos, PARAM | newFlags)
+ /** Symbol of an existential type T forSome { ... }
+ */
+ final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): TypeSymbol =
+ newAbstractType(name, pos, EXISTENTIAL | newFlags)
+
/** Synthetic value parameters when parameter symbols are not available
*/
- final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[Symbol]] = {
+ final def newSyntheticValueParamss(argtypess: List[List[Type]]): List[List[TermSymbol]] = {
var cnt = 0
def freshName() = { cnt += 1; nme.syntheticParamName(cnt) }
- mmap(argtypess)(tp => newValueParameter(freshName(), focusPos(owner.pos), SYNTHETIC) setInfo tp)
+ mmap(argtypess)(tp => newValueParameter(freshName(), owner.pos.focus, SYNTHETIC) setInfo tp)
}
- def newSyntheticTypeParam(): Symbol = newSyntheticTypeParam("T0", 0L)
- def newSyntheticTypeParam(name: String, newFlags: Long): Symbol = newTypeParameter(newTypeName(name), NoPosition, newFlags) setInfo TypeBounds.empty
- def newSyntheticTypeParams(num: Int): List[Symbol] = (0 until num).toList map (n => newSyntheticTypeParam("T" + n, 0L))
+ def newSyntheticTypeParam(): TypeSymbol = newSyntheticTypeParam("T0", 0L)
+ def newSyntheticTypeParam(name: String, newFlags: Long): TypeSymbol = newTypeParameter(newTypeName(name), NoPosition, newFlags) setInfo TypeBounds.empty
+ def newSyntheticTypeParams(num: Int): List[TypeSymbol] = (0 until num).toList map (n => newSyntheticTypeParam("T" + n, 0L))
/** Create a new existential type skolem with this symbol its owner,
* based on the given symbol and origin.
@@ -279,17 +352,13 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def newGADTSkolem(name: TypeName, origin: Symbol, info: Type): TypeSkolem =
newTypeSkolemSymbol(name, origin, origin.pos, origin.flags & ~(EXISTENTIAL | PARAM) | CASEACCESSOR | SYNTHETIC) setInfo info
-
- final def newExistential(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): Symbol =
- newAbstractType(name, pos, EXISTENTIAL | newFlags)
-
- final def freshExistential(suffix: String): Symbol =
+ final def freshExistential(suffix: String): TypeSymbol =
newExistential(freshExistentialName(suffix), pos)
/** Synthetic value parameters when parameter symbols are not available.
* Calling this method multiple times will re-use the same parameter names.
*/
- final def newSyntheticValueParams(argtypes: List[Type]): List[Symbol] =
+ final def newSyntheticValueParams(argtypes: List[Type]): List[TermSymbol] =
newSyntheticValueParamss(List(argtypes)).head
/** Synthetic value parameter when parameter symbol is not available.
@@ -303,41 +372,42 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* with name `T` in its typeParams list. While type checking the parameters, result type and
* body of the method, there's a local copy of `T` which is a TypeSkolem.
*/
- final def newTypeSkolem: Symbol =
+ final def newTypeSkolem: TypeSkolem =
owner.newTypeSkolemSymbol(name.toTypeName, this, pos, flags)
- final def newClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L) =
+ final def newClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
newClassSymbol(name, pos, newFlags)
/** A new class with its info set to a ClassInfoType with given scope and parents. */
- def newClassWithInfo(name: TypeName, parents: List[Type], scope: Scope, pos: Position = NoPosition, newFlags: Long = 0L) = {
+ def newClassWithInfo(name: TypeName, parents: List[Type], scope: Scope, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = {
val clazz = newClass(name, pos, newFlags)
clazz setInfo ClassInfoType(parents, scope, clazz)
}
- final def newErrorClass(name: TypeName) =
+ final def newErrorClass(name: TypeName): ClassSymbol =
newClassWithInfo(name, Nil, new ErrorScope(this), pos, SYNTHETIC | IS_ERROR)
- final def newModuleClass(name: TypeName, pos: Position = NoPosition) =
- newModuleClassSymbol(name, pos)
-
- final def newAnonymousClass(pos: Position) =
- newClassSymbol(tpnme.ANON_CLASS_NAME, pos)
+ final def newModuleClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
+ newModuleClassSymbol(name, pos, newFlags | MODULE)
- final def newAnonymousFunctionClass(pos: Position, newFlags: Long = 0L) =
+ final def newAnonymousFunctionClass(pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
newClassSymbol(tpnme.ANON_FUN_NAME, pos, FINAL | SYNTHETIC | newFlags)
- final def newAnonymousFunctionValue(pos: Position, newFlags: Long = 0L) =
+ final def newAnonymousFunctionValue(pos: Position, newFlags: Long = 0L): TermSymbol =
newTermSymbol(nme.ANON_FUN_NAME, pos, SYNTHETIC | newFlags) setInfo NoType
+ def newImplClass(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol = {
+ newClassSymbol(name, pos, newFlags | IMPLCLASS)
+ }
+
/** Refinement types P { val x: String; type T <: Number }
* also have symbols, they are refinementClasses
*/
- final def newRefinementClass(pos: Position) =
- newClass(tpnme.REFINE_CLASS_NAME, pos)
+ final def newRefinementClass(pos: Position): RefinementClassSymbol =
+ createRefinementClassSymbol(pos, 0L)
/** Create a new getter for current symbol (which must be a field)
*/
- final def newGetter: Symbol = (
+ final def newGetter: MethodSymbol = (
owner.newMethod(nme.getterName(name.toTermName), NoPosition, getterFlags(flags))
setPrivateWithin privateWithin
setInfo MethodType(Nil, tpe)
@@ -348,6 +418,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
case x: TermName => newErrorValue(x)
}
+ /** To overcome the crazy challenge of more specific types appearing
+ * in incoming positions. Don't need this much.
+ */
+ def asTypeSymbol: TypeSymbol = this match {
+ case x: TypeSymbol => x
+ case x => throw new FatalError(this + " is not a TypeSymbol")
+ }
+ def asTermSymbol: TermSymbol = this match {
+ case x: TermSymbol => x
+ case x => throw new FatalError(this + " is not a TermSymbol")
+ }
+
@deprecated("Use the other signature", "2.10.0")
def newClass(pos: Position, name: TypeName): Symbol = newClass(name, pos)
@deprecated("Use the other signature", "2.10.0")
@@ -371,7 +453,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// True if the symbol is locked but still below the allowed recursion depth.
// False otherwise
private[scala] def lockOK: Boolean = {
- ((rawflags & LOCKED) == 0L) ||
+ ((_rawflags & LOCKED) == 0L) ||
((settings.Yrecursion.value != 0) &&
(recursionTable get this match {
case Some(n) => (n <= settings.Yrecursion.value)
@@ -380,7 +462,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// Lock a symbol, using the handler if the recursion depth becomes too great.
private[scala] def lock(handler: => Unit): Boolean = {
- if ((rawflags & LOCKED) != 0L) {
+ if ((_rawflags & LOCKED) != 0L) {
if (settings.Yrecursion.value != 0) {
recursionTable get this match {
case Some(n) =>
@@ -397,7 +479,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
} else { handler; false }
} else {
- rawflags |= LOCKED
+ _rawflags |= LOCKED
true
// activeLocks += 1
// lockedSyms += this
@@ -406,10 +488,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// Unlock a symbol
private[scala] def unlock() = {
- if ((rawflags & LOCKED) != 0L) {
+ if ((_rawflags & LOCKED) != 0L) {
// activeLocks -= 1
// lockedSyms -= this
- _rawflags = rawflags & ~LOCKED
+ _rawflags &= ~LOCKED
if (settings.Yrecursion.value != 0)
recursionTable -= this
}
@@ -417,42 +499,101 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ----- tests ----------------------------------------------------------------------
- def isTerm = false // to be overridden
- def isType = false // to be overridden
- def isClass = false // to be overridden
- def isBottomClass = false // to be overridden
- def isAliasType = false // to be overridden
- def isAbstractType = false // to be overridden
- private[scala] def isSkolem = false // to be overridden
-
- /** Is this symbol a type but not a class? */
- def isNonClassType = false // to be overridden
-
- override final def isTrait = isClass && hasFlag(TRAIT)
- final def isAbstractClass = isClass && hasFlag(ABSTRACT)
- final def isBridge = hasFlag(BRIDGE)
- final def isContravariant = isType && hasFlag(CONTRAVARIANT)
- final def isConcreteClass = isClass && !hasFlag(ABSTRACT | TRAIT)
- final def isCovariant = isType && hasFlag(COVARIANT)
- final def isEarlyInitialized = isTerm && hasFlag(PRESUPER)
- final def isExistentiallyBound = isType && hasFlag(EXISTENTIAL)
- final def isImplClass = isClass && hasFlag(IMPLCLASS)
- final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol
- final def isMethod = isTerm && hasFlag(METHOD)
- final def isModule = isTerm && hasFlag(MODULE)
- final def isModuleClass = isClass && hasFlag(MODULE)
- final def isNumericValueClass = definitions.isNumericValueClass(this)
- final def isOverloaded = hasFlag(OVERLOADED)
- final def isOverridableMember = !(isClass || isEffectivelyFinal) && owner.isClass
- final def isRefinementClass = isClass && name == tpnme.REFINE_CLASS_NAME
- final def isSourceMethod = isMethod && !hasFlag(STABLE) // exclude all accessors!!!
- final def isTypeParameter = isType && isParameter && !isSkolem
- final def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this)
- final def isVarargsMethod = isMethod && hasFlag(VARARGS)
-
- /** Package tests */
- final def isPackage = isModule && hasFlag(PACKAGE)
- final def isPackageClass = isClass && hasFlag(PACKAGE)
+ /** All symbols are one of three categories: TermSymbol, TypeSymbol, or NoSymbol.
+ * There is only one NoSymbol.
+ */
+ def isTerm = false
+ def isType = false
+
+ /** TypeSymbols fall into four named direct subclasses:
+ * - ClassSymbol
+ * - AliasTypeSymbol
+ * - AbstractTypeSymbol
+ * - TypeSkolem
+ */
+ def isClass = false
+ def isAliasType = false
+ def isAbstractType = false
+ def isSkolem = false
+
+ /** A Type, but not a Class. */
+ def isNonClassType = false
+
+ /** The bottom classes are Nothing and Null, found in Definitions. */
+ def isBottomClass = false
+ def isSpecialized = this hasFlag SPECIALIZED
+
+ /** These are all tests for varieties of ClassSymbol, which has these subclasses:
+ * - ModuleClassSymbol
+ * - RefinementClassSymbol
+ * - PackageClassSymbol (extends ModuleClassSymbol)
+ */
+ def isAbstractClass = false
+ def isAnonOrRefinementClass = false
+ def isAnonymousClass = false
+ def isCaseClass = false
+ def isConcreteClass = false
+ def isImplClass = false // the implementation class of a trait
+ def isJavaInterface = false
+ def isModuleClass = false
+ def isNumericValueClass = false
+ def isPrimitiveValueClass = false
+ def isRefinementClass = false
+ override def isTrait = false
+
+ /** Qualities of Types, always false for TermSymbols.
+ */
+ def isContravariant = false
+ def isCovariant = false
+ def isExistentialQuantified = false
+ def isExistentialSkolem = false
+ def isExistentiallyBound = false
+ def isGADTSkolem = false
+ def isTypeParameter = false
+ def isTypeParameterOrSkolem = false
+ def isTypeSkolem = false
+ def isTypeMacro = false
+ def isFreeType = false
+
+ /** Qualities of Terms, always false for TypeSymbols.
+ */
+ def isAccessor = false
+ def isBridge = false
+ def isCapturedVariable = false
+ def isClassConstructor = false
+ def isConstructor = false
+ def isEarlyInitialized = false
+ def isGetter = false
+ def isLocalDummy = false
+ def isMixinConstructor = false
+ def isModule = false
+ def isOverloaded = false
+ def isSetter = false
+ def isSetterParameter = false
+ def isValue = false
+ def isValueParameter = false
+ def isVariable = false
+ override def hasDefault = false
+ def isTermMacro = false
+ def isFreeTerm = false
+
+ /** Qualities of MethodSymbols, always false for TypeSymbols
+ * and other TermSymbols.
+ */
+ def isCaseAccessorMethod = false
+ def isLiftedMethod = false
+ def isMethod = false
+ def isSourceMethod = false
+ def isVarargsMethod = false
+ override def isLabel = false
+
+ /** Package/package object tests */
+ def isPackage = false
+ def isPackageClass = false
+ def isPackageObject = false
+ def isPackageObjectClass = false
+ def isPackageObjectOrClass = isPackageObject || isPackageObjectClass
+ def isModuleOrModuleClass = isModule || isModuleClass
/** Overridden in custom objects in Definitions */
def isRoot = false
@@ -465,54 +606,64 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def isEffectiveRoot = false
- /** For RootClass, EmptyPackageClass. For all other symbols, itself.
+ /** For RootClass, this is EmptyPackageClass. For all other symbols,
+ * the symbol itself.
*/
def ownerOfNewSymbols = this
+ final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol
+ final def isOverridableMember = !(isClass || isEffectivelyFinal) && (this ne NoSymbol) && owner.isClass
+
/** Does this symbol denote a wrapper created by the repl? */
final def isInterpreterWrapper = (
- (isModule || isModuleClass)
+ (this hasFlag MODULE)
&& owner.isPackageClass
&& nme.isReplWrapperName(name)
)
+ @inline final override def getFlag(mask: Long): Long = flags & mask
+ /** Does symbol have ANY flag in `mask` set? */
+ @inline final override def hasFlag(mask: Long): Boolean = (flags & mask) != 0
+ /** Does symbol have ALL the flags in `mask` set? */
+ @inline final override def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask
- /** Term symbols with the exception of static parts of Java classes and packages.
- */
- final def isValue = isTerm && !(isModule && hasFlag(PACKAGE | JAVA))
+ override def setFlag(mask: Long): this.type = { _rawflags |= mask ; this }
+ override def resetFlag(mask: Long): this.type = { _rawflags &= ~mask ; this }
+ override def resetFlags() { rawflags &= (TopLevelCreationFlags | alwaysHasFlags) }
- final def isVariable = isTerm && isMutable && !isMethod
+ /** Default implementation calls the generic string function, which
+ * will print overloaded flags as <flag1/flag2/flag3>. Subclasses
+ * of Symbol refine.
+ */
+ override def resolveOverloadedFlag(flag: Long): String = Flags.flagToString(flag)
- // interesting only for lambda lift. Captured variables are accessed from inner lambdas.
- final def isCapturedVariable = isVariable && hasFlag(CAPTURED)
+ /** Set the symbol's flags to the given value, asserting
+ * that the previous value was 0.
+ */
+ override def initFlags(mask: Long): this.type = {
+ assert(rawflags == 0L, symbolCreationString)
+ _rawflags = mask
+ this
+ }
- final def isGetter = isTerm && hasAccessorFlag && !nme.isSetterName(name)
- // todo: make independent of name, as this can be forged.
- final def isSetter = isTerm && hasAccessorFlag && nme.isSetterName(name)
- def isSetterParameter = isValueParameter && owner.isSetter
+ final def flags: Long = {
+ val fs = _rawflags & phase.flagMask
+ (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift)
+ }
+ def flags_=(fs: Long) = _rawflags = fs
+ def rawflags_=(x: Long) { _rawflags = x }
final def hasGetter = isTerm && nme.isLocalName(name)
- final def isValueParameter = isTerm && hasFlag(PARAM)
- final def isLocalDummy = isTerm && nme.isLocalDummyName(name)
final def isInitializedToDefault = !isType && hasAllFlags(DEFAULTINIT | ACCESSOR)
- final def isClassConstructor = isTerm && (name == nme.CONSTRUCTOR)
- final def isMixinConstructor = isTerm && (name == nme.MIXIN_CONSTRUCTOR)
- final def isConstructor = isTerm && nme.isConstructorName(name)
final def isStaticModule = isModule && isStatic && !isMethod
final def isThisSym = isTerm && owner.thisSym == this
final def isError = hasFlag(IS_ERROR)
final def isErroneous = isError || isInitialized && tpe.isErroneous
- final def isTypeParameterOrSkolem = isType && hasFlag(PARAM)
- final def isHigherOrderTypeParameter = (this ne NoSymbol) && owner.isTypeParameterOrSkolem
- final def isTypeSkolem = isSkolem && hasFlag(PARAM)
- // a type symbol bound by an existential type, for instance the T in
- // List[T] forSome { type T }
- final def isExistentialSkolem = isExistentiallyBound && isSkolem
- final def isExistentialQuantified = isExistentiallyBound && !isSkolem
- final def isGADTSkolem = isSkolem && hasFlag(CASEACCESSOR | SYNTHETIC)
+
+ def isHigherOrderTypeParameter = owner.isTypeParameterOrSkolem
// class C extends D( { class E { ... } ... } ). Here, E is a class local to a constructor
- final def isClassLocalToConstructor = isClass && hasFlag(INCONSTRUCTOR)
+ def isClassLocalToConstructor = false
final def isDerivedValueClass =
isClass && info.firstParent.typeSymbol == AnyValClass && !isPrimitiveValueClass
@@ -520,29 +671,26 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isMethodWithExtension =
isMethod && owner.isDerivedValueClass && !isParamAccessor && !isConstructor && !hasFlag(SUPERACCESSOR)
- final def isAnonymousClass = isClass && (name containsName tpnme.ANON_CLASS_NAME)
- final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
- final def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass
-
- // A package object or its module class
- final def isPackageObjectOrClass = (this ne NoSymbol) && owner.isPackageClass && (name == nme.PACKAGE || name == tpnme.PACKAGE)
- final def isPackageObject = (this ne NoSymbol) && owner.isPackageClass && name == nme.PACKAGE
- final def isPackageObjectClass = (this ne NoSymbol) && owner.isPackageClass && name == tpnme.PACKAGE
-
+ final def isAnonymousFunction = isSynthetic && (name containsName tpnme.ANON_FUN_NAME)
final def isDefinedInPackage = effectiveOwner.isPackageClass
- final def isJavaInterface = isJavaDefined && isTrait
- final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass
+ final def needsFlatClasses = phase.flatClasses && rawowner != NoSymbol && !rawowner.isPackageClass
+
+ /** change name by appending $$<fully-qualified-name-of-class `base`>
+ * Do the same for any accessed symbols or setters/getters.
+ * Implementation in TermSymbol.
+ */
+ def expandName(base: Symbol) { }
// In java.lang, Predef, or scala package/package object
def isInDefaultNamespace = UnqualifiedOwners(effectiveOwner)
/** The owner, skipping package objects.
*/
- def effectiveOwner = if (owner.isPackageObjectClass) owner.skipPackageObject else owner
+ def effectiveOwner = owner.skipPackageObject
/** If this is a package object or its implementing class, its owner: otherwise this.
*/
- final def skipPackageObject: Symbol = if (isPackageObjectOrClass) owner else this
+ def skipPackageObject: Symbol = this
/** If this is a constructor, its owner: otherwise this.
*/
@@ -560,7 +708,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
|| isAnonOrRefinementClass // has uninteresting <anon> or <refinement> prefix
|| nme.isReplWrapperName(name) // has ugly $iw. prefix (doesn't call isInterpreterWrapper due to nesting)
)
- def isFBounded = info.baseTypeSeq exists (_ contains this)
+ def isFBounded = info match {
+ case TypeBounds(_, _) => info.baseTypeSeq exists (_ contains this)
+ case _ => false
+ }
/** Is symbol a monomorphic type?
* assumption: if a type starts out as monomorphic, it will not acquire
@@ -568,13 +719,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
final def isMonomorphicType =
isType && {
- var is = infos
- (is eq null) || {
- while (is.prev ne null) { is = is.prev }
- is.info.isComplete && !is.info.isHigherKinded // was: is.info.typeParams.isEmpty.
- // YourKit listed the call to PolyType.typeParams as a hot spot but it is likely an artefact.
- // The change to isHigherKinded did not reduce the total running time.
- }
+ val info = originalInfo
+ info.isComplete && !info.isHigherKinded
}
def isStrictFP = hasAnnotation(ScalaStrictFPAttr) || (enclClass hasAnnotation ScalaStrictFPAttr)
@@ -613,22 +759,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
/** Does this symbol denote a stable value? */
- final def isStable =
- isTerm &&
- !isMutable &&
- (!hasFlag(METHOD | BYNAMEPARAM) || hasFlag(STABLE)) &&
- !(tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
-
- // def isVirtualClass = hasFlag(DEFERRED) && isClass
- // def isVirtualTrait = hasFlag(DEFERRED) && isTrait
- def isLiftedMethod = isMethod && hasFlag(LIFTED)
- def isCaseClass = isClass && isCase
-
- // unfortunately having the CASEACCESSOR flag does not actually mean you
- // are a case accessor (you can also be a field.)
- def isCaseAccessorMethod = isMethod && isCaseAccessor
-
- def isMacro = isMethod && hasFlag(MACRO)
+ def isStable = false
/** Does this symbol denote the primary constructor of its enclosing class? */
final def isPrimaryConstructor =
@@ -643,23 +774,27 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
isMethod && isCase && isSynthetic
/** Is this symbol a trait which needs an implementation class? */
- final def needsImplClass: Boolean =
- isTrait && (!isInterface || hasFlag(lateINTERFACE)) && !isImplClass
+ final def needsImplClass = (
+ isTrait
+ && (!isInterface || hasFlag(lateINTERFACE))
+ && !isImplClass
+ )
/** Is this a symbol which exists only in the implementation class, not in its trait? */
- final def isImplOnly: Boolean =
- hasFlag(PRIVATE) ||
- (owner.isImplClass || owner.isTrait) &&
- ((hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE) || isConstructor) ||
- (hasFlag(LIFTED) && isModule && isMethod))
-
- /** Is this symbol a module variable?
- * This used to have to test for MUTABLE to distinguish the overloaded
- * MODULEVAR/SYNTHETICMETH flag, but now SYNTHETICMETH is gone.
- */
+ final def isImplOnly = isPrivate || (
+ (owner.isTrait || owner.isImplClass) && (
+ hasAllFlags(LIFTED | MODULE | METHOD)
+ || isConstructor
+ || hasFlag(notPRIVATE | LIFTED) && !hasFlag(ACCESSOR | SUPERACCESSOR | MODULE)
+ )
+ )
final def isModuleVar = hasFlag(MODULEVAR)
- /** Is this symbol static (i.e. with no outer instance)? */
+ /** Is this symbol static (i.e. with no outer instance)?
+ * Q: When exactly is a sym marked as STATIC?
+ * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep.
+ * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6
+ */
def isStatic = (this hasFlag STATIC) || owner.isStaticOwner
/** Is this symbol a static constructor? */
@@ -674,10 +809,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isStaticOwner: Boolean =
isPackageClass || isModuleClass && isStatic
+ def isTopLevelModule = hasFlag(MODULE) && owner.isPackageClass
+
/** Is this symbol effectively final? I.e, it cannot be overridden */
final def isEffectivelyFinal: Boolean = (
- isFinal
- || hasModuleFlag && !settings.overrideObjects.value
+ (this hasFlag FINAL | PACKAGE)
+ || isModuleOrModuleClass && (owner.isPackageClass || !settings.overrideObjects.value)
|| isTerm && (
isPrivate
|| isLocal
@@ -692,7 +829,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isConstant: Boolean = isStable && isConstantType(tpe.resultType)
/** Is this class nested in another class or module (not a package)? */
- def isNestedClass = isClass && !owner.isPackageClass
+ def isNestedClass = false
/** Is this class locally defined?
* A class is local, if
@@ -700,9 +837,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* - its owner is a value
* - it is defined within a local class
*/
- final def isLocalClass: Boolean =
- isClass && (isAnonOrRefinementClass || isLocal ||
- !owner.isPackageClass && owner.isLocalClass)
+ def isLocalClass = false
+
+ def isStableClass = false
/* code for fixing nested objects
override final def isModuleClass: Boolean =
@@ -713,6 +850,16 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isStructuralRefinement: Boolean =
(isClass || isType || isModule) && info.normalize/*.underlying*/.isStructuralRefinement
+ /** Is this a term symbol only defined in a refinement (so that it needs
+ * to be accessed by reflection)?
+ */
+ def isOnlyRefinementMember: Boolean =
+ isTerm && // type members are not affected
+ owner.isRefinementClass && // owner must be a refinement class
+ (owner.info decl name) == this && // symbol must be explicitly declared in the refinement (not synthesized from glb)
+ allOverriddenSymbols.isEmpty && // symbol must not override a symbol in a base class
+ !isConstant // symbol must not be a constant. Question: Can we exclude @inline methods as well?
+
final def isStructuralRefinementMember = owner.isStructuralRefinement && isPossibleInRefinement && isPublic
final def isPossibleInRefinement = !isConstructor && !isOverridingSymbol
@@ -737,25 +884,29 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// Does not always work if the rawInfo is a SourcefileLoader, see comment
// in "def coreClassesFirst" in Global.
- final def exists: Boolean =
- this != NoSymbol && (!owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType })
+ def exists = !owner.isPackageClass || { rawInfo.load(this); rawInfo != NoType }
final def isInitialized: Boolean =
validTo != NoPeriod
- final def isStableClass: Boolean = {
- def hasNoAbstractTypeMember(clazz: Symbol): Boolean =
- (clazz hasFlag STABLE) || {
- var e = clazz.info.decls.elems
- while ((e ne null) && !(e.sym.isAbstractType && info.member(e.sym.name) == e.sym))
- e = e.next
- e == null
- }
- def checkStable() =
- (info.baseClasses forall hasNoAbstractTypeMember) && { setFlag(STABLE); true }
- isClass && (hasFlag(STABLE) || checkStable())
+ // [Eugene] is this correct?
+ /** Determines whether this symbol can be loaded by subsequent reflective compilation */
+ final def isLocatable: Boolean = {
+ if (this == NoSymbol) return false
+ if (isRoot || isRootPackage) return true
+
+ if (!owner.isLocatable) return false
+ if (owner.isTerm) return false
+ if (isLocalDummy) return false
+
+ if (isType && isNonClassType) return false
+ if (isRefinementClass) return false
+ return true
}
+ // [Eugene] is it a good idea to add ``dealias'' to Symbol?
+ /** Expands type aliases */
+ def dealias: Symbol = this
/** The variance of this symbol as an integer */
final def variance: Int =
@@ -763,7 +914,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else if (isContravariant) -1
else 0
-
/** The sequence number of this parameter symbol among all type
* and value parameters of symbol's owner. -1 if symbol does not
* appear among the parameters of its owner.
@@ -787,6 +937,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ------ owner attribute --------------------------------------------------------------
def owner: Symbol = rawowner
+ // TODO - don't allow the owner to be changed without checking invariants, at least
+ // when under some flag. Define per-phase invariants for owner/owned relationships,
+ // e.g. after flatten all classes are owned by package classes, there are lots and
+ // lots of these to be declared (or more realistically, discovered.)
def owner_=(owner: Symbol) {
// don't keep the original owner in presentation compiler runs
// (the map will grow indefinitely, and the only use case is the
@@ -796,17 +950,16 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else originalOwner(this) = rawowner
}
assert(!inReflexiveMirror, "owner_= is not thread-safe; cannot be run in reflexive code")
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbolOwner(this, owner)
_rawowner = owner
}
def ownerChain: List[Symbol] = this :: owner.ownerChain
def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain
- def enclClassChain: List[Symbol] = {
- if ((this eq NoSymbol) || isPackageClass) Nil
- else if (isClass) this :: owner.enclClassChain
- else owner.enclClassChain
- }
+ // Non-classes skip self and return rest of owner chain; overridden in ClassSymbol.
+ def enclClassChain: List[Symbol] = owner.enclClassChain
def ownersIterator: Iterator[Symbol] = new Iterator[Symbol] {
private var current = Symbol.this
@@ -814,34 +967,17 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def next = { val r = current; current = current.owner; r }
}
- /** same as ownerChain contains sym, but more efficient, and
- * with a twist for refinement classes. A refinement class
- * has a transowner X if an of its parents has transowner X.
+ /** Same as `ownerChain contains sym` but more efficient, and
+ * with a twist for refinement classes (see RefinementClassSymbol.)
*/
def hasTransOwner(sym: Symbol): Boolean = {
var o = this
while ((o ne sym) && (o ne NoSymbol)) o = o.owner
- (o eq sym) ||
- isRefinementClass && (info.parents exists (_.typeSymbol.hasTransOwner(sym)))
+ (o eq sym)
}
// ------ name attribute --------------------------------------------------------------
- def name: Name = rawname
-
- def name_=(name: Name) {
- if (name != rawname) {
- if (owner.isClass) {
- var ifs = owner.infos
- while (ifs != null) {
- ifs.info.decls.rehash(this, name)
- ifs = ifs.prev
- }
- }
- _rawname = name
- }
- }
-
/** If this symbol has an expanded name, its original name, otherwise its name itself.
* @see expandName
*/
@@ -900,43 +1036,54 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
final def fullName: String = fullName('.')
-// ------ flags attribute --------------------------------------------------------------
+ /**
+ * Symbol creation implementations.
+ */
- final def flags: Long = {
- val fs = rawflags & phase.flagMask
- (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift)
- }
- def flags_=(fs: Long) = _rawflags = fs
+ protected def createAbstractTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AbstractTypeSymbol =
+ new AbstractTypeSymbol(this, pos, name) initFlags newFlags
- /** Set the symbol's flags to the given value, asserting
- * that the previous value was 0.
- */
- def initFlags(mask: Long): this.type = {
- assert(rawflags == 0L, this)
- _rawflags = mask
- this
- }
- def setFlag(mask: Long): this.type = { _rawflags = rawflags | mask ; this }
- def resetFlag(mask: Long): this.type = { _rawflags = rawflags & ~mask ; this }
- final def getFlag(mask: Long): Long = flags & mask
- final def resetFlags() { _rawflags = rawflags & TopLevelCreationFlags }
+ protected def createAliasTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AliasTypeSymbol =
+ new AliasTypeSymbol(this, pos, name) initFlags newFlags
- /** Does symbol have ANY flag in `mask` set? */
- final def hasFlag(mask: Long): Boolean = (flags & mask) != 0L
+ protected def createTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position, newFlags: Long): TypeSkolem =
+ new TypeSkolem(this, pos, name, origin) initFlags newFlags
- /** Does symbol have ALL the flags in `mask` set? */
- final def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask
+ protected def createClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol =
+ new ClassSymbol(this, pos, name) initFlags newFlags
- /** If the given flag is set on this symbol, also set the corresponding
- * notFLAG. For instance if flag is PRIVATE, the notPRIVATE flag will
- * be set if PRIVATE is currently set.
- */
- final def setNotFlag(flag: Int) = if (hasFlag(flag)) setFlag((flag: @annotation.switch) match {
- case PRIVATE => notPRIVATE
- case PROTECTED => notPROTECTED
- case OVERRIDE => notOVERRIDE
- case _ => abort("setNotFlag on invalid flag: " + flag)
- })
+ protected def createModuleClassSymbol(name: TypeName, pos: Position, newFlags: Long): ModuleClassSymbol =
+ new ModuleClassSymbol(this, pos, name) initFlags newFlags
+
+ protected def createPackageClassSymbol(name: TypeName, pos: Position, newFlags: Long): PackageClassSymbol =
+ new PackageClassSymbol(this, pos, name) initFlags newFlags
+
+ protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol =
+ new RefinementClassSymbol(this, pos) initFlags newFlags
+
+ protected def createPackageObjectClassSymbol(pos: Position, newFlags: Long): PackageObjectClassSymbol =
+ new PackageObjectClassSymbol(this, pos) initFlags newFlags
+
+ protected def createImplClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol =
+ new ClassSymbol(this, pos, name) with ImplClassSymbol initFlags newFlags
+
+ protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol =
+ new TermSymbol(this, pos, name) initFlags newFlags
+
+ protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol =
+ new MethodSymbol(this, pos, name) initFlags newFlags
+
+ protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol =
+ new ModuleSymbol(this, pos, name) initFlags newFlags
+
+ protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol =
+ new PackageSymbol(this, pos, name) initFlags newFlags
+
+ protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol =
+ new TermSymbol(this, pos, name) initFlags newFlags
+
+ protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol =
+ new TermSymbol(this, pos, name) initFlags newFlags
/** The class or term up to which this symbol is accessible,
* or RootClass if it is public. As java protected statics are
@@ -975,6 +1122,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ------ info and type -------------------------------------------------------------------
private[Symbols] var infos: TypeHistory = null
+ def originalInfo = {
+ if (infos eq null) null
+ else {
+ var is = infos
+ while (is.prev ne null) { is = is.prev }
+ is.info
+ }
+ }
/** Get type. The type of a symbol is:
* for a type symbol, the type corresponding to the symbol itself,
@@ -999,7 +1154,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
val tp = infos.info
//if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug
- if ((rawflags & LOCKED) != 0L) { // rolled out once for performance
+ if ((_rawflags & LOCKED) != 0L) { // rolled out once for performance
lock {
setInfo(ErrorType)
throw CyclicReference(this, tp)
@@ -1057,8 +1212,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Set new info valid from start of this phase. */
def updateInfo(info: Type): Symbol = {
- assert(phaseId(infos.validFrom) <= phase.id)
- if (phaseId(infos.validFrom) == phase.id) infos = infos.prev
+ val pid = phaseId(infos.validFrom)
+ assert(pid <= phase.id, (pid, phase.id))
+ if (pid == phase.id) infos = infos.prev
infos = TypeHistory(currentPeriod, info, infos)
_validTo = if (info.isComplete) currentPeriod else NoPeriod
this
@@ -1188,7 +1344,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* which immediately follows any of parser, namer, typer, or erasure.
* In effect that means this will return one of:
*
- * - packageobjects (follows namer)
+ * - packageobjects (follows namer)
* - superaccessors (follows typer)
* - lazyvals (follows erasure)
* - null
@@ -1197,9 +1353,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
var ph = phase
while (ph.prev.keepsTypeParams)
ph = ph.prev
- //
- // if (ph ne phase)
- // debuglog("checking unsafeTypeParams(" + this + ") at: " + phase + " reading at: " + ph)
ph
}
@@ -1231,7 +1384,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The value parameter sections of this symbol.
*/
def paramss: List[List[Symbol]] = info.paramss
- def hasParamWhich(cond: Symbol => Boolean) = paramss exists (_ exists cond)
+ def hasParamWhich(cond: Symbol => Boolean) = mexists(paramss)(cond)
/** The least proper supertype of a class; includes all parent types
* and refinement where needed. You need to compute that in a situation like this:
@@ -1272,7 +1425,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Reset symbol to initial state
*/
- def reset(completer: Type) {
+ def reset(completer: Type): this.type = {
resetFlags()
infos = null
_validTo = NoPeriod
@@ -1404,15 +1557,15 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
// ------ cloneing -------------------------------------------------------------------
/** A clone of this symbol. */
- final def cloneSymbol: Symbol =
+ final def cloneSymbol: TypeOfClonedSymbol =
cloneSymbol(owner)
/** A clone of this symbol, but with given owner. */
- final def cloneSymbol(newOwner: Symbol): Symbol =
- cloneSymbol(newOwner, this.rawflags)
- final def cloneSymbol(newOwner: Symbol, newFlags: Long): Symbol =
- cloneSymbol(newOwner, newFlags, nme.NO_NAME)
- final def cloneSymbol(newOwner: Symbol, newFlags: Long, newName: Name): Symbol = {
+ final def cloneSymbol(newOwner: Symbol): TypeOfClonedSymbol =
+ cloneSymbol(newOwner, _rawflags)
+ final def cloneSymbol(newOwner: Symbol, newFlags: Long): TypeOfClonedSymbol =
+ cloneSymbol(newOwner, newFlags, null)
+ final def cloneSymbol(newOwner: Symbol, newFlags: Long, newName: Name): TypeOfClonedSymbol = {
val clone = cloneSymbolImpl(newOwner, newFlags)
( clone
setPrivateWithin privateWithin
@@ -1421,15 +1574,15 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
)
if (clone.thisSym != clone)
clone.typeOfThis = (clone.typeOfThis cloneInfo clone)
- if (newName != nme.NO_NAME)
- clone.name = newName
+
+ if (newName ne null)
+ clone setName asNameType(newName)
clone
}
/** Internal method to clone a symbol's implementation with the given flags and no info. */
- def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol
- def cloneSymbolImpl(owner: Symbol): Symbol = cloneSymbolImpl(owner, 0L)
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeOfClonedSymbol
// ------ access to related symbols --------------------------------------------------
@@ -1440,14 +1593,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def enclMethod: Symbol = if (isSourceMethod) this else owner.enclMethod
/** The primary constructor of a class. */
- def primaryConstructor: Symbol = {
- var c = info.decl(
- if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR
- else nme.CONSTRUCTOR)
- c = if (c hasFlag OVERLOADED) c.alternatives.head else c
- //assert(c != NoSymbol)
- c
- }
+ def primaryConstructor: Symbol = NoSymbol
/** The self symbol (a TermSymbol) of a class with explicit self type, or else the
* symbol itself (a TypeSymbol).
@@ -1509,7 +1655,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* symbol with the same owner, and the name of this symbol with $class
* appended to it.
*/
- final def implClass: Symbol = owner.info.decl(nme.implClassName(name))
+ final def implClass: Symbol = owner.info.decl(tpnme.implClassName(name))
/** The class that is logically an outer class of given `clazz`.
* This is the enclosing class, except for classes defined locally to constructors,
@@ -1557,13 +1703,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The package class containing this symbol, or NoSymbol if there
* is not one. */
- def enclosingPackageClass: Symbol =
- if (this == NoSymbol) this else {
- var packSym = this.owner
- while (packSym != NoSymbol && !packSym.isPackageClass)
- packSym = packSym.owner
- packSym
- }
+ def enclosingPackageClass: Symbol = {
+ var packSym = this.owner
+ while (packSym != NoSymbol && !packSym.isPackageClass)
+ packSym = packSym.owner
+ packSym
+ }
/** The package containing this symbol, or NoSymbol if there
* is not one. */
@@ -1627,7 +1772,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
} else owner.enclosingTopLevelClass
/** Is this symbol defined in the same scope and compilation unit as `that` symbol? */
- def isCoDefinedWith(that: Symbol) = (
+ def isCoDefinedWith(that: Symbol) = {
+ import language.reflectiveCalls
(this.rawInfo ne NoType) &&
(this.effectiveOwner == that.effectiveOwner) && {
!this.effectiveOwner.isPackageClass ||
@@ -1646,7 +1792,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
false
}
}
- )
+ }
/** The internal representation of classes and objects:
*
@@ -1674,21 +1820,12 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* Note: does not work for classes owned by methods, see Namers.companionClassOf
*
* object Foo . companionClass --> class Foo
+ *
+ * !!! linkedClassOfClass depends on companionClass on the module class getting
+ * to the class. As presently implemented this potentially returns class for
+ * any symbol except NoSymbol.
*/
- final def companionClass: Symbol = {
- if (this != NoSymbol)
- flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
- else NoSymbol
- }
-
- /** A helper method that factors the common code used the discover a
- * companion module of a class. If a companion module exists, its symbol is
- * returned, otherwise, `NoSymbol` is returned. The method assumes that
- * `this` symbol has already been checked to be a class (using `isClass`).
- */
- private final def companionModule0: Symbol =
- flatOwnerInfo.decl(name.toTermName).suchThat(
- sym => sym.hasFlag(MODULE) && (sym isCoDefinedWith this) && !sym.isMethod)
+ def companionClass: Symbol = flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
/** For a class: the module or case class factory with the same name in the same package.
* For all others: NoSymbol
@@ -1696,9 +1833,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*
* class Foo . companionModule --> object Foo
*/
- final def companionModule: Symbol =
- if (isClass && !isRefinementClass) companionModule0
- else NoSymbol
+ def companionModule: Symbol = NoSymbol
/** For a module: its linked class
* For a plain class: its linked module or case factory.
@@ -1706,18 +1841,14 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*
* class Foo <-- companionSymbol --> object Foo
*/
- final def companionSymbol: Symbol =
- if (isTerm) companionClass
- else if (isClass) companionModule0
- else NoSymbol
+ def companionSymbol: Symbol = NoSymbol
/** For a module class: its linked class
* For a plain class: the module class of its linked module.
*
* class Foo <-- linkedClassOfClass --> class Foo$
*/
- final def linkedClassOfClass: Symbol =
- if (isModuleClass) companionClass else companionModule.moduleClass
+ def linkedClassOfClass: Symbol = NoSymbol
/**
* Returns the rawInfo of the owner. If the current phase has flat classes,
@@ -1730,7 +1861,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* symbol B in the decls of p. So to find a linked symbol ("object B" or "class B")
* we need to apply flatten to B first. Fixes #2470.
*/
- private final def flatOwnerInfo: Type = {
+ protected final def flatOwnerInfo: Type = {
if (needsFlatClasses)
info
owner.rawInfo
@@ -1744,18 +1875,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* This only works for implementation classes owned by other classes or traits.
* !!! Why?
*/
- final def toInterface: Symbol =
- if (isImplClass) {
- val result =
- if (phase.next.erasedTypes) {
- assert(!tpe.parents.isEmpty, this)
- tpe.parents.last.typeSymbol
- } else {
- owner.info.decl(nme.interfaceName(name))
- }
- assert(result != NoSymbol, this)
- result
- } else this
+ def toInterface: Symbol = this
/** The module class corresponding to this module.
*/
@@ -1776,7 +1896,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
site.nonPrivateMemberAdmitting(name, admit).filter(sym =>
!sym.isTerm || (site.memberType(this) matches site.memberType(sym)))
- /** The symbol overridden by this symbol in given class `ofclazz`.
+ /** The symbol, in class `ofclazz`, that is overridden by this symbol.
*
* @param ofclazz is a base class of this symbol's owner.
*/
@@ -1879,7 +1999,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** Remove private modifier from symbol `sym`s definition. If `sym` is a
* is not a constructor nor a static module rename it by expanding its name to avoid name clashes
- * @param base the fully qualified name of this class will be appended if name expansion is needed
+ * @param base the fully qualified name of this class will be appended if name expansion is needed
*/
final def makeNotPrivate(base: Symbol) {
if (this.isPrivate) {
@@ -1909,23 +2029,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
case p :: _ => p
case _ => NoSymbol
}
-
- /** change name by appending $$<fully-qualified-name-of-class `base`>
- * Do the same for any accessed symbols or setters/getters
- */
- def expandName(base: Symbol) {
- if (this.isTerm && this != NoSymbol && !hasFlag(EXPANDEDNAME)) {
- setFlag(EXPANDEDNAME)
- if (hasAccessorFlag && !isDeferred) {
- accessed.expandName(base)
- } else if (hasGetter) {
- getter(owner).expandName(base)
- setter(owner).expandName(base)
- }
- name = nme.expandedName(name.toTermName, base)
- if (isType) name = name
- }
- }
/* code for fixing nested objects
def expandModuleClassName() {
name = newTypeName(name.toString + "$")
@@ -1933,13 +2036,27 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def isExpandedModuleClass: Boolean = name(name.length - 1) == '$'
*/
- def sourceFile: AbstractFileType =
- if (isModule) moduleClass.sourceFile
- else enclosingTopLevelClass.sourceFile
- def sourceFile_=(f: AbstractFileType) {
- abort("sourceFile_= inapplicable for " + this)
- }
+ /** Desire to re-use the field in ClassSymbol which stores the source
+ * file to also store the classfile, but without changing the behavior
+ * of sourceFile (which is expected at least in the IDE only to
+ * return actual source code.) So sourceFile has classfiles filtered out.
+ */
+ private def sourceFileOnly(file: AbstractFileType): AbstractFileType =
+ if ((file eq null) || (file.path endsWith ".class")) null else file
+
+ private def binaryFileOnly(file: AbstractFileType): AbstractFileType =
+ if ((file eq null) || !(file.path endsWith ".class")) null else file
+
+ final def binaryFile: AbstractFileType = binaryFileOnly(associatedFile)
+ final def sourceFile: AbstractFileType = sourceFileOnly(associatedFile)
+
+ /** Overridden in ModuleSymbols to delegate to the module class. */
+ def associatedFile: AbstractFileType = enclosingTopLevelClass.associatedFile
+ def associatedFile_=(f: AbstractFileType) { abort("associatedFile_= inapplicable for " + this) }
+
+ @deprecated("Use associatedFile_= instead", "2.10.0")
+ def sourceFile_=(f: AbstractFileType): Unit = associatedFile_=(f)
/** If this is a sealed class, its known direct subclasses.
* Otherwise, the empty set.
@@ -1950,7 +2067,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def sealedDescendants: Set[Symbol] = children.flatMap(_.sealedDescendants) + this
- def orElse[T](alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt
+ @inline final def orElse(alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt
+ @inline final def andAlso(f: Symbol => Unit): Symbol = { if (this ne NoSymbol) f(this) ; this }
// ------ toString -------------------------------------------------------------------
@@ -1982,8 +2100,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private case class SymbolKind(accurate: String, sanitized: String, abbreviation: String)
private def symbolKind: SymbolKind = {
- val kind =
- if (isInstanceOf[FreeVar]) ("free variable", "free variable", "FV")
+ var kind =
+ if (isTermMacro) ("macro method", "macro method", "MAC")
+ else if (isInstanceOf[FreeTerm]) ("free term", "free term", "FTE")
+ else if (isInstanceOf[FreeType]) ("free type", "free type", "FTY")
else if (isPackage) ("package", "package", "PK")
else if (isPackageClass) ("package class", "package", "PKC")
else if (isPackageObject) ("package object", "package", "PKO")
@@ -2004,6 +2124,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else if (isSourceMethod) ("method", "method", "METH")
else if (isTerm) ("value", "value", "VAL")
else ("", "", "???")
+ if (isSkolem) kind = (kind._1, kind._2, kind._3 + "#SKO")
SymbolKind(kind._1, kind._2, kind._3)
}
@@ -2112,33 +2233,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
def infosString = infos.toString
def debugLocationString = fullLocationString + " " + debugFlagString
- def debugFlagString = hasFlagsToString(-1L)
- def hasFlagsToString(mask: Long): String = flagsToString(
- flags & mask,
- if (hasAccessBoundary) privateWithin.toString else ""
- )
-
- /** String representation of symbol's variance */
- def varianceString: String =
- if (variance == 1) "+"
- else if (variance == -1) "-"
- else ""
- def defaultFlagMask =
- if (isAbstractType) ExplicitFlags
- else if (settings.debug.value) -1L
- else if (owner.isRefinementClass) ExplicitFlags & ~OVERRIDE
- else ExplicitFlags
-
- // make the error message more googlable
- def flagsExplanationString =
- if (isGADTSkolem) " (this is a GADT skolem)"
- else ""
-
- def accessString = hasFlagsToString(PRIVATE | PROTECTED | LOCAL)
- def defaultFlagString = hasFlagsToString(defaultFlagMask)
private def defStringCompose(infoString: String) = compose(
- defaultFlagString,
+ flagString,
keyString,
varianceString + nameString + infoString + flagsExplanationString
)
@@ -2161,26 +2258,88 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** String representation of existentially bound variable */
def existentialToString =
if (isSingletonExistential && !settings.debug.value)
- "val " + nme.dropSingletonName(name) + ": " + dropSingletonType(info.bounds.hi)
+ "val " + tpnme.dropSingletonName(name) + ": " + dropSingletonType(info.bounds.hi)
else defString
}
/** A class for term symbols */
class TermSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
- extends Symbol(initOwner, initPos, initName) {
+ extends Symbol(initOwner, initPos, initName) with TermSymbolApi {
+ private[this] var _referenced: Symbol = NoSymbol
+ privateWithin = NoSymbol
+
+ final type NameType = TermName
+ type TypeOfClonedSymbol = TermSymbol
+
+ private[this] var _rawname: TermName = initName
+ def rawname = _rawname
+ def name = _rawname
+ def name_=(name: Name) {
+ if (name != rawname) {
+ log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name))
+ changeNameInOwners(name)
+ _rawname = name.toTermName
+ }
+ }
+ final def asNameType(n: Name) = n.toTermName
+
final override def isTerm = true
- override def name: TermName = rawname.toTermName
- privateWithin = NoSymbol
+ /** Term symbols with the exception of static parts of Java classes and packages.
+ */
+ override def isValue = !(isModule && hasFlag(PACKAGE | JAVA))
+ override def isVariable = isMutable && !isMethod
+ override def isTermMacro = hasFlag(MACRO)
- private[this] var _referenced: Symbol = NoSymbol
+ // interesting only for lambda lift. Captured variables are accessed from inner lambdas.
+ override def isCapturedVariable = hasAllFlags(MUTABLE | CAPTURED) && !hasFlag(METHOD)
+
+ override def companionSymbol: Symbol = companionClass
+ override def moduleClass = if (isModule) referenced else NoSymbol
+
+ override def hasDefault = this hasFlag DEFAULTPARAM // overloaded with TRAIT
+ override def isBridge = this hasFlag BRIDGE
+ override def isEarlyInitialized = this hasFlag PRESUPER
+ override def isMethod = this hasFlag METHOD
+ override def isModule = this hasFlag MODULE
+ override def isOverloaded = this hasFlag OVERLOADED
+ override def isPackage = this hasFlag PACKAGE
+ override def isValueParameter = this hasFlag PARAM
+
+ override def isSetterParameter = isValueParameter && owner.isSetter
+ override def isAccessor = this hasFlag ACCESSOR
+ override def isGetter = isAccessor && !isSetter
+ override def isSetter = isAccessor && nme.isSetterName(name) // todo: make independent of name, as this can be forged.
+ override def isLocalDummy = nme.isLocalDummyName(name)
+ override def isClassConstructor = name == nme.CONSTRUCTOR
+ override def isMixinConstructor = name == nme.MIXIN_CONSTRUCTOR
+ override def isConstructor = nme.isConstructorName(name)
+
+ override def isPackageObject = isModule && (name == nme.PACKAGE)
+ override def isStable = !isUnstable
+ private def isUnstable = (
+ isMutable
+ || (hasFlag(METHOD | BYNAMEPARAM) && !hasFlag(STABLE))
+ || (tpe.isVolatile && !hasAnnotation(uncheckedStableClass))
+ )
+
+ // The name in comments is what it is being disambiguated from.
+ // TODO - rescue CAPTURED from BYNAMEPARAM so we can see all the names.
+ override def resolveOverloadedFlag(flag: Long) = flag match {
+ case DEFAULTPARAM => "<defaultparam>" // TRAIT
+ case MIXEDIN => "<mixedin>" // EXISTENTIAL
+ case LABEL => "<label>" // CONTRAVARIANT / INCONSTRUCTOR
+ case PRESUPER => "<presuper>" // IMPLCLASS
+ case BYNAMEPARAM => if (this.isValueParameter) "<bynameparam>" else "<captured>" // COVARIANT
+ case _ => super.resolveOverloadedFlag(flag)
+ }
def referenced: Symbol = _referenced
def referenced_=(x: Symbol) { _referenced = x }
def existentialBound = singletonBounds(this.tpe)
- def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long): TermSymbol =
owner.newTermSymbol(name, pos, newFlags).copyAttrsFrom(this)
def copyAttrsFrom(original: TermSymbol): this.type = {
@@ -2204,14 +2363,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
override def outerSource: Symbol =
- if (name endsWith nme.OUTER) initialize.referenced
+ if (originalName == nme.OUTER) initialize.referenced
else NoSymbol
- override def moduleClass: Symbol =
- if (hasFlag(MODULE)) referenced else NoSymbol
-
def setModuleClass(clazz: Symbol): TermSymbol = {
- assert(hasFlag(MODULE), this)
+ assert(isModule, this)
referenced = clazz
this
}
@@ -2227,6 +2383,23 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
referenced
}
+ /** change name by appending $$<fully-qualified-name-of-class `base`>
+ * Do the same for any accessed symbols or setters/getters
+ */
+ override def expandName(base: Symbol) {
+ if (!hasFlag(EXPANDEDNAME)) {
+ setFlag(EXPANDEDNAME)
+ if (hasAccessorFlag && !isDeferred) {
+ accessed.expandName(base)
+ }
+ else if (hasGetter) {
+ getter(owner).expandName(base)
+ setter(owner).expandName(base)
+ }
+ name = nme.expandedName(name.toTermName, base)
+ }
+ }
+
protected def doCookJavaRawInfo() {
def cook(sym: Symbol) {
require(sym.isJavaDefined, sym)
@@ -2260,9 +2433,18 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** A class for module symbols */
class ModuleSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
- extends TermSymbol(initOwner, initPos, initName) {
+ extends TermSymbol(initOwner, initPos, initName) with DistinguishingFlag with ModuleSymbolApi {
+ def distinguishingFlag = MODULE
private var flatname: TermName = null
+ override def associatedFile = moduleClass.associatedFile
+ override def associatedFile_=(f: AbstractFileType) { moduleClass.associatedFile = f }
+
+ override def isModule = true
+ override def moduleClass = referenced
+ override def companionClass =
+ flatOwnerInfo.decl(name.toTypeName).suchThat(_ isCoDefinedWith this)
+
override def owner = (
if (!isMethod && needsFlatClasses) rawowner.owner
else rawowner
@@ -2274,23 +2456,41 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
flatname
}
- else rawname.toTermName
+ else rawname
)
+ }
- override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
- owner.newModuleSymbol(name, pos, newFlags).copyAttrsFrom(this)
+ class PackageSymbol protected[Symbols] (owner0: Symbol, pos0: Position, name0: TermName)
+ extends ModuleSymbol(owner0, pos0, name0) with DistinguishingFlag with PackageSymbolApi {
+ override def distinguishingFlag = super.distinguishingFlag | PACKAGE
+ override def isPackage = true
}
/** A class for method symbols */
class MethodSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TermName)
- extends TermSymbol(initOwner, initPos, initName) {
- private var mtpePeriod = NoPeriod
- private var mtpePre: Type = _
- private var mtpeResult: Type = _
- private var mtpeInfo: Type = _
-
- override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
- owner.newMethodSymbol(name, pos, newFlags).copyAttrsFrom(this)
+ extends TermSymbol(initOwner, initPos, initName) with DistinguishingFlag with MethodSymbolApi {
+ def distinguishingFlag = METHOD
+ // MethodSymbols pick up MODULE when trait-owned object accessors are cloned
+ // during mixin composition.
+ override protected def neverHasFlags = super.neverHasFlags & ~MODULE
+
+ private[this] var mtpePeriod = NoPeriod
+ private[this] var mtpePre: Type = _
+ private[this] var mtpeResult: Type = _
+ private[this] var mtpeInfo: Type = _
+
+ override def isMethod = true
+ override def isLabel = this hasFlag LABEL
+ override def isVarargsMethod = this hasFlag VARARGS
+ override def isLiftedMethod = this hasFlag LIFTED
+
+ // TODO - this seems a strange definition for "isSourceMethod", given that
+ // it does not make any specific effort to exclude synthetics. Figure out what
+ // this method is really for and what logic makes sense.
+ override def isSourceMethod = !(this hasFlag STABLE) // exclude all accessors
+ // unfortunately having the CASEACCESSOR flag does not actually mean you
+ // are a case accessor (you can also be a field.)
+ override def isCaseAccessorMethod = isCaseAccessor
def typeAsMemberOf(pre: Type): Type = {
if (mtpePeriod == currentPeriod) {
@@ -2310,73 +2510,80 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
class AliasTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
extends TypeSymbol(initOwner, initPos, initName) {
- // Temporary programmatic help tracking down who might do such a thing
- override def setFlag(mask: Long): this.type = {
- if (isSetting(DEFERRED, mask)) {
- println("Setting DEFERRED on alias at")
- (new Throwable).printStackTrace
- }
- super.setFlag(mask)
- }
+ type TypeOfClonedSymbol = TypeSymbol
final override def isAliasType = true
- override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AliasTypeSymbol =
- owner.newAliasTypeSymbol(name, pos, newFlags)
+ final override def dealias = info.typeSymbol.dealias
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeSymbol =
+ owner.newNonClassSymbol(name, pos, newFlags)
}
- class AbstractTypeSymbol(initOwner: Symbol, initPos: Position, initName: TypeName)
- extends TypeSymbol(initOwner, initPos, initName) with AbstractTypeMixin {
- override def cloneSymbolImpl(owner: Symbol, newFlags: Long): AbstractTypeSymbol =
- owner.newAbstractTypeSymbol(name, pos, newFlags)
- }
-
- /** Might be mixed into TypeSymbol or TypeSkolem.
- */
- trait AbstractTypeMixin extends TypeSymbol {
- override def resetFlag(mask: Long): this.type = {
- // Temporary programmatic help tracking down who might do such a thing
- if (settings.debug.value) {
- if (isClearing(DEFERRED, mask)) {
- println("Clearing DEFERRED on abstract type at")
- (new Throwable).printStackTrace
- }
- }
- super.resetFlag(mask)
- }
+ class AbstractTypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends TypeSymbol(initOwner, initPos, initName) {
+ type TypeOfClonedSymbol = TypeSymbol
final override def isAbstractType = true
override def existentialBound = this.info
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeSymbol =
+ owner.newNonClassSymbol(name, pos, newFlags)
}
/** A class of type symbols. Alias and abstract types are direct instances
* of this class. Classes are instances of a subclass.
*/
- abstract class TypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName) extends Symbol(initOwner, initPos, initName) {
+ abstract class TypeSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
+ extends Symbol(initOwner, initPos, initName) with TypeSymbolApi {
privateWithin = NoSymbol
+ private[this] var _rawname: TypeName = initName
+
+ final type NameType = TypeName
+ type TypeOfClonedSymbol >: Null <: TypeSymbol
+ // cloneSymbolImpl still abstract in TypeSymbol.
+
+ def rawname = _rawname
+ def name = _rawname
+ final def asNameType(n: Name) = n.toTypeName
+
+ final override def isType = true
+ override def isNonClassType = true
+ override def isTypeMacro = hasFlag(MACRO)
+
+ override def resolveOverloadedFlag(flag: Long) = flag match {
+ case TRAIT => "<trait>" // DEFAULTPARAM
+ case EXISTENTIAL => "<existential>" // MIXEDIN
+ case COVARIANT => "<covariant>" // BYNAMEPARAM / CAPTURED
+ case CONTRAVARIANT => "<contravariant>" // LABEL / INCONSTRUCTOR (overridden again in ClassSymbol)
+ case _ => super.resolveOverloadedFlag(flag)
+ }
+
private var tyconCache: Type = null
private var tyconRunId = NoRunId
private var tpeCache: Type = _
private var tpePeriod = NoPeriod
+ override def isAbstractType = this hasFlag DEFERRED
+ override def isContravariant = this hasFlag CONTRAVARIANT
+ override def isCovariant = this hasFlag COVARIANT
+ override def isExistentialQuantified = isExistentiallyBound && !isSkolem
+ override def isExistentiallyBound = this hasFlag EXISTENTIAL
+ override def isTypeParameter = isTypeParameterOrSkolem && !isSkolem
+ override def isTypeParameterOrSkolem = this hasFlag PARAM
+
/** Overridden in subclasses for which it makes sense.
*/
def existentialBound: Type = abort("unexpected type: "+this.getClass+ " "+debugLocationString)
- override def name: TypeName = super.name.toTypeName
- final override def isType = true
- override def isNonClassType = true
- override def isAbstractType = {
- if (settings.debug.value) {
- if (isDeferred) {
- println("TypeSymbol claims to be abstract type: " + this.getClass + " " + debugFlagString + " at ")
- (new Throwable).printStackTrace
- }
+ // TODO - don't allow names to be renamed in this unstructured a fashion.
+ // Rename as little as possible. Enforce invariants on all renames.
+ def name_=(name: Name) {
+ if (name != rawname) {
+ log("Renaming %s %s %s to %s".format(shortSymbolClass, debugFlagString, rawname, name))
+ changeNameInOwners(name)
+ _rawname = name.toTypeName
}
- isDeferred
- }
- private def newTypeRef(targs: List[Type]) = {
- val pre = if (hasFlag(PARAM | EXISTENTIAL)) NoPrefix else owner.thisType
- typeRef(pre, this, targs)
}
+ private def newPrefix = if (this hasFlag EXISTENTIAL | PARAM) NoPrefix else owner.thisType
+ private def newTypeRef(targs: List[Type]) = typeRef(newPrefix, this, targs)
+
/** Let's say you have a type definition
*
* {{{
@@ -2447,10 +2654,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
info.baseTypeIndex(that) >= 0
)
- override def reset(completer: Type) {
+ override def reset(completer: Type): this.type = {
super.reset(completer)
tpePeriod = NoPeriod
tyconRunId = NoRunId
+ this
}
/*** example:
@@ -2468,9 +2676,6 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
}
- def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
- owner.newTypeSymbol(name, pos, newFlags)
-
incCounter(typeSymbolCount)
}
@@ -2489,12 +2694,22 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
class TypeSkolem protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName, origin: AnyRef)
extends TypeSymbol(initOwner, initPos, initName) {
-
+ type TypeOfClonedSymbol = TypeSkolem
/** The skolemization level in place when the skolem was constructed */
val level = skolemizationLevel
final override def isSkolem = true
+ // a type symbol bound by an existential type, for instance the T in
+ // List[T] forSome { type T }
+ override def isExistentialSkolem = this hasFlag EXISTENTIAL
+ override def isGADTSkolem = this hasFlag CASEACCESSOR | SYNTHETIC
+ override def isTypeSkolem = this hasFlag PARAM
+ override def isAbstractType = this hasFlag DEFERRED
+
+ override def isExistentialQuantified = false
+ override def existentialBound = if (isAbstractType) this.info else super.existentialBound
+
/** If typeskolem comes from a type parameter, that parameter, otherwise skolem itself */
override def deSkolemize = origin match {
case s: Symbol => s
@@ -2507,7 +2722,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
//@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo
override def typeParams = info.typeParams
- override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol =
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): TypeSkolem =
owner.newTypeSkolemSymbol(name, origin, pos, newFlags)
override def nameString: String =
@@ -2517,33 +2732,118 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** A class for class symbols */
class ClassSymbol protected[Symbols] (initOwner: Symbol, initPos: Position, initName: TypeName)
- extends TypeSymbol(initOwner, initPos, initName) {
- private[this] var flatname: TypeName = null
- private[this] var source: AbstractFileType = null
- private[this] var thissym: Symbol = this
+ extends TypeSymbol(initOwner, initPos, initName) with ClassSymbolApi {
+ type TypeOfClonedSymbol = ClassSymbol
+
+ private[this] var flatname: TypeName = _
+ private[this] var _associatedFile: AbstractFileType = _
+ private[this] var thissym: Symbol = this
+
+ private[this] var thisTypeCache: Type = _
+ private[this] var thisTypePeriod = NoPeriod
+
+ override protected def alwaysHasFlags: Long = 0L
+ override protected def neverHasFlags: Long = 0L
+
+ override def resolveOverloadedFlag(flag: Long) = flag match {
+ case INCONSTRUCTOR => "<inconstructor>" // INCONSTRUCTOR / CONTRAVARIANT / LABEL
+ case EXISTENTIAL => "<existential>" // EXISTENTIAL / MIXEDIN
+ case IMPLCLASS => "<implclass>" // IMPLCLASS / PRESUPER
+ case _ => super.resolveOverloadedFlag(flag)
+ }
final override def isClass = true
final override def isNonClassType = false
final override def isAbstractType = false
final override def isAliasType = false
+ override def isAbstractClass = this hasFlag ABSTRACT
+ override def isCaseClass = this hasFlag CASE
+ override def isClassLocalToConstructor = this hasFlag INCONSTRUCTOR
+ override def isImplClass = this hasFlag IMPLCLASS
+ override def isModuleClass = this hasFlag MODULE
+ override def isPackageClass = this hasFlag PACKAGE
+ override def isTrait = this hasFlag TRAIT
+
+ override def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass
+ override def isAnonymousClass = name containsName tpnme.ANON_CLASS_NAME
+ override def isConcreteClass = !(this hasFlag ABSTRACT | TRAIT)
+ override def isJavaInterface = hasAllFlags(JAVA | TRAIT)
+ override def isNestedClass = !owner.isPackageClass
+ override def isNumericValueClass = definitions.isNumericValueClass(this)
+ override def isPackageObjectClass = isModuleClass && (name == tpnme.PACKAGE)
+ override def isPrimitiveValueClass = definitions.isPrimitiveValueClass(this)
+
+ // The corresponding interface is the last parent by convention.
+ private def lastParent = if (tpe.parents.isEmpty) NoSymbol else tpe.parents.last.typeSymbol
+ override def toInterface: Symbol = (
+ if (isImplClass) {
+ if (phase.next.erasedTypes) lastParent
+ else owner.info.decl(tpnme.interfaceName(name))
+ }
+ else super.toInterface
+ )
+
+ /** Is this class locally defined?
+ * A class is local, if
+ * - it is anonymous, or
+ * - its owner is a value
+ * - it is defined within a local class
+ */
+ override def isLocalClass = (
+ isAnonOrRefinementClass
+ || isLocal
+ || !owner.isPackageClass && owner.isLocalClass
+ )
+ override def isStableClass = (this hasFlag STABLE) || checkStable()
+
+ private def checkStable() = {
+ def hasNoAbstractTypeMember(clazz: Symbol): Boolean =
+ (clazz hasFlag STABLE) || {
+ var e = clazz.info.decls.elems
+ while ((e ne null) && !(e.sym.isAbstractType && info.member(e.sym.name) == e.sym))
+ e = e.next
+ e == null
+ }
+ (info.baseClasses forall hasNoAbstractTypeMember) && {
+ setFlag(STABLE)
+ true
+ }
+ }
+
+ override def enclClassChain = this :: owner.enclClassChain
+
+ /** A helper method that factors the common code used the discover a
+ * companion module of a class. If a companion module exists, its symbol is
+ * returned, otherwise, `NoSymbol` is returned.
+ */
+ protected final def companionModule0: Symbol =
+ flatOwnerInfo.decl(name.toTermName).suchThat(
+ sym => sym.hasFlag(MODULE) && (sym isCoDefinedWith this) && !sym.isMethod)
+
+ override def companionModule = companionModule0
+ override def companionSymbol = companionModule0
+ override def linkedClassOfClass = companionModule.moduleClass
+
+ override def sourceModule = if (isModuleClass) companionModule else NoSymbol
+
override def existentialBound = GenPolyType(this.typeParams, TypeBounds.upper(this.classBound))
- override def sourceFile =
- if (owner.isPackageClass) source
- else super.sourceFile
- override def sourceFile_=(f: AbstractFileType) { source = f }
+ def primaryConstructorName = if (this hasFlag TRAIT | IMPLCLASS) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR
- override def reset(completer: Type) {
- super.reset(completer)
- thissym = this
+ override def primaryConstructor = {
+ val c = info decl primaryConstructorName
+ if (c.isOverloaded) c.alternatives.head else c
}
- private var thisTypeCache: Type = _
- private var thisTypePeriod = NoPeriod
+ override def associatedFile = if (owner.isPackageClass) _associatedFile else super.associatedFile
+ override def associatedFile_=(f: AbstractFileType) { _associatedFile = f }
- private var typeOfThisCache: Type = _
- private var typeOfThisPeriod = NoPeriod
+ override def reset(completer: Type): this.type = {
+ super.reset(completer)
+ thissym = this
+ this
+ }
/** the type this.type in this class */
override def thisType: Type = {
@@ -2557,6 +2857,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def owner: Symbol =
if (needsFlatClasses) rawowner.owner else rawowner
+
override def name: TypeName = (
if (needsFlatClasses) {
if (flatname eq null)
@@ -2564,47 +2865,31 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
flatname
}
- else rawname.toTypeName
+ else rawname
)
/** A symbol carrying the self type of the class as its type */
override def thisSym: Symbol = thissym
- /** the self type of an object foo is foo.type, not class<foo>.this.type
- */
- override def typeOfThis: Type = {
- if (getFlag(MODULE | IMPLCLASS) == MODULE.toLong && owner != NoSymbol) {
- val period = typeOfThisPeriod
- if (period != currentPeriod) {
- typeOfThisPeriod = currentPeriod
- if (!isValid(period))
- typeOfThisCache = singleType(owner.thisType, sourceModule)
- }
- typeOfThisCache
- }
- else thisSym.tpe
- }
-
/** Sets the self type of the class */
override def typeOfThis_=(tp: Type) {
- thissym = newThisSym(pos).setInfo(tp)
+ thissym = newThisSym(nme.this_, pos).setInfo(tp)
}
- override def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = {
+ override def cloneSymbolImpl(owner: Symbol, newFlags: Long): ClassSymbol = {
val clone = owner.newClassSymbol(name, pos, newFlags)
if (thisSym != this) {
clone.typeOfThis = typeOfThis
- clone.thisSym.name = thisSym.name
+ clone.thisSym setName thisSym.name
}
+ if (_associatedFile ne null)
+ clone.associatedFile = _associatedFile
+
clone
}
- override def sourceModule =
- if (isModuleClass) companionModule else NoSymbol
-
override def firstParamAccessor =
- info.decls.find(m => (m hasFlag PARAMACCESSOR) && m.isMethod) getOrElse NoSymbol
-
+ info.decls.find(_ hasAllFlags PARAMACCESSOR | METHOD) getOrElse NoSymbol
private[this] var childSet: Set[Symbol] = Set()
override def children = childSet
@@ -2618,12 +2903,32 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
* plain class symbols!
*/
class ModuleClassSymbol protected[Symbols] (owner: Symbol, pos: Position, name: TypeName)
- extends ClassSymbol(owner, pos, name) {
- private var module: Symbol = null
- private var implicitMembersCacheValue: List[Symbol] = List()
+ extends ClassSymbol(owner, pos, name) with DistinguishingFlag {
+ private[this] var module: Symbol = _
+ private[this] var typeOfThisCache: Type = _
+ private[this] var typeOfThisPeriod = NoPeriod
+
+ def distinguishingFlag = MODULE
+
+ private var implicitMembersCacheValue: List[Symbol] = Nil
private var implicitMembersCacheKey1: Type = NoType
private var implicitMembersCacheKey2: ScopeEntry = null
+ override def isModuleClass = true
+ override def linkedClassOfClass = companionClass
+
+ /** the self type of an object foo is foo.type, not class<foo>.this.type
+ */
+ override def typeOfThis = {
+ val period = typeOfThisPeriod
+ if (period != currentPeriod) {
+ typeOfThisPeriod = currentPeriod
+ if (!isValid(period))
+ typeOfThisCache = singleType(owner.thisType, sourceModule)
+ }
+ typeOfThisCache
+ }
+
def implicitMembers: List[Symbol] = {
val tp = info
if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) {
@@ -2637,20 +2942,79 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
implicitMembersCacheValue
}
- override def sourceModule = module
+ // The null check seems to be necessary for the reifier.
+ override def sourceModule = if (module ne null) module else companionModule
override def sourceModule_=(module: Symbol) { this.module = module }
}
- class FreeVar(name0: TermName, val value: Any) extends TermSymbol(NoSymbol, NoPosition, name0) {
- override def hashCode = if (value == null) 0 else value.hashCode
- override def equals(other: Any): Boolean = other match {
- case that: FreeVar => this.value.asInstanceOf[AnyRef] eq that.value.asInstanceOf[AnyRef]
- case _ => false
+ class PackageObjectClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position)
+ extends ModuleClassSymbol(owner0, pos0, tpnme.PACKAGE) {
+ final override def isPackageObjectClass = true
+ final override def isPackageObjectOrClass = true
+ final override def skipPackageObject = owner
+ final override def setName(name: Name): this.type = {
+ abort("Can't rename a package object to " + name)
}
}
+ trait ImplClassSymbol extends ClassSymbol {
+ override def sourceModule = companionModule
+ // override def isImplClass = true
+ override def typeOfThis = thisSym.tpe // don't use the ModuleClassSymbol typeOfThisCache.
+ }
+
+ class PackageClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position, name0: TypeName)
+ extends ModuleClassSymbol(owner0, pos0, name0) with DistinguishingFlag {
+ override def distinguishingFlag = super.distinguishingFlag | PACKAGE
+ override def sourceModule = companionModule
+ override def enclClassChain = Nil
+ override def isPackageClass = true
+ }
+
+ class RefinementClassSymbol protected[Symbols] (owner0: Symbol, pos0: Position)
+ extends ClassSymbol(owner0, pos0, tpnme.REFINE_CLASS_NAME) {
+ override def name_=(name: Name) {
+ assert(false, "Cannot set name of RefinementClassSymbol to " + name)
+ super.name_=(name)
+ }
+ override def isRefinementClass = true
+ override def isAnonOrRefinementClass = true
+ override def isLocalClass = true
+ override def hasMeaninglessName = true
+ override def companionModule: Symbol = NoSymbol
+
+ /** The mentioned twist. A refinement class has transowner X
+ * if any of its parents has transowner X.
+ */
+ override def hasTransOwner(sym: Symbol) = (
+ super.hasTransOwner(sym)
+ || info.parents.exists(_.typeSymbol hasTransOwner sym)
+ )
+ }
+
+ trait FreeSymbol extends Symbol {
+ def origin: String
+ }
+ class FreeTerm(name0: TermName, value0: => Any, val origin: String) extends TermSymbol(NoSymbol, NoPosition, name0) with FreeSymbol {
+ def value = value0
+ override def isFreeTerm = true
+ }
+
+ class FreeType(name0: TypeName, value0: => Any, val origin: String) extends TypeSkolem(NoSymbol, NoPosition, name0, NoSymbol) with FreeSymbol {
+ def value = value0
+ override def isFreeType = true
+ }
+
/** An object representing a missing symbol */
class NoSymbol protected[Symbols]() extends Symbol(null, NoPosition, nme.NO_NAME) {
+ final type NameType = TermName
+ type TypeOfClonedSymbol = NoSymbol
+
+ def asNameType(n: Name) = n.toTermName
+ def rawname = nme.NO_NAME
+ def name = nme.NO_NAME
+ def name_=(n: Name) = abort("Cannot set NoSymbol's name to " + n)
+
synchronized {
setInfo(NoType)
privateWithin = this
@@ -2660,24 +3024,32 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
unlock()
validTo = currentPeriod
}
+ override def flagMask = AllFlags
+ override def exists = false
+ override def isHigherOrderTypeParameter = false
+ override def companionClass = NoSymbol
+ override def companionModule = NoSymbol
+ override def companionSymbol = NoSymbol
override def isSubClass(that: Symbol) = false
override def filter(cond: Symbol => Boolean) = this
override def defString: String = toString
override def locationString: String = ""
+ override def enclClassChain = Nil
override def enclClass: Symbol = this
override def enclosingTopLevelClass: Symbol = this
+ override def enclosingPackageClass: Symbol = this
override def enclMethod: Symbol = this
- override def sourceFile: AbstractFileType = null
+ override def associatedFile = null
override def ownerChain: List[Symbol] = List()
override def ownersIterator: Iterator[Symbol] = Iterator.empty
override def alternatives: List[Symbol] = List()
- override def reset(completer: Type) {}
+ override def reset(completer: Type): this.type = this
override def info: Type = NoType
override def existentialBound: Type = NoType
override def rawInfo: Type = NoType
protected def doCookJavaRawInfo() {}
override def accessBoundary(base: Symbol): Symbol = RootClass
- def cloneSymbolImpl(owner: Symbol, newFlags: Long): Symbol = abort("NoSymbol.clone()")
+ def cloneSymbolImpl(owner: Symbol, newFlags: Long) = abort("NoSymbol.clone()")
override def originalEnclosingMethod = this
override def owner: Symbol =
@@ -2686,9 +3058,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
abort("no-symbol does not have a type constructor (this may indicate scalac cannot find fundamental classes)")
}
- protected def makeNoSymbol = new NoSymbol
+ protected def makeNoSymbol: NoSymbol = new NoSymbol
- lazy val NoSymbol = makeNoSymbol
+ lazy val NoSymbol: NoSymbol = makeNoSymbol
/** Derives a new list of symbols from the given list by mapping the given
* list across the given function. Then fixes the info of all the new symbols
@@ -2766,20 +3138,22 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if (settings.debug.value) printStackTrace()
}
- case class InvalidCompanions(sym1: Symbol, sym2: Symbol) extends Throwable(
+ case class InvalidCompanions(sym1: Symbol, sym2: Symbol) extends Throwable({
+ import language.reflectiveCalls
"Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file:\n" +
" Found in " + sym1.sourceFile.canonicalPath + " and " + sym2.sourceFile.canonicalPath
- ) {
+ }) {
override def toString = getMessage
}
/** A class for type histories */
private sealed case class TypeHistory(var validFrom: Period, info: Type, prev: TypeHistory) {
assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this)
- assert(validFrom != NoPeriod)
+ assert(validFrom != NoPeriod, this)
+
override def toString() =
"TypeHistory(" + phaseOf(validFrom)+":"+runId(validFrom) + "," + info + "," + prev + ")"
-
+
def toList: List[TypeHistory] = this :: ( if (prev eq null) Nil else prev.toList )
}
}
diff --git a/src/compiler/scala/reflect/internal/TreeBuildUtil.scala b/src/compiler/scala/reflect/internal/TreeBuildUtil.scala
new file mode 100644
index 0000000000..d4d4652e91
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/TreeBuildUtil.scala
@@ -0,0 +1,66 @@
+package scala.reflect
+package internal
+
+import Flags._
+
+trait TreeBuildUtil extends api.TreeBuildUtil { self: SymbolTable =>
+
+ // ``staticClass'' and ``staticModule'' rely on ClassLoaders
+ // which are implementation-specific for different Universes
+
+ def staticClassIfDefined(fullName: String): Symbol =
+ try staticClass(fullName)
+ catch { case _: MissingRequirementError => NoSymbol }
+
+ def staticModuleIfDefined(fullName: String): Symbol =
+ try staticModule(fullName)
+ catch { case _: MissingRequirementError => NoSymbol }
+
+ def thisModuleType(fullname: String) = staticModule(fullname).moduleClass.thisType
+
+ def selectType(owner: Symbol, name: String): Symbol =
+ owner.info.decl(newTypeName(name)) orElse {
+ MissingRequirementError.notFound("type %s in %s".format(name, owner.fullName))
+ }
+
+ def selectTypeIfDefined(owner: Symbol, name: String): Symbol =
+ try selectType(owner, name)
+ catch { case _: MissingRequirementError => NoSymbol }
+
+// try getModule(fullname.toTermName)
+// catch { case _: MissingRequirementError => NoSymbol }
+
+ def selectTerm(owner: Symbol, name: String): Symbol = {
+ val sym = owner.info.decl(newTermName(name))
+ val result =
+ if (sym.isOverloaded) sym suchThat (!_.isMethod)
+ else sym
+ result orElse {
+ MissingRequirementError.notFound("term %s in %s".format(name, owner.fullName))
+ }
+ }
+
+ def selectTermIfDefined(owner: Symbol, name: String): Symbol =
+ try selectTerm(owner, name)
+ catch { case _: MissingRequirementError => NoSymbol }
+
+ def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol =
+ owner.info.decl(newTermName(name)).alternatives(index) orElse {
+ MissingRequirementError.notFound("overloaded method %s #%d in %s".format(name, index, owner.fullName))
+ }
+
+ def selectOverloadedMethodIfDefined(owner: Symbol, name: String, index: Int): Symbol =
+ try selectOverloadedMethod(owner, name, index)
+ catch { case _: MissingRequirementError => NoSymbol }
+
+ def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTermSymbol(newTermName(name), info, value, flags, origin)
+
+ def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) PARAM else flags) | DEFERRED, origin)
+
+ def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null) = newFreeTypeSymbol(newTypeName(name), info, value, (if (flags == 0L) EXISTENTIAL else flags) | DEFERRED, origin)
+
+ def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers =
+ Modifiers(flags, privateWithin, annotations)
+
+ val gen: TreeGen { val global: TreeBuildUtil.this.type }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/internal/TreeGen.scala b/src/compiler/scala/reflect/internal/TreeGen.scala
index 141ff12f8a..f2f9842595 100644
--- a/src/compiler/scala/reflect/internal/TreeGen.scala
+++ b/src/compiler/scala/reflect/internal/TreeGen.scala
@@ -1,19 +1,20 @@
package scala.reflect
package internal
-abstract class TreeGen {
+abstract class TreeGen extends api.AbsTreeGen {
val global: SymbolTable
import global._
import definitions._
- def rootId(name: Name) = Select(Ident(nme.ROOTPKG), name)
- def rootScalaDot(name: Name) = Select(rootId(nme.scala_) setSymbol ScalaPackage, name)
- def scalaDot(name: Name) = Select(Ident(nme.scala_) setSymbol ScalaPackage, name)
- def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) setSymbol AnyRefClass
- def scalaUnitConstr = scalaDot(tpnme.Unit) setSymbol UnitClass
- def productConstr = scalaDot(tpnme.Product) setSymbol ProductRootClass
- def serializableConstr = scalaDot(tpnme.Serializable) setSymbol SerializableClass
+ def rootId(name: Name) = Select(Ident(nme.ROOTPKG), name)
+ def rootScalaDot(name: Name) = Select(rootId(nme.scala_) setSymbol ScalaPackage, name)
+ def scalaDot(name: Name) = Select(Ident(nme.scala_) setSymbol ScalaPackage, name)
+ def scalaAnnotationDot(name: Name) = Select(scalaDot(nme.annotation), name)
+ def scalaAnyRefConstr = scalaDot(tpnme.AnyRef) setSymbol AnyRefClass
+ def scalaUnitConstr = scalaDot(tpnme.Unit) setSymbol UnitClass
+ def productConstr = scalaDot(tpnme.Product) setSymbol ProductRootClass
+ def serializableConstr = scalaDot(tpnme.Serializable) setSymbol SerializableClass
def scalaFunctionConstr(argtpes: List[Tree], restpe: Tree, abstractFun: Boolean = false): Tree = {
val cls = if (abstractFun)
@@ -48,6 +49,9 @@ abstract class TreeGen {
def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree =
Apply(mkTypeApply(target, targs map TypeTree), args)
+ def mkNullaryCall(method: Symbol, targs: List[Type]): Tree =
+ mkTypeApply(mkAttributedRef(method), targs map TypeTree)
+
/** Builds a reference to value whose type is given stable prefix.
* The type must be suitable for this. For example, it
* must not be a TypeRef pointing to an abstract type variable.
diff --git a/src/compiler/scala/reflect/internal/TreeInfo.scala b/src/compiler/scala/reflect/internal/TreeInfo.scala
index ce3de94335..2251310f35 100644
--- a/src/compiler/scala/reflect/internal/TreeInfo.scala
+++ b/src/compiler/scala/reflect/internal/TreeInfo.scala
@@ -227,8 +227,11 @@ abstract class TreeInfo {
/** Is tree a variable pattern? */
def isVarPattern(pat: Tree): Boolean = pat match {
- case _: BackQuotedIdent => false
- case x: Ident => isVariableName(x.name)
+ case x: Ident => !x.isBackquoted && isVariableName(x.name)
+ case _ => false
+ }
+ def isDeprecatedIdentifier(tree: Tree): Boolean = tree match {
+ case x: Ident => !x.isBackquoted && nme.isDeprecatedIdentifierName(x.name)
case _ => false
}
@@ -531,4 +534,214 @@ abstract class TreeInfo {
case _ => None
}
}
+
+ def isApplyDynamicName(name: Name) = (name == nme.updateDynamic) || (name == nme.selectDynamic) || (name == nme.applyDynamic) || (name == nme.applyDynamicNamed)
+
+ class DynamicApplicationExtractor(nameTest: Name => Boolean) {
+ def unapply(tree: Tree) = tree match {
+ case Apply(TypeApply(Select(qual, oper), _), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name))
+ case Apply(Select(qual, oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((qual, name))
+ case Apply(Ident(oper), List(Literal(Constant(name)))) if nameTest(oper) => Some((EmptyTree, name))
+ case _ => None
+ }
+ }
+ object DynamicUpdate extends DynamicApplicationExtractor(_ == nme.updateDynamic)
+ object DynamicApplication extends DynamicApplicationExtractor(isApplyDynamicName)
+ object DynamicApplicationNamed extends DynamicApplicationExtractor(_ == nme.applyDynamicNamed)
+
+
+ // domain-specific extractors for reification
+
+ import definitions._
+
+ object TypedOrAnnotated {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case ty @ Typed(_, _) =>
+ Some(ty)
+ case at @ Annotated(_, _) =>
+ Some(at)
+ case _ =>
+ None
+ }
+ }
+
+ object TreeSplice {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(splicee, _) if tree.symbol == ExprEval || tree.symbol == ExprValue =>
+ Some(splicee)
+ case _ =>
+ None
+ }
+ }
+
+ object EvalSplice {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(splicee, _) if tree.symbol == ExprEval =>
+ Some(splicee)
+ case _ =>
+ None
+ }
+ }
+
+ object ValueSplice {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(splicee, _) if tree.symbol == ExprValue =>
+ Some(splicee)
+ case _ =>
+ None
+ }
+ }
+
+ object Reified {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
+ case ReifiedTree(reifee, symbolTable, reified, _) =>
+ Some(reifee, symbolTable, reified)
+ case ReifiedType(reifee, symbolTable, reified) =>
+ Some(reifee, symbolTable, reified)
+ case _ =>
+ None
+ }
+ }
+
+ object ReifiedTree {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match {
+ case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(Apply(_, List(tree)), List(Apply(_, tpe :: _)))) if mrDef.name == nme.MIRROR_SHORT =>
+ Some(reifee, symbolTable, tree, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object InlineableTreeSplice {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree, Symbol)] = tree match {
+ case select @ Select(ReifiedTree(splicee, symbolTable, tree, tpe), _) if select.symbol == ExprEval || select.symbol == ExprValue =>
+ Some(splicee, symbolTable, tree, tpe, select.symbol)
+ case _ =>
+ None
+ }
+ }
+
+ object InlinedTreeSplice {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree, Tree)] = tree match {
+ case Select(ReifiedTree(splicee, symbolTable, tree, tpe), name) if name == ExprTree.name =>
+ Some(splicee, symbolTable, tree, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object ReifiedType {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
+ case reifee @ Block((mrDef @ ValDef(_, _, _, _)) :: symbolTable, Apply(_, tpe :: _)) if mrDef.name == nme.MIRROR_SHORT =>
+ Some(reifee, symbolTable, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object InlinedTypeSplice {
+ def unapply(tree: Tree): Option[(Tree, List[Tree], Tree)] = tree match {
+ case Select(ReifiedType(splicee, symbolTable, tpe), name) if name == TypeTagTpe.name =>
+ Some(splicee, symbolTable, tpe)
+ case _ =>
+ None
+ }
+ }
+
+ object FreeDef {
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
+ case FreeTermDef(mrRef, name, binding, flags, origin) =>
+ Some(mrRef, name, binding, flags, origin)
+ case FreeTypeDef(mrRef, name, binding, flags, origin) =>
+ Some(mrRef, name, binding, flags, origin)
+ case _ =>
+ None
+ }
+ }
+
+ object FreeTermDef {
+ lazy val newFreeTermMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeTerm)
+
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
+ case ValDef(_, name, _, Apply(Select(mrRef @ Ident(_), newFreeTerm), List(_, _, binding, Literal(Constant(flags: Long)), Literal(Constant(origin: String)))))
+ if mrRef.name == nme.MIRROR_SHORT && newFreeTerm == newFreeTermMethod.name =>
+ Some(mrRef, name, binding, flags, origin)
+ case _ =>
+ None
+ }
+ }
+
+ object FreeTypeDef {
+ lazy val newFreeExistentialMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeType)
+ lazy val newFreeTypeMethod = getMember(getRequiredClass("scala.reflect.api.TreeBuildUtil"), nme.newFreeExistential)
+
+ def unapply(tree: Tree): Option[(Tree, TermName, Tree, Long, String)] = tree match {
+ case ValDef(_, name, _, Apply(Select(mrRef1 @ Ident(_), newFreeType), List(_, _, value, Literal(Constant(flags: Long)), Literal(Constant(origin: String)))))
+ if mrRef1.name == nme.MIRROR_SHORT && (newFreeType == newFreeTypeMethod.name || newFreeType == newFreeExistentialMethod.name) =>
+ value match {
+ case Apply(TypeApply(Select(Select(mrRef2 @ Ident(_), typeTag), apply), List(binding)), List(Literal(Constant(null)), _))
+ if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag && apply == nme.apply =>
+ Some(mrRef1, name, binding, flags, origin)
+ case Apply(TypeApply(Select(mrRef2 @ Ident(_), typeTag), List(binding)), List(Literal(Constant(null)), _))
+ if mrRef2.name == nme.MIRROR_SHORT && typeTag == nme.TypeTag =>
+ Some(mrRef1, name, binding, flags, origin)
+ case _ =>
+ throw new Error("unsupported free type def: %s%n%s".format(value, showRaw(value)))
+ }
+ case _ =>
+ None
+ }
+ }
+
+ object FreeRef {
+ def unapply(tree: Tree): Option[(Tree, TermName)] = tree match {
+ case Apply(Select(mrRef @ Ident(_), ident), List(Ident(name: TermName))) if ident == nme.Ident && name.startsWith(nme.MIRROR_FREE_PREFIX) =>
+ Some(mrRef, name)
+ case _ =>
+ None
+ }
+ }
+
+ object TypeRefToFreeType {
+ def unapply(tree: Tree): Option[TermName] = tree match {
+ case Apply(Select(Select(mrRef @ Ident(_), typeRef), apply), List(Select(_, noSymbol), Ident(freeType: TermName), nil))
+ if (mrRef.name == nme.MIRROR_SHORT && typeRef == nme.TypeRef && noSymbol == nme.NoSymbol && freeType.startsWith(nme.MIRROR_FREE_PREFIX)) =>
+ Some(freeType)
+ case _ =>
+ None
+ }
+ }
+
+ object NestedExpr {
+ def unapply(tree: Tree): Option[(Tree, Tree, Tree)] = tree match {
+ case Apply(Apply(factory @ Select(expr, apply), List(tree)), List(typetag)) if expr.symbol == ExprModule && apply == nme.apply =>
+ Some(factory, tree, typetag)
+ case _ =>
+ None
+ }
+ }
+
+ object BoundTerm {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Ident(name) if name.isTermName =>
+ Some(tree)
+ case This(_) =>
+ Some(tree)
+ case _ =>
+ None
+ }
+ }
+
+ object BoundType {
+ def unapply(tree: Tree): Option[Tree] = tree match {
+ case Select(_, name) if name.isTypeName =>
+ Some(tree)
+ case SelectFromTypeTree(_, name) if name.isTypeName =>
+ Some(tree)
+ case Ident(name) if name.isTypeName =>
+ Some(tree)
+ case _ =>
+ None
+ }
+ }
}
diff --git a/src/compiler/scala/reflect/internal/TreePrinters.scala b/src/compiler/scala/reflect/internal/TreePrinters.scala
index 8ed0ee6357..b3e4318fdc 100644
--- a/src/compiler/scala/reflect/internal/TreePrinters.scala
+++ b/src/compiler/scala/reflect/internal/TreePrinters.scala
@@ -23,6 +23,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
else s
}
def quotedName(name: Name): String = quotedName(name, false)
+ def quotedName(name: String): String = quotedName(newTermName(name), false)
private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = {
val sym = tree.symbol
@@ -31,7 +32,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
var suffix = ""
if (settings.uniqid.value) suffix += ("#" + sym.id)
if (settings.Yshowsymkinds.value) suffix += ("#" + sym.abbreviatedKindString)
- prefix + tree.symbol.decodedName + suffix
+ prefix + quotedName(tree.symbol.decodedName) + suffix
} else {
quotedName(name, decoded)
}
@@ -64,7 +65,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
def indent() = indentMargin += indentStep
def undent() = indentMargin -= indentStep
- def printPosition(tree: Tree) = if (doPrintPositions) print(showPos(tree.pos))
+ def printPosition(tree: Tree) = if (doPrintPositions) print(tree.pos.show)
def println() {
out.println()
@@ -102,6 +103,16 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
}
}
+ def printLabelParams(ps: List[Ident]) {
+ print("(")
+ printSeq(ps){printLabelParam}{print(", ")}
+ print(")")
+ }
+
+ def printLabelParam(p: Ident) {
+ print(symName(p, p.name)); printOpt(": ", TypeTree() setType p.tpe)
+ }
+
def printValueParams(ts: List[ValDef]) {
print("(")
if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "")
@@ -175,7 +186,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
printAnnotations(tree)
printModifiers(tree, mods)
val word =
- if (mods.hasTraitFlag) "trait"
+ if (mods.isTrait) "trait"
else if (ifSym(tree, _.isModuleClass)) "object"
else "class"
@@ -218,7 +229,7 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
}
case LabelDef(name, params, rhs) =>
- print(symName(tree, name)); printRow(params, "(", ",", ")"); printBlock(rhs)
+ print(symName(tree, name)); printLabelParams(params); printBlock(rhs)
case Import(expr, selectors) =>
// Is this selector remapping a name (i.e, {name1 => name2})
@@ -362,8 +373,9 @@ trait TreePrinters extends api.TreePrinters { self: SymbolTable =>
case Select(qualifier, name) =>
print(backquotedPath(qualifier), ".", symName(tree, name))
- case Ident(name) =>
- print(symName(tree, name))
+ case id @ Ident(name) =>
+ val str = symName(tree, name)
+ print( if (id.isBackquoted) "`" + str + "`" else str )
case Literal(x) =>
print(x.escapedStringValue)
diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala
index 1a40e0105c..e2d9310424 100644
--- a/src/compiler/scala/reflect/internal/Trees.scala
+++ b/src/compiler/scala/reflect/internal/Trees.scala
@@ -42,7 +42,6 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
/* Abstract types from HasFlags. */
- type FlagsType = Long
type AccessBoundaryType = Name
type AnnotationType = Tree
@@ -57,11 +56,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
def hasAccessBoundary = privateWithin != tpnme.EMPTY
def hasAllFlags(mask: Long): Boolean = (flags & mask) == mask
def hasFlag(flag: Long) = (flag & flags) != 0L
- def hasFlagsToString(mask: Long): String = flagsToString(
- flags & mask,
- if (hasAccessBoundary) privateWithin.toString else ""
- )
- def defaultFlagString = hasFlagsToString(-1L)
+
def & (flag: Long): Modifiers = {
val flags1 = flags & flag
if (flags1 == flags) this
@@ -91,7 +86,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
override def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers =
Modifiers(flags, privateWithin, f(annotations)) setPositions positions
- override def toString = "Modifiers(%s, %s, %s)".format(defaultFlagString, annotations mkString ", ", positions)
+ override def toString = "Modifiers(%s, %s, %s)".format(flagString, annotations mkString ", ", positions)
}
def Modifiers(flags: Long, privateWithin: Name): Modifiers = Modifiers(flags, privateWithin, List())
@@ -108,9 +103,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
// --- extension methods --------------------------------------------------------
- implicit def treeOps(tree: Tree): TreeOps = new TreeOps(tree)
-
- class TreeOps(tree: Tree) {
+ implicit class TreeOps(tree: Tree) {
def isErroneous = (tree.tpe ne null) && tree.tpe.isErroneous
def isTyped = (tree.tpe ne null) && !tree.tpe.isErroneous
@@ -151,11 +144,9 @@ trait Trees extends api.Trees { self: SymbolTable =>
* less than the whole tree.
*/
def summaryString: String = tree match {
- case Select(qual, name) => qual.summaryString + "." + name.decode
- case Ident(name) => name.longString
case Literal(const) => "Literal(" + const + ")"
- case t: DefTree => t.shortClass + " `" + t.name.decode + "`"
- case t: RefTree => t.shortClass + " `" + t.name.longString + "`"
+ case Select(qual, name) => qual.summaryString + "." + name.decode
+ case t: NameTree => t.name.longString
case t =>
t.shortClass + (
if (t.symbol != null && t.symbol != NoSymbol) " " + t.symbol
@@ -189,7 +180,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
def ValDef(sym: Symbol, rhs: Tree): ValDef =
atPos(sym.pos) {
ValDef(Modifiers(sym.flags), sym.name.toTermName,
- TypeTree(sym.tpe) setPos focusPos(sym.pos),
+ TypeTree(sym.tpe) setPos sym.pos.focus,
rhs) setSymbol sym
}
@@ -208,7 +199,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
sym.name.toTermName,
sym.typeParams map TypeDef,
vparamss,
- TypeTree(sym.tpe.finalResultType) setPos focusPos(sym.pos),
+ TypeTree(sym.tpe.finalResultType) setPos sym.pos.focus,
rhs) setSymbol sym
}
@@ -240,7 +231,8 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
/** casedef shorthand */
- def CaseDef(pat: Tree, body: Tree): CaseDef = CaseDef(pat, EmptyTree, body)
+ def CaseDef(pat: Tree, body: Tree): CaseDef =
+ CaseDef(pat, EmptyTree, body)
def Bind(sym: Symbol, body: Tree): Bind =
Bind(sym.name, body) setSymbol sym
@@ -254,10 +246,39 @@ trait Trees extends api.Trees { self: SymbolTable =>
def Apply(sym: Symbol, args: Tree*): Tree =
Apply(Ident(sym), args.toList)
+ /** Factory method for object creation `new tpt(args_1)...(args_n)`
+ * A `New(t, as)` is expanded to: `(new t).<init>(as)`
+ */
+ def New(tpt: Tree, argss: List[List[Tree]]): Tree = argss match {
+ case Nil => new ApplyConstructor(tpt, Nil)
+ case xs :: rest => rest.foldLeft(new ApplyConstructor(tpt, xs): Tree)(Apply)
+ }
+
+ /** 0-1 argument list new, based on a type.
+ */
+ def New(tpe: Type, args: Tree*): Tree =
+ new ApplyConstructor(TypeTree(tpe), args.toList)
+
def New(sym: Symbol, args: Tree*): Tree =
New(sym.tpe, args: _*)
- def Super(sym: Symbol, mix: TypeName): Tree = Super(This(sym), mix)
+ def Super(sym: Symbol, mix: TypeName): Tree =
+ Super(This(sym), mix)
+
+ def This(sym: Symbol): Tree =
+ This(sym.name.toTypeName) setSymbol sym
+
+ def Select(qualifier: Tree, name: String): Select =
+ Select(qualifier, newTermName(name))
+
+ def Select(qualifier: Tree, sym: Symbol): Select =
+ Select(qualifier, sym.name) setSymbol sym
+
+ def Ident(name: String): Ident =
+ Ident(newTermName(name))
+
+ def Ident(sym: Symbol): Ident =
+ Ident(sym.name) setSymbol sym
/** Block factory that flattens directly nested blocks.
*/
@@ -271,6 +292,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
}
// --- specific traversers and transformers
+ // todo. move these into scala.reflect.api
protected[scala] def duplicateTree(tree: Tree): Tree = duplicator transform tree
@@ -278,44 +300,11 @@ trait Trees extends api.Trees { self: SymbolTable =>
override val treeCopy = newStrictTreeCopier
override def transform(t: Tree) = {
val t1 = super.transform(t)
- if ((t1 ne t) && isRangePos(t1.pos)) t1 setPos focusPos(t.pos)
+ if ((t1 ne t) && t1.pos.isRange) t1 setPos t.pos.focus
t1
}
}
- trait PosAssigner extends Traverser {
- var pos: Position
- }
- protected[this] lazy val posAssigner: PosAssigner = new DefaultPosAssigner
-
- protected class DefaultPosAssigner extends PosAssigner {
- var pos: Position = _
- override def traverse(t: Tree) {
- if (t eq EmptyTree) ()
- else if (t.pos == NoPosition) {
- t.setPos(pos)
- super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if?
- // @PP: it's pruning whenever it encounters a node with a
- // position, which I interpret to mean that (in the author's
- // mind at least) either the children of a positioned node will
- // already be positioned, or the children of a positioned node
- // do not merit positioning.
- //
- // Whatever the author's rationale, it does seem like a bad idea
- // to press on through a positioned node to find unpositioned
- // children beneath it and then to assign whatever happens to
- // be in `pos` to such nodes. There are supposed to be some
- // position invariants which I can't imagine surviving that.
- }
- }
- }
-
- def atPos[T <: Tree](pos: Position)(tree: T): T = {
- posAssigner.pos = pos
- posAssigner.traverse(tree)
- tree
- }
-
class ForeachPartialTreeTraverser(pf: PartialFunction[Tree, Tree]) extends Traverser {
override def traverse(tree: Tree) {
val t = if (pf isDefinedAt tree) pf(tree) else tree
@@ -326,11 +315,19 @@ trait Trees extends api.Trees { self: SymbolTable =>
class ChangeOwnerTraverser(val oldowner: Symbol, val newowner: Symbol) extends Traverser {
def changeOwner(tree: Tree) = tree match {
case Return(expr) =>
- if (tree.symbol == oldowner)
- tree.symbol = newowner
+ if (tree.symbol == oldowner) {
+ // SI-5612
+ if (newowner hasTransOwner oldowner)
+ log("NOT changing owner of %s because %s is nested in %s".format(tree, newowner, oldowner))
+ else {
+ log("changing owner of %s: %s => %s".format(tree, oldowner, newowner))
+ tree.symbol = newowner
+ }
+ }
case _: DefTree | _: Function =>
- if (tree.symbol != NoSymbol && tree.symbol.owner == oldowner)
+ if (tree.symbol != NoSymbol && tree.symbol.owner == oldowner) {
tree.symbol.owner = newowner
+ }
case _ =>
}
override def traverse(tree: Tree) {
@@ -368,7 +365,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
override def toString = substituterString("Symbol", "Tree", from, to)
}
- /** Substitute clazz.this with `to`. `to` must be an attributed tree.
+ /** Substitute clazz.this with `to`. `to` must be an attributed tree.
*/
class ThisSubstituter(clazz: Symbol, to: => Tree) extends Transformer {
val newtpe = to.tpe
@@ -423,7 +420,7 @@ trait Trees extends api.Trees { self: SymbolTable =>
tree match {
case Ident(name0) if tree.symbol != NoSymbol =>
treeCopy.Ident(tree, tree.symbol.name)
- case Select(qual, name0) =>
+ case Select(qual, name0) if tree.symbol != NoSymbol =>
treeCopy.Select(tree, transform(qual), tree.symbol.name)
case _ =>
super.transform(tree)
@@ -435,4 +432,3 @@ trait Trees extends api.Trees { self: SymbolTable =>
override def toString() = "TreeSymSubstituter/" + substituterString("Symbol", "Symbol", from, to)
}
}
-
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 5afa5343ed..09e7303b90 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -6,7 +6,8 @@
package scala.reflect
package internal
-import scala.collection.{ mutable, immutable }
+import scala.collection.{ mutable, immutable, generic }
+import generic.Clearable
import scala.ref.WeakReference
import mutable.ListBuffer
import Flags._
@@ -97,7 +98,7 @@ trait Types extends api.Types { self: SymbolTable =>
*/
private final val propagateParameterBoundsToTypeVars = sys.props contains "scalac.debug.prop-constraints"
- protected val enableTypeVarExperimentals = settings.Xexperimental.value || settings.YvirtPatmat.value
+ protected val enableTypeVarExperimentals = settings.Xexperimental.value
/** Empty immutable maps to avoid allocations. */
private val emptySymMap = immutable.Map[Symbol, Symbol]()
@@ -115,7 +116,7 @@ trait Types extends api.Types { self: SymbolTable =>
protected def newUndoLog = new UndoLog
- class UndoLog {
+ class UndoLog extends Clearable {
private type UndoPairs = List[(TypeVar, TypeConstraint)]
private var log: UndoPairs = List()
@@ -139,7 +140,7 @@ trait Types extends api.Types { self: SymbolTable =>
log ::= ((tv, tv.constr.cloneInternal))
}
- private[scala] def clear() {
+ def clear() {
if (settings.debug.value)
self.log("Clearing " + log.size + " entries from the undoLog.")
@@ -254,7 +255,9 @@ trait Types extends api.Types { self: SymbolTable =>
case object UnmappableTree extends TermTree {
override def toString = "<unmappable>"
super.tpe_=(NoType)
- override def tpe_=(t: Type) = if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>")
+ override def tpe_=(t: Type) = if (t != NoType) {
+ throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>")
+ }
}
abstract class AbsTypeImpl extends AbsType { this: Type =>
@@ -262,8 +265,53 @@ trait Types extends api.Types { self: SymbolTable =>
def nonPrivateDeclaration(name: Name): Symbol = nonPrivateDecl(name)
def declarations = decls
def typeArguments = typeArgs
- def erasedType = transformedType(this)
+ def erasure = this match {
+ case ConstantType(value) => widen.erasure // [Eugene to Martin] constant types are unaffected by erasure. weird.
+ case _ =>
+ var result = transformedType(this)
+ result = result.normalize match { // necessary to deal with erasures of HK types, typeConstructor won't work
+ case PolyType(undets, underlying) => existentialAbstraction(undets, underlying) // we don't want undets in the result
+ case _ => result
+ }
+ // [Eugene] erasure screws up all ThisTypes for modules into PackageTypeRefs
+ // we need to unscrew them, or certain typechecks will fail mysteriously
+ // http://groups.google.com/group/scala-internals/browse_thread/thread/6d3277ae21b6d581
+ result = result.map(tpe => tpe match {
+ case tpe: PackageTypeRef => ThisType(tpe.sym)
+ case _ => tpe
+ })
+ result
+ }
def substituteTypes(from: List[Symbol], to: List[Type]): Type = subst(from, to)
+
+ // [Eugene] to be discussed and refactored
+ def isConcrete = {
+ def notConcreteSym(sym: Symbol) =
+ sym.isAbstractType && !sym.isExistential
+
+ def notConcreteTpe(tpe: Type): Boolean = tpe match {
+ case ThisType(_) => false
+ case SuperType(_, _) => false
+ case SingleType(pre, sym) => notConcreteSym(sym)
+ case ConstantType(_) => false
+ case TypeRef(_, sym, args) => notConcreteSym(sym) || (args exists (arg => notConcreteTpe(arg)))
+ case RefinedType(_, _) => false
+ case ExistentialType(_, _) => false
+ case AnnotatedType(_, tp, _) => notConcreteTpe(tp)
+ case _ => true
+ }
+
+ !notConcreteTpe(this)
+ }
+
+ // [Eugene] is this comprehensive?
+ // the only thingies that we want to splice are: 1) type parameters, 2) type members
+ // the thingies that we don't want to splice are: 1) concrete types (obviously), 2) existential skolems
+ // this check seems to cover them all, right?
+ // todo. after we discuss this, move the check to subclasses
+ def isSpliceable = {
+ this.isInstanceOf[TypeRef] && typeSymbol.isAbstractType && !typeSymbol.isExistential
+ }
}
/** The base class for all types */
@@ -710,7 +758,9 @@ trait Types extends api.Types { self: SymbolTable =>
/** Returns all parts of this type which satisfy predicate `p` */
def filter(p: Type => Boolean): List[Type] = new FilterTypeCollector(p) collect this
- def withFilter(p: Type => Boolean) = new FilterTypeCollector(p) {
+ def withFilter(p: Type => Boolean) = new FilterMapForeach(p)
+
+ class FilterMapForeach(p: Type => Boolean) extends FilterTypeCollector(p){
def foreach[U](f: Type => U): Unit = collect(Type.this) foreach f
def map[T](f: Type => T): List[T] = collect(Type.this) map f
}
@@ -723,6 +773,9 @@ trait Types extends api.Types { self: SymbolTable =>
/** Apply `f` to each part of this type */
def foreach(f: Type => Unit) { new ForEachTypeTraverser(f).traverse(this) }
+ /** Apply `pf' to each part of this type on which the function is defined */
+ def collect[T](pf: PartialFunction[Type, T]): List[T] = new CollectTypeCollector(pf).collect(this)
+
/** Apply `f` to each part of this type; children get mapped before their parents */
def map(f: Type => Type): Type = new TypeMap {
def apply(x: Type) = f(mapOver(x))
@@ -910,14 +963,10 @@ trait Types extends api.Types { self: SymbolTable =>
*/
def directObjectString = safeToString
- /** A test whether a type contains any unification type variables. */
+ /** A test whether a type contains any unification type variables.
+ * Overridden with custom logic except where trivially true.
+ */
def isGround: Boolean = this match {
- case TypeVar(_, constr) =>
- constr.instValid && constr.inst.isGround
- case TypeRef(pre, sym, args) =>
- sym.isPackageClass || pre.isGround && (args forall (_.isGround))
- case SingleType(pre, sym) =>
- sym.isPackageClass || pre.isGround
case ThisType(_) | NoPrefix | WildcardType | NoType | ErrorType | ConstantType(_) =>
true
case _ =>
@@ -1194,6 +1243,8 @@ trait Types extends api.Types { self: SymbolTable =>
override def kind = "BoundedWildcardType"
}
+ object BoundedWildcardType extends BoundedWildcardTypeExtractor
+
/** An object representing a non-existing type */
case object NoType extends Type {
override def isTrivial: Boolean = true
@@ -1251,6 +1302,8 @@ trait Types extends api.Types { self: SymbolTable =>
*/
abstract case class SingleType(pre: Type, sym: Symbol) extends SingletonType {
override val isTrivial: Boolean = pre.isTrivial
+ override def isGround = sym.isPackageClass || pre.isGround
+
// override def isNullable = underlying.isNullable
override def isNotNull = underlying.isNotNull
private[reflect] var underlyingCache: Type = NoType
@@ -1306,7 +1359,8 @@ trait Types extends api.Types { self: SymbolTable =>
if (period != currentPeriod) {
tpe.underlyingPeriod = currentPeriod
if (!isValid(period)) {
- tpe.underlyingCache = tpe.pre.memberType(tpe.sym).resultType;
+ // [Eugene to Paul] needs review
+ tpe.underlyingCache = if (tpe.sym == NoSymbol) ThisType(RootClass) else tpe.pre.memberType(tpe.sym).resultType;
assert(tpe.underlyingCache ne tpe, tpe)
}
}
@@ -1456,7 +1510,8 @@ trait Types extends api.Types { self: SymbolTable =>
case tv: TypeVar => tvs += tv
case _ =>
}
- val varToParamMap: Map[Type, Symbol] = tvs map (tv => tv -> tv.origin.typeSymbol.cloneSymbol) toMap
+ val varToParamMap: Map[Type, Symbol] =
+ mapFrom[TypeVar, Type, Symbol](tvs.toList)(_.origin.typeSymbol.cloneSymbol)
val paramToVarMap = varToParamMap map (_.swap)
val varToParam = new TypeMap {
def apply(tp: Type) = varToParamMap get tp match {
@@ -1555,12 +1610,26 @@ trait Types extends api.Types { self: SymbolTable =>
override def typeConstructor =
copyRefinedType(this, parents map (_.typeConstructor), decls)
- /* MO to AM: This is probably not correct
- * If they are several higher-kinded parents with different bounds we need
- * to take the intersection of their bounds
- */
- override def normalize = {
- if (isHigherKinded) {
+ final override def normalize: Type =
+ if (phase.erasedTypes) normalizeImpl
+ else {
+ if (normalized eq null) normalized = normalizeImpl
+ normalized
+ }
+
+ private var normalized: Type = _
+ private def normalizeImpl = {
+ // TODO see comments around def intersectionType and def merge
+ def flatten(tps: List[Type]): List[Type] = tps flatMap { case RefinedType(parents, ds) if ds.isEmpty => flatten(parents) case tp => List(tp) }
+ val flattened = flatten(parents).distinct
+ if (decls.isEmpty && flattened.tail.isEmpty) {
+ flattened.head
+ } else if (flattened != parents) {
+ refinedType(flattened, if (typeSymbol eq NoSymbol) NoSymbol else typeSymbol.owner, decls, NoPosition)
+ } else if (isHigherKinded) {
+ // MO to AM: This is probably not correct
+ // If they are several higher-kinded parents with different bounds we need
+ // to take the intersection of their bounds
typeFun(
typeParams,
RefinedType(
@@ -1570,8 +1639,7 @@ trait Types extends api.Types { self: SymbolTable =>
},
decls,
typeSymbol))
- }
- else super.normalize
+ } else super.normalize
}
/** A refined type P1 with ... with Pn { decls } is volatile if
@@ -1822,7 +1890,35 @@ trait Types extends api.Types { self: SymbolTable =>
object ConstantType extends ConstantTypeExtractor {
def apply(value: Constant): ConstantType = {
- unique(new UniqueConstantType(value)).asInstanceOf[ConstantType]
+ val tpe = new UniqueConstantType(value)
+ if (value.tag == ClazzTag) {
+ // if we carry a classOf, we might be in trouble
+ // http://groups.google.com/group/scala-internals/browse_thread/thread/45185b341aeb6a30
+ // I don't have time for a thorough fix, so I put a hacky workaround here
+ val alreadyThere = uniques findEntry tpe
+ if ((alreadyThere ne null) && (alreadyThere ne tpe) && (alreadyThere.toString != tpe.toString)) {
+ // we need to remove a stale type that has the same hashcode as we do
+ // HashSet doesn't support removal, and this makes our task non-trivial
+ // also we cannot simply recreate it, because that'd skew hashcodes (that change over time, omg!)
+ // the only solution I can see is getting into the underlying array and sneakily manipulating it
+ val ftable = uniques.getClass.getDeclaredFields().find(f => f.getName endsWith "table").get
+ ftable.setAccessible(true)
+ val table = ftable.get(uniques).asInstanceOf[Array[AnyRef]]
+ def overwrite(hc: Int, x: Type) {
+ def index(x: Int): Int = math.abs(x % table.length)
+ var h = index(hc)
+ var entry = table(h)
+ while (entry ne null) {
+ if (x == entry)
+ table(h) = x
+ h = index(h + 1)
+ entry = table(h)
+ }
+ }
+ overwrite(tpe.##, tpe)
+ }
+ }
+ unique(tpe).asInstanceOf[ConstantType]
}
}
@@ -2018,7 +2114,7 @@ trait Types extends api.Types { self: SymbolTable =>
// TODO: is there another way a typeref's symbol can refer to a symbol defined in its pre?
case _ => sym
}
-
+ override def kind = "AliasTypeRef"
}
trait AbstractTypeRef extends NonClassTypeRef {
@@ -2071,6 +2167,7 @@ trait Types extends api.Types { self: SymbolTable =>
override def bounds = thisInfo.bounds
// def transformInfo(tp: Type): Type = appliedType(tp.asSeenFrom(pre, sym.owner), typeArgsOrDummies)
override protected[Types] def baseTypeSeqImpl: BaseTypeSeq = transform(bounds.hi).baseTypeSeq prepend this
+ override def kind = "AbstractTypeRef"
}
/** A class for named types of the form
@@ -2108,6 +2205,11 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ override def isGround = (
+ sym.isPackageClass
+ || pre.isGround && args.forall(_.isGround)
+ )
+
def etaExpand: Type = {
// must initialise symbol, see test/files/pos/ticket0137.scala
val tpars = initializedTypeParams
@@ -2200,10 +2302,10 @@ trait Types extends api.Types { self: SymbolTable =>
parentsString(thisInfo.parents) + refinementString
else rest
)
- private def customToString = this match {
- case TypeRef(_, RepeatedParamClass, arg :: _) => arg + "*"
- case TypeRef(_, ByNameParamClass, arg :: _) => "=> " + arg
- case _ =>
+ private def customToString = sym match {
+ case RepeatedParamClass => args.head + "*"
+ case ByNameParamClass => "=> " + args.head
+ case _ =>
def targs = normalize.typeArgs
if (isFunctionType(this)) {
@@ -2240,7 +2342,7 @@ trait Types extends api.Types { self: SymbolTable =>
else if (sym.isPackageClass || sym.isPackageObjectOrClass)
sym.skipPackageObject.fullName + "."
else if (isStable && nme.isSingletonName(sym.name))
- nme.dropSingletonName(sym.name) + "."
+ tpnme.dropSingletonName(sym.name) + "."
else
super.prefixString
)
@@ -2460,8 +2562,8 @@ trait Types extends api.Types { self: SymbolTable =>
override def prefix = maybeRewrap(underlying.prefix)
override def typeArgs = underlying.typeArgs map maybeRewrap
override def params = underlying.params mapConserve { param =>
- val tpe1 = rewrap(param.tpe)
- if (tpe1 eq param.tpe) param else param.cloneSymbol.setInfo(tpe1)
+ val tpe1 = rewrap(param.tpeHK)
+ if (tpe1 eq param.tpeHK) param else param.cloneSymbol.setInfo(tpe1)
}
override def paramTypes = underlying.paramTypes map maybeRewrap
override def instantiateTypeParams(formals: List[Symbol], actuals: List[Type]) = {
@@ -2480,39 +2582,46 @@ trait Types extends api.Types { self: SymbolTable =>
override def skolemizeExistential(owner: Symbol, origin: AnyRef) =
deriveType(quantified, tparam => (owner orElse tparam.owner).newExistentialSkolem(tparam, origin))(underlying)
- private def wildcardArgsString(available: Set[Symbol], args: List[Type]): List[String] = args match {
- case TypeRef(_, sym, _) :: args1 if (available contains sym) =>
- ("_"+sym.infoString(sym.info)) :: wildcardArgsString(available - sym, args1)
- case arg :: args1 if !(quantified exists (arg contains _)) =>
- arg.toString :: wildcardArgsString(available, args1)
- case _ =>
- List()
+ private def wildcardArgsString(qset: Set[Symbol], args: List[Type]): List[String] = args map {
+ case TypeRef(_, sym, _) if (qset contains sym) =>
+ "_"+sym.infoString(sym.info)
+ case arg =>
+ arg.toString
}
+
/** An existential can only be printed with wildcards if:
* - the underlying type is a typeref
- * - where there is a 1-to-1 correspondence between underlying's typeargs and quantified
- * - and none of the existential parameters is referenced from anywhere else in the type
- * - and none of the existential parameters are singleton types
+ * - every quantified variable appears at most once as a type argument and
+ * nowhere inside a type argument
+ * - no quantified type argument contains a quantified variable in its bound
+ * - the typeref's symbol is not itself quantified
+ * - the prefix is not quanitified
*/
- private def isRepresentableWithWildcards = !settings.debug.value && {
+ def isRepresentableWithWildcards = {
val qset = quantified.toSet
- !qset.exists(_.isSingletonExistential) && (underlying match {
- case TypeRef(_, sym, args) =>
- sameLength(args, quantified) && {
- args forall { arg =>
- qset(arg.typeSymbol) && !qset.exists(arg.typeSymbol.info.bounds contains _)
- }
+ underlying match {
+ case TypeRef(pre, sym, args) =>
+ def isQuantified(tpe: Type): Boolean = {
+ (tpe exists (t => qset contains t.typeSymbol)) ||
+ tpe.typeSymbol.isRefinementClass && (tpe.parents exists isQuantified)
}
+ val (wildcardArgs, otherArgs) = args partition (arg => qset contains arg.typeSymbol)
+ wildcardArgs.distinct == wildcardArgs &&
+ !(otherArgs exists (arg => isQuantified(arg))) &&
+ !(wildcardArgs exists (arg => isQuantified(arg.typeSymbol.info.bounds))) &&
+ !(qset contains sym) &&
+ !isQuantified(pre)
case _ => false
- })
}
+ }
+
override def safeToString: String = {
def clauses = {
val str = quantified map (_.existentialToString) mkString (" forSome { ", "; ", " }")
if (settings.explaintypes.value) "(" + str + ")" else str
}
underlying match {
- case TypeRef(pre, sym, args) if isRepresentableWithWildcards =>
+ case TypeRef(pre, sym, args) if !settings.debug.value && isRepresentableWithWildcards =>
"" + TypeRef(pre, sym, Nil) + wildcardArgsString(quantified.toSet, args).mkString("[", ", ", "]")
case MethodType(_, _) | NullaryMethodType(_) | PolyType(_, _) =>
"(" + underlying + ")" + clauses
@@ -2640,21 +2749,35 @@ trait Types extends api.Types { self: SymbolTable =>
else new TypeConstraint
}
def unapply(tv: TypeVar): Some[(Type, TypeConstraint)] = Some((tv.origin, tv.constr))
+ def untouchable(tparam: Symbol): TypeVar = createTypeVar(tparam, untouchable = true)
+ def apply(tparam: Symbol): TypeVar = createTypeVar(tparam, untouchable = false)
def apply(origin: Type, constr: TypeConstraint): TypeVar = apply(origin, constr, Nil, Nil)
- def apply(tparam: Symbol): TypeVar = apply(tparam.tpeHK, deriveConstraint(tparam), Nil, tparam.typeParams)
+ def apply(origin: Type, constr: TypeConstraint, args: List[Type], params: List[Symbol]): TypeVar =
+ createTypeVar(origin, constr, args, params, untouchable = false)
/** This is the only place TypeVars should be instantiated.
*/
- def apply(origin: Type, constr: TypeConstraint, args: List[Type], params: List[Symbol]): TypeVar = {
+ private def createTypeVar(origin: Type, constr: TypeConstraint, args: List[Type], params: List[Symbol], untouchable: Boolean): TypeVar = {
val tv = (
- if (args.isEmpty && params.isEmpty) new TypeVar(origin, constr)
- else if (args.size == params.size) new AppliedTypeVar(origin, constr, params zip args)
- else if (args.isEmpty) new HKTypeVar(origin, constr, params)
+ if (args.isEmpty && params.isEmpty) {
+ if (untouchable) new TypeVar(origin, constr) with UntouchableTypeVar
+ else new TypeVar(origin, constr)
+ }
+ else if (args.size == params.size) {
+ if (untouchable) new AppliedTypeVar(origin, constr, params zip args) with UntouchableTypeVar
+ else new AppliedTypeVar(origin, constr, params zip args)
+ }
+ else if (args.isEmpty) {
+ if (untouchable) new HKTypeVar(origin, constr, params) with UntouchableTypeVar
+ else new HKTypeVar(origin, constr, params)
+ }
else throw new Error("Invalid TypeVar construction: " + ((origin, constr, args, params)))
)
trace("create", "In " + tv.originLocation)(tv)
}
+ private def createTypeVar(tparam: Symbol, untouchable: Boolean): TypeVar =
+ createTypeVar(tparam.tpeHK, deriveConstraint(tparam), Nil, tparam.typeParams, untouchable)
}
/** Repack existential types, otherwise they sometimes get unpacked in the
@@ -2703,6 +2826,23 @@ trait Types extends api.Types { self: SymbolTable =>
)
}
+ trait UntouchableTypeVar extends TypeVar {
+ override def untouchable = true
+ override def isGround = true
+ override def registerTypeEquality(tp: Type, typeVarLHS: Boolean) = tp match {
+ case t: TypeVar if !t.untouchable =>
+ t.registerTypeEquality(this, !typeVarLHS)
+ case _ =>
+ super.registerTypeEquality(tp, typeVarLHS)
+ }
+ override def registerBound(tp: Type, isLowerBound: Boolean, isNumericBound: Boolean = false): Boolean = tp match {
+ case t: TypeVar if !t.untouchable =>
+ t.registerBound(this, !isLowerBound, isNumericBound)
+ case _ =>
+ super.registerBound(tp, isLowerBound, isNumericBound)
+ }
+ }
+
/** A class representing a type variable: not used after phase `typer`.
*
* A higher-kinded TypeVar has params (Symbols) and typeArgs (Types).
@@ -2716,6 +2856,7 @@ trait Types extends api.Types { self: SymbolTable =>
val origin: Type,
val constr0: TypeConstraint
) extends Type {
+ def untouchable = false // by other typevars
override def params: List[Symbol] = Nil
override def typeArgs: List[Type] = Nil
override def isHigherKinded = false
@@ -2728,6 +2869,7 @@ trait Types extends api.Types { self: SymbolTable =>
*/
var constr = constr0
def instValid = constr.instValid
+ override def isGround = instValid && constr.inst.isGround
/** The variable's skolemization level */
val level = skolemizationLevel
@@ -2770,6 +2912,7 @@ trait Types extends api.Types { self: SymbolTable =>
// existential.
// were we compared to skolems at a higher skolemizationLevel?
// EXPERIMENTAL: value will not be considered unless enableTypeVarExperimentals is true
+ // see SI-5729 for why this is still experimental
private var encounteredHigherLevel = false
private def shouldRepackType = enableTypeVarExperimentals && encounteredHigherLevel
@@ -2896,14 +3039,13 @@ trait Types extends api.Types { self: SymbolTable =>
// would be pointless. In this case, each check we perform causes us to lose specificity: in
// the end the best we'll do is the least specific type we tested against, since the typevar
// does not see these checks as "probes" but as requirements to fulfill.
- // TODO: the `suspended` flag can be used to poke around with leaving a trace
+ // TODO: can the `suspended` flag be used to poke around without leaving a trace?
//
// So the strategy used here is to test first the type, then the direct parents, and finally
// to fall back on the individual base types. This warrants eventual re-examination.
// AM: I think we could use the `suspended` flag to avoid side-effecting during unification
-
- if (suspended) // constraint accumulation is disabled
+ if (suspended) // constraint accumulation is disabled
checkSubtype(tp, origin)
else if (constr.instValid) // type var is already set
checkSubtype(tp, constr.inst)
@@ -3001,7 +3143,7 @@ trait Types extends api.Types { self: SymbolTable =>
override def safeToString = (
if ((constr eq null) || (constr.inst eq null)) "TVar<" + originName + "=null>"
else if (constr.inst ne NoType) "" + constr.inst
- else "?" + levelString + originName
+ else (if(untouchable) "!?" else "?") + levelString + originName
)
override def kind = "TypeVar"
@@ -3134,8 +3276,10 @@ trait Types extends api.Types { self: SymbolTable =>
final class UniqueErasedValueType(sym: Symbol) extends ErasedValueType(sym) with UniqueType
object ErasedValueType {
- def apply(sym: Symbol): Type =
+ def apply(sym: Symbol): Type = {
+ assert(sym ne NoSymbol, "ErasedValueType cannot be NoSymbol")
unique(new UniqueErasedValueType(sym))
+ }
}
/** A class representing an as-yet unevaluated type.
@@ -3193,7 +3337,7 @@ trait Types extends api.Types { self: SymbolTable =>
if (phase.erasedTypes)
if (parents.isEmpty) ObjectClass.tpe else parents.head
else {
- val clazz = owner.newRefinementClass(NoPosition)
+ val clazz = owner.newRefinementClass(pos) // TODO: why were we passing in NoPosition instead of pos?
val result = RefinedType(parents, decls, clazz)
clazz.setInfo(result)
result
@@ -3332,6 +3476,10 @@ trait Types extends api.Types { self: SymbolTable =>
case _ => abort(debugString(tycon))
}
+ /** Very convenient. */
+ def appliedType(tyconSym: Symbol, args: Type*): Type =
+ appliedType(tyconSym.typeConstructor, args.toList)
+
/** A creator for existential types where the type arguments,
* rather than being applied directly, are interpreted as the
* upper bounds of unknown types. For instance if the type argument
@@ -3343,7 +3491,7 @@ trait Types extends api.Types { self: SymbolTable =>
case TypeRef(pre, sym, _) if sameLength(sym.typeParams, args) =>
val eparams = typeParamsToExistentials(sym)
val bounds = args map (TypeBounds upper _)
- (eparams, bounds).zipped foreach (_ setInfo _)
+ foreach2(eparams, bounds)(_ setInfo _)
newExistentialType(eparams, typeRef(pre, sym, eparams map (_.tpe)))
case _ =>
@@ -3525,7 +3673,7 @@ trait Types extends api.Types { self: SymbolTable =>
else owner.newValueParameter(name.toTermName)
paramStack = newParams :: paramStack
try {
- (newParams, ptypes).zipped foreach ((p, t) => p setInfo this(t))
+ foreach2(newParams, ptypes)((p, t) => p setInfo this(t))
val restpe1 = this(restpe)
if (isType) PolyType(newParams, restpe1)
else MethodType(newParams, restpe1)
@@ -3747,6 +3895,8 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ // todo. move these into scala.reflect.api
+
/** A prototype for mapping a function over all possible types
*/
abstract class TypeMap extends (Type => Type) {
@@ -4559,6 +4709,16 @@ trait Types extends api.Types { self: SymbolTable =>
}
}
+ /** A map to implement the `collect` method. */
+ class CollectTypeCollector[T](pf: PartialFunction[Type, T]) extends TypeCollector[List[T]](Nil) {
+ override def collect(tp: Type) = super.collect(tp).reverse
+
+ def traverse(tp: Type) {
+ if (pf.isDefinedAt(tp)) result ::= pf(tp)
+ mapOver(tp)
+ }
+ }
+
class ForEachTypeTraverser(f: Type => Unit) extends TypeTraverser {
def traverse(tp: Type) {
f(tp)
@@ -4682,16 +4842,21 @@ trait Types extends api.Types { self: SymbolTable =>
val sym1 = adaptToNewRun(sym.owner.thisType, sym)
if (sym1 == sym) tp else ThisType(sym1)
} catch {
- case ex: MissingTypeControl =>
+ case ex: MissingTypeControl =>
tp
}
case SingleType(pre, sym) =>
if (sym.isPackage) tp
else {
val pre1 = this(pre)
- val sym1 = adaptToNewRun(pre1, sym)
- if ((pre1 eq pre) && (sym1 eq sym)) tp
- else singleType(pre1, sym1)
+ try {
+ val sym1 = adaptToNewRun(pre1, sym)
+ if ((pre1 eq pre) && (sym1 eq sym)) tp
+ else singleType(pre1, sym1)
+ } catch {
+ case _: MissingTypeControl =>
+ tp
+ }
}
case TypeRef(pre, sym, args) =>
if (sym.isPackageClass) tp
@@ -5059,6 +5224,8 @@ trait Types extends api.Types { self: SymbolTable =>
case (_, tv @ TypeVar(_,_)) => tv.registerTypeSelection(tr2.sym, tr1)
case _ => false
})
+ case _: SingleType =>
+ return isSameType2(tp2, tp1) // put singleton type on the left, caught below
case _ =>
}
case tt1: ThisType =>
@@ -5071,6 +5238,8 @@ trait Types extends api.Types { self: SymbolTable =>
tp2 match {
case st2: SingleType =>
if (equalSymsAndPrefixes(st1.sym, st1.pre, st2.sym, st2.pre)) return true
+ case TypeRef(pre2, sym2, Nil) =>
+ if (sym2.isModuleClass && equalSymsAndPrefixes(st1.sym, st1.pre, sym2.sourceModule, pre2)) return true
case _ =>
}
case ct1: ConstantType =>
@@ -5481,7 +5650,7 @@ trait Types extends api.Types { self: SymbolTable =>
* - handle typerefs, refined types, notnull and singleton types.
*/
def fourthTry = tp1 match {
- case tr1 @ TypeRef(_, sym1, _) =>
+ case tr1 @ TypeRef(pre1, sym1, _) =>
sym1 match {
case NothingClass => true
case NullClass =>
@@ -5495,8 +5664,8 @@ trait Types extends api.Types { self: SymbolTable =>
if (isRaw(sym1, tr1.args))
isSubType(rawToExistential(tp1), tp2, depth)
else if (sym1.isModuleClass) tp2 match {
- case SingleType(_, sym2) => sym1 == sym2
- case _ => false
+ case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
+ case _ => false
}
else if (sym1.isRefinementClass)
isSubType(sym1.info, tp2, depth)
@@ -5550,14 +5719,15 @@ trait Types extends api.Types { self: SymbolTable =>
val info1 = tp1.memberInfo(sym1)
val info2 = tp2.memberInfo(sym2).substThis(tp2.typeSymbol, tp1)
//System.out.println("specializes "+tp1+"."+sym1+":"+info1+sym1.locationString+" AND "+tp2+"."+sym2+":"+info2)//DEBUG
- sym2.isTerm && (info1 <:< info2) /*&& (!sym2.isStable || sym1.isStable) */ ||
- sym2.isAbstractType && {
- val memberTp1 = tp1.memberType(sym1)
- // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner)))
- info2.bounds.containsType(memberTp1) &&
- kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner)
- } ||
- sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok
+ ( sym2.isTerm && (info1 <:< info2) && (!sym2.isStable || sym1.isStable)
+ || sym2.isAbstractType && {
+ val memberTp1 = tp1.memberType(sym1)
+ // println("kinds conform? "+(memberTp1, tp1, sym2, kindsConform(List(sym2), List(memberTp1), tp2, sym2.owner)))
+ info2.bounds.containsType(memberTp1) &&
+ kindsConform(List(sym2), List(memberTp1), tp1, sym1.owner)
+ }
+ || sym2.isAliasType && tp2.memberType(sym2).substThis(tp2.typeSymbol, tp1) =:= tp1.memberType(sym1) //@MAT ok
+ )
}
/** A function implementing `tp1` matches `tp2`. */
@@ -5732,8 +5902,8 @@ trait Types extends api.Types { self: SymbolTable =>
foreach3(tvars, tparams, variances)((tvar2, tparam2, variance2) => {
val ok = (tparam2 != tparam) && (
(bound contains tparam2)
- || up && (tparam2.info.bounds.lo =:= tparam.tpe)
- || !up && (tparam2.info.bounds.hi =:= tparam.tpe)
+ || up && (tparam2.info.bounds.lo =:= tparam.tpeHK)
+ || !up && (tparam2.info.bounds.hi =:= tparam.tpeHK)
)
if (ok) {
if (tvar2.constr.inst eq null) cyclic = true
@@ -5747,7 +5917,7 @@ trait Types extends api.Types { self: SymbolTable =>
for (tparam2 <- tparams)
tparam2.info.bounds.lo.dealias match {
case TypeRef(_, `tparam`, _) =>
- tvar addHiBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
+ tvar addHiBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars)
case _ =>
}
} else {
@@ -5757,7 +5927,7 @@ trait Types extends api.Types { self: SymbolTable =>
for (tparam2 <- tparams)
tparam2.info.bounds.hi.dealias match {
case TypeRef(_, `tparam`, _) =>
- tvar addLoBound tparam2.tpe.instantiateTypeParams(tparams, tvars)
+ tvar addLoBound tparam2.tpeHK.instantiateTypeParams(tparams, tvars)
case _ =>
}
}
@@ -5989,8 +6159,9 @@ trait Types extends api.Types { self: SymbolTable =>
def stripType(tp: Type) = tp match {
case ExistentialType(_, res) =>
res
- case TypeVar(_, constr) =>
- if (constr.instValid) constr.inst
+ case tv@TypeVar(_, constr) =>
+ if (tv.instValid) constr.inst
+ else if (tv.untouchable) tv
else abort("trying to do lub/glb of typevar "+tp)
case t => t
}
@@ -6551,6 +6722,21 @@ trait Types extends api.Types { self: SymbolTable =>
try { explainSwitch = true; op } finally { explainSwitch = s }
}
+ def isUnboundedGeneric(tp: Type) = tp match {
+ case t @ TypeRef(_, sym, _) => sym.isAbstractType && !(t <:< AnyRefClass.tpe)
+ case _ => false
+ }
+ def isBoundedGeneric(tp: Type) = tp match {
+ case TypeRef(_, sym, _) if sym.isAbstractType => (tp <:< AnyRefClass.tpe)
+ case TypeRef(_, sym, _) => !isPrimitiveValueClass(sym)
+ case _ => false
+ }
+ // Add serializable to a list of parents, unless one of them already is
+ def addSerializable(ps: Type*): List[Type] = (
+ if (ps exists (_ <:< SerializableClass.tpe)) ps.toList
+ else (ps :+ SerializableClass.tpe).toList
+ )
+
def objToAny(tp: Type): Type =
if (!phase.erasedTypes && tp.typeSymbol == ObjectClass) AnyClass.tpe
else tp
diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
index f1ec64bda9..fd3fac1b37 100644
--- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
@@ -257,12 +257,11 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
}
def isModuleFlag = (flags & MODULE) != 0L
- def isMethodFlag = (flags & METHOD) != 0L
def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner)
def isModuleRoot = (name == moduleRoot.name) && (owner == moduleRoot.owner)
+ def pflags = flags & PickledFlags
def finishSym(sym: Symbol): Symbol = {
- sym.flags = flags & PickledFlags
sym.privateWithin = privateWithin
sym.info = (
if (atEnd) {
@@ -282,27 +281,27 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
}
finishSym(tag match {
- case TYPEsym => owner.newAbstractType(name.toTypeName)
- case ALIASsym => owner.newAliasType(name.toTypeName)
+ case TYPEsym | ALIASsym =>
+ owner.newNonClassSymbol(name.toTypeName, NoPosition, pflags)
case CLASSsym =>
- val sym = (isClassRoot, isModuleFlag) match {
- case (true, true) => moduleRoot.moduleClass
- case (true, false) => classRoot
- case (false, true) => owner.newModuleClass(name.toTypeName)
- case (false, false) => owner.newClass(name.toTypeName)
- }
+ val sym = (
+ if (isClassRoot) {
+ if (isModuleFlag) moduleRoot.moduleClass setFlag pflags
+ else classRoot setFlag pflags
+ }
+ else owner.newClassSymbol(name.toTypeName, NoPosition, pflags)
+ )
if (!atEnd)
sym.typeOfThis = newLazyTypeRef(readNat())
sym
case MODULEsym =>
val clazz = at(inforef, () => readType()).typeSymbol // after the NMT_TRANSITION period, we can leave off the () => ... ()
- if (isModuleRoot) moduleRoot
- else owner.newLinkedModule(clazz)
+ if (isModuleRoot) moduleRoot setFlag pflags
+ else owner.newLinkedModule(clazz, pflags)
case VALsym =>
if (isModuleRoot) { assert(false); NoSymbol }
- else if (isMethodFlag) owner.newMethod(name.toTermName)
- else owner.newValue(name.toTermName)
+ else owner.newTermSymbol(name.toTermName, NoPosition, pflags)
case _ =>
errorBadSignature("bad symbol tag: " + tag)
@@ -448,7 +447,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
private def readArrayAnnot() = {
readByte() // skip the `annotargarray` tag
val end = readNat() + readIndex
- until(end, () => readClassfileAnnotArg(readNat())).toArray(classfileAnnotArgManifest)
+ until(end, () => readClassfileAnnotArg(readNat())).toArray(classfileAnnotArgTag)
}
protected def readClassfileAnnotArg(i: Int): ClassfileAnnotArg = bytes(index(i)) match {
case ANNOTINFO => NestedAnnotArg(at(i, readAnnotation))
@@ -817,16 +816,10 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg)
protected def errorMissingRequirement(name: Name, owner: Symbol): Symbol =
- missingHook(owner, name) orElse {
- val what = if (name.isTypeName) "type" else "value"
- MissingRequirementError.notFound(
- "while unpickling %s, reference %s %s of %s/%s/%s".format(
- filename,
- what, name.decode, owner.tpe.widen,
- owner.tpe.typeSymbol.ownerChain,
- owner.info.members.mkString("\n ", "\n ", ""))
- )
- }
+ missingHook(owner, name) orElse MissingRequirementError.notFound(
+ "bad reference while unpickling %s: %s not found in %s".format(
+ filename, name.longString, owner.tpe.widen)
+ )
def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) {} // can't do it; need a compiler for that.
@@ -850,7 +843,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
atPhase(p) (sym setInfo tp)
if (currentRunId != definedAtRunId)
sym.setInfo(adaptToNewRunMap(tp))
- }
+ }
catch {
case e: MissingRequirementError => throw toTypeError(e)
}
diff --git a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
index b556c33aba..45ba4ed3e6 100644
--- a/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
+++ b/src/compiler/scala/reflect/internal/settings/MutableSettings.scala
@@ -43,5 +43,5 @@ abstract class MutableSettings extends AbsSettings {
def Yrecursion: IntSetting
def maxClassfileName: IntSetting
def Xexperimental: BooleanSetting
- def YvirtPatmat: BooleanSetting
+ def XoldPatmat: BooleanSetting
} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/internal/transform/Erasure.scala b/src/compiler/scala/reflect/internal/transform/Erasure.scala
index e87de8db80..1b323f839b 100644
--- a/src/compiler/scala/reflect/internal/transform/Erasure.scala
+++ b/src/compiler/scala/reflect/internal/transform/Erasure.scala
@@ -69,6 +69,9 @@ trait Erasure {
clazz.firstParamAccessor.tpe.resultType
abstract class ErasureMap extends TypeMap {
+ private lazy val ObjectArray = arrayType(ObjectClass.tpe)
+ private lazy val ErasedObject = erasedTypeRef(ObjectClass)
+
def mergeParents(parents: List[Type]): Type
def eraseNormalClassRef(pre: Type, clazz: Symbol): Type =
@@ -87,7 +90,7 @@ trait Erasure {
if (unboundedGenericArrayLevel(tp) == 1) ObjectClass.tpe
else if (args.head.typeSymbol.isBottomClass) ObjectArray
else typeRef(apply(pre), sym, args map applyInArray)
- else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) erasedTypeRef(ObjectClass)
+ else if (sym == AnyClass || sym == AnyValClass || sym == SingletonClass || sym == NotNullClass) ErasedObject
else if (sym == UnitClass) erasedTypeRef(BoxedUnitClass)
else if (sym.isRefinementClass) apply(mergeParents(tp.parents))
else if (sym.isDerivedValueClass) eraseDerivedValueClassRef(sym)
@@ -111,7 +114,7 @@ trait Erasure {
case ClassInfoType(parents, decls, clazz) =>
ClassInfoType(
if (clazz == ObjectClass || isPrimitiveValueClass(clazz)) Nil
- else if (clazz == ArrayClass) List(erasedTypeRef(ObjectClass))
+ else if (clazz == ArrayClass) List(ErasedObject)
else removeLaterObjects(parents map this),
decls, clazz)
case _ =>
diff --git a/src/compiler/scala/reflect/internal/transform/UnCurry.scala b/src/compiler/scala/reflect/internal/transform/UnCurry.scala
index fd6d4e177d..0c1640ceb9 100644
--- a/src/compiler/scala/reflect/internal/transform/UnCurry.scala
+++ b/src/compiler/scala/reflect/internal/transform/UnCurry.scala
@@ -12,14 +12,8 @@ trait UnCurry {
private def expandAlias(tp: Type): Type = if (!tp.isHigherKinded) tp.normalize else tp
- private def isUnboundedGeneric(tp: Type) = tp match {
- case t @ TypeRef(_, sym, _) => sym.isAbstractType && !(t <:< AnyRefClass.tpe)
- case _ => false
- }
-
val uncurry: TypeMap = new TypeMap {
def apply(tp0: Type): Type = {
- // tp0.typeSymbolDirect.initialize
val tp = expandAlias(tp0)
tp match {
case MethodType(params, MethodType(params1, restpe)) =>
@@ -31,13 +25,13 @@ trait UnCurry {
apply(MethodType(h.cloneSymbol.resetFlag(IMPLICIT) :: t, restpe))
case NullaryMethodType(restpe) =>
apply(MethodType(List(), restpe))
- case TypeRef(pre, ByNameParamClass, List(arg)) =>
+ case TypeRef(pre, ByNameParamClass, arg :: Nil) =>
apply(functionType(List(), arg))
- case TypeRef(pre, RepeatedParamClass, args) =>
- apply(appliedType(SeqClass.typeConstructor, args))
- case TypeRef(pre, JavaRepeatedParamClass, args) =>
+ case TypeRef(pre, RepeatedParamClass, arg :: Nil) =>
+ apply(seqType(arg))
+ case TypeRef(pre, JavaRepeatedParamClass, arg :: Nil) =>
apply(arrayType(
- if (isUnboundedGeneric(args.head)) ObjectClass.tpe else args.head))
+ if (isUnboundedGeneric(arg)) ObjectClass.tpe else arg))
case _ =>
expandAlias(mapOver(tp))
}
diff --git a/src/compiler/scala/reflect/internal/util/Collections.scala b/src/compiler/scala/reflect/internal/util/Collections.scala
index d26a1abadb..2e119f8ccc 100644
--- a/src/compiler/scala/reflect/internal/util/Collections.scala
+++ b/src/compiler/scala/reflect/internal/util/Collections.scala
@@ -10,6 +10,8 @@ import scala.annotation.tailrec
import mutable.ListBuffer
/** Profiler driven changes.
+ * TODO - inlining doesn't work from here because of the bug that
+ * methods in traits aren't inlined.
*/
trait Collections {
/** True if all three arguments have the same number of elements and
@@ -22,18 +24,21 @@ trait Collections {
)
/** All these mm methods are "deep map" style methods for
- * mapping etc. on a list of lists.
+ * mapping etc. on a list of lists while avoiding unnecessary
+ * intermediate structures like those created via flatten.
*/
final def mexists[A](xss: List[List[A]])(p: A => Boolean) =
xss exists (_ exists p)
+ final def mforall[A](xss: List[List[A]])(p: A => Boolean) =
+ xss forall (_ forall p)
final def mmap[A, B](xss: List[List[A]])(f: A => B) =
xss map (_ map f)
final def mforeach[A](xss: List[List[A]])(f: A => Unit) =
xss foreach (_ foreach f)
final def mfind[A](xss: List[List[A]])(p: A => Boolean): Option[A] = {
- for (xs <- xss; x <- xs)
- if (p(x)) return Some(x)
- None
+ var res: Option[A] = null
+ mforeach(xss)(x => if ((res eq null) && p(x)) res = Some(x))
+ if (res eq null) None else res
}
final def mfilter[A](xss: List[List[A]])(p: A => Boolean) =
for (xs <- xss; x <- xs; if p(x)) yield x
@@ -64,6 +69,31 @@ trait Collections {
}
lb.toList
}
+
+ final def flatCollect[A, B](elems: List[A])(pf: PartialFunction[A, Traversable[B]]): List[B] = {
+ val lb = new ListBuffer[B]
+ for (x <- elems ; if pf isDefinedAt x)
+ lb ++= pf(x)
+
+ lb.toList
+ }
+
+ final def distinctBy[A, B](xs: List[A])(f: A => B): List[A] = {
+ val buf = new ListBuffer[A]
+ val seen = mutable.Set[B]()
+ xs foreach { x =>
+ val y = f(x)
+ if (!seen(y)) {
+ buf += x
+ seen += y
+ }
+ }
+ buf.toList
+ }
+
+ @tailrec final def flattensToEmpty(xss: Seq[Seq[_]]): Boolean = {
+ xss.isEmpty || xss.head.isEmpty && flattensToEmpty(xss.tail)
+ }
final def foreachWithIndex[A, B](xs: List[A])(f: (A, Int) => Unit) {
var index = 0
@@ -75,10 +105,15 @@ trait Collections {
}
}
- @inline final def findOrElse[A](xs: TraversableOnce[A])(p: A => Boolean)(orElse: => A): A = {
+ // @inline
+ final def findOrElse[A](xs: TraversableOnce[A])(p: A => Boolean)(orElse: => A): A = {
xs find p getOrElse orElse
}
+ final def mapFrom[A, A1 >: A, B](xs: List[A])(f: A => B): Map[A1, B] = {
+ Map[A1, B](xs map (x => (x, f(x))): _*)
+ }
+
final def mapWithIndex[A, B](xs: List[A])(f: (A, Int) => B): List[B] = {
val lb = new ListBuffer[B]
var index = 0
diff --git a/src/compiler/scala/reflect/internal/util/Origins.scala b/src/compiler/scala/reflect/internal/util/Origins.scala
index b9985c8f50..19b3adda9d 100644
--- a/src/compiler/scala/reflect/internal/util/Origins.scala
+++ b/src/compiler/scala/reflect/internal/util/Origins.scala
@@ -88,7 +88,7 @@ object Origins {
sys.addShutdownHook(counters foreach (_.purge()))
}
- def apply[T: Manifest](tag: String): Origins = apply(tag, manifest[T].erasure)
+ def apply[T: ClassTag](tag: String): Origins = apply(tag, classTag[T].erasure)
def apply(tag: String, clazz: Class[_]): Origins = apply(tag, new OneLine(clazz))
def apply(tag: String, orElse: => Origins): Origins = {
counters find (_.tag == tag) getOrElse {
diff --git a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala
new file mode 100644
index 0000000000..eb384f9a85
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala
@@ -0,0 +1,168 @@
+package scala.reflect.internal
+package util
+
+import scala.collection.{ mutable, immutable }
+
+trait TraceSymbolActivity {
+ val global: SymbolTable
+ import global._
+
+ if (traceSymbolActivity)
+ scala.sys addShutdownHook showAllSymbols()
+
+ private type Set[T] = scala.collection.immutable.Set[T]
+ private val Set = scala.collection.immutable.Set
+
+ val allSymbols = mutable.Map[Int, Symbol]()
+ val allChildren = mutable.Map[Int, List[Int]]() withDefaultValue Nil
+ val prevOwners = mutable.Map[Int, List[(Int, Phase)]]() withDefaultValue Nil
+ val symsCaused = mutable.Map[Int, Int]() withDefaultValue 0
+ val allTrees = mutable.Set[Tree]()
+
+ def recordSymbolsInTree(tree: Tree) {
+ allTrees += tree
+ }
+
+ def recordNewSymbol(sym: Symbol) {
+ if (sym.id > 1) {
+ allSymbols(sym.id) = sym
+ allChildren(sym.owner.id) ::= sym.id
+ }
+ }
+ def recordNewSymbolOwner(sym: Symbol, newOwner: Symbol) {
+ val sid = sym.id
+ val oid = sym.owner.id
+ val nid = newOwner.id
+
+ prevOwners(sid) ::= (oid -> phase)
+ allChildren(oid) = allChildren(oid) filterNot (_ == sid)
+ allChildren(nid) ::= sid
+ }
+
+ /** TODO.
+ */
+ private def reachableDirectlyFromSymbol(sym: Symbol): List[Symbol] = (
+ List(sym.owner, sym.alias, sym.thisSym)
+ ++ sym.children
+ ++ sym.info.parents.map(_.typeSymbol)
+ ++ sym.typeParams
+ ++ sym.paramss.flatten
+ )
+ private def reachable[T](inputs: Traversable[T], mkSymbol: T => Symbol): Set[Symbol] = {
+ def loop(seen: Set[Symbol], remaining: List[Symbol]): Set[Symbol] = {
+ remaining match {
+ case Nil => seen
+ case head :: rest =>
+ if ((head eq null) || (head eq NoSymbol) || seen(head)) loop(seen, rest)
+ else loop(seen + head, rest ++ reachableDirectlyFromSymbol(head).filterNot(seen))
+ }
+ }
+ loop(immutable.Set(), inputs.toList map mkSymbol filterNot (_ eq null) distinct)
+ }
+ private def treeList(t: Tree) = {
+ val buf = mutable.ListBuffer[Tree]()
+ t foreach (buf += _)
+ buf.toList
+ }
+
+ private def reachableFromSymbol(root: Symbol): Set[Symbol] =
+ reachable[Symbol](List(root, root.info.typeSymbol), x => x)
+
+ private def reachableFromTree(tree: Tree): Set[Symbol] =
+ reachable[Tree](treeList(tree), _.symbol)
+
+ private def signature(id: Int) = runBeforeErasure(allSymbols(id).defString)
+
+ private def dashes(s: Any): String = ("" + s) map (_ => '-')
+ private def show(s1: Any, ss: Any*) {
+ println("%-12s".format(s1) +: ss mkString " ")
+ }
+ private def showHeader(s1: Any, ss: Any*) {
+ show(s1, ss: _*)
+ show(dashes(s1), ss map dashes: _*)
+ }
+ private def showSym(sym: Symbol) {
+ def prefix = (" " * (sym.ownerChain.length - 1)) + sym.id
+ try println("%s#%s %s".format(prefix, sym.accurateKindString, sym.name.decode))
+ catch {
+ case x => println(prefix + " failed: " + x)
+ }
+ allChildren(sym.id).sorted foreach showIdAndRemove
+ }
+ private def showIdAndRemove(id: Int) {
+ allSymbols remove id foreach showSym
+ }
+ private def symbolStr(id: Int): String = {
+ if (id == 1) "NoSymbol" else {
+ val sym = allSymbols(id)
+ sym.accurateKindString + " " + sym.name.decode
+ }
+ }
+ private def ownerStr(id: Int): String = {
+ val sym = allSymbols(id)
+ sym.name.decode + "#" + sym.id
+ }
+
+ private def freq[T, U](xs: collection.Traversable[T])(fn: T => U): List[(U, Int)] = {
+ val ys = xs groupBy fn mapValues (_.size)
+ ys.toList sortBy (-_._2)
+ }
+
+ private def showMapFreq[T](xs: collection.Map[T, Traversable[_]])(showFn: T => String) {
+ xs.mapValues(_.size).toList.sortBy(-_._2) take 100 foreach { case (k, size) =>
+ show(size, showFn(k))
+ }
+ println("\n")
+ }
+ private def showFreq[T, U](xs: Traversable[T])(groupFn: T => U, showFn: U => String = (x: U) => "" + x) = {
+ showMapFreq(xs.toList groupBy groupFn)(showFn)
+ }
+ private lazy val findErasurePhase: Phase = {
+ var ph = phase
+ while (ph != NoPhase && ph.name != "erasure") {
+ ph = ph.prev
+ }
+ ph
+ }
+ private def runBeforeErasure[T](body: => T): T = atPhase(findErasurePhase)(body)
+
+ def showAllSymbols() {
+ if (!traceSymbolActivity) return
+ allSymbols(1) = NoSymbol
+
+ println("" + allSymbols.size + " symbols created.")
+ println("")
+
+ showHeader("descendants", "symbol")
+ showFreq(allSymbols.values flatMap (_.ownerChain drop 1))(_.id, symbolStr)
+
+ showHeader("children", "symbol")
+ showMapFreq(allChildren)(symbolStr)
+
+ if (prevOwners.nonEmpty) {
+ showHeader("prev owners", "symbol")
+ showMapFreq(prevOwners) { k =>
+ val owners = (((allSymbols(k).owner.id, NoPhase)) :: prevOwners(k)) map {
+ case (oid, NoPhase) => "-> owned by " + ownerStr(oid)
+ case (oid, ph) => "-> owned by %s (until %s)".format(ownerStr(oid), ph)
+ }
+ signature(k) :: owners mkString "\n "
+ }
+ }
+
+ val nameFreq = allSymbols.values.toList groupBy (_.name)
+ showHeader("frequency", "%-15s".format("name"), "owners")
+ showMapFreq(nameFreq) { name =>
+ "%-15s %s".format(name.decode, {
+ val owners = freq(nameFreq(name))(_.owner)
+
+ "%4s owners (%s)".format(
+ owners.size,
+ owners.take(3).map({ case (k, v) => v + "/" + k }).mkString(", ") + ", ..."
+ )
+ })
+ }
+
+ allSymbols.keys.toList.sorted foreach showIdAndRemove
+ }
+}
diff --git a/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala b/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala
new file mode 100644
index 0000000000..d78eae9237
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/AbortMacroException.scala
@@ -0,0 +1,6 @@
+package scala.reflect.makro
+package runtime
+
+import scala.reflect.api.Position
+
+class AbortMacroException(val pos: Position, val msg: String) extends Throwable(msg)
diff --git a/src/compiler/scala/reflect/makro/runtime/Aliases.scala b/src/compiler/scala/reflect/makro/runtime/Aliases.scala
new file mode 100644
index 0000000000..a4f208ca34
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Aliases.scala
@@ -0,0 +1,21 @@
+package scala.reflect.makro
+package runtime
+
+trait Aliases {
+ self: Context =>
+
+ /** Aliases of mirror types */
+ override type Symbol = mirror.Symbol
+ override type Type = mirror.Type
+ override type Name = mirror.Name
+ override type Tree = mirror.Tree
+ override type Position = mirror.Position
+ override type Scope = mirror.Scope
+ override type Modifiers = mirror.Modifiers
+ override type Expr[+T] = mirror.Expr[T]
+ override type TypeTag[T] = mirror.TypeTag[T]
+
+ /** Creator/extractor objects for Expr and TypeTag values */
+ override val TypeTag = mirror.TypeTag
+ override val Expr = mirror.Expr
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala b/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala
new file mode 100644
index 0000000000..4e93d4e06d
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/CapturedVariables.scala
@@ -0,0 +1,14 @@
+package scala.reflect.makro
+package runtime
+
+trait CapturedVariables {
+ self: Context =>
+
+ import mirror._
+
+ def captureVariable(vble: Symbol): Unit = mirror.captureVariable(vble)
+
+ def referenceCapturedVariable(vble: Symbol): Tree = mirror.referenceCapturedVariable(vble)
+
+ def capturedVariableType(vble: Symbol): Type = mirror.capturedVariableType(vble)
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Context.scala b/src/compiler/scala/reflect/makro/runtime/Context.scala
new file mode 100644
index 0000000000..ca02822788
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Context.scala
@@ -0,0 +1,27 @@
+package scala.reflect.makro
+package runtime
+
+import scala.tools.nsc.Global
+
+abstract class Context extends scala.reflect.makro.Context
+ with Aliases
+ with CapturedVariables
+ with Infrastructure
+ with Enclosures
+ with Names
+ with Reifiers
+ with FrontEnds
+ with Settings
+ with Symbols
+ with Typers
+ with Util
+ with Traces {
+
+ val mirror: Global
+
+ val callsiteTyper: mirror.analyzer.Typer
+
+ val prefix: Expr[PrefixType]
+
+ val expandee: Tree
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Enclosures.scala b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
new file mode 100644
index 0000000000..ab38fc024d
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Enclosures.scala
@@ -0,0 +1,23 @@
+package scala.reflect.makro
+package runtime
+
+trait Enclosures {
+ self: Context =>
+
+ import mirror._
+
+ private def site = callsiteTyper.context
+ private def enclTrees = site.enclosingContextChain map (_.tree)
+ private def enclPoses = enclosingMacros map (_.macroApplication.pos) filterNot (_ eq NoPosition)
+
+ // vals are eager to simplify debugging
+ // after all we wouldn't save that much time by making them lazy
+ val macroApplication: Tree = expandee
+ val enclosingApplication: Tree = enclTrees collectFirst { case t: Apply => t } getOrElse EmptyTree
+ val enclosingClass: Tree = site.enclClass.tree
+ val enclosingImplicits: List[(Type, Tree)] = site.openImplicits
+ val enclosingMacros: List[Context] = this :: mirror.analyzer.openMacros // include self
+ val enclosingMethod: Tree = site.enclMethod.tree
+ val enclosingPosition: Position = if (enclPoses.isEmpty) NoPosition else enclPoses.head.pos
+ val enclosingUnit: CompilationUnit = currentRun.currentUnit
+}
diff --git a/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala
new file mode 100644
index 0000000000..7cfa8e80f3
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/FrontEnds.scala
@@ -0,0 +1,44 @@
+package scala.reflect.makro
+package runtime
+
+trait FrontEnds {
+ self: Context =>
+
+ import mirror._
+
+ def frontEnd: FrontEnd = wrapReporter(mirror.reporter)
+
+ def setFrontEnd(frontEnd: FrontEnd): this.type = {
+ mirror.reporter = wrapFrontEnd(frontEnd)
+ this
+ }
+
+ def withFrontEnd[T](frontEnd: FrontEnd)(op: => T): T = {
+ val old = mirror.reporter
+ setFrontEnd(frontEnd)
+ try op
+ finally mirror.reporter = old
+ }
+
+ def echo(pos: Position, msg: String): Unit = mirror.reporter.echo(pos, msg)
+
+ def info(pos: Position, msg: String, force: Boolean): Unit = mirror.reporter.info(pos, msg, force)
+
+ def hasWarnings: Boolean = mirror.reporter.hasErrors
+
+ def hasErrors: Boolean = mirror.reporter.hasErrors
+
+ def warning(pos: Position, msg: String): Unit = callsiteTyper.context.warning(pos, msg)
+
+ def error(pos: Position, msg: String): Unit = callsiteTyper.context.error(pos, msg)
+
+ def abort(pos: Position, msg: String): Nothing = {
+ callsiteTyper.context.error(pos, msg)
+ throw new AbortMacroException(pos, msg)
+ }
+
+ def interactive(): Unit = mirror.reporter match {
+ case reporter: tools.nsc.reporters.AbstractReporter => reporter.displayPrompt()
+ case _ => ()
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala b/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala
new file mode 100644
index 0000000000..6d8e55cc35
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Infrastructure.scala
@@ -0,0 +1,34 @@
+package scala.reflect.makro
+package runtime
+
+trait Infrastructure {
+ self: Context =>
+
+ val forJVM: Boolean = mirror.forJVM
+
+ val forMSIL: Boolean = mirror.forMSIL
+
+ val forInteractive: Boolean = mirror.forInteractive
+
+ val forScaladoc: Boolean = mirror.forScaladoc
+
+ val currentRun: Run = mirror.currentRun
+
+ type Run = mirror.Run
+
+ object Run extends RunExtractor {
+ def unapply(run: Run): Option[(CompilationUnit, List[CompilationUnit])] = Some(run.currentUnit, run.units.toList)
+ }
+
+ type CompilationUnit = mirror.CompilationUnit
+
+ object CompilationUnit extends CompilationUnitExtractor {
+ def unapply(compilationUnit: CompilationUnit): Option[(java.io.File, Array[Char], Tree)] = Some(compilationUnit.source.file.file, compilationUnit.source.content, compilationUnit.body)
+ }
+
+ val currentMacro: Symbol = expandee.symbol
+
+ val globalCache: collection.mutable.Map[Any, Any] = mirror.analyzer.globalMacroCache
+
+ val cache: collection.mutable.Map[Any, Any] = mirror.analyzer.perRunMacroCache.getOrElseUpdate(currentMacro, collection.mutable.Map[Any, Any]())
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Names.scala b/src/compiler/scala/reflect/makro/runtime/Names.scala
new file mode 100644
index 0000000000..d8ecc2b89e
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Names.scala
@@ -0,0 +1,20 @@
+package scala.reflect.makro
+package runtime
+
+trait Names {
+ self: Context =>
+
+ lazy val freshNameCreator = callsiteTyper.context.unit.fresh
+
+ def fresh(): String = {
+ freshNameCreator.newName()
+ }
+
+ def fresh(name: String): String = {
+ freshNameCreator.newName(name)
+ }
+
+ def fresh(name: Name): Name = {
+ name.mapName(freshNameCreator.newName(_))
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Reifiers.scala b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
new file mode 100644
index 0000000000..1c5af4b752
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Reifiers.scala
@@ -0,0 +1,34 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Gilles Dubochet
+ */
+
+package scala.reflect.makro
+package runtime
+
+trait Reifiers {
+ self: Context =>
+
+ import mirror._
+ import definitions._
+
+ lazy val reflectMirrorPrefix: Tree = ReflectMirrorPrefix
+
+ def reifyTree(prefix: Tree, tree: Tree): Tree = {
+ val result = scala.reflect.reify.`package`.reifyTree(mirror)(callsiteTyper, prefix, tree)
+ logFreeVars(enclosingPosition, result)
+ result
+ }
+
+ def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree = {
+ val result = scala.reflect.reify.`package`.reifyType(mirror)(callsiteTyper, prefix, tpe, dontSpliceAtTopLevel, concrete)
+ logFreeVars(enclosingPosition, result)
+ result
+ }
+
+ def reifyErasure(tpe: Type, concrete: Boolean = true): Tree =
+ scala.reflect.reify.`package`.reifyErasure(mirror)(callsiteTyper, tpe, concrete)
+
+ def unreifyTree(tree: Tree): Tree =
+ Select(tree, definitions.ExprEval)
+}
diff --git a/src/compiler/scala/reflect/makro/runtime/Settings.scala b/src/compiler/scala/reflect/makro/runtime/Settings.scala
new file mode 100644
index 0000000000..32f7115db8
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Settings.scala
@@ -0,0 +1,36 @@
+package scala.reflect.makro
+package runtime
+
+trait Settings {
+ self: Context =>
+
+ def settings: List[String] = {
+ val optionName = mirror.settings.XmacroSettings.name
+ val settings = compilerSettings.find(opt => opt.startsWith(optionName)).map(opt => opt.substring(optionName.length + 1)).getOrElse("")
+ settings.split(",").toList
+ }
+
+ def compilerSettings: List[String] = mirror.settings.recreateArgs
+
+ def setCompilerSettings(options: String): this.type =
+ // todo. is not going to work with quoted arguments with embedded whitespaces
+ setCompilerSettings(options.split(" ").toList)
+
+ def setCompilerSettings(options: List[String]): this.type = {
+ val settings = new tools.nsc.Settings(_ => ())
+ // [Eugene] what settings should we exclude?
+ settings.copyInto(mirror.settings)
+ this
+ }
+
+ def withCompilerSettings[T](options: String)(op: => T): T =
+ // todo. is not going to work with quoted arguments with embedded whitespaces
+ withCompilerSettings(options.split(" ").toList)(op)
+
+ def withCompilerSettings[T](options: List[String])(op: => T): T = {
+ val old = options
+ setCompilerSettings(options)
+ try op
+ finally setCompilerSettings(old)
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Symbols.scala b/src/compiler/scala/reflect/makro/runtime/Symbols.scala
new file mode 100644
index 0000000000..6341523486
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Symbols.scala
@@ -0,0 +1,10 @@
+package scala.reflect.makro
+package runtime
+
+trait Symbols {
+ self: Context =>
+
+ def isLocatable(sym: Symbol) = sym.isLocatable
+
+ def isStatic(sym: Symbol) = sym.isStatic
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Traces.scala b/src/compiler/scala/reflect/makro/runtime/Traces.scala
new file mode 100644
index 0000000000..6b61842316
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Traces.scala
@@ -0,0 +1,8 @@
+package scala.reflect.makro
+package runtime
+
+trait Traces extends util.Traces {
+ self: Context =>
+
+ def globalSettings = mirror.settings
+}
diff --git a/src/compiler/scala/reflect/makro/runtime/Typers.scala b/src/compiler/scala/reflect/makro/runtime/Typers.scala
new file mode 100644
index 0000000000..c61e492250
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Typers.scala
@@ -0,0 +1,75 @@
+package scala.reflect.makro
+package runtime
+
+trait Typers {
+ self: Context =>
+
+ def openMacros: List[Context] = this :: mirror.analyzer.openMacros
+
+ def openImplicits: List[(Type, Tree)] = callsiteTyper.context.openImplicits
+
+ def typeCheck(tree: Tree, pt: Type = mirror.WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = {
+ macroLogVerbose("typechecking %s with expected type %s, implicit views = %s, macros = %s".format(tree, pt, !withImplicitViewsDisabled, !withMacrosDisabled))
+ val wrapper1 = if (!withImplicitViewsDisabled) (callsiteTyper.context.withImplicitsEnabled[Tree] _) else (callsiteTyper.context.withImplicitsDisabled[Tree] _)
+ val wrapper2 = if (!withMacrosDisabled) (callsiteTyper.context.withMacrosEnabled[Tree] _) else (callsiteTyper.context.withMacrosDisabled[Tree] _)
+ def wrapper (tree: => Tree) = wrapper1(wrapper2(tree))
+ // if you get a "silent mode is not available past typer" here
+ // don't rush to change the typecheck not to use the silent method when the silent parameter is false
+ // typechecking uses silent anyways (e.g. in typedSelect), so you'll only waste your time
+ // I'd advise fixing the root cause: finding why the context is not set to report errors
+ // (also see reflect.runtime.ToolBoxes.typeCheckExpr for a workaround that might work for you)
+ wrapper(callsiteTyper.silent(_.typed(tree, mirror.analyzer.EXPRmode, pt)) match {
+ case mirror.analyzer.SilentResultValue(result) =>
+ macroLogVerbose(result)
+ result
+ case error @ mirror.analyzer.SilentTypeError(_) =>
+ macroLogVerbose(error.err.errMsg)
+ if (!silent) throw new mirror.TypeError(error.err.errPos, error.err.errMsg)
+ mirror.EmptyTree
+ })
+ }
+
+ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree = {
+ macroLogVerbose("inferring implicit value of type %s, macros = %s".format(pt, !withMacrosDisabled))
+ import mirror.analyzer.SearchResult
+ val context = callsiteTyper.context
+ val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _)
+ def wrapper (inference: => SearchResult) = wrapper1(inference)
+ wrapper(mirror.analyzer.inferImplicit(mirror.EmptyTree, pt, true, false, context, !silent, pos)) match {
+ case failure if failure.tree.isEmpty =>
+ macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits")
+ if (context.hasErrors) throw new mirror.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg)
+ mirror.EmptyTree
+ case success =>
+ success.tree
+ }
+ }
+
+ def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree = {
+ macroLogVerbose("inferring implicit view from %s to %s for %s, macros = %s, reportAmbiguous = %s".format(from, to, tree, !withMacrosDisabled, reportAmbiguous))
+ import mirror.analyzer.SearchResult
+ val context = callsiteTyper.context
+ val wrapper1 = if (!withMacrosDisabled) (context.withMacrosEnabled[SearchResult] _) else (context.withMacrosDisabled[SearchResult] _)
+ def wrapper (inference: => SearchResult) = wrapper1(inference)
+ val fun1 = mirror.definitions.FunctionClass(1)
+ val viewTpe = mirror.TypeRef(fun1.typeConstructor.prefix, fun1, List(from, to))
+ wrapper(mirror.analyzer.inferImplicit(tree, viewTpe, reportAmbiguous, true, context, !silent, pos)) match {
+ case failure if failure.tree.isEmpty =>
+ macroLogVerbose("implicit search has failed. to find out the reason, turn on -Xlog-implicits")
+ if (context.hasErrors) throw new mirror.TypeError(context.errBuffer.head.errPos, context.errBuffer.head.errMsg)
+ mirror.EmptyTree
+ case success =>
+ success.tree
+ }
+ }
+
+ type TypeError = mirror.TypeError
+
+ object TypeError extends TypeErrorExtractor {
+ def unapply(error: TypeError): Option[(Position, String)] = Some((error.pos, error.msg))
+ }
+
+ def resetAllAttrs[T <: Tree](tree: T): T = mirror.resetAllAttrs(tree)
+
+ def resetLocalAttrs[T <: Tree](tree: T): T = mirror.resetLocalAttrs(tree)
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/makro/runtime/Util.scala b/src/compiler/scala/reflect/makro/runtime/Util.scala
new file mode 100644
index 0000000000..2671155721
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/runtime/Util.scala
@@ -0,0 +1,34 @@
+package scala.reflect.makro
+package runtime
+
+trait Util {
+ self: Context =>
+
+ import mirror._
+
+ def literalNull = Expr[Null](Literal(Constant(null)))(TypeTag.Null)
+
+ def literalUnit = Expr[Unit](Literal(Constant(())))(TypeTag.Unit)
+
+ def literalTrue = Expr[Boolean](Literal(Constant(true)))(TypeTag.Boolean)
+
+ def literalFalse = Expr[Boolean](Literal(Constant(false)))(TypeTag.Boolean)
+
+ def literal(x: Boolean) = Expr[Boolean](Literal(Constant(x)))(TypeTag.Boolean)
+
+ def literal(x: Byte) = Expr[Byte](Literal(Constant(x)))(TypeTag.Byte)
+
+ def literal(x: Short) = Expr[Short](Literal(Constant(x)))(TypeTag.Short)
+
+ def literal(x: Int) = Expr[Int](Literal(Constant(x)))(TypeTag.Int)
+
+ def literal(x: Long) = Expr[Long](Literal(Constant(x)))(TypeTag.Long)
+
+ def literal(x: Float) = Expr[Float](Literal(Constant(x)))(TypeTag.Float)
+
+ def literal(x: Double) = Expr[Double](Literal(Constant(x)))(TypeTag.Double)
+
+ def literal(x: String) = Expr[String](Literal(Constant(x)))(TypeTag.String)
+
+ def literal(x: Char) = Expr[Char](Literal(Constant(x)))(TypeTag.Char)
+}
diff --git a/src/compiler/scala/reflect/makro/util/Traces.scala b/src/compiler/scala/reflect/makro/util/Traces.scala
new file mode 100644
index 0000000000..2363cc4bac
--- /dev/null
+++ b/src/compiler/scala/reflect/makro/util/Traces.scala
@@ -0,0 +1,18 @@
+package scala.reflect.makro
+package util
+
+trait Traces {
+ def globalSettings: tools.nsc.Settings
+
+ // [Eugene] lots of ways to log:
+ // 1) trace(...)
+ // 2) log(...)
+ // 3) if (foo) { doStuff(); includingSomeLogs(); }
+ // what is the conventional way of unifying this?
+ val macroDebugLite = globalSettings.YmacrodebugLite.value
+ val macroDebugVerbose = globalSettings.YmacrodebugVerbose.value
+ val macroTraceLite = scala.tools.nsc.util.trace when (macroDebugLite || macroDebugVerbose)
+ val macroTraceVerbose = scala.tools.nsc.util.trace when macroDebugVerbose
+ @inline final def macroLogLite(msg: => Any) { if (macroDebugLite || macroDebugVerbose) println(msg) }
+ @inline final def macroLogVerbose(msg: => Any) { if (macroDebugVerbose) println(msg) }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/Errors.scala b/src/compiler/scala/reflect/reify/Errors.scala
new file mode 100644
index 0000000000..4466f281b8
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/Errors.scala
@@ -0,0 +1,60 @@
+package scala.reflect
+package reify
+
+import scala.reflect.makro.ReificationError
+import scala.reflect.makro.UnexpectedReificationError
+
+trait Errors {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+
+ def defaultErrorPosition = analyzer.enclosingMacroPosition
+
+ // expected errors: these can happen if the user casually writes whatever.reify(...)
+ // hence we don't crash here, but nicely report a typechecking error and bail out asap
+
+ def CannotReifyReifeeThatHasTypeLocalToReifee(tree: Tree) = {
+ val msg = "implementation restriction: cannot reify block of type %s that involves a type declared inside the block being reified. consider casting the return value to a suitable type".format(tree.tpe)
+ throw new ReificationError(tree.pos, msg)
+ }
+
+ def CannotReifyType(tpe: Type) = {
+ val msg = "implementation restriction: cannot reify type %s (%s)".format(tpe, tpe.kind)
+ throw new ReificationError(defaultErrorPosition, msg)
+ }
+
+ def CannotReifySymbol(sym: Symbol) = {
+ val msg = "implementation restriction: cannot reify symbol %s (%s)".format(sym, sym.accurateKindString)
+ throw new ReificationError(defaultErrorPosition, msg)
+ }
+
+ def CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(tpe: Type) = {
+ val msg = "cannot reify ConcreteTypeTag having unresolved type parameter %s".format(tpe)
+ throw new ReificationError(defaultErrorPosition, msg)
+ }
+
+ // unexpected errors: these can never happen under normal conditions unless there's a bug in the compiler (or in a compiler plugin or in a macro)
+ // hence, we fail fast and loudly and don't care about being nice - in this situation noone will appreciate our quiet nicety
+
+ def CannotReifyUntypedPrefix(prefix: Tree) = {
+ val msg = "internal error: untyped prefixes are not supported, consider typechecking the prefix before passing it to the reifier"
+ throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ }
+
+ def CannotReifyUntypedReifee(reifee: Any) = {
+ val msg = "internal error: untyped trees are not supported, consider typechecking the reifee before passing it to the reifier"
+ throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ }
+
+ def CannotReifyErroneousPrefix(prefix: Tree) = {
+ val msg = "internal error: erroneous prefixes are not supported, make sure that your prefix has typechecked successfully before passing it to the reifier"
+ throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ }
+
+ def CannotReifyErroneousReifee(reifee: Any) = {
+ val msg = "internal error: erroneous reifees are not supported, make sure that your reifee has typechecked successfully before passing it to the reifier"
+ throw new UnexpectedReificationError(defaultErrorPosition, msg)
+ }
+}
diff --git a/src/compiler/scala/reflect/reify/NodePrinters.scala b/src/compiler/scala/reflect/reify/NodePrinters.scala
new file mode 100644
index 0000000000..eaca9a4968
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/NodePrinters.scala
@@ -0,0 +1,111 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package reify
+
+import scala.Array.canBuildFrom
+import scala.compat.Platform.EOL
+import scala.tools.nsc.symtab.Flags
+import scala.tools.nsc.Global
+
+trait NodePrinters { self: scala.tools.nsc.ast.NodePrinters =>
+
+ val global: Global
+ import global._
+
+ object reifiedNodeToString extends Function2[Tree, Tree, String] {
+ def apply(prefix: Tree, tree: Tree): String = {
+ import scala.reflect.api.Modifier
+ var modifierIsUsed = false
+ var flagsAreUsed = false
+
+ // @PP: I fervently hope this is a test case or something, not anything being
+ // depended upon. Of more fragile code I cannot conceive.
+ // @Eugene: This stuff is only needed to debug-print out reifications in human-readable format
+ // Rolling a full-fledged, robust TreePrinter would be several times more code.
+ val (List(mirror), reified) = (for (line <- (tree.toString.split(EOL).toList drop 1 dropRight 1)) yield {
+ var s = line.trim
+ s = s.replace("$mr.", "")
+ s = s.replace(".apply", "")
+ s = s.replace("scala.collection.immutable.", "")
+ s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List")
+ s = "List\\[.*?\\]".r.replaceAllIn(s, "List")
+ s = s.replace("immutable.this.Nil", "List()")
+ s = s.replace("modifiersFromInternalFlags", "Modifiers")
+ s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()")
+ s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => {
+ val buf = new collection.mutable.ListBuffer[String]
+
+ val annotations = m.group(3)
+ if (buf.nonEmpty || annotations.nonEmpty)
+ buf.append("List(" + annotations + ")")
+
+ val privateWithin = "" + m.group(2)
+ if (buf.nonEmpty || privateWithin != "")
+ buf.append("newTypeName(\"" + privateWithin + "\")")
+
+ val flags = m.group(1).toLong
+ val s_flags = Flags.modifiersOfFlags(flags) map (_.sourceString) mkString ", "
+ if (buf.nonEmpty || s_flags != "") {
+ modifierIsUsed = true
+ buf.append("Set(" + s_flags + ")")
+ }
+
+ "Modifiers(" + buf.reverse.mkString(", ") + ")"
+ })
+ s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => {
+ flagsAreUsed = true
+ val flags = m.group(1).toLong
+ val mods = Flags.modifiersOfFlags(flags) map (_.sourceString)
+ "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))"
+ })
+
+ s
+ }) splitAt 1
+
+ val printout = collection.mutable.ListBuffer(mirror);
+ printout += "import " + nme.MIRROR_SHORT + "._"
+ if (modifierIsUsed) printout += "import scala.reflect.api.Modifier._"
+ if (flagsAreUsed) printout += "import scala.reflect.internal.Flags._"
+ val body = reified dropWhile (_.startsWith("val"))
+ if (body.length > 0 && body(0).startsWith("Expr[")) {
+ if (reified(0) startsWith "val") {
+ printout += "val code = {"
+ printout ++= (reified map (" " + _))
+ printout += "}"
+ printout += "mkToolBox().runExpr(code)"
+ } else {
+ printout += "val code = " + reified(0)
+ printout ++= reified drop 1
+ printout += "mkToolBox().runExpr(code)"
+ }
+ try {
+ val prefix = Select(Select(Ident(definitions.ScalaPackage), newTermName("reflect")), newTermName("mirror"))
+ val tree1 = new global.Transformer {
+ override def transform(tree: Tree) = super.transform(tree match {
+ case Block(ValDef(_, mr, _, _) :: Nil, expr) if mr == nme.MIRROR_SHORT => transform(expr)
+ case Block(ValDef(_, mr, _, _) :: symbolTable, expr) if mr == nme.MIRROR_SHORT => transform(Block(symbolTable, expr))
+ case Select(Ident(mr), name) if mr == nme.MIRROR_SHORT => Select(prefix, name)
+ case tree => tree
+ })
+ }.transform(tree)
+ val stringified = mkToolBox().runExpr(tree1).toString
+ if (settings.Yreifydebug.value) printout += "*****************************"
+ printout += stringified
+ } catch {
+ case ex: Throwable =>
+// val realex = ReflectionUtils.unwrapThrowable(ex)
+// val message = new java.io.StringWriter()
+// realex.printStackTrace(new java.io.PrintWriter(message))
+// println(message)
+ }
+ } else {
+ printout ++= reified
+ }
+ printout mkString EOL
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/Phases.scala b/src/compiler/scala/reflect/reify/Phases.scala
new file mode 100644
index 0000000000..49d5a45e8e
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/Phases.scala
@@ -0,0 +1,42 @@
+package scala.reflect
+package reify
+
+import scala.reflect.reify.phases._
+
+trait Phases extends Calculate
+ with Reshape
+ with Metalevels
+ with Reify {
+
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+
+ private var alreadyRun = false
+
+ lazy val mkReificationPipeline: Tree => Tree = tree0 => {
+ assert(!alreadyRun, "reifier instance cannot be used more than once")
+ alreadyRun = true
+
+ var tree = tree0
+
+ if (reifyDebug) println("[calculate phase]")
+ calculate.traverse(tree)
+
+ if (reifyDebug) println("[reshape phase]")
+ tree = reshape.transform(tree)
+
+ if (reifyDebug) println("[metalevels phase]")
+ tree = metalevels.transform(tree)
+
+ if (reifyDebug) println("[interlude]")
+ if (reifyDebug) println("symbol table = " + (if (symbolTable.length == 0) "<empty>" else ""))
+ if (reifyDebug) symbolTable foreach (println(_))
+ if (reifyDebug) println("reifee = " + (if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString))
+ if (reifyDebug) println("[reify phase]")
+ var result = reify(tree)
+
+ result
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/Reifier.scala b/src/compiler/scala/reflect/reify/Reifier.scala
new file mode 100644
index 0000000000..fea825358e
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/Reifier.scala
@@ -0,0 +1,164 @@
+package scala.reflect
+package reify
+
+import scala.tools.nsc.Global
+import scala.reflect.makro.ReificationError
+import scala.reflect.makro.UnexpectedReificationError
+
+/** Given a tree or a type, generate a tree that when executed at runtime produces the original tree or type.
+ * See more info in the comments to ``reify'' in scala.reflect.api.Universe.
+ *
+ * @author Martin Odersky
+ * @version 2.10
+ */
+abstract class Reifier extends Phases
+ with Errors {
+
+ val mirror: Global
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ val typer: mirror.analyzer.Typer
+ val prefix: Tree
+ val reifee: Any
+ val dontSpliceAtTopLevel: Boolean
+ val concrete: Boolean
+
+ /**
+ * For ``reifee'' and other reification parameters, generate a tree of the form
+ *
+ * {
+ * val $mr = <[ prefix ]>
+ * $mr.Expr[T](rtree) // if data is a Tree
+ * $mr.TypeTag[T](rtree) // if data is a Type
+ * }
+ *
+ * where
+ *
+ * - `prefix` is the tree that represents the universe
+ * the result will be bound to
+ * - `rtree` is code that generates `reifee` at runtime.
+ * - `T` is the type that corresponds to `data`.
+ *
+ * This is not a method, but a value to indicate the fact that Reifier instances are a one-off.
+ */
+ lazy val reified: Tree = {
+ try {
+ // [Eugene] conventional way of doing this?
+ if (prefix exists (_.isErroneous)) CannotReifyErroneousPrefix(prefix)
+ if (prefix.tpe == null) CannotReifyUntypedPrefix(prefix)
+
+ val rtree = reifee match {
+ case tree: Tree =>
+ reifyTrace("reifying = ")(if (opt.showTrees) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
+ reifyTrace("reifee is located at: ")(tree.pos)
+ reifyTrace("prefix = ")(prefix)
+ // [Eugene] conventional way of doing this?
+ if (tree exists (_.isErroneous)) CannotReifyErroneousReifee(prefix)
+ if (tree.tpe == null) CannotReifyUntypedReifee(tree)
+ val pipeline = mkReificationPipeline
+ val rtree = pipeline(tree)
+
+ // consider the following code snippet
+ //
+ // val x = reify { class C; new C }
+ //
+ // inferred type for x will be C
+ // but C ceases to exist after reification so this type is clearly incorrect
+ // however, reify is "just" a library function, so it cannot affect type inference
+ //
+ // hence we crash here even though the reification itself goes well
+ // fortunately, all that it takes to fix the error is to cast "new C" to Object
+ // so I'm not very much worried about introducing this restriction
+ if (tree.tpe exists (sub => sub.typeSymbol.isLocalToReifee))
+ CannotReifyReifeeThatHasTypeLocalToReifee(tree)
+
+ val taggedType = typer.packedType(tree, NoSymbol)
+ val tagModule = if (reificationIsConcrete) ConcreteTypeTagModule else TypeTagModule
+ val tagCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(taggedType)))
+ val exprCtor = TypeApply(Select(Ident(nme.MIRROR_SHORT), ExprModule.name), List(TypeTree(taggedType)))
+ val tagArgs = List(reify(taggedType), reifyErasure(mirror)(typer, taggedType, concrete = false))
+ Apply(Apply(exprCtor, List(rtree)), List(Apply(tagCtor, tagArgs)))
+
+ case tpe: Type =>
+ reifyTrace("reifying = ")(tpe.toString)
+ reifyTrace("prefix = ")(prefix)
+ val rtree = reify(tpe)
+
+ val taggedType = tpe
+ val tagModule = if (reificationIsConcrete) ConcreteTypeTagModule else TypeTagModule
+ val ctor = TypeApply(Select(Ident(nme.MIRROR_SHORT), tagModule.name), List(TypeTree(taggedType)))
+ val args = List(rtree, reifyErasure(mirror)(typer, taggedType, concrete = false))
+ Apply(ctor, args)
+
+ case _ =>
+ throw new Error("reifee %s of type %s is not supported".format(reifee, if (reifee == null) "null" else reifee.getClass.toString))
+ }
+
+ val mirrorAlias = ValDef(NoMods, nme.MIRROR_SHORT, SingletonTypeTree(prefix), prefix)
+ val wrapped = Block(mirrorAlias :: symbolTable, rtree)
+
+ // todo. why do we resetAllAttrs?
+ //
+ // typically we do some preprocessing before reification and
+ // the code emitted/moved around during preprocessing is very hard to typecheck, so we leave it as it is
+ // however this "as it is" sometimes doesn't make any sense
+ //
+ // ===example 1===
+ // we move a freevar from a nested symbol table to a top-level symbol table,
+ // and then the reference to mr$ becomes screwed up, because nested symbol tables are already typechecked,
+ // so we have an mr$ symbol that points to the nested mr$ rather than to the top-level one.
+ //
+ // ===example 2===
+ // we inline a freevar by replacing a reference to it, e.g. $mr.Apply($mr.Select($mr.Ident($mr.newTermName("$mr")), $mr.newTermName("Ident")), List($mr.Ident($mr.newTermName("free$x"))))
+ // with its original binding (e.g. $mr.Ident("x"))
+ // we'd love to typecheck the result, but we cannot do this easily, because $mr is external to this tree
+ // what's even worse, sometimes $mr can point to the top-level symbol table's $mr, which doesn't have any symbol/type yet -
+ // it's just a ValDef that will be emitted only after the reification is completed
+ //
+ // hence, the simplest solution is to erase all attrs so that invalid (as well as non-existent) bindings get rebound correctly
+ // this is ugly, but it's the best we can do
+ //
+ // todo. this is a common problem with non-trivial macros in our current macro system
+ // needs to be solved some day
+ //
+ // list of non-hygienic transformations:
+ // 1) local freetype inlining in Nested
+ // 2) external freevar moving in Nested
+ // 3) local freeterm inlining in Metalevels
+ // 4) trivial tree splice inlining in Reify (Trees.scala)
+ // 5) trivial type splice inlining in Reify (Types.scala)
+ val freevarBindings = symbolTable collect { case entry @ FreeDef(_, _, binding, _, _) => binding.symbol } toSet
+ // [Eugene] yeah, ugly and extremely brittle, but we do need to do resetAttrs. will be fixed later
+ var importantSymbols = Set[Symbol](PredefModule, ScalaRunTimeModule)
+ importantSymbols ++= importantSymbols map (_.companionSymbol)
+ importantSymbols ++= importantSymbols map (_.moduleClass)
+ importantSymbols ++= importantSymbols map (_.linkedClassOfClass)
+ def importantSymbol(sym: Symbol): Boolean = sym != null && sym != NoSymbol && importantSymbols(sym)
+ val untyped = resetAllAttrs(wrapped, leaveAlone = {
+ case ValDef(_, mr, _, _) if mr == nme.MIRROR_SHORT => true
+ case tree if freevarBindings contains tree.symbol => true
+ case tree if importantSymbol(tree.symbol) => true
+ case _ => false
+ })
+
+ if (reifyCopypaste) {
+ if (reifyDebug) println("=============================")
+ println(reifiedNodeToString(prefix, untyped))
+ if (reifyDebug) println("=============================")
+ } else {
+ reifyTrace("reified = ")(untyped)
+ }
+
+ untyped
+ } catch {
+ case ex: ReificationError =>
+ throw ex
+ case ex: UnexpectedReificationError =>
+ throw ex
+ case ex: Throwable =>
+ throw new UnexpectedReificationError(defaultErrorPosition, "reification crashed", ex)
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/codegen/AnnotationInfos.scala b/src/compiler/scala/reflect/reify/codegen/AnnotationInfos.scala
new file mode 100644
index 0000000000..1d218317dc
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/codegen/AnnotationInfos.scala
@@ -0,0 +1,56 @@
+package scala.reflect.reify
+package codegen
+
+trait AnnotationInfos {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ // usually annotations are reified as their originals from Modifiers
+ // however, when reifying free and tough types, we're forced to reify annotation infos as is
+ // why is that bad? take a look inside
+ def reifyAnnotationInfo(ann: AnnotationInfo): Tree = {
+ val reifiedArgs = ann.args map { arg =>
+ val saved1 = reifyTreeSymbols
+ val saved2 = reifyTreeTypes
+
+ try {
+ // one more quirk of reifying annotations
+ //
+ // when reifying AnnotatedTypes we need to reify all the types and symbols of inner ASTs
+ // that's because a lot of logic expects post-typer trees to have non-null tpes
+ //
+ // Q: reified trees are pre-typer, so there's shouldn't be a problem.
+ // reflective typechecker will fill in missing symbols and types, right?
+ // A: actually, no. annotation ASTs live inside AnnotatedTypes,
+ // and insides of the types is the place where typechecker doesn't look.
+ reifyTreeSymbols = true
+ reifyTreeTypes = true
+
+ // todo. every AnnotationInfo is an island, entire of itself
+ // no regular Traverser or Transformer can reach it
+ // hence we need to run its contents through the entire reification pipeline
+ // e.g. to apply reshaping or to check metalevels
+ reify(arg)
+ } finally {
+ reifyTreeSymbols = saved1
+ reifyTreeTypes = saved2
+ }
+ }
+
+ def reifyClassfileAnnotArg(arg: ClassfileAnnotArg): Tree = arg match {
+ case LiteralAnnotArg(const) =>
+ mirrorFactoryCall(nme.LiteralAnnotArg, reifyProduct(const))
+ case ArrayAnnotArg(args) =>
+ mirrorFactoryCall(nme.ArrayAnnotArg, scalaFactoryCall(nme.Array, args map reifyClassfileAnnotArg: _*))
+ case NestedAnnotArg(ann) =>
+ mirrorFactoryCall(nme.NestedAnnotArg, reifyAnnotationInfo(ann))
+ }
+
+ // if you reify originals of anns, you get SO when trying to reify AnnotatedTypes, so screw it - after all, it's not that important
+ val reifiedAssocs = ann.assocs map (assoc => scalaFactoryCall(nme.Tuple2, reify(assoc._1), reifyClassfileAnnotArg(assoc._2)))
+ mirrorFactoryCall(nme.AnnotationInfo, reify(ann.atp), mkList(reifiedArgs), mkList(reifiedAssocs))
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/codegen/Names.scala b/src/compiler/scala/reflect/reify/codegen/Names.scala
new file mode 100644
index 0000000000..589f6355d0
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/codegen/Names.scala
@@ -0,0 +1,15 @@
+package scala.reflect.reify
+package codegen
+
+trait Names {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ def reifyName(name: Name) = {
+ val factory = if (name.isTypeName) nme.nmeNewTypeName else nme.nmeNewTermName
+ mirrorCall(factory, Literal(Constant(name.toString)))
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/codegen/Positions.scala b/src/compiler/scala/reflect/reify/codegen/Positions.scala
new file mode 100644
index 0000000000..ac9195ef31
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/codegen/Positions.scala
@@ -0,0 +1,18 @@
+package scala.reflect.reify
+package codegen
+
+trait Positions {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ // we do not reify positions because this inflates resulting trees, but doesn't buy as anything
+ // where would one use positions? right, in error messages
+ // but I can hardly imagine when one would need a position that points to the reified code
+ // usually reified trees are used to compose macro expansions or to be fed to the runtime compiler
+ // however both macros and toolboxes have their own means to report errors in synthetic trees
+ def reifyPosition(pos: Position): Tree =
+ reifyMirrorObject(NoPosition)
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/codegen/Symbols.scala b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
new file mode 100644
index 0000000000..21a08b7efb
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/codegen/Symbols.scala
@@ -0,0 +1,184 @@
+package scala.reflect.reify
+package codegen
+
+trait Symbols {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ /** Reify a reference to a symbol */
+ def reifySymRef(sym0: Symbol): Tree = {
+ assert(sym0 != null, "sym is null")
+ val sym = sym0.dealias
+
+ if (sym == NoSymbol)
+ mirrorSelect(nme.NoSymbol)
+ else if (sym == RootPackage)
+ Select(mirrorSelect(nme.definitions), nme.RootPackage)
+ else if (sym == RootClass)
+ Select(mirrorSelect(nme.definitions), nme.RootClass)
+ else if (sym == EmptyPackage)
+ Select(mirrorSelect(nme.definitions), nme.EmptyPackage)
+ else if (sym == EmptyPackageClass)
+ Select(mirrorSelect(nme.definitions), nme.EmptyPackageClass)
+ else if (sym.isModuleClass)
+ Select(reify(sym.sourceModule), nme.moduleClass)
+ else if (sym.isLocatable) {
+ // [Eugene] am I doing this right?
+// if (sym.isStaticOwner) { // no good for us, because it returns false for packages
+ if (sym.isStatic && (sym.isClass || sym.isModule)) {
+ val resolver = if (sym.isType) nme.staticClass else nme.staticModule
+ mirrorCall(resolver, reify(sym.fullName))
+ } else {
+ if (reifyDebug) println("Locatable: %s (%s) owned by %s (%s) at %s".format(sym, sym.accurateKindString, sym.owner, sym.owner.accurateKindString, sym.owner.fullNameString))
+ val rowner = reify(sym.owner)
+ val rname = reify(sym.name.toString)
+ if (sym.isType)
+ mirrorCall(nme.selectType, rowner, rname)
+ else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) {
+ val index = sym.owner.info.decl(sym.name).alternatives indexOf sym
+ assert(index >= 0, sym)
+ mirrorCall(nme.selectOverloadedMethod, rowner, rname, reify(index))
+ } else
+ mirrorCall(nme.selectTerm, rowner, rname)
+ }
+ } else {
+ // todo. make sure that free methods and free local defs work correctly
+ if (sym.isTerm) reifyFreeTerm(sym, Ident(sym))
+ else reifyFreeType(sym, Ident(sym))
+ }
+ }
+
+ def reifyFreeTerm(sym: Symbol, value: Tree): Tree =
+ locallyReified get sym match {
+ case Some(reified) =>
+ reified
+ case None =>
+ if (reifyDebug) println("Free term" + (if (sym.isCapturedVariable) " (captured)" else "") + ": " + sym + "(" + sym.accurateKindString + ")")
+ var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name)
+ if (sym.isType) name = name.append(nme.MIRROR_FREE_THIS_SUFFIX)
+ if (sym.isCapturedVariable) {
+ assert(value.isInstanceOf[Ident], showRaw(value))
+ val capturedTpe = capturedVariableType(sym)
+ val capturedValue = referenceCapturedVariable(sym)
+ locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(capturedTpe), capturedValue, reify(sym.flags), reify(origin(sym))))
+ } else {
+ locallyReify(sym, name, mirrorCall(nme.newFreeTerm, reify(sym.name.toString), reify(sym.tpe), value, reify(sym.flags), reify(origin(sym))))
+ }
+ }
+
+ def reifyFreeType(sym: Symbol, value: Tree): Tree =
+ locallyReified get sym match {
+ case Some(reified) =>
+ reified
+ case None =>
+ if (reifyDebug) println("Free type: %s (%s)".format(sym, sym.accurateKindString))
+ var name = newTermName(nme.MIRROR_FREE_PREFIX + sym.name)
+ val phantomTypeTag = Apply(TypeApply(Select(Ident(nme.MIRROR_SHORT), nme.TypeTag), List(value)), List(Literal(Constant(null)), Literal(Constant(null))))
+ val flavor = if (sym.isExistential) nme.newFreeExistential else nme.newFreeType
+ locallyReify(sym, name, mirrorCall(flavor, reify(sym.name.toString), reify(sym.info), phantomTypeTag, reify(sym.flags), reify(origin(sym))))
+ }
+
+ def reifySymDef(sym: Symbol): Tree =
+ locallyReified get sym match {
+ case Some(reified) =>
+ reified
+ case None =>
+ if (reifyDebug) println("Sym def: %s (%s)".format(sym, sym.accurateKindString))
+ assert(!sym.isLocatable, sym) // if this assertion fires, then tough type reification needs to be rethought
+ sym.owner.ownersIterator find (!_.isLocatable) foreach reifySymDef
+ var name = newTermName(nme.MIRROR_SYMDEF_PREFIX + sym.name)
+ locallyReify(sym, name, Apply(Select(reify(sym.owner), nme.newNestedSymbol), List(reify(sym.name), reify(sym.pos), reify(sym.flags), reify(sym.isClass))))
+ }
+
+ // todo. very brittle abstraction, needs encapsulation
+ import scala.collection.mutable._
+ private val localReifications = ArrayBuffer[Tree]()
+ private val locallyReified = Map[Symbol, Tree]()
+ private var filledIn = false
+ def symbolTable: List[Tree] = { fillInSymbolTable(); localReifications.toList }
+ def symbolTable_=(newSymbolTable: List[Tree]): Unit = {
+ localReifications.clear()
+ locallyReified.clear()
+ filledIn = false
+ newSymbolTable foreach {
+ case entry =>
+ val att = entry.attachmentOpt[ReifyAttachment]
+ att match {
+ case Some(ReifyAttachment(sym)) =>
+ // don't duplicate reified symbols when merging inlined reifee
+ if (!(locallyReified contains sym)) {
+ val ValDef(_, name, _, _) = entry
+ localReifications += entry
+ locallyReified(sym) = Ident(name)
+ }
+ case other =>
+ // do nothing => symbol table fill-ins will be repopulated later
+ }
+ }
+ }
+
+ private def localName(name0: TermName): TermName = {
+ var name = name0.toString
+ name = name.replace(".type", "$type")
+ name = name.replace(" ", "$")
+ val fresh = typer.context.unit.fresh
+ newTermName(fresh.newName(name))
+ }
+
+ private def locallyReify(sym: Symbol, name0: TermName, reificode: => Tree): Tree = {
+ val reified = reificode
+ val name = localName(name0)
+ // todo. tried to declare a private class here to carry an attachment, but it's path-dependent
+ // so got troubles with exchanging free variables between nested and enclosing quasiquotes
+ // attaching just Symbol isn't good either, so we need to think of a principled solution
+ val local = ValDef(NoMods, name, TypeTree(), reified) withAttachment ReifyAttachment(sym)
+ localReifications += local
+ filledIn = false
+ locallyReified(sym) = Ident(name)
+ locallyReified(sym)
+ }
+
+ /** Sets type signatures and annotations for locally reified symbols */
+ private def fillInSymbolTable() = {
+ if (!filledIn) {
+ val fillIns = new ArrayBuffer[Tree]
+ var i = 0
+ while (i < localReifications.length) {
+ // fillInSymbol might create new locallyReified symbols, that's why this is done iteratively
+ val reified = localReifications(i)
+ val att = reified.attachmentOpt[ReifyAttachment]
+ att match {
+ case Some(ReifyAttachment(sym)) => fillIns += fillInSymbol(sym)
+ case other => // do nothing
+ }
+ i += 1
+ }
+
+ filledIn = true
+ localReifications ++= fillIns.toList
+ }
+ }
+
+ /** Generate code to add type and annotation info to a reified symbol */
+ private def fillInSymbol(sym: Symbol): Tree = {
+ if (reifyDebug) println("Filling in: %s (%s)".format(sym, sym.accurateKindString))
+ val isFree = locallyReified(sym) match { case Ident(name) => name startsWith nme.MIRROR_FREE_PREFIX }
+ if (isFree) {
+ if (sym.annotations.isEmpty) EmptyTree
+ else Apply(Select(locallyReified(sym), nme.setAnnotations), List(reify(sym.annotations)))
+ } else {
+ import scala.reflect.internal.Flags._
+ if (sym hasFlag LOCKED) {
+ // [Eugene] better to have a symbol without a type signature, than to crash with a CyclicReference
+ EmptyTree
+ } else {
+ val rset = Apply(Select(locallyReified(sym), nme.setTypeSignature), List(reify(sym.info)))
+ if (sym.annotations.isEmpty) rset
+ else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations)))
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/codegen/Trees.scala b/src/compiler/scala/reflect/reify/codegen/Trees.scala
new file mode 100644
index 0000000000..c9f5fc5b8d
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/codegen/Trees.scala
@@ -0,0 +1,259 @@
+package scala.reflect.reify
+package codegen
+
+trait Trees {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+ import scala.reflect.api.Modifier
+
+ // unfortunately, these are necessary to reify AnnotatedTypes
+ // I'd gladly got rid of them, but I don't fancy making a metaprogramming API that doesn't work with annotated types
+ var reifyTreeSymbols = false
+ var reifyTreeTypes = false
+
+ /**
+ * Reify a tree.
+ * For internal use only, use ``reified'' instead.
+ */
+ def reifyTree(tree: Tree): Tree = {
+ assert(tree != null, "tree is null")
+
+ if (tree.isErroneous)
+ CannotReifyErroneousReifee(tree)
+
+ val splicedTree = spliceTree(tree)
+ if (splicedTree != EmptyTree)
+ return splicedTree
+
+ // the idea behind the new reincarnation of reifier is a simple maxim:
+ //
+ // never call ``reifyType'' to reify a tree
+ //
+ // this works because the stuff we are reifying was once represented with trees only
+ // and lexical scope information can be fully captured by reifying symbols
+ //
+ // to enable this idyll, we work hard in the ``Reshape'' phase
+ // which replaces all types with equivalent trees and works around non-idempotencies of the typechecker
+ //
+ // why bother? because this brings method to the madness
+ // the first prototype of reification reified all types and symbols for all trees => this quickly became unyieldy
+ // the second prototype reified external types, but avoided reifying local ones => this created an ugly irregularity
+ // current approach is uniform and compact
+ var rtree = tree match {
+ case mirror.EmptyTree =>
+ reifyMirrorObject(EmptyTree)
+ case mirror.emptyValDef =>
+ mirrorSelect(nme.emptyValDef)
+ case FreeDef(_, _, _, _, _) =>
+ reifyNestedFreeDef(tree)
+ case FreeRef(_, _) =>
+ reifyNestedFreeRef(tree)
+ case BoundTerm(tree) =>
+ reifyBoundTerm(tree)
+ case BoundType(tree) =>
+ reifyBoundType(tree)
+ case NestedExpr(_, _, _) =>
+ reifyNestedExpr(tree)
+ case Literal(const @ Constant(_)) =>
+ // [Eugene] was necessary when we reified erasures as normalized tycons
+ // now, when we do existentialAbstraction on normalizations, everything works great
+ // todo. find an explanation
+// if (const.tag == ClazzTag) {
+//// def preprocess(tpe: Type): Type = tpe.typeSymbol match {
+//// case ArrayClass => appliedType(ArrayClass, preprocess(tpe.typeArgs.head))
+//// case _ => tpe.typeConstructor
+//// }
+//// val tpe = preprocess(const.typeValue)
+// val tpe = const.typeValue
+// var reified = reify(tpe)
+// reified = mirrorCall(nme.Literal, mirrorCall(nme.Constant, reified))
+//// val skolems = ClassClass.typeParams map (_ => newTypeName(typer.context.unit.fresh.newName("_$")))
+//// var existential = mirrorCall(nme.AppliedTypeTree, mirrorCall(nme.TypeTree, reify(ClassClass.typeConstructor)), mkList(skolems map (skolem => mirrorCall(nme.Ident, reify(skolem)))))
+//// existential = mirrorCall(nme.ExistentialTypeTree, existential, reify(skolems map (skolem => TypeDef(Modifiers(Set(Modifier.deferred: Modifier)), skolem, Nil, TypeBoundsTree(Ident(NothingClass) setType NothingClass.tpe, Ident(AnyClass) setType AnyClass.tpe)))))
+//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(existential)))
+// // why is this required??
+//// reified = mirrorCall(nme.TypeApply, mirrorCall(nme.Select, reified, reify(nme.asInstanceOf_)), mkList(List(mirrorCall(nme.TypeTree, reify(appliedType(ClassClass.tpe, List(AnyClass.tpe)))))))
+// reified
+// } else {
+// mirrorCall(nme.Literal, reifyProduct(const))
+// }
+ mirrorCall(nme.Literal, reifyProduct(const))
+ case Import(expr, selectors) =>
+ mirrorCall(nme.Import, reify(expr), mkList(selectors map reifyProduct))
+ case _ =>
+ reifyProduct(tree)
+ }
+
+ // usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation
+ // however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why.
+ if (reifyTreeSymbols && tree.hasSymbol) {
+ if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree))
+ rtree = Apply(Select(rtree, nme.setSymbol), List(reify(tree.symbol)))
+ }
+ if (reifyTreeTypes && tree.tpe != null) {
+ if (reifyDebug) println("reifying type %s for tree %s".format(tree.tpe, tree))
+ rtree = Apply(Select(rtree, nme.setType), List(reify(tree.tpe)))
+ }
+
+ rtree
+ }
+
+ def reifyModifiers(m: mirror.Modifiers) =
+ mirrorCall("modifiersFromInternalFlags", reify(m.flags), reify(m.privateWithin), reify(m.annotations))
+
+ private def spliceTree(tree: Tree): Tree = {
+ tree match {
+ case EvalSplice(splicee) =>
+ if (reifyDebug) println("splicing eval " + tree)
+
+ // see ``Metalevels'' for more info about metalevel breaches
+ // and about how we deal with splices that contain them
+ if (splicee exists (sub => sub.hasSymbol && sub.symbol != NoSymbol && sub.symbol.metalevel > 0)) {
+ if (reifyDebug) println("splicing has failed: cannot splice when facing a metalevel breach")
+ EmptyTree
+ } else {
+ if (reifyDebug) println("splicing has succeeded")
+ var splice = Select(splicee, nme.tree)
+ splice match {
+ case InlinedTreeSplice(_, inlinedSymbolTable, tree, _) =>
+ if (reifyDebug) println("inlining the splicee")
+ // all free vars local to the enclosing reifee should've already been inlined by ``Metalevels''
+ inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) }
+ symbolTable ++= inlinedSymbolTable
+ tree
+ case tree =>
+ // we need to preserve types of exprs, because oftentimes they cannot be inferred later
+ // this circumvents regular reification scheme, therefore we go the extra mile here
+ new Transformer {
+ override def transform(tree: Tree) = super.transform(tree match {
+ case NestedExpr(factory, tree, typetag) =>
+ val typedFactory = TypeApply(factory, List(TypeTree(typetag.tpe.typeArgs(0))))
+ Apply(Apply(typedFactory, List(tree)), List(typetag))
+ case _ =>
+ tree
+ })
+ }.transform(tree)
+ }
+ }
+ case ValueSplice(splicee) =>
+ // todo. implement this
+ ???
+ case _ =>
+ EmptyTree
+ }
+ }
+
+ private def reifyBoundTerm(tree: Tree): Tree = tree match {
+ case tree @ This(_) if tree.symbol == NoSymbol =>
+ throw new Error("unexpected: bound term that doesn't have a symbol: " + showRaw(tree))
+ case tree @ This(_) if tree.symbol.isClass && !tree.symbol.isModuleClass && !tree.symbol.isLocalToReifee =>
+ val sym = tree.symbol
+ if (reifyDebug) println("This for %s, reified as freeVar".format(sym))
+ if (reifyDebug) println("Free: " + sym)
+ mirrorCall(nme.Ident, reifyFreeTerm(sym, This(sym)))
+ case tree @ This(_) if !tree.symbol.isLocalToReifee =>
+ if (reifyDebug) println("This for %s, reified as This".format(tree.symbol))
+ mirrorCall(nme.This, reify(tree.symbol))
+ case tree @ This(_) if tree.symbol.isLocalToReifee =>
+ mirrorCall(nme.This, reify(tree.qual))
+ case tree @ Ident(_) if tree.symbol == NoSymbol =>
+ // this sometimes happens, e.g. for binds that don't have a body
+ // or for untyped code generated during previous phases
+ // (see a comment in Reifiers about the latter, starting with "why do we resetAllAttrs?")
+ mirrorCall(nme.Ident, reify(tree.name))
+ case tree @ Ident(_) if !tree.symbol.isLocalToReifee =>
+ if (tree.symbol.isVariable && tree.symbol.owner.isTerm) {
+ captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reification here.
+ mirrorCall(nme.Select, mirrorCall(nme.Ident, reify(tree.symbol)), reify(nme.elem))
+ } else {
+ mirrorCall(nme.Ident, reify(tree.symbol))
+ }
+ case tree @ Ident(_) if tree.symbol.isLocalToReifee =>
+ mirrorCall(nme.Ident, reify(tree.name))
+ case _ =>
+ throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ }
+
+ private def reifyBoundType(tree: Tree): Tree = {
+ def reifyBoundType(tree: Tree): Tree = {
+ if (tree.tpe == null)
+ throw new Error("unexpected: bound type that doesn't have a tpe: " + showRaw(tree))
+
+ if (tree.symbol.isLocalToReifee)
+ reifyProduct(tree)
+ else {
+ val sym0 = tree.symbol
+ val sym = sym0.dealias
+ val tpe0 = tree.tpe
+ val tpe = tpe0.dealias
+ if (reifyDebug) println("reifying bound type %s (underlying type is %s, dealiased is %s)".format(sym0, tpe0, tpe))
+
+ if (tpe.isSpliceable) {
+ val spliced = spliceType(tpe)
+ if (spliced == EmptyTree) {
+ if (reifyDebug) println("splicing failed: reify as is")
+ mirrorCall(nme.TypeTree, reify(tpe))
+ } else {
+ spliced match {
+ case TypeRefToFreeType(freeType) =>
+ if (reifyDebug) println("splicing returned a free type: " + freeType)
+ Ident(freeType)
+ case _ =>
+ if (reifyDebug) println("splicing succeeded: " + spliced)
+ mirrorCall(nme.TypeTree, spliced)
+ }
+ }
+ } else {
+ if (sym.isLocatable) {
+ if (reifyDebug) println("tpe is locatable: reify as Ident(%s)".format(sym))
+ mirrorCall(nme.Ident, reify(sym))
+ } else {
+ if (reifyDebug) println("tpe is an alias, but not a locatable: reify as TypeTree(%s)".format(tpe))
+ mirrorCall(nme.TypeTree, reify(tpe))
+ }
+ }
+ }
+ }
+
+ tree match {
+ case Select(_, _) =>
+ reifyBoundType(tree)
+ case SelectFromTypeTree(_, _) =>
+ reifyBoundType(tree)
+ case Ident(_) =>
+ reifyBoundType(tree)
+ case _ =>
+ throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ }
+ }
+
+ private def reifyNestedFreeDef(tree: Tree): Tree = {
+ if (reifyDebug) println("nested free def: %s".format(showRaw(tree)))
+ reifyProduct(tree)
+ }
+
+ private def reifyNestedFreeRef(tree: Tree): Tree = tree match {
+ case Apply(Select(mrRef @ Ident(_), ident), List(Ident(name: TermName))) if ident == nme.Ident && name.startsWith(nme.MIRROR_FREE_PREFIX) =>
+ if (reifyDebug) println("nested free ref: %s".format(showRaw(tree)))
+ reifyProduct(tree)
+ case _ =>
+ throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ }
+
+ private def reifyNestedExpr(tree: Tree): Tree = tree match {
+ case NestedExpr(factory, tree, typetag) =>
+ // we need to preserve types of exprs, because oftentimes they cannot be inferred later
+ // this circumvents regular reification scheme, therefore we go through this crazy dance
+ if (reifyDebug) println("nested expr: %s".format(showRaw(tree)))
+ val rtype = mirrorCall(nme.TypeTree, reify(typetag.tpe.typeArgs(0)))
+ val rfactory = mirrorCall(nme.TypeApply, reify(factory), mkList(List(rtype)))
+ val rexpr = mirrorCall(nme.Apply, rfactory, reify(List(tree)))
+ val rwrapped = mirrorCall(nme.Apply, rexpr, reify(List(typetag)))
+ rwrapped
+ case _ =>
+ throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/codegen/Types.scala b/src/compiler/scala/reflect/reify/codegen/Types.scala
new file mode 100644
index 0000000000..a2b074c6b2
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/codegen/Types.scala
@@ -0,0 +1,168 @@
+package scala.reflect.reify
+package codegen
+
+trait Types {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ /**
+ * Reify a type.
+ * For internal use only, use ``reified'' instead.
+ */
+ def reifyType(tpe0: Type): Tree = {
+ assert(tpe0 != null, "tpe is null")
+ val tpe = tpe0.dealias
+
+ if (tpe.isErroneous)
+ CannotReifyErroneousReifee(tpe)
+ if (tpe.isLocalToReifee)
+ CannotReifyType(tpe)
+
+ // [Eugene] how do I check that the substitution is legal w.r.t tpe.info?
+ val spliced = spliceType(tpe)
+ if (spliced != EmptyTree)
+ return spliced
+
+ val tsym = tpe.typeSymbol
+ if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic)
+ Select(reify(tpe.typeSymbol), nme.asTypeConstructor)
+ else tpe match {
+ case tpe @ NoType =>
+ reifyMirrorObject(tpe)
+ case tpe @ NoPrefix =>
+ reifyMirrorObject(tpe)
+ case tpe @ ThisType(root) if root == RootClass =>
+ mirrorSelect("definitions.RootClass.thisPrefix")
+ case tpe @ ThisType(empty) if empty == EmptyPackageClass =>
+ mirrorSelect("definitions.EmptyPackageClass.thisPrefix")
+ case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic =>
+ mirrorCall(nme.thisModuleType, reify(clazz.fullName))
+ case tpe @ ThisType(_) =>
+ reifyProduct(tpe)
+ case tpe @ SuperType(thistpe, supertpe) =>
+ reifyProduct(tpe)
+ case tpe @ SingleType(pre, sym) =>
+ reifyProduct(tpe)
+ case tpe @ ConstantType(value) =>
+ mirrorFactoryCall(nme.ConstantType, reifyProduct(value))
+ case tpe @ TypeRef(pre, sym, args) =>
+ reifyProduct(tpe)
+ case tpe @ TypeBounds(lo, hi) =>
+ reifyProduct(tpe)
+ case tpe @ NullaryMethodType(restpe) =>
+ reifyProduct(tpe)
+ case tpe @ AnnotatedType(anns, underlying, selfsym) =>
+ reifyAnnotatedType(tpe)
+ case _ =>
+ reifyToughType(tpe)
+ }
+ }
+
+ /** An obscure flag necessary for implicit TypeTag generation */
+ private var spliceTypesEnabled = !dontSpliceAtTopLevel
+
+ /** Keeps track of whether this reification contains abstract type parameters */
+ private var _reificationIsConcrete = true
+ def reificationIsConcrete = _reificationIsConcrete
+ def reificationIsConcrete_=(value: Boolean) {
+ _reificationIsConcrete = value
+ if (!value && concrete) {
+ assert(current.isInstanceOf[Type], current)
+ val offender = current.asInstanceOf[Type]
+ CannotReifyConcreteTypeTagHavingUnresolvedTypeParameters(offender)
+ }
+ }
+
+ private type SpliceCacheKey = (Symbol, Symbol)
+ private lazy val spliceCache: collection.mutable.Map[SpliceCacheKey, Tree] = {
+ val cache = analyzer.perRunMacroCache.getOrElseUpdate(MacroContextReify, collection.mutable.Map[Any, Any]())
+ cache.getOrElseUpdate("spliceCache", collection.mutable.Map[SpliceCacheKey, Tree]()).asInstanceOf[collection.mutable.Map[SpliceCacheKey, Tree]]
+ }
+
+ def spliceType(tpe: Type): Tree = {
+ // [Eugene] it seems that depending on the context the very same symbol can be either a spliceable tparam or a quantified existential. very weird!
+ val quantified = currentQuantified
+ if (tpe.isSpliceable && !(quantified contains tpe.typeSymbol)) {
+ if (reifyDebug) println("splicing " + tpe)
+
+ if (spliceTypesEnabled) {
+ var tagClass = if (concrete) ConcreteTypeTagClass else TypeTagClass
+ val tagTpe = singleType(prefix.tpe, prefix.tpe member tagClass.name)
+
+ // [Eugene] this should be enough for an abstract type, right?
+ val key = (tagClass, tpe.typeSymbol)
+ if (reifyDebug && spliceCache.contains(key)) println("cache hit: " + spliceCache(key))
+ val result = spliceCache.getOrElseUpdate(key, {
+ // if this fails, it might produce the dreaded "erroneous or inaccessible type" error
+ // to find out the whereabouts of the error run scalac with -Ydebug
+ if (reifyDebug) println("launching implicit search for %s.%s[%s]".format(prefix, tagClass.name, tpe))
+ typer.resolveTypeTag(prefix.tpe, tpe, defaultErrorPosition, concrete) match {
+ case failure if failure.isEmpty =>
+ if (reifyDebug) println("implicit search was fruitless")
+ EmptyTree
+ case success =>
+ if (reifyDebug) println("implicit search has produced a result: " + success)
+ reificationIsConcrete &= concrete
+ var splice = Select(success, nme.tpe)
+ splice match {
+ case InlinedTypeSplice(_, inlinedSymbolTable, tpe) =>
+ // all free vars local to the enclosing reifee should've already been inlined by ``Metalevels''
+ inlinedSymbolTable collect { case freedef @ FreeDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => assert(false, freedef) }
+ symbolTable ++= inlinedSymbolTable
+ reifyTrace("inlined the splicee: ")(tpe)
+ case tpe =>
+ tpe
+ }
+ }
+ })
+ if (result != EmptyTree) return result.duplicate
+ } else {
+ if (reifyDebug) println("splicing has been cancelled: spliceTypesEnabled = false")
+ }
+
+ reificationIsConcrete = false
+ }
+
+ spliceTypesEnabled = true
+ EmptyTree
+ }
+
+ /** Reify an annotated type, i.e. the one that makes us deal with AnnotationInfos */
+ private def reifyAnnotatedType(tpe: AnnotatedType): Tree = {
+ val AnnotatedType(anns, underlying, selfsym) = tpe
+ mirrorFactoryCall(nme.AnnotatedType, mkList(anns map reifyAnnotationInfo), reify(underlying), reify(selfsym))
+ }
+
+ /** Reify a tough type, i.e. the one that leads to creation of auxiliary symbols */
+ private def reifyToughType(tpe: Type): Tree = {
+ if (reifyDebug) println("tough type: %s (%s)".format(tpe, tpe.kind))
+
+ def reifyScope(scope: Scope): Tree = {
+ scope foreach reifySymDef
+ mirrorCall(nme.newScopeWith, scope.toList map reify: _*)
+ }
+
+ tpe match {
+ case tpe @ RefinedType(parents, decls) =>
+ reifySymDef(tpe.typeSymbol)
+ mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol))
+ case tpe @ ExistentialType(tparams, underlying) =>
+ tparams foreach reifySymDef
+ mirrorFactoryCall(tpe, reify(tparams), reify(underlying))
+ case tpe @ ClassInfoType(parents, decls, clazz) =>
+ reifySymDef(clazz)
+ mirrorFactoryCall(tpe, reify(parents), reifyScope(decls), reify(tpe.typeSymbol))
+ case tpe @ MethodType(params, restpe) =>
+ params foreach reifySymDef
+ mirrorFactoryCall(tpe, reify(params), reify(restpe))
+ case tpe @ PolyType(tparams, underlying) =>
+ tparams foreach reifySymDef
+ mirrorFactoryCall(tpe, reify(tparams), reify(underlying))
+ case _ =>
+ throw new Error("internal error: %s (%s) is not supported".format(tpe, tpe.kind))
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/codegen/Util.scala b/src/compiler/scala/reflect/reify/codegen/Util.scala
new file mode 100644
index 0000000000..bb369a1adb
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/codegen/Util.scala
@@ -0,0 +1,112 @@
+package scala.reflect.reify
+package codegen
+
+trait Util {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ val reifyDebug = settings.Yreifydebug.value
+ val reifyCopypaste = settings.Yreifycopypaste.value
+ val reifyTrace = scala.tools.nsc.util.trace when reifyDebug
+ object reifiedNodePrinters extends { val global: mirror.type = mirror } with tools.nsc.ast.NodePrinters with NodePrinters
+ val reifiedNodeToString = reifiedNodePrinters.reifiedNodeToString
+
+ def reifyList(xs: List[Any]): Tree =
+ mkList(xs map reify)
+
+ def reifyProduct(x: Product): Tree =
+ reifyProduct(x.productPrefix, x.productIterator.toList)
+
+ def reifyProduct(prefix: String, elements: List[Any]): Tree = {
+ // reflection would be more robust, but, hey, this is a hot path
+ if (prefix.startsWith("Tuple")) scalaFactoryCall(prefix, (elements map reify).toList: _*)
+ else mirrorCall(prefix, (elements map reify): _*)
+ }
+
+ // helper functions
+
+ /** Reify a case object defined in Mirror */
+ def reifyMirrorObject(name: String): Tree =
+ mirrorSelect(name)
+
+ def reifyMirrorObject(x: Product): Tree =
+ reifyMirrorObject(x.productPrefix)
+
+ def call(fname: String, args: Tree*): Tree =
+ Apply(termPath(fname), args.toList)
+
+ def mirrorSelect(name: String): Tree =
+ termPath(nme.MIRROR_PREFIX + name)
+
+ def mirrorCall(name: TermName, args: Tree*): Tree =
+ call("" + (nme.MIRROR_PREFIX append name), args: _*)
+
+ def mirrorCall(name: String, args: Tree*): Tree =
+ call(nme.MIRROR_PREFIX + name, args: _*)
+
+ def mirrorFactoryCall(value: Product, args: Tree*): Tree =
+ mirrorFactoryCall(value.productPrefix, args: _*)
+
+ def mirrorFactoryCall(prefix: String, args: Tree*): Tree =
+ mirrorCall(prefix, args: _*)
+
+ def scalaFactoryCall(name: String, args: Tree*): Tree =
+ call("scala." + name + ".apply", args: _*)
+
+ def mkList(args: List[Tree]): Tree =
+ scalaFactoryCall("collection.immutable.List", args: _*)
+
+ /**
+ * An (unreified) path that refers to definition with given fully qualified name
+ * @param mkName Creator for last portion of name (either TermName or TypeName)
+ */
+ def path(fullname: String, mkName: String => Name): Tree = {
+ val parts = fullname split "\\."
+ val prefixParts = parts.init
+ val lastName = mkName(parts.last)
+ if (prefixParts.isEmpty) Ident(lastName)
+ else {
+ val prefixTree = ((Ident(prefixParts.head): Tree) /: prefixParts.tail)(Select(_, _))
+ Select(prefixTree, lastName)
+ }
+ }
+
+ /** An (unreified) path that refers to term definition with given fully qualified name */
+ def termPath(fullname: String): Tree = path(fullname, newTermName)
+
+ /** An (unreified) path that refers to type definition with given fully qualified name */
+ def typePath(fullname: String): Tree = path(fullname, newTypeName)
+
+ def isTough(tpe: Type) = {
+ def isTough(tpe: Type) = tpe match {
+ case _: RefinedType => true
+ case _: ExistentialType => true
+ case _: ClassInfoType => true
+ case _: MethodType => true
+ case _: PolyType => true
+ case _ => false
+ }
+
+ tpe != null && (tpe exists isTough)
+ }
+
+ def isAnnotated(tpe: Type) = {
+ def isAnnotated(tpe: Type) = tpe match {
+ case _: AnnotatedType => true
+ case _ => false
+ }
+
+ tpe != null && (tpe exists isAnnotated)
+ }
+
+ def origin(sym: Symbol) = {
+ var origin = ""
+ if (sym.owner != NoSymbol) origin += "defined by %s".format(sym.owner.name)
+ if (sym.pos != NoPosition) origin += " in %s:%s:%s".format(sym.pos.source.file.name, sym.pos.line, sym.pos.column)
+ if (origin == "") origin = "of unknown origin"
+ origin
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/package.scala b/src/compiler/scala/reflect/reify/package.scala
new file mode 100644
index 0000000000..a096e2e93b
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/package.scala
@@ -0,0 +1,59 @@
+package scala.reflect
+
+import scala.tools.nsc.Global
+import scala.reflect.makro.ReificationError
+import scala.reflect.makro.UnexpectedReificationError
+
+package object reify {
+ private def mkReifier(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, reifee: Any, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Reifier { val mirror: global.type } = {
+ val typer1: typer.type = typer
+ val prefix1: prefix.type = prefix
+ val reifee1 = reifee
+ val dontSpliceAtTopLevel1 = dontSpliceAtTopLevel
+ val concrete1 = concrete
+
+ new {
+ val mirror: global.type = global
+ val typer = typer1
+ val prefix = prefix1
+ val reifee = reifee1
+ val dontSpliceAtTopLevel = dontSpliceAtTopLevel1
+ val concrete = concrete1
+ } with Reifier
+ }
+
+ def reifyTree(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tree: global.Tree): global.Tree =
+ mkReifier(global)(typer, prefix, tree, false, false).reified.asInstanceOf[global.Tree]
+
+ def reifyType(global: Global)(typer: global.analyzer.Typer, prefix: global.Tree, tpe: global.Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): global.Tree =
+ mkReifier(global)(typer, prefix, tpe, dontSpliceAtTopLevel, concrete).reified.asInstanceOf[global.Tree]
+
+ def reifyErasure(global: Global)(typer0: global.analyzer.Typer, tpe: global.Type, concrete: Boolean = true): global.Tree = {
+ import global._
+ import definitions._
+ import analyzer.enclosingMacroPosition
+
+ def erasureTagInScope = typer0.context.withMacrosDisabled(typer0.resolveErasureTag(tpe, enclosingMacroPosition, concrete = concrete))
+ def arrayTagInScope = typer0.context.withMacrosDisabled(typer0.resolveArrayTag(tpe, enclosingMacroPosition))
+ val inScope = (erasureTagInScope, arrayTagInScope)
+
+ inScope match {
+ case (success, _) if !success.isEmpty =>
+ Select(success, nme.erasure)
+ case (_, success) if !success.isEmpty =>
+ gen.mkMethodCall(arrayElementClassMethod, List(success))
+ case _ =>
+ tpe.normalize match {
+ case TypeRef(_, ArrayClass, componentTpe :: Nil) =>
+ val componentErasure = reifyErasure(global)(typer0, componentTpe, concrete)
+ gen.mkMethodCall(arrayClassMethod, List(componentErasure))
+ case _ =>
+ if (tpe.isSpliceable && concrete)
+ throw new ReificationError(enclosingMacroPosition, "tpe %s is an unresolved spliceable type".format(tpe))
+ var erasure = tpe.erasure
+ if (tpe.typeSymbol.isDerivedValueClass && global.phase.id < global.currentRun.erasurePhase.id) erasure = tpe
+ gen.mkNullaryCall(Predef_classOf, List(erasure))
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/reflect/reify/phases/Calculate.scala b/src/compiler/scala/reflect/reify/phases/Calculate.scala
new file mode 100644
index 0000000000..93ef46472e
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/phases/Calculate.scala
@@ -0,0 +1,60 @@
+package scala.reflect.reify
+package phases
+
+trait Calculate {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ implicit class RichSymbol(sym: Symbol) {
+ def metalevel: Int = { assert(sym != NoSymbol); localSymbols.getOrElse(sym, 0) }
+ def isLocalToReifee = (localSymbols contains sym) // [Eugene] how do I account for local skolems?
+ }
+
+ implicit class RichType(tpe: Type) {
+ def isLocalToReifee = tpe != null && (tpe exists (tp => (localSymbols contains tp.typeSymbol) || (localSymbols contains tp.termSymbol)))
+ }
+
+ private var localSymbols = collection.mutable.Map[Symbol, Int]() // set of all symbols that are local to the tree to be reified
+ private def registerLocalSymbol(sym: Symbol, metalevel: Int): Unit =
+ if (sym != null && sym != NoSymbol) {
+ if (localSymbols contains sym)
+ assert(localSymbols(sym) == metalevel, "metalevel mismatch: expected %s, actual %s".format(localSymbols(sym), metalevel))
+ localSymbols(sym) = metalevel
+ }
+
+ /**
+ * Merely traverses the reifiee and records local symbols along with their metalevels.
+ */
+ val calculate = new Traverser {
+ // see the explanation of metalevels in ``Metalevels''
+ var currMetalevel = 1
+
+ override def traverse(tree: Tree): Unit = tree match {
+ case TreeSplice(_) =>
+ currMetalevel -= 1
+ try super.traverse(tree)
+ finally currMetalevel += 1
+ case tree if tree.isDef =>
+ if (reifyDebug) println("boundSym: %s of type %s".format(tree.symbol, (tree.productIterator.toList collect { case tt: TypeTree => tt } headOption).getOrElse(TypeTree(tree.tpe))))
+ registerLocalSymbol(tree.symbol, currMetalevel)
+
+ bindRelatedSymbol(tree.symbol.sourceModule, "sourceModule")
+ bindRelatedSymbol(tree.symbol.moduleClass, "moduleClass")
+ bindRelatedSymbol(tree.symbol.companionClass, "companionClass")
+ bindRelatedSymbol(tree.symbol.companionModule, "companionModule")
+ Some(tree.symbol) collect { case termSymbol: TermSymbol => bindRelatedSymbol(termSymbol.referenced, "referenced") }
+ Some(tree) collect { case labelDef: LabelDef => labelDef.params foreach (param => bindRelatedSymbol(param.symbol, "labelParam")) }
+ def bindRelatedSymbol(related: Symbol, name: String): Unit =
+ if (related != null && related != NoSymbol) {
+ if (reifyDebug) println("boundSym (" + name + "): " + related)
+ registerLocalSymbol(related, currMetalevel)
+ }
+ super.traverse(tree)
+ case _ =>
+ super.traverse(tree)
+ }
+ }
+}
diff --git a/src/compiler/scala/reflect/reify/phases/Metalevels.scala b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
new file mode 100644
index 0000000000..206f3b1118
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/phases/Metalevels.scala
@@ -0,0 +1,150 @@
+package scala.reflect.reify
+package phases
+
+trait Metalevels {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ /**
+ * Makes sense of cross-stage bindings.
+ *
+ * ================
+ *
+ * Analysis of cross-stage bindings becomes convenient if we introduce the notion of metalevels.
+ * Metalevel of a tree is a number that gets incremented every time you reify something and gets decremented when you splice something.
+ * Metalevel of a symbol is equal to the metalevel of its definition.
+ *
+ * Example 1. Consider the following snippet:
+ *
+ * reify {
+ * val x = 2 // metalevel of symbol x is 1, because it's declared inside reify
+ * val y = reify{x} // metalevel of symbol y is 1, because it's declared inside reify
+ * // metalevel of Ident(x) is 2, because it's inside two reifies
+ * y.eval // metalevel of Ident(y) is 0, because it's inside a designator of a splice
+ * }
+ *
+ * Cross-stage bindings are introduced when symbol.metalevel != curr_metalevel.
+ * Both bindings introduced in Example 1 are cross-stage.
+ *
+ * Depending on what side of the inequality is greater, the following situations might occur:
+ *
+ * 1) symbol.metalevel < curr_metalevel. In this case reifier will generate a free variable
+ * that captures both the name of the symbol (to be compiled successfully) and its value (to be run successfully).
+ * For example, x in Example 1 will be reified as follows: Ident(newFreeVar("x", IntClass.tpe, x))
+ *
+ * 2) symbol.metalevel > curr_metalevel. This leads to a metalevel breach that violates intuitive perception of splicing.
+ * As defined in macro spec, splicing takes a tree and inserts it into another tree - as simple as that.
+ * However, how exactly do we do that in the case of y.eval? In this very scenario we can use dataflow analysis and inline it,
+ * but what if y were a var, and what if it were calculated randomly at runtime?
+ *
+ * This question has a genuinely simple answer. Sure, we cannot resolve such splices statically (i.e. during macro expansion of ``reify''),
+ * but now we have runtime toolboxes, so noone stops us from picking up that reified tree and evaluating it at runtime
+ * (in fact, this is something that ``Expr.eval'' and ``Expr.value'' do transparently).
+ *
+ * This is akin to early vs late binding dilemma.
+ * The prior is faster, plus, the latter (implemented with reflection) might not work because of visibility issues or might be not available on all platforms.
+ * But the latter still has its uses, so I'm allowing metalevel breaches, but introducing the -Xlog-runtime-evals to log them.
+ *
+ * ================
+ *
+ * As we can see, the only problem is the fact that lhs'es of eval can be code blocks that can capture variables from the outside.
+ * Code inside the lhs of an eval is not reified, while the code from the enclosing reify is.
+ *
+ * Hence some bindings become cross-stage, which is not bad per se (in fact, some cross-stage bindings have sane semantics, as in the example above).
+ * However this affects freevars, since they are delicate inter-dimensional beings that refer to both current and next planes of existence.
+ * When splicing tears the fabric of the reality apart, some freevars have to go single-dimensional to retain their sanity.
+ *
+ * Example 2. Consider the following snippet:
+ *
+ * reify {
+ * val x = 2
+ * reify{x}.eval
+ * }
+ *
+ * Since the result of the inner reify is wrapped in an eval, it won't be reified
+ * together with the other parts of the outer reify, but will be inserted into that result verbatim.
+ *
+ * The inner reify produces an Expr[Int] that wraps Ident(freeVar("x", IntClass.tpe, x)).
+ * However the freevar the reification points to will vanish when the compiler processes the outer reify.
+ * That's why we need to replace that freevar with a regular symbol that will point to reified x.
+ *
+ * Example 3. Consider the following fragment:
+ *
+ * reify {
+ * val x = 2
+ * val y = reify{x}
+ * y.eval
+ * }
+ *
+ * In this case the inner reify doesn't appear next to eval, so it will be reified together with x.
+ * This means that no special processing is needed here.
+ *
+ * Example 4. Consider the following fragment:
+ *
+ * reify {
+ * val x = 2
+ * {
+ * val y = 2
+ * val z = reify{reify{x + y}}
+ * z.eval
+ * }.eval
+ * }
+ *
+ * The reasoning from Example 2 still holds here - we do need to inline the freevar that refers to x.
+ * However, we must not touch anything inside the eval'd block, because it's not getting reified.
+ */
+ var metalevels = new Transformer {
+ var insideSplice = false
+ var freedefsToInline = collection.mutable.Map[String, ValDef]()
+
+ def withinSplice[T](op: => T) = {
+ val old = insideSplice
+ insideSplice = true
+ try op
+ finally insideSplice = old
+ }
+
+ // Q: here we deal with all sorts of reified trees. what about ReifiedType(_, _, _, _)?
+ // A: nothing. reified trees give us problems because they sometimes create dimensional rifts as described above
+ // to the contrast, reified types (i.e. synthetic typetags materialized by Implicits.scala) always stay on the same metalevel as their enclosing code
+ override def transform(tree: Tree): Tree = tree match {
+ case InlineableTreeSplice(splicee, inlinedSymbolTable, _, _, flavor) =>
+ if (reifyDebug) println("entering inlineable splice: " + splicee)
+ val Block(mrDef :: symbolTable, expr) = splicee
+ // [Eugene] how to express the fact that a scrutinee is both of some type and matches an extractor?
+ val freedefsToInline = symbolTable collect { case freedef @ FreeTermDef(_, _, binding, _, _) if binding.symbol.isLocalToReifee => freedef.asInstanceOf[ValDef] }
+ freedefsToInline foreach (vdef => this.freedefsToInline(vdef.name) = vdef)
+ val symbolTable1 = symbolTable diff freedefsToInline
+ val tree1 = Select(Block(mrDef :: symbolTable1, expr), flavor)
+ if (reifyDebug) println("trimmed %s inlineable free defs from its symbol table: %s".format(freedefsToInline.length, freedefsToInline map (_.name) mkString(", ")))
+ withinSplice { super.transform(tree1) }
+ case TreeSplice(splicee) =>
+ if (reifyDebug) println("entering splice: " + splicee)
+ val hasBreaches = splicee exists (_.symbol.metalevel > 0)
+ if (!insideSplice && hasBreaches) {
+ if (settings.logRuntimeSplices.value) reporter.echo(tree.pos, "this splice cannot be resolved statically")
+ if (reifyDebug) println("metalevel breach in %s: %s".format(tree, (splicee filter (_.symbol.metalevel > 0) map (_.symbol) distinct) mkString ", "))
+ }
+ withinSplice { super.transform(tree) }
+ // todo. also inline usages of ``freedefsToInline'' in the symbolTable itself
+ // e.g. a free$Foo can well use free$x, if Foo is path-dependent w.r.t x
+ // FreeRef(_, _) check won't work, because metalevels of symbol table and body are different, hence, freerefs in symbol table look different from freerefs in body
+ // todo. also perform garbage collection on local symbols
+ // so that local symbols used only in type signatures of free vars get removed
+ // todo. same goes for auxiliary symbol defs reified to support tough types
+ // some of them need to be rebuilt, some of them need to be removed, because they're no longer necessary
+ case FreeRef(mr, name) if freedefsToInline contains name =>
+ if (reifyDebug) println("inlineable free ref: %s in %s".format(name, showRaw(tree)))
+ val freedef @ FreeDef(_, _, binding, _, _) = freedefsToInline(name)
+ if (reifyDebug) println("related definition: %s".format(showRaw(freedef)))
+ val inlined = reify(binding)
+ if (reifyDebug) println("verdict: inlined as %s".format(showRaw(inlined)))
+ inlined
+ case _ =>
+ super.transform(tree)
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/phases/Reify.scala b/src/compiler/scala/reflect/reify/phases/Reify.scala
new file mode 100644
index 0000000000..e03ff5832c
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/phases/Reify.scala
@@ -0,0 +1,65 @@
+package scala.reflect.reify
+package phases
+
+import scala.runtime.ScalaRunTime.isAnyVal
+import scala.runtime.ScalaRunTime.isTuple
+import scala.reflect.reify.codegen._
+
+trait Reify extends Symbols
+ with Types
+ with Names
+ with Trees
+ with AnnotationInfos
+ with Positions
+ with Util {
+
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ // `reify` looked so nice, I wanted to push the last bit of orthogonal
+ // logic out of it so you can see the improvement. There is no cost to
+ // wrapper methods of this form because the inliner will eliminate them,
+ // but they are very good at separating concerns like pushing/popping
+ // a stack, and they are great for composition and reuse.
+ //
+ // Also, please avoid public vars whenever possible.
+ private object reifyStack {
+ var currents: List[Any] = reifee :: Nil
+
+ @inline final def push[T](reifee: Any)(body: => T): T = {
+ currents ::= reifee
+ try body
+ finally currents = currents.tail
+ }
+ }
+ def currentQuantified = flatCollect(reifyStack.currents)({ case ExistentialType(quantified, _) => quantified })
+ def current = reifyStack.currents.head
+
+ /**
+ * Reifies any supported value.
+ * For internal use only, use ``reified'' instead.
+ */
+ def reify(reifee: Any): Tree = reifyStack.push(reifee)(reifee match {
+ // before adding some case here, in global scope, please, consider
+ // whether it can be localized like reifyAnnotationInfo or reifyScope
+ // this will help reification stay as sane as possible
+ case sym: Symbol => reifySymRef(sym)
+ case tpe: Type => reifyType(tpe)
+ case name: Name => reifyName(name)
+ case tree: Tree => reifyTree(tree)
+ // disabled because this is a very special case that I plan to remove later
+ // why do I dislike annotations? see comments to `reifyAnnotationInfo`
+// case ann: AnnotationInfo => reifyAnnotationInfo(ann)
+ case pos: Position => reifyPosition(pos)
+ case mods: mirror.Modifiers => reifyModifiers(mods)
+ case xs: List[_] => reifyList(xs)
+ case s: String => Literal(Constant(s))
+ case v if isAnyVal(v) => Literal(Constant(v))
+ case null => Literal(Constant(null))
+ case _ =>
+ throw new Error("reifee %s of type %s is not supported".format(reifee, reifee.getClass))
+ })
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/reify/phases/Reshape.scala b/src/compiler/scala/reflect/reify/phases/Reshape.scala
new file mode 100644
index 0000000000..4ab306a13f
--- /dev/null
+++ b/src/compiler/scala/reflect/reify/phases/Reshape.scala
@@ -0,0 +1,290 @@
+package scala.reflect.reify
+package phases
+
+import scala.tools.nsc.symtab.Flags._
+
+trait Reshape {
+ self: Reifier =>
+
+ import mirror._
+ import definitions._
+ import treeInfo._
+
+ /**
+ * Rolls back certain changes that were introduced during typechecking of the reifee.
+ *
+ * These include:
+ * * Replacing type trees with TypeTree(tpe)
+ * * Transforming Modifiers.annotations into Symbol.annotations
+ * * Transforming Annotated annotations into AnnotatedType annotations
+ * * Transforming Annotated(annot, expr) into Typed(expr, TypeTree(Annotated(annot, _))
+ * * Non-idempotencies of the typechecker: https://issues.scala-lang.org/browse/SI-5464
+ */
+ val reshape = new Transformer {
+ var currentSymbol: Symbol = NoSymbol
+
+ override def transform(tree: Tree) = {
+ currentSymbol = tree.symbol
+
+ val preTyper = tree match {
+ case tree if tree.isErroneous =>
+ tree
+ case tt @ TypeTree() =>
+ toPreTyperTypeTree(tt)
+ case toa @ TypedOrAnnotated(_) =>
+ toPreTyperTypedOrAnnotated(toa)
+ case ta @ TypeApply(hk, ts) =>
+ val discard = ts collect { case tt: TypeTree => tt } exists isDiscarded
+ if (reifyDebug && discard) println("discarding TypeApply: " + tree)
+ if (discard) hk else ta
+ case classDef @ ClassDef(mods, name, params, impl) =>
+ val Template(parents, self, body) = impl
+ var body1 = trimAccessors(classDef, body)
+ body1 = trimSyntheticCaseClassMembers(classDef, body1)
+ var impl1 = Template(parents, self, body1).copyAttrs(impl)
+ ClassDef(mods, name, params, impl1).copyAttrs(classDef)
+ case moduledef @ ModuleDef(mods, name, impl) =>
+ val Template(parents, self, body) = impl
+ var body1 = trimAccessors(moduledef, body)
+ body1 = trimSyntheticCaseClassMembers(moduledef, body1)
+ var impl1 = Template(parents, self, body1).copyAttrs(impl)
+ ModuleDef(mods, name, impl1).copyAttrs(moduledef)
+ case template @ Template(parents, self, body) =>
+ val discardedParents = parents collect { case tt: TypeTree => tt } filter isDiscarded
+ if (reifyDebug && discardedParents.length > 0) println("discarding parents in Template: " + discardedParents.mkString(", "))
+ val parents1 = parents diff discardedParents
+ val body1 = trimSyntheticCaseClassCompanions(body)
+ Template(parents1, self, body1).copyAttrs(template)
+ case block @ Block(stats, expr) =>
+ val stats1 = trimSyntheticCaseClassCompanions(stats)
+ Block(stats1, expr).copyAttrs(block)
+ case valdef @ ValDef(mods, name, tpt, rhs) if valdef.symbol.isLazy =>
+ if (reifyDebug) println("dropping $lzy in lazy val's name: " + tree)
+ val name1 = if (name endsWith nme.LAZY_LOCAL) name dropRight nme.LAZY_LOCAL.length else name
+ ValDef(mods, name1, tpt, rhs).copyAttrs(valdef)
+ case unapply @ UnApply(fun, args) =>
+ def extractExtractor(tree: Tree): Tree = {
+ val Apply(fun, args) = tree
+ args match {
+ case List(Ident(special)) if special == nme.SELECTOR_DUMMY =>
+ val Select(extractor, flavor) = fun
+ assert(flavor == nme.unapply || flavor == nme.unapplySeq)
+ extractor
+ case _ =>
+ extractExtractor(fun)
+ }
+ }
+
+ if (reifyDebug) println("unapplying unapply: " + tree)
+ val fun1 = extractExtractor(fun)
+ Apply(fun1, args).copyAttrs(unapply)
+ case _ =>
+ tree
+ }
+
+ super.transform(preTyper)
+ }
+
+ override def transformModifiers(mods: Modifiers) = {
+ val mods1 = toPreTyperModifiers(mods, currentSymbol)
+ super.transformModifiers(mods1)
+ }
+
+ private def toPreTyperModifiers(mods: Modifiers, sym: Symbol) = {
+ if (!sym.annotations.isEmpty) {
+ val Modifiers(flags, privateWithin, annotations) = mods
+ val postTyper = sym.annotations filter (_.original != EmptyTree)
+ if (reifyDebug && !postTyper.isEmpty) println("reify symbol annotations for: " + sym)
+ if (reifyDebug && !postTyper.isEmpty) println("originals are: " + sym.annotations)
+ val preTyper = postTyper map toPreTyperAnnotation
+ mods.withAnnotations(preTyper)
+ } else {
+ mods
+ }
+ }
+
+ /** Restore pre-typer representation of a type.
+ *
+ * NB: This is the trickiest part of reification!
+ *
+ * In most cases, we're perfectly fine to reify a Type itself (see ``reifyType'').
+ * However if the type involves a symbol declared inside the quasiquote (i.e. registered in ``boundSyms''),
+ * then we cannot reify it, or otherwise subsequent reflective compilation will fail.
+ *
+ * Why will it fail? Because reified deftrees (e.g. ClassDef(...)) will generate fresh symbols during that compilation,
+ * so naively reified symbols will become out of sync, which brings really funny compilation errors and/or crashes, e.g.:
+ * https://issues.scala-lang.org/browse/SI-5230
+ *
+ * To deal with this unpleasant fact, we need to fall back from types to equivalent trees (after all, parser trees don't contain any types, just trees, so it should be possible).
+ * Luckily, these original trees get preserved for us in the ``original'' field when Trees get transformed into TypeTrees.
+ * And if an original of a type tree is empty, we can safely assume that this type is non-essential (e.g. was inferred/generated by the compiler).
+ * In that case the type can be omitted (e.g. reified as an empty TypeTree), since it will be inferred again later on.
+ *
+ * An important property of the original is that it isn't just a pre-typer tree.
+ * It's actually kind of a post-typer tree with symbols assigned to its Idents (e.g. Ident("List") will contain a symbol that points to immutable.this.List).
+ * This is very important, since subsequent reflective compilation won't have to resolve these symbols.
+ * In general case, such resolution cannot be performed, since reification doesn't preserve lexical context,
+ * which means that reflective compilation won't be aware of, say, imports that were provided when the reifee has been compiled.
+ *
+ * This workaround worked surprisingly well and allowed me to fix several important reification bugs, until the abstraction has leaked.
+ * Suddenly I found out that in certain contexts original trees do not contain symbols, but are just parser trees.
+ * To the moment I know only one such situation: typedAnnotations does not typecheck the annotation in-place, but rather creates new trees and typechecks them, so the original remains symless.
+ * Thus we apply a workaround for that in typedAnnotated. I hope this will be the only workaround in this department.
+ *
+ * upd. Recently I went ahead and started using original for all TypeTrees, regardless of whether they refer to local symbols or not.
+ * As a result, ``reifyType'' is never called directly by tree reification (and, wow, it seems to work great!).
+ * The only usage of ``reifyType'' now is for servicing typetags, however, I have some ideas how to get rid of that as well.
+ */
+ private def isDiscarded(tt: TypeTree) = tt.original == null
+ private def toPreTyperTypeTree(tt: TypeTree): Tree = {
+ if (tt.original != null) {
+ // here we rely on the fact that the originals that reach this point
+ // have all necessary symbols attached to them (i.e. that they can be recompiled in any lexical context)
+ // if this assumption fails, please, don't be quick to add postprocessing here (like I did before)
+ // but rather try to fix this in Typer, so that it produces quality originals (like it's done for typedAnnotated)
+ if (reifyDebug) println("TypeTree, essential: %s (%s)".format(tt.tpe, tt.tpe.kind))
+ if (reifyDebug) println("verdict: rolled back to original %s".format(tt.original))
+ transform(tt.original)
+ } else {
+ // type is deemed to be non-essential
+ // erase it and hope that subsequent reflective compilation will be able to recreate it again
+ if (reifyDebug) println("TypeTree, non-essential: %s (%s)".format(tt.tpe, tt.tpe.kind))
+ if (reifyDebug) println("verdict: discarded")
+ TypeTree()
+ }
+ }
+
+ private def toPreTyperTypedOrAnnotated(tree: Tree): Tree = tree match {
+ case ty @ Typed(expr1, tt @ TypeTree()) =>
+ if (reifyDebug) println("reify typed: " + tree)
+ val annotatedArg = {
+ def loop(tree: Tree): Tree = tree match {
+ case annotated1 @ Annotated(ann, annotated2 @ Annotated(_, _)) => loop(annotated2)
+ case annotated1 @ Annotated(ann, arg) => arg
+ case _ => EmptyTree
+ }
+
+ loop(tt.original)
+ }
+ if (annotatedArg != EmptyTree) {
+ if (annotatedArg.isType) {
+ if (reifyDebug) println("verdict: was an annotated type, reify as usual")
+ ty
+ } else {
+ if (reifyDebug) println("verdict: was an annotated value, equivalent is " + tt.original)
+ toPreTyperTypedOrAnnotated(tt.original)
+ }
+ } else {
+ if (reifyDebug) println("verdict: wasn't annotated, reify as usual")
+ ty
+ }
+ case at @ Annotated(annot, arg) =>
+ if (reifyDebug) println("reify type annotations for: " + tree)
+ assert(at.tpe.isInstanceOf[AnnotatedType], "%s (%s)".format(at.tpe, at.tpe.kind))
+ val annot1 = toPreTyperAnnotation(at.tpe.asInstanceOf[AnnotatedType].annotations(0))
+ if (reifyDebug) println("originals are: " + annot1)
+ Annotated(annot1, arg).copyAttrs(at)
+ }
+
+ /** Restore pre-typer representation of an annotation.
+ * The trick here is to retain the symbols that have been populated during typechecking of the annotation.
+ * If we do not do that, subsequent reflective compilation will fail.
+ */
+ private def toPreTyperAnnotation(ann: AnnotationInfo): Tree = {
+ val args = if (ann.assocs.isEmpty) {
+ ann.args
+ } else {
+ def toScalaAnnotation(jann: ClassfileAnnotArg): Tree = jann match {
+ case LiteralAnnotArg(const) =>
+ Literal(const)
+ case ArrayAnnotArg(arr) =>
+ Apply(Ident(definitions.ArrayModule), arr.toList map toScalaAnnotation)
+ case NestedAnnotArg(ann) =>
+ toPreTyperAnnotation(ann)
+ }
+
+ ann.assocs map { case (nme, arg) => AssignOrNamedArg(Ident(nme), toScalaAnnotation(arg)) }
+ }
+
+ def extractOriginal: PartialFunction[Tree, Tree] = { case Apply(Select(New(tpt), _), _) => tpt }
+ assert(extractOriginal.isDefinedAt(ann.original), showRaw(ann.original))
+ New(TypeTree(ann.atp) setOriginal extractOriginal(ann.original), List(args))
+ }
+
+ // [Eugene] is this implemented correctly?
+ private def trimAccessors(deff: Tree, stats: List[Tree]): List[Tree] = {
+ val symdefs = stats collect { case vodef: ValOrDefDef => vodef } map (vodeff => vodeff.symbol -> vodeff) toMap
+ val accessors = collection.mutable.Map[ValDef, List[DefDef]]()
+ stats collect { case ddef: DefDef => ddef } foreach (defdef => {
+ val valdef = symdefs get defdef.symbol.accessedOrSelf collect { case vdef: ValDef => vdef } getOrElse null
+ if (valdef != null) accessors(valdef) = accessors.getOrElse(valdef, Nil) :+ defdef
+
+ def detectBeanAccessors(prefix: String): Unit = {
+ if (defdef.name.startsWith(prefix)) {
+ var name = defdef.name.toString.substring(prefix.length)
+ def uncapitalize(s: String) = if (s.length == 0) "" else { val chars = s.toCharArray; chars(0) = chars(0).toLower; new String(chars) }
+ def findValDef(name: String) = symdefs.values collect { case vdef: ValDef if nme.dropLocalSuffix(vdef.name).toString == name => vdef } headOption;
+ val valdef = findValDef(name) orElse findValDef(uncapitalize(name)) orNull;
+ if (valdef != null) accessors(valdef) = accessors.getOrElse(valdef, Nil) :+ defdef
+ }
+ }
+ detectBeanAccessors("get")
+ detectBeanAccessors("set")
+ detectBeanAccessors("is")
+ });
+
+ var stats1 = stats flatMap {
+ case vdef @ ValDef(mods, name, tpt, rhs) =>
+ val mods1 = if (accessors.contains(vdef)) {
+ val ddef = accessors(vdef)(0) // any accessor will do
+ val Modifiers(flags, privateWithin, annotations) = mods
+ var flags1 = flags & ~LOCAL
+ if (!ddef.symbol.isPrivate) flags1 = flags1 & ~PRIVATE
+ val privateWithin1 = ddef.mods.privateWithin
+ val annotations1 = accessors(vdef).foldLeft(annotations)((curr, acc) => curr ++ (acc.symbol.annotations map toPreTyperAnnotation))
+ Modifiers(flags1, privateWithin1, annotations1) setPositions mods.positions
+ } else {
+ mods
+ }
+ val mods2 = toPreTyperModifiers(mods1, vdef.symbol)
+ val name1 = nme.dropLocalSuffix(name)
+ val vdef1 = ValDef(mods2, name1, tpt, rhs)
+ if (reifyDebug) println("resetting visibility of field: %s => %s".format(vdef, vdef1))
+ Some(vdef1) // no copyAttrs here, because new ValDef and old symbols are not out of sync
+ case ddef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ if (accessors.values.exists(_.contains(ddef))) {
+ if (reifyDebug) println("discarding accessor method: " + ddef)
+ None
+ } else {
+ Some(ddef)
+ }
+ case tree =>
+ Some(tree)
+ }
+
+ stats1
+ }
+
+ private def trimSyntheticCaseClassMembers(deff: Tree, stats: List[Tree]): List[Tree] =
+ stats filterNot (memberDef => memberDef.isDef && {
+ val isSynthetic = memberDef.symbol.isSynthetic
+ // this doesn't work for local classes, e.g. for ones that are top-level to a quasiquote (see comments to companionClass)
+ // that's why I replace the check with an assumption that all synthetic members are, in fact, generated of case classes
+ // val isCaseMember = deff.symbol.isCaseClass || deff.symbol.companionClass.isCaseClass
+ val isCaseMember = true
+ if (isSynthetic && isCaseMember && reifyDebug) println("discarding case class synthetic def: " + memberDef)
+ isSynthetic && isCaseMember
+ })
+
+ private def trimSyntheticCaseClassCompanions(stats: List[Tree]): List[Tree] =
+ stats diff (stats collect { case moddef: ModuleDef => moddef } filter (moddef => {
+ val isSynthetic = moddef.symbol.isSynthetic
+ // this doesn't work for local classes, e.g. for ones that are top-level to a quasiquote (see comments to companionClass)
+ // that's why I replace the check with an assumption that all synthetic modules are, in fact, companions of case classes
+ // val isCaseCompanion = moddef.symbol.companionClass.isCaseClass
+ val isCaseCompanion = true
+ if (isSynthetic && isCaseCompanion && reifyDebug) println("discarding synthetic case class companion: " + moddef)
+ isSynthetic && isCaseCompanion
+ }))
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/AbstractFile.scala b/src/compiler/scala/reflect/runtime/AbstractFile.scala
index bf3b47298b..414bba020b 100644
--- a/src/compiler/scala/reflect/runtime/AbstractFile.scala
+++ b/src/compiler/scala/reflect/runtime/AbstractFile.scala
@@ -1,6 +1,7 @@
-package scala.reflect.runtime
+package scala.reflect
+package runtime
-class AbstractFile(val jfile: java.io.File) {
- def path: String = jfile.getPath()
- def canonicalPath: String = jfile.getCanonicalPath()
-} \ No newline at end of file
+class AbstractFile(val jfile: java.io.File) extends api.RequiredFile {
+ def path: String = jfile.getPath()
+ def canonicalPath: String = jfile.getCanonicalPath()
+}
diff --git a/src/compiler/scala/reflect/runtime/ClassLoaders.scala b/src/compiler/scala/reflect/runtime/ClassLoaders.scala
new file mode 100644
index 0000000000..b73d57c04d
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/ClassLoaders.scala
@@ -0,0 +1,25 @@
+package scala.reflect
+package runtime
+
+trait ClassLoaders extends internal.SymbolTable { self: SymbolTable =>
+
+ def staticClass(fullname: String) =
+ definitions.getRequiredClass(fullname)
+
+ def staticModule(fullname: String) =
+ definitions.getRequiredModule(fullname)
+
+ /** If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package
+ * <owner>.<name>, otherwise return NoSymbol.
+ * Exception: If owner is root and a java class with given name exists, create symbol in empty package instead.
+ */
+ override def missingHook(owner: Symbol, name: Name): Symbol =
+ if (owner.isRoot && isJavaClass(name.toString))
+ definitions.EmptyPackageClass.info decl name
+ else if (name.isTermName && owner.hasPackageFlag && !owner.isEmptyPackageClass)
+ makeScalaPackage(if (owner.isRoot) name.toString else owner.fullName+"."+name).sourceModule
+ else {
+ info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass)
+ super.missingHook(owner, name)
+ }
+}
diff --git a/src/compiler/scala/reflect/runtime/ConversionUtil.scala b/src/compiler/scala/reflect/runtime/ConversionUtil.scala
index 8c32026e37..e45fc243c6 100644
--- a/src/compiler/scala/reflect/runtime/ConversionUtil.scala
+++ b/src/compiler/scala/reflect/runtime/ConversionUtil.scala
@@ -12,6 +12,7 @@ trait ConversionUtil { self: SymbolTable =>
/** A cache that maintains a bijection between Java reflection type `J`
* and Scala reflection type `S`.
*/
+ // todo. should be weak
protected class TwoWayCache[J, S] {
private val toScalaMap = new HashMap[J, S]
diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala
index 89fd6bab64..e11f6140c9 100644
--- a/src/compiler/scala/reflect/runtime/JavaToScala.scala
+++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala
@@ -34,16 +34,42 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
val global: JavaToScala.this.type = self
}
- protected def defaultReflectiveClassLoader(): JClassLoader = {
- val cl = Thread.currentThread.getContextClassLoader
- if (cl == null) getClass.getClassLoader else cl
- }
+ /** Defines the classloader that will be used for all class resolution activities in this mirror.
+ * Is mutable, since sometimes we need to change it in flight (e.g. to make the default mirror work with REPL).
+ *
+ * If you want to have a mirror with non-standard class resolution, override this var
+ * (or, even simpler, use the `mkMirror` function from `scala.reflect` package)
+ *
+ * Be careful, though, since fancy stuff might happen.
+ * Here's one example:
+ *
+ * partest uses a URLClassLoader(urls, null) with custom classpath to run workers (in separate threads)
+ * however it doesn't set the context classloader for them, so they inherit the system classloader
+ * http://www.javaworld.com/javaworld/javaqa/2003-06/01-qa-0606-load.html
+ *
+ * Once upon a time, scala.reflect.mirror was loaded using getClass.getClassLoader,
+ * which also means that classOf[...] constructs such as:
+ *
+ * classOf[scala.reflect.ScalaSignature]
+ *
+ * in unpickleClass were also loaded by the URLClassLoader
+ *
+ * But mirror's classLoader used Thread.currentThread.getContextClassLoader,
+ * which introduced a subtle bug that made the following snippet incorrectly:
+ *
+ * jclazz.getAnnotation(classOf[scala.reflect.ScalaSignature])
+ *
+ * Indeed, jclazz was loaded by context classloader, which defaulted to system classloader,
+ * while ScalaSignature class was loaded by getClass.getClassLoader, which was incompatible with system classloader.
+ * As a result, unpickler couldn't see the signature and that blew up the mirror.
+ */
+ var classLoader: ClassLoader
/** Paul: It seems the default class loader does not pick up root classes, whereas the system classloader does.
* Can you check with your newly acquired classloader fu whether this implementation makes sense?
*/
def javaClass(path: String): jClass[_] =
- javaClass(path, defaultReflectiveClassLoader())
+ javaClass(path, classLoader)
def javaClass(path: String, classLoader: JClassLoader): jClass[_] =
Class.forName(path, true, classLoader)
@@ -75,19 +101,70 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
(if (msg eq null) "reflection error while loading " + clazz.name
else "error while loading " + clazz.name) + ", " + msg)
}
- try {
- markAbsent(NoType)
- val ssig = jclazz.getAnnotation(classOf[scala.reflect.ScalaSignature])
+ // don't use classOf[scala.reflect.ScalaSignature] here, because it will use getClass.getClassLoader, not mirror's classLoader
+ // don't use asInstanceOf either because of the same reason (lol, I cannot believe I fell for it)
+ // don't use structural types to simplify reflective invocations because of the same reason
+ // todo. test for this
+ def loadAnnotation(name: String): java.lang.annotation.Annotation = {
+ def inferClasspath(cl: ClassLoader) = cl match {
+ case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
+ case _ => "<unknown>"
+ }
+ def show(cl: ClassLoader) = cl match {
+ case cl if cl != null =>
+ "%s of type %s with classpath %s".format(cl, cl.getClass, inferClasspath(cl))
+ case null =>
+ import scala.tools.util.PathResolver.Environment._
+ "primordial classloader with boot classpath [%s]".format(javaBootClassPath)
+ }
+
+ try {
+ val cls_ann = Class.forName(name, true, classLoader)
+ val anns = jclazz.getAnnotations
+ val ann = anns find (_.annotationType == cls_ann) orNull;
+ if (ann == null && anns.find(_.annotationType.getName == name).isDefined) {
+ val msg = "Mirror classloader mismatch: %s (loaded by %s)%nis unrelated to the mirror's classloader (%s)"
+ throw new Error(msg.format(jclazz, show(jclazz.getClassLoader), show(classLoader)))
+ }
+ ann
+ } catch {
+ case ex: ClassNotFoundException =>
+ val msg = "Dysfunctional mirror classloader, cannot load %s: %s."
+ throw new Error(msg.format(name, show(classLoader)), ex)
+ }
+ }
+ def loadScalaSignature: Option[String] = {
+ val ssig = loadAnnotation("scala.reflect.ScalaSignature")
if (ssig != null) {
- info("unpickling Scala "+clazz + " and " + module+ ", owner = " + clazz.owner)
- val bytes = ssig.bytes.getBytes
- val len = ByteCodecs.decode(bytes)
- unpickler.unpickle(bytes take len, 0, clazz, module, jclazz.getName)
+ val bytesMethod = ssig.annotationType.getMethod("bytes")
+ val result = bytesMethod.invoke(ssig)
+ Some(result.asInstanceOf[String])
+ } else {
+ None
+ }
+ }
+ def loadScalaLongSignature: Option[Array[String]] = {
+ val slsig = loadAnnotation("scala.reflect.ScalaLongSignature")
+ if (slsig != null) {
+ val bytesMethod = slsig.annotationType.getMethod("bytes")
+ val result = bytesMethod.invoke(slsig)
+ Some(result.asInstanceOf[Array[String]])
} else {
- val slsig = jclazz.getAnnotation(classOf[scala.reflect.ScalaLongSignature])
- if (slsig != null) {
+ None
+ }
+ }
+ try {
+ markAbsent(NoType)
+ val sigs = (loadScalaSignature, loadScalaLongSignature)
+ sigs match {
+ case (Some(ssig), _) =>
+ info("unpickling Scala "+clazz + " and " + module+ ", owner = " + clazz.owner)
+ val bytes = ssig.getBytes
+ val len = ByteCodecs.decode(bytes)
+ unpickler.unpickle(bytes take len, 0, clazz, module, jclazz.getName)
+ case (_, Some(slsig)) =>
info("unpickling Scala "+clazz + " and " + module + " with long Scala signature")
- val byteSegments = slsig.bytes map (_.getBytes)
+ val byteSegments = slsig map (_.getBytes)
val lens = byteSegments map ByteCodecs.decode
val bytes = Array.ofDim[Byte](lens.sum)
var len = 0
@@ -96,10 +173,10 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
len += l
}
unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName)
- } else { // class does not have a Scala signature; it's a Java class
+ case (None, None) =>
+ // class does not have a Scala signature; it's a Java class
info("translating reflection info for Java " + jclazz) //debug
initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz))
- }
}
} catch {
case ex: MissingRequirementError =>
@@ -237,6 +314,27 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
private def followStatic(clazz: Symbol, mods: Int) =
if (jModifier.isStatic(mods)) clazz.companionModule.moduleClass else clazz
+ /** Methods which need to be wrapped because they either are getSimpleName
+ * or call getSimpleName:
+ *
+ * public String getSimpleName()
+ * public boolean isAnonymousClass()
+ * public boolean isLocalClass()
+ * public boolean isMemberClass()
+ * public String getCanonicalName()
+ *
+ * TODO - find all such calls and wrap them.
+ * TODO - create mechanism to avoid the recurrence of unwrapped calls.
+ */
+ private def wrapClassCheck[T](alt: T)(body: => T): T =
+ try body catch { case x: InternalError if x.getMessage == "Malformed class name" => alt }
+
+ private def wrapIsLocalClass(clazz: jClass[_]): Boolean =
+ wrapClassCheck(false)(clazz.isLocalClass)
+
+ private def wrapGetSimpleName(clazz: jClass[_]): String =
+ wrapClassCheck("")(clazz.getSimpleName)
+
/**
* The Scala owner of the Scala class corresponding to the Java class `jclazz`
*/
@@ -245,7 +343,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
val jEnclosingClass = jclazz.getEnclosingClass
val sEnclosingClass = classToScala(jEnclosingClass)
followStatic(sEnclosingClass, jclazz.getModifiers)
- } else if (jclazz.isLocalClass) {
+ } else if (wrapIsLocalClass(jclazz)) {
val jEnclosingMethod = jclazz.getEnclosingMethod
if (jEnclosingMethod != null) {
methodToScala(jEnclosingMethod)
@@ -383,52 +481,70 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
*/
def classToScala(jclazz: jClass[_]): Symbol = classCache.toScala(jclazz) {
val jname = javaTypeName(jclazz)
- val owner = sOwner(jclazz)
- val simpleName = scalaSimpleName(jclazz)
-
- val sym = {
- def lookup = {
- def coreLookup(name: Name): Symbol = {
- val sym = owner.info.decl(name)
- sym orElse {
- if (name.startsWith(nme.NAME_JOIN_STRING))
- coreLookup(name.subName(1, name.length))
- else
- NoSymbol
+
+ val sym =
+ if (jname == fulltpnme.RuntimeNothing)
+ NothingClass
+ else if (jname == fulltpnme.RuntimeNull)
+ NullClass
+ else
+ {
+ val owner = sOwner(jclazz)
+ val simpleName = scalaSimpleName(jclazz)
+
+ def lookup = {
+ def coreLookup(name: Name): Symbol = {
+ val sym = owner.info.decl(name)
+ sym orElse {
+ if (name.startsWith(nme.NAME_JOIN_STRING))
+ coreLookup(name.subName(1, name.length))
+ else
+ NoSymbol
+ }
+ }
+
+ if (nme.isModuleName(simpleName)) {
+ val moduleName = nme.stripModuleSuffix(simpleName).toTermName
+ val sym = coreLookup(moduleName)
+ if (sym == NoSymbol) sym else sym.moduleClass
+ } else {
+ coreLookup(simpleName)
}
}
- if (nme.isModuleName(simpleName)) {
- val moduleName = nme.stripModuleSuffix(simpleName).toTermName
- val sym = coreLookup(moduleName)
- if (sym == NoSymbol) sym else sym.moduleClass
- } else {
- coreLookup(simpleName)
+ val sym = {
+ if (jclazz.isMemberClass && !nme.isImplClassName(jname)) {
+ lookup
+ } else if (wrapIsLocalClass(jclazz) || invalidClassName(jname)) {
+ // local classes and implementation classes not preserved by unpickling - treat as Java
+ jclassAsScala(jclazz)
+ } else if (jclazz.isArray) {
+ ArrayClass
+ } else javaTypeToValueClass(jclazz) orElse {
+ // jclazz is top-level - get signature
+ lookup
+ // val (clazz, module) = createClassModule(
+ // sOwner(jclazz), newTypeName(jclazz.getSimpleName), new TopClassCompleter(_, _))
+ // classCache enter (jclazz, clazz)
+ // clazz
+ }
}
- }
- if (jclazz.isMemberClass && !nme.isImplClassName(jname)) {
- lookup
- } else if (jclazz.isLocalClass || invalidClassName(jname)) {
- // local classes and implementation classes not preserved by unpickling - treat as Java
- jclassAsScala(jclazz)
- } else if (jclazz.isArray) {
- ArrayClass
- } else javaTypeToValueClass(jclazz) orElse {
- // jclazz is top-level - get signature
- lookup
- // val (clazz, module) = createClassModule(
- // sOwner(jclazz), newTypeName(jclazz.getSimpleName), new TopClassCompleter(_, _))
- // classCache enter (jclazz, clazz)
- // clazz
- }
- }
+ if (!sym.isType) {
+ val classloader = jclazz.getClassLoader
+ println("classloader is: %s of type %s".format(classloader, classloader.getClass))
+ def inferClasspath(cl: ClassLoader) = cl match {
+ case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
+ case _ => "<unknown>"
+ }
+ println("classpath is: %s".format(inferClasspath(classloader)))
+ def msgNoSym = "no symbol could be loaded from %s (scala equivalent is %s) by name %s".format(owner, jclazz, simpleName)
+ def msgIsNotType = "not a type: symbol %s loaded from %s (scala equivalent is %s) by name %s".format(sym, owner, jclazz, simpleName)
+ assert(false, if (sym == NoSymbol) msgNoSym else msgIsNotType)
+ }
- if (!sym.isType) {
- def msgNoSym = "no symbol could be loaded from %s (scala equivalent is %s) by name %s".format(owner, jclazz, simpleName)
- def msgIsNotType = "not a type: symbol %s loaded from %s (scala equivalent is %s) by name %s".format(sym, owner, jclazz, simpleName)
- assert(false, if (sym == NoSymbol) msgNoSym else msgIsNotType)
- }
+ sym
+ }
sym.asInstanceOf[ClassSymbol]
}
diff --git a/src/compiler/scala/reflect/runtime/Memoizer.scala b/src/compiler/scala/reflect/runtime/Memoizer.scala
deleted file mode 100644
index 4c1b82ae6d..0000000000
--- a/src/compiler/scala/reflect/runtime/Memoizer.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-package scala.reflect.runtime
-
-import collection.mutable.ArrayBuffer
-import Mirror.Type
-
-/** Class that can be used for memoizing types in reified trees */
-class Memoizer {
- private val mem = new ArrayBuffer[Mirror.Type]
- def get(n: Int): Type = mem(n)
- def add(n: Int, tpe: Type): Type = {
- while (mem.length <= n) mem += null
- mem(n) = tpe
- tpe
- }
-}
diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala
index d3e4dd7619..bf4bc83bea 100644
--- a/src/compiler/scala/reflect/runtime/Mirror.scala
+++ b/src/compiler/scala/reflect/runtime/Mirror.scala
@@ -1,31 +1,31 @@
package scala.reflect
package runtime
-import internal.{SomePhase, NoPhase, Phase, TreeGen}
import java.lang.reflect.Array
+import ReflectionUtils._
+import scala.tools.nsc.util.ScalaClassLoader._
/** The mirror for standard runtime reflection from Java.
*/
-class Mirror extends Universe with RuntimeTypes with TreeBuildUtil with ToolBoxes with api.Mirror {
+class Mirror(var classLoader: ClassLoader) extends Universe with api.Mirror {
definitions.init()
-
import definitions._
def symbolForName(name: String): Symbol = {
- val clazz = javaClass(name, defaultReflectiveClassLoader())
+ val clazz = javaClass(name, classLoader)
classToScala(clazz)
}
def companionInstance(clazz: Symbol): AnyRef = {
- val singleton = ReflectionUtils.singletonInstance(clazz.fullName, defaultReflectiveClassLoader())
+ val singleton = singletonInstance(classLoader, clazz.fullName)
singleton
}
def symbolOfInstance(obj: Any): Symbol = classToScala(obj.getClass)
def typeOfInstance(obj: Any): Type = typeToScala(obj.getClass)
// to do add getClass/getType for instances of primitive types, probably like this:
- // def getClass[T <: AnyVal : Manifest](x: T): Symbol = manifest[T].getClass
+ // def getClass[T <: AnyVal : ClassTag](x: T): Symbol = classTag[T].sym
def getValueOfField(receiver: AnyRef, field: Symbol): Any = {
fieldToJava(field).get(receiver)
@@ -46,17 +46,31 @@ class Mirror extends Universe with RuntimeTypes with TreeBuildUtil with ToolBoxe
jmeth.invoke(receiver, args.asInstanceOf[Seq[AnyRef]]: _*)
}
- override def classToType(jclazz: java.lang.Class[_]): Type = typeToScala(jclazz)
- override def classToSymbol(jclazz: java.lang.Class[_]): Symbol = classToScala(jclazz)
+ private def validateIncomingClassLoader(wannabeCl: ClassLoader) = {
+ val ourCls = loaderChain(classLoader)
+ if (wannabeCl != null && !(ourCls contains wannabeCl))
+ throw new Error("class doesn't belong to the classloader chain of the mirror")
+ }
+
+ def classToType(jclazz: java.lang.Class[_]): Type = {
+ validateIncomingClassLoader(jclazz.getClassLoader)
+ typeToScala(jclazz)
+ }
+
+ def classToSymbol(jclazz: java.lang.Class[_]): Symbol = {
+ validateIncomingClassLoader(jclazz.getClassLoader)
+ classToScala(jclazz)
+ }
+
+ def typeToClass(tpe: Type): java.lang.Class[_] =
+ typeToJavaClass(tpe)
- override def typeToClass(tpe: Type): java.lang.Class[_] = typeToJavaClass(tpe)
- override def symbolToClass(sym: Symbol): java.lang.Class[_] = classToJava(sym)
+ def symbolToClass(sym: Symbol): java.lang.Class[_] =
+ classToJava(sym)
override def inReflexiveMirror = true
}
-object Mirror extends Mirror
-
/** test code; should go to tests once things settle down a bit
*
diff --git a/src/compiler/scala/reflect/runtime/RuntimeTypes.scala b/src/compiler/scala/reflect/runtime/RuntimeTypes.scala
deleted file mode 100644
index 84d02ab7a0..0000000000
--- a/src/compiler/scala/reflect/runtime/RuntimeTypes.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-package scala.reflect
-package runtime
-
-import collection.mutable.ListBuffer
-
-trait RuntimeTypes extends Universe with api.RuntimeTypes {
-
- /** To lift path dependent types into reflection, we use InstanceRefSymbols.
- * Two of these are equal if they point to the same object reference. Todo: remove
- */
- case class InstanceRefSymbol(value: AnyRef) extends TermSymbol(NoSymbol, NoPosition, nme.EMPTY)
- object InstanceRefSymbol extends InstanceRefSymbolExtractor
-
- override private[reflect] def namedType(pre: Type, sym: Symbol, args: List[Type]): Type = {
- val tparamBuf = new ListBuffer[Symbol]
- val args1 = for (arg <- args) yield arg match {
- case _: TypeBounds =>
- val ex = pre.typeSymbol.freshExistential("$ex") setInfo arg
- tparamBuf += ex
- TypeRef(NoPrefix, ex, List())
- case _ =>
- arg
- }
- existentialAbstraction(tparamBuf.toList, typeRef(pre, sym, args1))
- }
-
-} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/Settings.scala b/src/compiler/scala/reflect/runtime/Settings.scala
index 27e90c94bd..bbe4d60e9c 100644
--- a/src/compiler/scala/reflect/runtime/Settings.scala
+++ b/src/compiler/scala/reflect/runtime/Settings.scala
@@ -34,5 +34,5 @@ class Settings extends internal.settings.MutableSettings {
val maxClassfileName = new IntSetting(255)
val Xexperimental = new BooleanSetting(false)
val deepCloning = new BooleanSetting (false)
- val YvirtPatmat = new BooleanSetting(false)
+ val XoldPatmat = new BooleanSetting(false)
}
diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/SymbolLoaders.scala
index 4b35a5b37e..7c1cc16152 100644
--- a/src/compiler/scala/reflect/runtime/Loaders.scala
+++ b/src/compiler/scala/reflect/runtime/SymbolLoaders.scala
@@ -5,7 +5,7 @@ import internal.Flags
import java.lang.{Class => jClass, Package => jPackage}
import collection.mutable
-trait Loaders { self: SymbolTable =>
+trait SymbolLoaders { self: SymbolTable =>
/** The lazy type for root.
*/
@@ -123,6 +123,11 @@ trait Loaders { self: SymbolTable =>
}
}
+ /** Assert that packages have package scopes */
+ override def validateClassInfo(tp: ClassInfoType) {
+ assert(!tp.typeSymbol.isPackageClass || tp.decls.isInstanceOf[PackageScope])
+ }
+
override def newPackageScope(pkgClass: Symbol) = new PackageScope(pkgClass)
override def scopeTransform(owner: Symbol)(op: => Scope): Scope =
diff --git a/src/compiler/scala/reflect/runtime/SymbolTable.scala b/src/compiler/scala/reflect/runtime/SymbolTable.scala
index 5331f0a53e..64a5894d01 100644
--- a/src/compiler/scala/reflect/runtime/SymbolTable.scala
+++ b/src/compiler/scala/reflect/runtime/SymbolTable.scala
@@ -3,29 +3,10 @@ package runtime
/**
* This symbol table trait fills in the definitions so that class information is obtained by refection.
- * It can be used either from the reflexive mirror itself (class Universe), or else from
+ * It can be used either from the reflexive mirror itself (class Mirror), or else from
* a runtime compiler that uses reflection to get a class information (class scala.tools.nsc.ReflectGlobal)
*/
-trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with Loaders with SynchronizedOps {
-
- /** If `owner` is a package class (but not the empty package) and `name` is a term name, make a new package
- * <owner>.<name>, otherwise return NoSymbol.
- * Exception: If owner is root and a java class with given name exists, create symbol in empty package instead.
- */
- override def missingHook(owner: Symbol, name: Name): Symbol =
- if (owner.isRoot && isJavaClass(name.toString))
- definitions.EmptyPackageClass.info decl name
- else if (name.isTermName && owner.hasPackageFlag && !owner.isEmptyPackageClass)
- makeScalaPackage(if (owner.isRoot) name.toString else owner.fullName+"."+name).sourceModule
- else {
- info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass)
- super.missingHook(owner, name)
- }
-
- /** Assert that packages have package scopes */
- override def validateClassInfo(tp: ClassInfoType) {
- assert(!tp.typeSymbol.isPackageClass || tp.decls.isInstanceOf[PackageScope])
- }
+trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with ClassLoaders with SymbolLoaders with SynchronizedOps {
def info(msg: => String) =
if (settings.verbose.value) println("[reflect-compiler] "+msg)
diff --git a/src/compiler/scala/reflect/runtime/SynchronizedOps.scala b/src/compiler/scala/reflect/runtime/SynchronizedOps.scala
index dd806beb2a..907c0dd369 100644
--- a/src/compiler/scala/reflect/runtime/SynchronizedOps.scala
+++ b/src/compiler/scala/reflect/runtime/SynchronizedOps.scala
@@ -39,7 +39,7 @@ trait SynchronizedOps extends internal.SymbolTable
trait SynchronizedScope extends Scope {
override def isEmpty: Boolean = synchronized { super.isEmpty }
override def size: Int = synchronized { super.size }
- override def enter(sym: Symbol) = synchronized { super.enter(sym) }
+ override def enter[T <: Symbol](sym: T): T = synchronized { super.enter(sym) }
override def rehash(sym: Symbol, newname: Name) = synchronized { super.rehash(sym, newname) }
override def unlink(e: ScopeEntry) = synchronized { super.unlink(e) }
override def unlink(sym: Symbol) = synchronized { super.unlink(sym) }
diff --git a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
index 3f2fa30be2..2322911220 100644
--- a/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
+++ b/src/compiler/scala/reflect/runtime/SynchronizedSymbols.scala
@@ -14,19 +14,20 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
override def connectModuleToClass(m: ModuleSymbol, moduleClass: ClassSymbol): ModuleSymbol =
synchronized { super.connectModuleToClass(m, moduleClass) }
- override def newFreeVar(name: TermName, tpe: Type, value: Any, newFlags: Long = 0L): FreeVar =
- new FreeVar(name, value) with SynchronizedTermSymbol initFlags newFlags setInfo tpe
+ override def newFreeTermSymbol(name: TermName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeTerm =
+ new FreeTerm(name, value, origin) with SynchronizedTermSymbol initFlags flags setInfo info
- override protected def makeNoSymbol = new NoSymbol with SynchronizedSymbol
+ override def newFreeTypeSymbol(name: TypeName, info: Type, value: => Any, flags: Long = 0L, origin: String = null): FreeType =
+ new FreeType(name, value, origin) with SynchronizedTypeSymbol initFlags flags setInfo info
+
+ override protected def makeNoSymbol: NoSymbol = new NoSymbol with SynchronizedSymbol
trait SynchronizedSymbol extends Symbol {
- override def rawowner = synchronized { super.rawowner }
- override def rawname = synchronized { super.rawname }
override def rawflags = synchronized { super.rawflags }
+ override def rawflags_=(x: Long) = synchronized { super.rawflags_=(x) }
- override def rawflags_=(x: FlagsType) = synchronized { super.rawflags_=(x) }
- override def name_=(x: Name) = synchronized { super.name_=(x) }
+ override def rawowner = synchronized { super.rawowner }
override def owner_=(owner: Symbol) = synchronized { super.owner_=(owner) }
override def validTo = synchronized { super.validTo }
@@ -45,7 +46,7 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
override def typeParams: List[Symbol] = synchronized { super.typeParams }
- override def reset(completer: Type) = synchronized { super.reset(completer) }
+ override def reset(completer: Type): this.type = synchronized { super.reset(completer) }
override def infosString: String = synchronized { super.infosString }
@@ -55,37 +56,55 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
// ------ creators -------------------------------------------------------------------
- override def newTermSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): TermSymbol =
- new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags
-
- override def newAbstractTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AbstractTypeSymbol =
+ override protected def createAbstractTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AbstractTypeSymbol =
new AbstractTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags
- override def newAliasTypeSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): AliasTypeSymbol =
+ override protected def createAliasTypeSymbol(name: TypeName, pos: Position, newFlags: Long): AliasTypeSymbol =
new AliasTypeSymbol(this, pos, name) with SynchronizedTypeSymbol initFlags newFlags
- override def newModuleSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleSymbol =
- new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags
-
- override def newMethodSymbol(name: TermName, pos: Position = NoPosition, newFlags: Long = 0L): MethodSymbol =
- new MethodSymbol(this, pos, name) with SynchronizedMethodSymbol initFlags newFlags
+ override protected def createTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position, newFlags: Long): TypeSkolem =
+ new TypeSkolem(this, pos, name, origin) with SynchronizedTypeSymbol initFlags newFlags
- override def newClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ClassSymbol =
+ override protected def createClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol =
new ClassSymbol(this, pos, name) with SynchronizedClassSymbol initFlags newFlags
- override def newModuleClassSymbol(name: TypeName, pos: Position = NoPosition, newFlags: Long = 0L): ModuleClassSymbol =
+ override protected def createModuleClassSymbol(name: TypeName, pos: Position, newFlags: Long): ModuleClassSymbol =
new ModuleClassSymbol(this, pos, name) with SynchronizedModuleClassSymbol initFlags newFlags
- override def newTypeSkolemSymbol(name: TypeName, origin: AnyRef, pos: Position = NoPosition, newFlags: Long = 0L): TypeSkolem =
- if ((newFlags & DEFERRED) == 0L)
- new TypeSkolem(this, pos, name, origin) with SynchronizedTypeSymbol initFlags newFlags
- else
- new TypeSkolem(this, pos, name, origin) with AbstractTypeMixin with SynchronizedTypeSymbol initFlags newFlags
+ override protected def createPackageClassSymbol(name: TypeName, pos: Position, newFlags: Long): PackageClassSymbol =
+ new PackageClassSymbol(this, pos, name) with SynchronizedModuleClassSymbol initFlags newFlags
+
+ override protected def createRefinementClassSymbol(pos: Position, newFlags: Long): RefinementClassSymbol =
+ new RefinementClassSymbol(this, pos) with SynchronizedClassSymbol initFlags newFlags
+
+ override protected def createImplClassSymbol(name: TypeName, pos: Position, newFlags: Long): ClassSymbol =
+ new ClassSymbol(this, pos, name) with ImplClassSymbol with SynchronizedClassSymbol initFlags newFlags
+
+ override protected def createPackageObjectClassSymbol(pos: Position, newFlags: Long): PackageObjectClassSymbol =
+ new PackageObjectClassSymbol(this, pos) with SynchronizedClassSymbol initFlags newFlags
+
+ override protected def createTermSymbol(name: TermName, pos: Position, newFlags: Long): TermSymbol =
+ new TermSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags
+
+ override protected def createMethodSymbol(name: TermName, pos: Position, newFlags: Long): MethodSymbol =
+ new MethodSymbol(this, pos, name) with SynchronizedMethodSymbol initFlags newFlags
+
+ override protected def createModuleSymbol(name: TermName, pos: Position, newFlags: Long): ModuleSymbol =
+ new ModuleSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags
+
+ override protected def createPackageSymbol(name: TermName, pos: Position, newFlags: Long): PackageSymbol =
+ new PackageSymbol(this, pos, name) with SynchronizedTermSymbol initFlags newFlags
+
+ // TODO
+ // override protected def createValueParameterSymbol(name: TermName, pos: Position, newFlags: Long)
+ // override protected def createValueMemberSymbol(name: TermName, pos: Position, newFlags: Long)
}
// ------- subclasses ---------------------------------------------------------------------
trait SynchronizedTermSymbol extends TermSymbol with SynchronizedSymbol {
+ override def name_=(x: Name) = synchronized { super.name_=(x) }
+ override def rawname = synchronized { super.rawname }
override def referenced: Symbol = synchronized { super.referenced }
override def referenced_=(x: Symbol) = synchronized { super.referenced_=(x) }
}
@@ -95,13 +114,15 @@ trait SynchronizedSymbols extends internal.Symbols { self: SymbolTable =>
}
trait SynchronizedTypeSymbol extends TypeSymbol with SynchronizedSymbol {
+ override def name_=(x: Name) = synchronized { super.name_=(x) }
+ override def rawname = synchronized { super.rawname }
override def typeConstructor: Type = synchronized { super.typeConstructor }
override def tpe: Type = synchronized { super.tpe }
}
trait SynchronizedClassSymbol extends ClassSymbol with SynchronizedTypeSymbol {
- override def sourceFile = synchronized { super.sourceFile }
- override def sourceFile_=(f: AbstractFileType) = synchronized { super.sourceFile_=(f) }
+ override def associatedFile = synchronized { super.associatedFile }
+ override def associatedFile_=(f: AbstractFileType) = synchronized { super.associatedFile_=(f) }
override def thisSym: Symbol = synchronized { super.thisSym }
override def thisType: Type = synchronized { super.thisType }
override def typeOfThis: Type = synchronized { super.typeOfThis }
diff --git a/src/compiler/scala/reflect/runtime/ToolBoxes.scala b/src/compiler/scala/reflect/runtime/ToolBoxes.scala
index 28f12b378f..7b1fc9fc0d 100644
--- a/src/compiler/scala/reflect/runtime/ToolBoxes.scala
+++ b/src/compiler/scala/reflect/runtime/ToolBoxes.scala
@@ -1,28 +1,27 @@
package scala.reflect
package runtime
-import scala.tools.nsc
-import scala.tools.nsc.reporters.Reporter
-import scala.tools.nsc.reporters.StoreReporter
-import scala.tools.nsc.reporters.AbstractReporter
+import scala.tools.nsc.reporters._
import scala.tools.nsc.ReflectGlobal
import scala.tools.nsc.CompilerCommand
import scala.tools.nsc.Global
import scala.tools.nsc.typechecker.Modes
import scala.tools.nsc.io.VirtualDirectory
import scala.tools.nsc.interpreter.AbstractFileClassLoader
-import reflect.{mirror => rm}
import scala.tools.nsc.util.FreshNameCreator
import scala.reflect.internal.Flags
import scala.tools.nsc.util.{NoSourceFile, NoFile}
import java.lang.{Class => jClass}
-import scala.tools.nsc.util.trace
+import scala.compat.Platform.EOL
trait ToolBoxes extends { self: Universe =>
- class ToolBox(val reporter: Reporter = new StoreReporter, val options: String = "") {
+ def mkToolBox(frontEnd: FrontEnd = mkSilentFrontEnd(), options: String = "") = new ToolBox(frontEnd, options)
- class ToolBoxGlobal(settings0: nsc.Settings, reporter0: nsc.reporters.Reporter) extends ReflectGlobal(settings0, reporter0) {
+ class ToolBox(val frontEnd: FrontEnd, val options: String) extends AbsToolBox {
+
+ class ToolBoxGlobal(settings: scala.tools.nsc.Settings, reporter: Reporter)
+ extends ReflectGlobal(settings, reporter, ToolBox.this.classLoader) {
import definitions._
private val trace = scala.tools.nsc.util.trace when settings.debug.value
@@ -36,64 +35,7 @@ trait ToolBoxes extends { self: Universe =>
newTermName("__wrapper$" + wrapCount)
}
- private def moduleFileName(className: String) = className + "$"
-
- private def isFree(t: Tree) = t.isInstanceOf[Ident] && t.symbol.isInstanceOf[FreeVar]
-
- def typedTopLevelExpr(tree: Tree, pt: Type): Tree = {
- // !!! Why is this is in the empty package? If it's only to make
- // it inaccessible then please put it somewhere designed for that
- // rather than polluting the empty package with synthetics.
- trace("typing: ")(showAttributed(tree, true, true, settings.Yshowsymkinds.value))
- val ownerClass = EmptyPackageClass.newClassWithInfo(newTypeName("<expression-owner>"), List(ObjectClass.tpe), newScope)
- val owner = ownerClass.newLocalDummy(tree.pos)
- val ttree = typer.atOwner(tree, owner).typed(tree, analyzer.EXPRmode, pt)
- trace("typed: ")(showAttributed(ttree, true, true, settings.Yshowsymkinds.value))
- ttree
- }
-
- def defOwner(tree: Tree): Symbol = tree find (_.isDef) map (_.symbol) match {
- case Some(sym) if sym != null && sym != NoSymbol => sym.owner
- case _ => NoSymbol
- }
-
- def wrapInObject(expr: Tree, fvs: List[Symbol]): ModuleDef = {
- val obj = EmptyPackageClass.newModule(nextWrapperModuleName())
- val minfo = ClassInfoType(List(ObjectClass.tpe), newScope, obj.moduleClass)
- obj.moduleClass setInfo minfo
- obj setInfo obj.moduleClass.tpe
- val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName))
- def makeParam(fv: Symbol) = meth.newValueParameter(fv.name.toTermName) setInfo fv.tpe
- meth setInfo MethodType(fvs map makeParam, AnyClass.tpe)
- minfo.decls enter meth
- trace("wrapping ")(defOwner(expr) -> meth)
- val methdef = DefDef(meth, expr changeOwner (defOwner(expr) -> meth))
- val moduledef = ModuleDef(
- obj,
- Template(
- List(TypeTree(ObjectClass.tpe)),
- emptyValDef,
- NoMods,
- List(),
- List(List()),
- List(methdef),
- NoPosition))
- trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value))
- val cleanedUp = resetLocalAttrs(moduledef)
- trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value))
- cleanedUp
- }
-
- def wrapInPackage(clazz: Tree): PackageDef =
- PackageDef(Ident(nme.EMPTY_PACKAGE_NAME), List(clazz))
-
- def wrapInCompilationUnit(tree: Tree): CompilationUnit = {
- val unit = new CompilationUnit(NoSourceFile)
- unit.body = tree
- unit
- }
-
- def compileExpr(expr: Tree, fvs: List[Symbol]): String = {
+ def verifyExpr(expr: Tree): Unit = {
// Previously toolboxes used to typecheck their inputs before compiling.
// Actually, the initial demo by Martin first typechecked the reified tree,
// then ran it, which typechecked it again, and only then launched the
@@ -104,44 +46,186 @@ trait ToolBoxes extends { self: Universe =>
// That's why we cannot allow inputs of toolboxes to be typechecked,
// at least not until the aforementioned issue is closed.
val typed = expr filter (t => t.tpe != null && t.tpe != NoType && !t.isInstanceOf[TypeTree])
- if (!typed.isEmpty) {
- throw new Error("cannot compile trees that are already typed")
+ if (!typed.isEmpty) throw new ToolBoxError(ToolBox.this, "reflective toolbox has failed: cannot operate on trees that are already typed")
+
+ val freeTypes = this.freeTypes(expr)
+ if (freeTypes.length > 0) {
+ var msg = "reflective toolbox has failed:" + EOL
+ msg += "unresolved free type variables (namely: " + (freeTypes map (ft => "%s %s".format(ft.name, ft.origin)) mkString ", ") + "). "
+ msg += "have you forgot to use TypeTag annotations for type parameters external to a reifee? "
+ msg += "if you have troubles tracking free type variables, consider using -Xlog-free-types"
+ throw new ToolBoxError(ToolBox.this, msg)
}
+ }
- val mdef = wrapInObject(expr, fvs)
- val pdef = wrapInPackage(mdef)
- val unit = wrapInCompilationUnit(pdef)
- val run = new Run
- run.compileUnits(List(unit), run.namerPhase)
- mdef.symbol.fullName
+ def typeCheckExpr(expr0: Tree, pt: Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = {
+ verifyExpr(expr0)
+
+ // need to wrap the expr, because otherwise you won't be able to typecheck macros against something that contains free vars
+ // [Eugene] get rid of the copy/paste w.r.t compileExpr
+ val freeTerms = this.freeTerms(expr0)
+ val freeTermNames = collection.mutable.Map[Symbol, TermName]()
+ freeTerms foreach (ft => {
+ var name = ft.name.toString
+ val namesakes = freeTerms takeWhile (_ != ft) filter (ft2 => ft != ft2 && ft.name == ft2.name)
+ if (namesakes.length > 0) name += ("$" + (namesakes.length + 1))
+ freeTermNames += (ft -> newTermName(name + nme.MIRROR_FREE_VALUE_SUFFIX))
+ })
+ var expr = new Transformer {
+ override def transform(tree: Tree): Tree =
+ if (tree.hasSymbol && tree.symbol.isFreeTerm) {
+ tree match {
+ case Ident(_) =>
+ Ident(freeTermNames(tree.symbol))
+ case _ =>
+ throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ }
+ } else {
+ super.transform(tree)
+ }
+ }.transform(expr0)
+ val dummies = freeTerms map (freeTerm => ValDef(NoMods, freeTermNames(freeTerm), TypeTree(freeTerm.info), Select(Ident(PredefModule), newTermName("$qmark$qmark$qmark"))))
+ expr = Block(dummies, expr)
+
+ // [Eugene] how can we implement that?
+ // !!! Why is this is in the empty package? If it's only to make
+ // it inaccessible then please put it somewhere designed for that
+ // rather than polluting the empty package with synthetics.
+ val ownerClass = EmptyPackageClass.newClassWithInfo(newTypeName("<expression-owner>"), List(ObjectClass.tpe), newScope)
+ val owner = ownerClass.newLocalDummy(expr.pos)
+ var currentTyper = typer.atOwner(expr, owner)
+ val wrapper1 = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _)
+ val wrapper2 = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _)
+ def wrapper (tree: => Tree) = wrapper1(wrapper2(tree))
+
+ phase = (new Run).typerPhase // need to set a phase to something <= typerPhase, otherwise implicits in typedSelect will be disabled
+ currentTyper.context.setReportErrors() // need to manually set context mode, otherwise typer.silent will throw exceptions
+ reporter.reset()
+
+ trace("typing (implicit views = %s, macros = %s): ".format(!withImplicitViewsDisabled, !withMacrosDisabled))(showAttributed(expr, true, true, settings.Yshowsymkinds.value))
+ wrapper(currentTyper.silent(_.typed(expr, analyzer.EXPRmode, pt)) match {
+ case analyzer.SilentResultValue(result) =>
+ trace("success: ")(showAttributed(result, true, true, settings.Yshowsymkinds.value))
+ var Block(dummies, unwrapped) = result
+ var reversedFreeTermNames = freeTermNames map (_.swap)
+ // todo. also fixup singleton types
+ unwrapped = new Transformer {
+ override def transform(tree: Tree): Tree =
+ tree match {
+ case Ident(name) if reversedFreeTermNames contains name =>
+ Ident(reversedFreeTermNames(name)) setType tree.tpe
+ case _ =>
+ super.transform(tree)
+ }
+ }.transform(unwrapped)
+ new TreeTypeSubstituter(dummies map (_.symbol), dummies map (dummy => SingleType(NoPrefix, reversedFreeTermNames(dummy.symbol.name)))).traverse(unwrapped)
+ unwrapped
+ case error @ analyzer.SilentTypeError(_) =>
+ trace("failed: ")(error.err.errMsg)
+ if (!silent) throw new ToolBoxError(ToolBox.this, "reflective typecheck has failed: %s".format(error.err.errMsg))
+ EmptyTree
+ })
}
- private def getMethod(jclazz: jClass[_], name: String) =
- jclazz.getDeclaredMethods.find(_.getName == name).get
+ def compileExpr(expr: Tree): (Object, java.lang.reflect.Method) = {
+ verifyExpr(expr)
+
+ def wrapExpr(expr0: Tree): Tree = {
+ def defOwner(tree: Tree): Symbol = tree find (_.isDef) map (_.symbol) match {
+ case Some(sym) if sym != null && sym != NoSymbol => sym.owner
+ case _ => NoSymbol
+ }
+
+ val freeTerms = this.freeTerms(expr0)
+ val freeTermNames = collection.mutable.Map[Symbol, TermName]()
+ freeTerms foreach (ft => {
+ var name = ft.name.toString
+ val namesakes = freeTerms takeWhile (_ != ft) filter (ft2 => ft != ft2 && ft.name == ft2.name)
+ if (namesakes.length > 0) name += ("$" + (namesakes.length + 1))
+ freeTermNames += (ft -> newTermName(name + nme.MIRROR_FREE_VALUE_SUFFIX))
+ })
+ val expr = new Transformer {
+ override def transform(tree: Tree): Tree =
+ if (tree.hasSymbol && tree.symbol.isFreeTerm) {
+ tree match {
+ case Ident(_) =>
+ Apply(Ident(freeTermNames(tree.symbol)), List())
+ case _ =>
+ throw new Error("internal error: %s (%s, %s) is not supported".format(tree, tree.productPrefix, tree.getClass))
+ }
+ } else {
+ super.transform(tree)
+ }
+ }.transform(expr0)
+
+ val obj = EmptyPackageClass.newModule(nextWrapperModuleName())
+ val minfo = ClassInfoType(List(ObjectClass.tpe), newScope, obj.moduleClass)
+ obj.moduleClass setInfo minfo
+ obj setInfo obj.moduleClass.tpe
+ val meth = obj.moduleClass.newMethod(newTermName(wrapperMethodName))
+ def makeParam(fv: Symbol) = {
+ // [Eugene] conventional way of doing this?
+ val underlying = fv.tpe.resultType
+ val tpe = appliedType(definitions.FunctionClass(0).tpe, List(underlying))
+ meth.newValueParameter(freeTermNames(fv)) setInfo tpe
+ }
+ meth setInfo MethodType(freeTerms map makeParam, AnyClass.tpe)
+ minfo.decls enter meth
+ trace("wrapping ")(defOwner(expr) -> meth)
+ val methdef = DefDef(meth, expr changeOwner (defOwner(expr) -> meth))
+ val moduledef = ModuleDef(
+ obj,
+ Template(
+ List(TypeTree(ObjectClass.tpe)),
+ emptyValDef,
+ NoMods,
+ List(),
+ List(List()),
+ List(methdef),
+ NoPosition))
+ trace("wrapped: ")(showAttributed(moduledef, true, true, settings.Yshowsymkinds.value))
+ var cleanedUp = resetLocalAttrs(moduledef)
+ trace("cleaned up: ")(showAttributed(cleanedUp, true, true, settings.Yshowsymkinds.value))
+ cleanedUp
+ }
- def runExpr(expr: Tree): Any = {
- val fvs = (expr filter isFree map (_.symbol)).distinct
+ val mdef = wrapExpr(expr)
+ val pdef = PackageDef(Ident(nme.EMPTY_PACKAGE_NAME), List(mdef))
+ val unit = new CompilationUnit(NoSourceFile)
+ unit.body = pdef
+ val run = new Run
reporter.reset()
- val className = compileExpr(expr, fvs)
- if (reporter.hasErrors) {
- throw new Error("reflective compilation has failed")
- }
+ run.compileUnits(List(unit), run.namerPhase)
+ throwIfErrors()
+ val className = mdef.symbol.fullName
if (settings.debug.value) println("generated: "+className)
+ def moduleFileName(className: String) = className + "$"
val jclazz = jClass.forName(moduleFileName(className), true, classLoader)
val jmeth = jclazz.getDeclaredMethods.find(_.getName == wrapperMethodName).get
val jfield = jclazz.getDeclaredFields.find(_.getName == NameTransformer.MODULE_INSTANCE_NAME).get
val singleton = jfield.get(null)
+ (singleton, jmeth)
+ }
+
+ def runExpr(expr: Tree, freeTypes: Map[TypeName, Type] = Map[TypeName, Type]()): Any = {
+ val freeTerms = this.freeTerms(expr) // need to calculate them here, because later on they will be erased
+ val thunks = freeTerms map (fte => () => fte.value) // need to be lazy in order not to distort evaluation order
+
// @odersky writes: Not sure we will be able to drop this. I forgot the reason why we dereference () functions,
// but there must have been one. So I propose to leave old version in comments to be resurrected if the problem resurfaces.
-// val result = jmeth.invoke(singleton, fvs map (sym => sym.asInstanceOf[FreeVar].value.asInstanceOf[AnyRef]): _*)
+ // @Eugene writes: this dates back to the days when one could only reify functions
+ // hence, blocks were translated into nullary functions, so
+ // presumably, it was useful to immediately evaluate them to get the result of a block
+// val result = jmeth.invoke(singleton, freeTerms map (sym => sym.asInstanceOf[FreeTermVar].value.asInstanceOf[AnyRef]): _*)
// if (etpe.typeSymbol != FunctionClass(0)) result
// else {
// val applyMeth = result.getClass.getMethod("apply")
// applyMeth.invoke(result)
// }
- jmeth.invoke(singleton, fvs map (sym => sym.asInstanceOf[FreeVar].value.asInstanceOf[AnyRef]): _*)
+ val (singleton, jmeth) = compileExpr(expr)
+ jmeth.invoke(singleton, thunks map (_.asInstanceOf[AnyRef]): _*)
}
def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = {
@@ -159,8 +243,18 @@ trait ToolBoxes extends { self: Universe =>
settings.Yshowsymkinds.value = saved3
}
}
+
+ // reporter doesn't accumulate errors, but the front-end does
+ def throwIfErrors() = {
+ if (frontEnd.hasErrors) {
+ var msg = "reflective compilation has failed: " + EOL + EOL
+ msg += frontEnd.infos map (_.msg) mkString EOL
+ throw new ToolBoxError(ToolBox.this, msg)
+ }
+ }
}
+ // todo. is not going to work with quoted arguments with embedded whitespaces
lazy val arguments = options.split(" ")
lazy val virtualDirectory =
@@ -170,49 +264,90 @@ trait ToolBoxes extends { self: Universe =>
}
lazy val compiler: ToolBoxGlobal = {
- val errorFn: String => Unit = reporter.error(scala.tools.nsc.util.NoPosition, _)
- val command = reporter match {
- case reporter: AbstractReporter => new CompilerCommand(arguments.toList, reporter.settings, errorFn)
- case _ => new CompilerCommand(arguments.toList, errorFn)
+ try {
+ val errorFn: String => Unit = msg => frontEnd.log(NoPosition, msg, frontEnd.ERROR)
+ val command = new CompilerCommand(arguments.toList, errorFn)
+ command.settings.outputDirs setSingleOutput virtualDirectory
+ val instance = new ToolBoxGlobal(command.settings, new FrontEndToReporterProxy(frontEnd) { val settings = command.settings })
+ if (frontEnd.hasErrors) {
+ var msg = "reflective compilation has failed: cannot initialize the compiler: " + EOL + EOL
+ msg += frontEnd.infos map (_.msg) mkString EOL
+ throw new ToolBoxError(this, msg)
+ }
+ instance.phase = (new instance.Run).typerPhase // need to manually set a phase, because otherwise TypeHistory will crash
+ instance
+ } catch {
+ case ex: Throwable =>
+ var msg = "reflective compilation has failed: cannot initialize the compiler due to %s".format(ex.toString)
+ throw new ToolBoxError(this, msg, ex)
}
-
- command.settings.outputDirs setSingleOutput virtualDirectory
- val instance = new ToolBoxGlobal(command.settings, reporter)
-
- // need to establish a run an phase because otherwise we run into an assertion in TypeHistory
- // that states that the period must be different from NoPeriod
- val run = new instance.Run
- instance.phase = run.refchecksPhase
- instance
}
- lazy val importer = new compiler.Importer {
- val from: self.type = self
- }
+ // @Eugene: how do I make this work without casts?
+ // lazy val importer = compiler.mkImporter(self)
+ lazy val importer = compiler.mkImporter(self).asInstanceOf[compiler.Importer { val from: self.type }]
lazy val exporter = importer.reverse
- lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, defaultReflectiveClassLoader)
+ lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, self.classLoader)
- def typeCheck(tree: rm.Tree, expectedType: rm.Type): rm.Tree = {
- if (compiler.settings.verbose.value) println("typing "+tree+", pt = "+expectedType)
- val ctree: compiler.Tree = importer.importTree(tree.asInstanceOf[Tree])
- val pt: compiler.Type = importer.importType(expectedType.asInstanceOf[Type])
- val ttree: compiler.Tree = compiler.typedTopLevelExpr(ctree, pt)
- val rmttree = exporter.importTree(ttree).asInstanceOf[rm.Tree]
+ def typeCheck(tree: Tree, expectedType: Type = WildcardType, freeTypes: Map[FreeType, Type] = Map[FreeType, Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = {
+ if (compiler.settings.verbose.value) println("typing "+tree+", expectedType = "+expectedType+", freeTypes = "+freeTypes)
+ var ctree: compiler.Tree = importer.importTree(tree)
+ var cexpectedType: compiler.Type = importer.importType(expectedType)
+
+ if (compiler.settings.verbose.value) println("substituting "+ctree+", expectedType = "+expectedType)
+ val cfreeTypes: Map[compiler.FreeType, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeType], importer.importType(v)) }
+ ctree = compiler.substituteFreeTypes(ctree, cfreeTypes)
+ cexpectedType = compiler.substituteFreeTypes(cexpectedType, cfreeTypes)
+
+ if (compiler.settings.verbose.value) println("typing "+ctree+", expectedType = "+expectedType)
+ val ttree: compiler.Tree = compiler.typeCheckExpr(ctree, cexpectedType, silent = silent, withImplicitViewsDisabled = withImplicitViewsDisabled, withMacrosDisabled = withMacrosDisabled)
+ val rmttree = exporter.importTree(ttree)
rmttree
}
- def typeCheck(tree: rm.Tree): rm.Tree =
- typeCheck(tree, WildcardType.asInstanceOf[rm.Type])
+ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): Tree =
+ // todo. implement this
+ ???
+
+ def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): Tree =
+ // todo. implement this
+ ???
+
+ def resetAllAttrs[T <: Tree](tree: T): T = {
+ val ctree: compiler.Tree = importer.importTree(tree)
+ val ttree: compiler.Tree = compiler.resetAllAttrs(ctree)
+ val rmttree = exporter.importTree(ttree)
+ rmttree.asInstanceOf[T]
+ }
+
+ def resetLocalAttrs[T <: Tree](tree: T): T = {
+ val ctree: compiler.Tree = importer.importTree(tree)
+ val ttree: compiler.Tree = compiler.resetLocalAttrs(ctree)
+ val rmttree = exporter.importTree(ttree)
+ rmttree.asInstanceOf[T]
+ }
+
+ def showAttributed(tree: Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String =
+ compiler.showAttributed(importer.importTree(tree), printTypes, printIds, printKinds)
+
+ def runExpr(tree: Tree, freeTypes: Map[FreeType, Type] = Map[FreeType, Type]()): Any = {
+ if (compiler.settings.verbose.value) println("running "+tree+", freeTypes = "+freeTypes)
+ var ctree: compiler.Tree = importer.importTree(tree)
- def showAttributed(tree: rm.Tree, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String =
- compiler.showAttributed(importer.importTree(tree.asInstanceOf[Tree]), printTypes, printIds, printKinds)
+ if (compiler.settings.verbose.value) println("substituting "+ctree)
+ val cfreeTypes: Map[compiler.FreeType, compiler.Type] = freeTypes map { case (k, v) => (importer.importSymbol(k).asInstanceOf[compiler.FreeType], importer.importType(v)) }
+ ctree = compiler.substituteFreeTypes(ctree, cfreeTypes)
- def runExpr(tree: rm.Tree): Any = {
- if (compiler.settings.verbose.value) println("running "+tree)
- val ctree: compiler.Tree = importer.importTree(tree.asInstanceOf[Tree])
+ if (compiler.settings.verbose.value) println("running "+ctree)
compiler.runExpr(ctree)
}
+
+ class ToolBoxError(val toolBox: ToolBox, val message: String, val cause: Throwable = null) extends Throwable(message, cause)
+
+ object ToolBoxError extends ToolBoxErrorExtractor {
+ def unapply(error: ToolBoxError): Option[(ToolBox, String)] = Some((error.toolBox, error.message))
+ }
}
}
diff --git a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala b/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
deleted file mode 100644
index 61001a4778..0000000000
--- a/src/compiler/scala/reflect/runtime/TreeBuildUtil.scala
+++ /dev/null
@@ -1,49 +0,0 @@
-package scala.reflect
-package runtime
-
-trait TreeBuildUtil extends Universe with api.TreeBuildUtil {
- /** A comment to the effect of why initialize was added to all these
- * would be appreciated. (We may as well start somewhere.)
- */
- def staticClass(fullname: String) = definitions.getRequiredClass(fullname).initialize
- def staticModule(fullname: String) = definitions.getRequiredModule(fullname).initialize
- def thisModuleType(fullname: String) = staticModule(fullname).moduleClass.initialize.thisType
-
- /** Selects type symbol with given name from the defined members of prefix type
- */
- def selectType(owner: Symbol, name: String): Symbol =
- owner.info.decl(newTypeName(name))
-
- /** Selects term symbol with given name and type from the defined members of prefix type
- * @pre The prefix type
- * @name The name of the selected member
- */
- def selectTerm(owner: Symbol, name: String): Symbol = {
- val sym = owner.info.decl(newTermName(name))
- if (sym.isOverloaded) sym suchThat (!_.isMethod)
- else sym
- }
-
- def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol =
- owner.info.decl(newTermName(name)).alternatives(index)
-
- def selectParam(owner: Symbol, idx: Int): Symbol = {
- def selectInList(params: List[Symbol], idx: Int, fallback: Type): Symbol = {
- if (params.isEmpty) selectIn(fallback, idx)
- else if (idx == 0) params.head
- else selectInList(params.tail, idx - 1, fallback)
- }
- def selectIn(tpe: Type, idx: Int): Symbol = tpe match {
- case PolyType(tparams, res) => selectInList(tparams, idx, res)
- case MethodType(params, res) => selectInList(params, idx, res)
- case _ => NoSymbol
- }
- selectIn(owner.info, idx)
- }
-
- def newFreeVar(name: String, info: Type, value: Any) = newFreeVar(newTermName(name), info, value)
-
- def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers =
- Modifiers(flags, privateWithin, annotations)
-
-} \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/Universe.scala b/src/compiler/scala/reflect/runtime/Universe.scala
index 7a5dda3d8e..fd53308d0a 100644
--- a/src/compiler/scala/reflect/runtime/Universe.scala
+++ b/src/compiler/scala/reflect/runtime/Universe.scala
@@ -8,12 +8,14 @@ import internal.{SomePhase, NoPhase, Phase, TreeGen}
* It also provides methods to go from Java members to Scala members,
* using the code in JavaConversions.
*/
-class Universe extends SymbolTable {
+abstract class Universe extends SymbolTable with ToolBoxes {
type AbstractFileType = AbstractFile
def picklerPhase = SomePhase
+ type TreeGen = internal.TreeGen
+
val gen = new TreeGen { val global: Universe.this.type = Universe.this }
lazy val settings = new Settings
@@ -30,24 +32,12 @@ class Universe extends SymbolTable {
def newStrictTreeCopier: TreeCopier = new StrictTreeCopier
def newLazyTreeCopier: TreeCopier = new LazyTreeCopier
- def focusPos(pos: Position) = pos
- def isRangePos(pos: Position) = false
- def showPos(pos: Position) = "<unknown position>"
-
- type Position = String // source file?
- val NoPosition = ""
-
definitions.AnyValClass // force it.
- type TreeAnnotation = Position
- val NoTreeAnnotation: TreeAnnotation = NoPosition
- def positionToAnnotation(pos: Position): TreeAnnotation = pos // TODO
- def annotationToPosition(annot: TreeAnnotation): Position = annot //TODO
-
// establish root association to avoid cyclic dependency errors later
- classToScala(classOf[java.lang.Object]).initialize
+ // don't use classOf[...] here, because it gets serviced by getClass.getClassLoader!
+ classToScala(Class.forName("java.lang.Object", true, classLoader)).initialize
// println("initializing definitions")
definitions.init()
-
}
diff --git a/src/compiler/scala/reflect/runtime/package.scala b/src/compiler/scala/reflect/runtime/package.scala
new file mode 100644
index 0000000000..52ab2c5deb
--- /dev/null
+++ b/src/compiler/scala/reflect/runtime/package.scala
@@ -0,0 +1,5 @@
+package scala.reflect
+
+package object runtime {
+ def mkMirror(classLoader: ClassLoader): api.Mirror = new Mirror(classLoader)
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/ant/Scaladoc.scala b/src/compiler/scala/tools/ant/Scaladoc.scala
index c92474b33e..daa08ef8a7 100644
--- a/src/compiler/scala/tools/ant/Scaladoc.scala
+++ b/src/compiler/scala/tools/ant/Scaladoc.scala
@@ -75,6 +75,11 @@ class Scaladoc extends ScalaMatchingTask {
*/
object Flag extends PermissibleValue {
val values = List("yes", "no", "on", "off")
+ def getBooleanValue(value: String, flagName: String): Boolean =
+ if (Flag.isPermissible(value))
+ return ("yes".equals(value) || "on".equals(value))
+ else
+ buildError("Unknown " + flagName + " flag '" + value + "'")
}
/** The directories that contain source files to compile. */
@@ -127,6 +132,25 @@ class Scaladoc extends ScalaMatchingTask {
/** Instruct the ant task not to fail in the event of errors */
private var nofail: Boolean = false
+ /** Instruct the scaladoc tool to document implicit conversions */
+ private var docImplicits: Boolean = false
+
+ /** Instruct the scaladoc tool to document all (including impossible) implicit conversions */
+ private var docImplicitsShowAll: Boolean = false
+
+ /** Instruct the scaladoc tool to output implicits debugging information */
+ private var docImplicitsDebug: Boolean = false
+
+ /** Instruct the scaladoc tool to create diagrams */
+ private var docDiagrams: Boolean = false
+
+ /** Instruct the scaladoc tool to output diagram creation debugging information */
+ private var docDiagramsDebug: Boolean = false
+
+ /** Instruct the scaladoc tool to use the binary given to create diagrams */
+ private var docDiagramsDotPath: Option[String] = None
+
+
/*============================================================================*\
** Properties setters **
\*============================================================================*/
@@ -361,12 +385,39 @@ class Scaladoc extends ScalaMatchingTask {
*
* @param input One of the flags `yes/no` or `on/off`. Default if no/off.
*/
- def setNoFail(input: String) {
- if (Flag.isPermissible(input))
- nofail = "yes".equals(input) || "on".equals(input)
- else
- buildError("Unknown nofail flag '" + input + "'")
- }
+ def setNoFail(input: String) =
+ nofail = Flag.getBooleanValue(input, "nofail")
+
+ /** Set the `implicits` info attribute.
+ * @param input One of the flags `yes/no` or `on/off`. Default if no/off. */
+ def setImplicits(input: String) =
+ docImplicits = Flag.getBooleanValue(input, "implicits")
+
+ /** Set the `implicitsShowAll` info attribute to enable scaladoc to show all implicits, including those impossible to
+ * convert to from the default scope
+ * @param input One of the flags `yes/no` or `on/off`. Default if no/off. */
+ def setImplicitsShowAll(input: String) =
+ docImplicitsShowAll = Flag.getBooleanValue(input, "implicitsShowAll")
+
+ /** Set the `implicitsDebug` info attribute so scaladoc outputs implicit conversion debug information
+ * @param input One of the flags `yes/no` or `on/off`. Default if no/off. */
+ def setImplicitsDebug(input: String) =
+ docImplicitsDebug = Flag.getBooleanValue(input, "implicitsDebug")
+
+ /** Set the `diagrams` bit so Scaladoc adds diagrams to the documentation
+ * @param input One of the flags `yes/no` or `on/off`. Default if no/off. */
+ def setDiagrams(input: String) =
+ docDiagrams = Flag.getBooleanValue(input, "diagrams")
+
+ /** Set the `diagramsDebug` bit so Scaladoc outputs diagram building debug information
+ * @param input One of the flags `yes/no` or `on/off`. Default if no/off. */
+ def setDiagramsDebug(input: String) =
+ docDiagramsDebug = Flag.getBooleanValue(input, "diagramsDebug")
+
+ /** Set the `diagramsDotPath` attribute to the path where graphviz dot can be found (including the binary file name,
+ * eg: /usr/bin/dot) */
+ def setDiagramsDotPath(input: String) =
+ docDiagramsDotPath = Some(input)
/*============================================================================*\
** Properties getters **
@@ -560,6 +611,13 @@ class Scaladoc extends ScalaMatchingTask {
docSettings.deprecation.value = deprecation
docSettings.unchecked.value = unchecked
+ docSettings.docImplicits.value = docImplicits
+ docSettings.docImplicitsDebug.value = docImplicitsDebug
+ docSettings.docImplicitsShowAll.value = docImplicitsShowAll
+ docSettings.docDiagrams.value = docDiagrams
+ docSettings.docDiagramsDebug.value = docDiagramsDebug
+ if(!docDiagramsDotPath.isEmpty) docSettings.docDiagramsDotPath.value = docDiagramsDotPath.get
+
if (!docgenerator.isEmpty) docSettings.docgenerator.value = docgenerator.get
if (!docrootcontent.isEmpty) docSettings.docRootContent.value = docrootcontent.get.getAbsolutePath()
log("Scaladoc params = '" + addParams + "'", Project.MSG_DEBUG)
diff --git a/src/compiler/scala/tools/asm/AnnotationVisitor.java b/src/compiler/scala/tools/asm/AnnotationVisitor.java
new file mode 100644
index 0000000000..b96e730a73
--- /dev/null
+++ b/src/compiler/scala/tools/asm/AnnotationVisitor.java
@@ -0,0 +1,157 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A visitor to visit a Java annotation. The methods of this class must be
+ * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
+ * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public abstract class AnnotationVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4}.
+ */
+ protected final int api;
+
+ /**
+ * The annotation visitor to which this visitor must delegate method calls.
+ * May be null.
+ */
+ protected AnnotationVisitor av;
+
+ /**
+ * Constructs a new {@link AnnotationVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ public AnnotationVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link AnnotationVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param av the annotation visitor to which this visitor must delegate
+ * method calls. May be null.
+ */
+ public AnnotationVisitor(final int api, final AnnotationVisitor av) {
+ /*if (api != Opcodes.ASM4) {
+ throw new IllegalArgumentException();
+ }*/
+ this.api = api;
+ this.av = av;
+ }
+
+ /**
+ * Visits a primitive value of the annotation.
+ *
+ * @param name the value name.
+ * @param value the actual value, whose type must be {@link Byte},
+ * {@link Boolean}, {@link Character}, {@link Short}, {@link Integer}
+ * , {@link Long}, {@link Float}, {@link Double}, {@link String} or
+ * {@link Type} or OBJECT or ARRAY sort. This value can also be an
+ * array of byte, boolean, short, char, int, long, float or double
+ * values (this is equivalent to using {@link #visitArray visitArray}
+ * and visiting each array element in turn, but is more convenient).
+ */
+ public void visit(String name, Object value) {
+ if (av != null) {
+ av.visit(name, value);
+ }
+ }
+
+ /**
+ * Visits an enumeration value of the annotation.
+ *
+ * @param name the value name.
+ * @param desc the class descriptor of the enumeration class.
+ * @param value the actual enumeration value.
+ */
+ public void visitEnum(String name, String desc, String value) {
+ if (av != null) {
+ av.visitEnum(name, desc, value);
+ }
+ }
+
+ /**
+ * Visits a nested annotation value of the annotation.
+ *
+ * @param name the value name.
+ * @param desc the class descriptor of the nested annotation class.
+ * @return a visitor to visit the actual nested annotation value, or
+ * <tt>null</tt> if this visitor is not interested in visiting
+ * this nested annotation. <i>The nested annotation value must be
+ * fully visited before calling other methods on this annotation
+ * visitor</i>.
+ */
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ if (av != null) {
+ return av.visitAnnotation(name, desc);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an array value of the annotation. Note that arrays of primitive
+ * types (such as byte, boolean, short, char, int, long, float or double)
+ * can be passed as value to {@link #visit visit}. This is what
+ * {@link ClassReader} does.
+ *
+ * @param name the value name.
+ * @return a visitor to visit the actual array value elements, or
+ * <tt>null</tt> if this visitor is not interested in visiting
+ * these values. The 'name' parameters passed to the methods of this
+ * visitor are ignored. <i>All the array values must be visited
+ * before calling other methods on this annotation visitor</i>.
+ */
+ public AnnotationVisitor visitArray(String name) {
+ if (av != null) {
+ return av.visitArray(name);
+ }
+ return null;
+ }
+
+ /**
+ * Visits the end of the annotation.
+ */
+ public void visitEnd() {
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/AnnotationWriter.java b/src/compiler/scala/tools/asm/AnnotationWriter.java
new file mode 100644
index 0000000000..e530780249
--- /dev/null
+++ b/src/compiler/scala/tools/asm/AnnotationWriter.java
@@ -0,0 +1,322 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * An {@link AnnotationVisitor} that generates annotations in bytecode form.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+final class AnnotationWriter extends AnnotationVisitor {
+
+ /**
+ * The class writer to which this annotation must be added.
+ */
+ private final ClassWriter cw;
+
+ /**
+ * The number of values in this annotation.
+ */
+ private int size;
+
+ /**
+ * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
+ * writers used for annotation default and annotation arrays use unnamed
+ * values.
+ */
+ private final boolean named;
+
+ /**
+ * The annotation values in bytecode form. This byte vector only contains
+ * the values themselves, i.e. the number of values must be stored as a
+ * unsigned short just before these bytes.
+ */
+ private final ByteVector bv;
+
+ /**
+ * The byte vector to be used to store the number of values of this
+ * annotation. See {@link #bv}.
+ */
+ private final ByteVector parent;
+
+ /**
+ * Where the number of values of this annotation must be stored in
+ * {@link #parent}.
+ */
+ private final int offset;
+
+ /**
+ * Next annotation writer. This field is used to store annotation lists.
+ */
+ AnnotationWriter next;
+
+ /**
+ * Previous annotation writer. This field is used to store annotation lists.
+ */
+ AnnotationWriter prev;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link AnnotationWriter}.
+ *
+ * @param cw the class writer to which this annotation must be added.
+ * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+ * @param bv where the annotation values must be stored.
+ * @param parent where the number of annotation values must be stored.
+ * @param offset where in <tt>parent</tt> the number of annotation values must
+ * be stored.
+ */
+ AnnotationWriter(
+ final ClassWriter cw,
+ final boolean named,
+ final ByteVector bv,
+ final ByteVector parent,
+ final int offset)
+ {
+ super(Opcodes.ASM4);
+ this.cw = cw;
+ this.named = named;
+ this.bv = bv;
+ this.parent = parent;
+ this.offset = offset;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ if (value instanceof String) {
+ bv.put12('s', cw.newUTF8((String) value));
+ } else if (value instanceof Byte) {
+ bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
+ } else if (value instanceof Boolean) {
+ int v = ((Boolean) value).booleanValue() ? 1 : 0;
+ bv.put12('Z', cw.newInteger(v).index);
+ } else if (value instanceof Character) {
+ bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
+ } else if (value instanceof Short) {
+ bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
+ } else if (value instanceof Type) {
+ bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
+ } else if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('B', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('S', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('C', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('I', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('J', cw.newLong(v[i]).index);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('F', cw.newFloat(v[i]).index);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('D', cw.newDouble(v[i]).index);
+ }
+ } else {
+ Item i = cw.newConstItem(value);
+ bv.put12(".s.IFJDCS".charAt(i.type), i.index);
+ }
+ }
+
+ @Override
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ // write tag and type, and reserve space for values count
+ bv.put12('@', cw.newUTF8(desc)).putShort(0);
+ return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ // write tag, and reserve space for array size
+ bv.put12('[', 0);
+ return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (parent != null) {
+ byte[] data = parent.data;
+ data[offset] = (byte) (size >>> 8);
+ data[offset + 1] = (byte) size;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of this annotation writer list.
+ *
+ * @return the size of this annotation writer list.
+ */
+ int getSize() {
+ int size = 0;
+ AnnotationWriter aw = this;
+ while (aw != null) {
+ size += aw.bv.length;
+ aw = aw.next;
+ }
+ return size;
+ }
+
+ /**
+ * Puts the annotations of this annotation writer list into the given byte
+ * vector.
+ *
+ * @param out where the annotations must be put.
+ */
+ void put(final ByteVector out) {
+ int n = 0;
+ int size = 2;
+ AnnotationWriter aw = this;
+ AnnotationWriter last = null;
+ while (aw != null) {
+ ++n;
+ size += aw.bv.length;
+ aw.visitEnd(); // in case user forgot to call visitEnd
+ aw.prev = last;
+ last = aw;
+ aw = aw.next;
+ }
+ out.putInt(size);
+ out.putShort(n);
+ aw = last;
+ while (aw != null) {
+ out.putByteArray(aw.bv.data, 0, aw.bv.length);
+ aw = aw.prev;
+ }
+ }
+
+ /**
+ * Puts the given annotation lists into the given byte vector.
+ *
+ * @param panns an array of annotation writer lists.
+ * @param off index of the first annotation to be written.
+ * @param out where the annotations must be put.
+ */
+ static void put(
+ final AnnotationWriter[] panns,
+ final int off,
+ final ByteVector out)
+ {
+ int size = 1 + 2 * (panns.length - off);
+ for (int i = off; i < panns.length; ++i) {
+ size += panns[i] == null ? 0 : panns[i].getSize();
+ }
+ out.putInt(size).putByte(panns.length - off);
+ for (int i = off; i < panns.length; ++i) {
+ AnnotationWriter aw = panns[i];
+ AnnotationWriter last = null;
+ int n = 0;
+ while (aw != null) {
+ ++n;
+ aw.visitEnd(); // in case user forgot to call visitEnd
+ aw.prev = last;
+ last = aw;
+ aw = aw.next;
+ }
+ out.putShort(n);
+ aw = last;
+ while (aw != null) {
+ out.putByteArray(aw.bv.data, 0, aw.bv.length);
+ aw = aw.prev;
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/Attribute.java b/src/compiler/scala/tools/asm/Attribute.java
new file mode 100644
index 0000000000..408f21ce1e
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Attribute.java
@@ -0,0 +1,254 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A non standard class, field, method or code attribute.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Attribute {
+
+ /**
+ * The type of this attribute.
+ */
+ public final String type;
+
+ /**
+ * The raw value of this attribute, used only for unknown attributes.
+ */
+ byte[] value;
+
+ /**
+ * The next attribute in this attribute list. May be <tt>null</tt>.
+ */
+ Attribute next;
+
+ /**
+ * Constructs a new empty attribute.
+ *
+ * @param type the type of the attribute.
+ */
+ protected Attribute(final String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this type of attribute is unknown. The default
+ * implementation of this method always returns <tt>true</tt>.
+ *
+ * @return <tt>true</tt> if this type of attribute is unknown.
+ */
+ public boolean isUnknown() {
+ return true;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this type of attribute is a code attribute.
+ *
+ * @return <tt>true</tt> if this type of attribute is a code attribute.
+ */
+ public boolean isCodeAttribute() {
+ return false;
+ }
+
+ /**
+ * Returns the labels corresponding to this attribute.
+ *
+ * @return the labels corresponding to this attribute, or <tt>null</tt> if
+ * this attribute is not a code attribute that contains labels.
+ */
+ protected Label[] getLabels() {
+ return null;
+ }
+
+ /**
+ * Reads a {@link #type type} attribute. This method must return a <i>new</i>
+ * {@link Attribute} object, of type {@link #type type}, corresponding to
+ * the <tt>len</tt> bytes starting at the given offset, in the given class
+ * reader.
+ *
+ * @param cr the class that contains the attribute to be read.
+ * @param off index of the first byte of the attribute's content in {@link
+ * ClassReader#b cr.b}. The 6 attribute header bytes, containing the
+ * type and the length of the attribute, are not taken into account
+ * here.
+ * @param len the length of the attribute's content.
+ * @param buf buffer to be used to call
+ * {@link ClassReader#readUTF8 readUTF8},
+ * {@link ClassReader#readClass(int,char[]) readClass} or
+ * {@link ClassReader#readConst readConst}.
+ * @param codeOff index of the first byte of code's attribute content in
+ * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
+ * not a code attribute. The 6 attribute header bytes, containing the
+ * type and the length of the attribute, are not taken into account
+ * here.
+ * @param labels the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
+ * @return a <i>new</i> {@link Attribute} object corresponding to the given
+ * bytes.
+ */
+ protected Attribute read(
+ final ClassReader cr,
+ final int off,
+ final int len,
+ final char[] buf,
+ final int codeOff,
+ final Label[] labels)
+ {
+ Attribute attr = new Attribute(type);
+ attr.value = new byte[len];
+ System.arraycopy(cr.b, off, attr.value, 0, len);
+ return attr;
+ }
+
+ /**
+ * Returns the byte array form of this attribute.
+ *
+ * @param cw the class to which this attribute must be added. This parameter
+ * can be used to add to the constant pool of this class the items
+ * that corresponds to this attribute.
+ * @param code the bytecode of the method corresponding to this code
+ * attribute, or <tt>null</tt> if this attribute is not a code
+ * attributes.
+ * @param len the length of the bytecode of the method corresponding to this
+ * code attribute, or <tt>null</tt> if this attribute is not a code
+ * attribute.
+ * @param maxStack the maximum stack size of the method corresponding to
+ * this code attribute, or -1 if this attribute is not a code
+ * attribute.
+ * @param maxLocals the maximum number of local variables of the method
+ * corresponding to this code attribute, or -1 if this attribute is
+ * not a code attribute.
+ * @return the byte array form of this attribute.
+ */
+ protected ByteVector write(
+ final ClassWriter cw,
+ final byte[] code,
+ final int len,
+ final int maxStack,
+ final int maxLocals)
+ {
+ ByteVector v = new ByteVector();
+ v.data = value;
+ v.length = value.length;
+ return v;
+ }
+
+ /**
+ * Returns the length of the attribute list that begins with this attribute.
+ *
+ * @return the length of the attribute list that begins with this attribute.
+ */
+ final int getCount() {
+ int count = 0;
+ Attribute attr = this;
+ while (attr != null) {
+ count += 1;
+ attr = attr.next;
+ }
+ return count;
+ }
+
+ /**
+ * Returns the size of all the attributes in this attribute list.
+ *
+ * @param cw the class writer to be used to convert the attributes into byte
+ * arrays, with the {@link #write write} method.
+ * @param code the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes are
+ * not code attributes.
+ * @param maxStack the maximum stack size of the method corresponding to
+ * these code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these attributes
+ * are not code attributes.
+ * @return the size of all the attributes in this attribute list. This size
+ * includes the size of the attribute headers.
+ */
+ final int getSize(
+ final ClassWriter cw,
+ final byte[] code,
+ final int len,
+ final int maxStack,
+ final int maxLocals)
+ {
+ Attribute attr = this;
+ int size = 0;
+ while (attr != null) {
+ cw.newUTF8(attr.type);
+ size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
+ attr = attr.next;
+ }
+ return size;
+ }
+
+ /**
+ * Writes all the attributes of this attribute list in the given byte
+ * vector.
+ *
+ * @param cw the class writer to be used to convert the attributes into byte
+ * arrays, with the {@link #write write} method.
+ * @param code the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes are
+ * not code attributes.
+ * @param maxStack the maximum stack size of the method corresponding to
+ * these code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these attributes
+ * are not code attributes.
+ * @param out where the attributes must be written.
+ */
+ final void put(
+ final ClassWriter cw,
+ final byte[] code,
+ final int len,
+ final int maxStack,
+ final int maxLocals,
+ final ByteVector out)
+ {
+ Attribute attr = this;
+ while (attr != null) {
+ ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
+ out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
+ out.putByteArray(b.data, 0, b.length);
+ attr = attr.next;
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/ByteVector.java b/src/compiler/scala/tools/asm/ByteVector.java
new file mode 100644
index 0000000000..5081f0184b
--- /dev/null
+++ b/src/compiler/scala/tools/asm/ByteVector.java
@@ -0,0 +1,293 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to
+ * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
+ *
+ * @author Eric Bruneton
+ */
+public class ByteVector {
+
+ /**
+ * The content of this vector.
+ */
+ byte[] data;
+
+ /**
+ * Actual number of bytes in this vector.
+ */
+ int length;
+
+ /**
+ * Constructs a new {@link ByteVector ByteVector} with a default initial
+ * size.
+ */
+ public ByteVector() {
+ data = new byte[64];
+ }
+
+ /**
+ * Constructs a new {@link ByteVector ByteVector} with the given initial
+ * size.
+ *
+ * @param initialSize the initial size of the byte vector to be constructed.
+ */
+ public ByteVector(final int initialSize) {
+ data = new byte[initialSize];
+ }
+
+ /**
+ * Puts a byte into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param b a byte.
+ * @return this byte vector.
+ */
+ public ByteVector putByte(final int b) {
+ int length = this.length;
+ if (length + 1 > data.length) {
+ enlarge(1);
+ }
+ data[length++] = (byte) b;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts two bytes into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param b1 a byte.
+ * @param b2 another byte.
+ * @return this byte vector.
+ */
+ ByteVector put11(final int b1, final int b2) {
+ int length = this.length;
+ if (length + 2 > data.length) {
+ enlarge(2);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) b1;
+ data[length++] = (byte) b2;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a short into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param s a short.
+ * @return this byte vector.
+ */
+ public ByteVector putShort(final int s) {
+ int length = this.length;
+ if (length + 2 > data.length) {
+ enlarge(2);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) (s >>> 8);
+ data[length++] = (byte) s;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a byte and a short into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param b a byte.
+ * @param s a short.
+ * @return this byte vector.
+ */
+ ByteVector put12(final int b, final int s) {
+ int length = this.length;
+ if (length + 3 > data.length) {
+ enlarge(3);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) b;
+ data[length++] = (byte) (s >>> 8);
+ data[length++] = (byte) s;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts an int into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param i an int.
+ * @return this byte vector.
+ */
+ public ByteVector putInt(final int i) {
+ int length = this.length;
+ if (length + 4 > data.length) {
+ enlarge(4);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a long into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param l a long.
+ * @return this byte vector.
+ */
+ public ByteVector putLong(final long l) {
+ int length = this.length;
+ if (length + 8 > data.length) {
+ enlarge(8);
+ }
+ byte[] data = this.data;
+ int i = (int) (l >>> 32);
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ i = (int) l;
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param s a String.
+ * @return this byte vector.
+ */
+ public ByteVector putUTF8(final String s) {
+ int charLength = s.length();
+ int len = length;
+ if (len + 2 + charLength > data.length) {
+ enlarge(2 + charLength);
+ }
+ byte[] data = this.data;
+ // optimistic algorithm: instead of computing the byte length and then
+ // serializing the string (which requires two loops), we assume the byte
+ // length is equal to char length (which is the most frequent case), and
+ // we start serializing the string right away. During the serialization,
+ // if we find that this assumption is wrong, we continue with the
+ // general method.
+ data[len++] = (byte) (charLength >>> 8);
+ data[len++] = (byte) charLength;
+ for (int i = 0; i < charLength; ++i) {
+ char c = s.charAt(i);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else {
+ int byteLength = i;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ byteLength++;
+ } else if (c > '\u07FF') {
+ byteLength += 3;
+ } else {
+ byteLength += 2;
+ }
+ }
+ data[length] = (byte) (byteLength >>> 8);
+ data[length + 1] = (byte) byteLength;
+ if (length + 2 + byteLength > data.length) {
+ length = len;
+ enlarge(2 + byteLength);
+ data = this.data;
+ }
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else if (c > '\u07FF') {
+ data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+ data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ } else {
+ data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ }
+ }
+ break;
+ }
+ }
+ length = len;
+ return this;
+ }
+
+ /**
+ * Puts an array of bytes into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+ * null bytes into this byte vector.
+ * @param off index of the fist byte of b that must be copied.
+ * @param len number of bytes of b that must be copied.
+ * @return this byte vector.
+ */
+ public ByteVector putByteArray(final byte[] b, final int off, final int len)
+ {
+ if (length + len > data.length) {
+ enlarge(len);
+ }
+ if (b != null) {
+ System.arraycopy(b, off, data, length, len);
+ }
+ length += len;
+ return this;
+ }
+
+ /**
+ * Enlarge this byte vector so that it can receive n more bytes.
+ *
+ * @param size number of additional bytes that this byte vector should be
+ * able to receive.
+ */
+ private void enlarge(final int size) {
+ int length1 = 2 * data.length;
+ int length2 = length + size;
+ byte[] newData = new byte[length1 > length2 ? length1 : length2];
+ System.arraycopy(data, 0, newData, 0, length);
+ data = newData;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/ClassReader.java b/src/compiler/scala/tools/asm/ClassReader.java
new file mode 100644
index 0000000000..f3287d41ae
--- /dev/null
+++ b/src/compiler/scala/tools/asm/ClassReader.java
@@ -0,0 +1,2216 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A Java class parser to make a {@link ClassVisitor} visit an existing class.
+ * This class parses a byte array conforming to the Java class file format and
+ * calls the appropriate visit methods of a given class visitor for each field,
+ * method and bytecode instruction encountered.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassReader {
+
+ /**
+ * True to enable signatures support.
+ */
+ static final boolean SIGNATURES = true;
+
+ /**
+ * True to enable annotations support.
+ */
+ static final boolean ANNOTATIONS = true;
+
+ /**
+ * True to enable stack map frames support.
+ */
+ static final boolean FRAMES = true;
+
+ /**
+ * True to enable bytecode writing support.
+ */
+ static final boolean WRITER = true;
+
+ /**
+ * True to enable JSR_W and GOTO_W support.
+ */
+ static final boolean RESIZE = true;
+
+ /**
+ * Flag to skip method code. If this class is set <code>CODE</code>
+ * attribute won't be visited. This can be used, for example, to retrieve
+ * annotations for methods and method parameters.
+ */
+ public static final int SKIP_CODE = 1;
+
+ /**
+ * Flag to skip the debug information in the class. If this flag is set the
+ * debug information of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+ * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
+ * called.
+ */
+ public static final int SKIP_DEBUG = 2;
+
+ /**
+ * Flag to skip the stack map frames in the class. If this flag is set the
+ * stack map frames of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
+ * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
+ * used: it avoids visiting frames that will be ignored and recomputed from
+ * scratch in the class writer.
+ */
+ public static final int SKIP_FRAMES = 4;
+
+ /**
+ * Flag to expand the stack map frames. By default stack map frames are
+ * visited in their original format (i.e. "expanded" for classes whose
+ * version is less than V1_6, and "compressed" for the other classes). If
+ * this flag is set, stack map frames are always visited in expanded format
+ * (this option adds a decompression/recompression step in ClassReader and
+ * ClassWriter which degrades performances quite a lot).
+ */
+ public static final int EXPAND_FRAMES = 8;
+
+ /**
+ * The class to be parsed. <i>The content of this array must not be
+ * modified. This field is intended for {@link Attribute} sub classes, and
+ * is normally not needed by class generators or adapters.</i>
+ */
+ public final byte[] b;
+
+ /**
+ * The start index of each constant pool item in {@link #b b}, plus one.
+ * The one byte offset skips the constant pool item tag that indicates its
+ * type.
+ */
+ private final int[] items;
+
+ /**
+ * The String objects corresponding to the CONSTANT_Utf8 items. This cache
+ * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
+ * which GREATLY improves performances (by a factor 2 to 3). This caching
+ * strategy could be extended to all constant pool items, but its benefit
+ * would not be so great for these items (because they are much less
+ * expensive to parse than CONSTANT_Utf8 items).
+ */
+ private final String[] strings;
+
+ /**
+ * Maximum length of the strings contained in the constant pool of the
+ * class.
+ */
+ private final int maxStringLength;
+
+ /**
+ * Start index of the class header information (access, name...) in
+ * {@link #b b}.
+ */
+ public final int header;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b the bytecode of the class to be read.
+ */
+ public ClassReader(final byte[] b) {
+ this(b, 0, b.length);
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b the bytecode of the class to be read.
+ * @param off the start offset of the class data.
+ * @param len the length of the class data.
+ */
+ public ClassReader(final byte[] b, final int off, final int len) {
+ this.b = b;
+ // checks the class version
+ if (readShort(6) > Opcodes.V1_7) {
+ throw new IllegalArgumentException();
+ }
+ // parses the constant pool
+ items = new int[readUnsignedShort(off + 8)];
+ int n = items.length;
+ strings = new String[n];
+ int max = 0;
+ int index = off + 10;
+ for (int i = 1; i < n; ++i) {
+ items[i] = index + 1;
+ int size;
+ switch (b[index]) {
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ case ClassWriter.NAME_TYPE:
+ case ClassWriter.INDY:
+ size = 5;
+ break;
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ size = 9;
+ ++i;
+ break;
+ case ClassWriter.UTF8:
+ size = 3 + readUnsignedShort(index + 1);
+ if (size > max) {
+ max = size;
+ }
+ break;
+ case ClassWriter.HANDLE:
+ size = 4;
+ break;
+ // case ClassWriter.CLASS:
+ // case ClassWriter.STR:
+ // case ClassWriter.MTYPE
+ default:
+ size = 3;
+ break;
+ }
+ index += size;
+ }
+ maxStringLength = max;
+ // the class header information starts just after the constant pool
+ header = index;
+ }
+
+ /**
+ * Returns the class's access flags (see {@link Opcodes}). This value may
+ * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
+ * and those flags are represented by attributes.
+ *
+ * @return the class access flags
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public int getAccess() {
+ return readUnsignedShort(header);
+ }
+
+ /**
+ * Returns the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the internal class name
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getClassName() {
+ return readClass(header + 2, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For interfaces, the
+ * super class is {@link Object}.
+ *
+ * @return the internal name of super class, or <tt>null</tt> for
+ * {@link Object} class.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getSuperName() {
+ int n = items[readUnsignedShort(header + 4)];
+ return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the array of internal names for all implemented interfaces or
+ * <tt>null</tt>.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String[] getInterfaces() {
+ int index = header + 6;
+ int n = readUnsignedShort(index);
+ String[] interfaces = new String[n];
+ if (n > 0) {
+ char[] buf = new char[maxStringLength];
+ for (int i = 0; i < n; ++i) {
+ index += 2;
+ interfaces[i] = readClass(index, buf);
+ }
+ }
+ return interfaces;
+ }
+
+ /**
+ * Copies the constant pool data into the given {@link ClassWriter}. Should
+ * be called before the {@link #accept(ClassVisitor,int)} method.
+ *
+ * @param classWriter the {@link ClassWriter} to copy constant pool into.
+ */
+ void copyPool(final ClassWriter classWriter) {
+ char[] buf = new char[maxStringLength];
+ int ll = items.length;
+ Item[] items2 = new Item[ll];
+ for (int i = 1; i < ll; i++) {
+ int index = items[i];
+ int tag = b[index - 1];
+ Item item = new Item(i);
+ int nameType;
+ switch (tag) {
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(tag,
+ readClass(index, buf),
+ readUTF8(nameType, buf),
+ readUTF8(nameType + 2, buf));
+ break;
+
+ case ClassWriter.INT:
+ item.set(readInt(index));
+ break;
+
+ case ClassWriter.FLOAT:
+ item.set(Float.intBitsToFloat(readInt(index)));
+ break;
+
+ case ClassWriter.NAME_TYPE:
+ item.set(tag,
+ readUTF8(index, buf),
+ readUTF8(index + 2, buf),
+ null);
+ break;
+
+ case ClassWriter.LONG:
+ item.set(readLong(index));
+ ++i;
+ break;
+
+ case ClassWriter.DOUBLE:
+ item.set(Double.longBitsToDouble(readLong(index)));
+ ++i;
+ break;
+
+ case ClassWriter.UTF8: {
+ String s = strings[i];
+ if (s == null) {
+ index = items[i];
+ s = strings[i] = readUTF(index + 2,
+ readUnsignedShort(index),
+ buf);
+ }
+ item.set(tag, s, null, null);
+ }
+ break;
+
+ case ClassWriter.HANDLE: {
+ int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+ nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+ item.set(ClassWriter.HANDLE_BASE + readByte(index),
+ readClass(fieldOrMethodRef, buf),
+ readUTF8(nameType, buf),
+ readUTF8(nameType + 2, buf));
+
+ }
+ break;
+
+
+ case ClassWriter.INDY:
+ if (classWriter.bootstrapMethods == null) {
+ copyBootstrapMethods(classWriter, items2, buf);
+ }
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(readUTF8(nameType, buf),
+ readUTF8(nameType + 2, buf),
+ readUnsignedShort(index));
+ break;
+
+
+ // case ClassWriter.STR:
+ // case ClassWriter.CLASS:
+ // case ClassWriter.MTYPE
+ default:
+ item.set(tag, readUTF8(index, buf), null, null);
+ break;
+ }
+
+ int index2 = item.hashCode % items2.length;
+ item.next = items2[index2];
+ items2[index2] = item;
+ }
+
+ int off = items[1] - 1;
+ classWriter.pool.putByteArray(b, off, header - off);
+ classWriter.items = items2;
+ classWriter.threshold = (int) (0.75d * ll);
+ classWriter.index = ll;
+ }
+
+ private void copyBootstrapMethods(ClassWriter classWriter, Item[] items2, char[] buf) {
+ int i, j, k, u, v;
+
+ // skip class header
+ v = header;
+ v += 8 + (readUnsignedShort(v + 6) << 1);
+
+ // skips fields and methods
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j) {
+ v += 6 + readInt(v + 2);
+ }
+ }
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j) {
+ v += 6 + readInt(v + 2);
+ }
+ }
+
+ // read class attributes
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ String attrName = readUTF8(v, buf);
+ int size = readInt(v + 2);
+ if ("BootstrapMethods".equals(attrName)) {
+ int boostrapMethodCount = readUnsignedShort(v + 6);
+ int x = v + 8;
+ for (j = 0; j < boostrapMethodCount; j++) {
+ int hashCode = readConst(readUnsignedShort(x), buf).hashCode();
+ k = readUnsignedShort(x + 2);
+ u = x + 4;
+ for(; k > 0; --k) {
+ hashCode ^= readConst(readUnsignedShort(u), buf).hashCode();
+ u += 2;
+ }
+ Item item = new Item(j);
+ item.set(x - v - 8, hashCode & 0x7FFFFFFF);
+
+ int index2 = item.hashCode % items2.length;
+ item.next = items2[index2];
+ items2[index2] = item;
+
+ x = u;
+ }
+
+ classWriter.bootstrapMethodsCount = boostrapMethodCount;
+ ByteVector bootstrapMethods = new ByteVector(size + 62);
+ bootstrapMethods.putByteArray(b, v + 8, size - 2);
+ classWriter.bootstrapMethods = bootstrapMethods;
+ return;
+ }
+ v += 6 + size;
+ }
+
+ // we are in trouble !!!
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param is an input stream from which to read the class.
+ * @throws IOException if a problem occurs during reading.
+ */
+ public ClassReader(final InputStream is) throws IOException {
+ this(readClass(is, false));
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param name the binary qualified name of the class to be read.
+ * @throws IOException if an exception occurs during reading.
+ */
+ public ClassReader(final String name) throws IOException {
+ this(readClass(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+ + ".class"), true));
+ }
+
+ /**
+ * Reads the bytecode of a class.
+ *
+ * @param is an input stream from which to read the class.
+ * @param close true to close the input stream after reading.
+ * @return the bytecode read from the given input stream.
+ * @throws IOException if a problem occurs during reading.
+ */
+ private static byte[] readClass(final InputStream is, boolean close)
+ throws IOException
+ {
+ if (is == null) {
+ throw new IOException("Class not found");
+ }
+ try {
+ byte[] b = new byte[is.available()];
+ int len = 0;
+ while (true) {
+ int n = is.read(b, len, b.length - len);
+ if (n == -1) {
+ if (len < b.length) {
+ byte[] c = new byte[len];
+ System.arraycopy(b, 0, c, 0, len);
+ b = c;
+ }
+ return b;
+ }
+ len += n;
+ if (len == b.length) {
+ int last = is.read();
+ if (last < 0) {
+ return b;
+ }
+ byte[] c = new byte[b.length + 1000];
+ System.arraycopy(b, 0, c, 0, len);
+ c[len++] = (byte) last;
+ b = c;
+ }
+ }
+ } finally {
+ if (close) {
+ is.close();
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Public methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}.
+ * This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+ * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(final ClassVisitor classVisitor, final int flags) {
+ accept(classVisitor, new Attribute[0], flags);
+ }
+
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}.
+ * This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param attrs prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to the
+ * type of one the prototypes will not be parsed: its byte array
+ * value will be passed unchanged to the ClassWriter. <i>This may
+ * corrupt it if this value contains references to the constant pool,
+ * or has syntactic or semantic links with a class element that has
+ * been transformed by a class adapter between the reader and the
+ * writer</i>.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+ * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(
+ final ClassVisitor classVisitor,
+ final Attribute[] attrs,
+ final int flags)
+ {
+ byte[] b = this.b; // the bytecode array
+ char[] c = new char[maxStringLength]; // buffer used to read strings
+ int i, j, k; // loop variables
+ int u, v, w; // indexes in b
+ Attribute attr;
+
+ int access;
+ String name;
+ String desc;
+ String attrName;
+ String signature;
+ int anns = 0;
+ int ianns = 0;
+ Attribute cattrs = null;
+
+ // visits the header
+ u = header;
+ access = readUnsignedShort(u);
+ name = readClass(u + 2, c);
+ v = items[readUnsignedShort(u + 4)];
+ String superClassName = v == 0 ? null : readUTF8(v, c);
+ String[] implementedItfs = new String[readUnsignedShort(u + 6)];
+ w = 0;
+ u += 8;
+ for (i = 0; i < implementedItfs.length; ++i) {
+ implementedItfs[i] = readClass(u, c);
+ u += 2;
+ }
+
+ boolean skipCode = (flags & SKIP_CODE) != 0;
+ boolean skipDebug = (flags & SKIP_DEBUG) != 0;
+ boolean unzip = (flags & EXPAND_FRAMES) != 0;
+
+ // skips fields and methods
+ v = u;
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j) {
+ v += 6 + readInt(v + 2);
+ }
+ }
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j) {
+ v += 6 + readInt(v + 2);
+ }
+ }
+ // reads the class's attributes
+ signature = null;
+ String sourceFile = null;
+ String sourceDebug = null;
+ String enclosingOwner = null;
+ String enclosingName = null;
+ String enclosingDesc = null;
+ int[] bootstrapMethods = null; // start indexed of the bsms
+
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ attrName = readUTF8(v, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("SourceFile".equals(attrName)) {
+ sourceFile = readUTF8(v + 6, c);
+ } else if ("InnerClasses".equals(attrName)) {
+ w = v + 6;
+ } else if ("EnclosingMethod".equals(attrName)) {
+ enclosingOwner = readClass(v + 6, c);
+ int item = readUnsignedShort(v + 8);
+ if (item != 0) {
+ enclosingName = readUTF8(items[item], c);
+ enclosingDesc = readUTF8(items[item] + 2, c);
+ }
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(v + 6, c);
+ } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = v + 6;
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if ("SourceDebugExtension".equals(attrName)) {
+ int len = readInt(v + 2);
+ sourceDebug = readUTF(v + 6, len, new char[len]);
+ } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = v + 6;
+ } else if ("BootstrapMethods".equals(attrName)) {
+ int boostrapMethodCount = readUnsignedShort(v + 6);
+ bootstrapMethods = new int[boostrapMethodCount];
+ int x = v + 8;
+ for (j = 0; j < boostrapMethodCount; j++) {
+ bootstrapMethods[j] = x;
+ x += 2 + readUnsignedShort(x + 2) << 1;
+ }
+ } else {
+ attr = readAttribute(attrs,
+ attrName,
+ v + 6,
+ readInt(v + 2),
+ c,
+ -1,
+ null);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ v += 6 + readInt(v + 2);
+ }
+ // calls the visit method
+ classVisitor.visit(readInt(4),
+ access,
+ name,
+ signature,
+ superClassName,
+ implementedItfs);
+
+ // calls the visitSource method
+ if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+ classVisitor.visitSource(sourceFile, sourceDebug);
+ }
+
+ // calls the visitOuterClass method
+ if (enclosingOwner != null) {
+ classVisitor.visitOuterClass(enclosingOwner,
+ enclosingName,
+ enclosingDesc);
+ }
+
+ // visits the class annotations
+ if (ANNOTATIONS) {
+ for (i = 1; i >= 0; --i) {
+ v = i == 0 ? ianns : anns;
+ if (v != 0) {
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ v = readAnnotationValues(v + 2,
+ c,
+ true,
+ classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
+ }
+ }
+ }
+ }
+
+ // visits the class attributes
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ classVisitor.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+
+ // calls the visitInnerClass method
+ if (w != 0) {
+ i = readUnsignedShort(w);
+ w += 2;
+ for (; i > 0; --i) {
+ classVisitor.visitInnerClass(readUnsignedShort(w) == 0
+ ? null
+ : readClass(w, c), readUnsignedShort(w + 2) == 0
+ ? null
+ : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
+ ? null
+ : readUTF8(w + 4, c), readUnsignedShort(w + 6));
+ w += 8;
+ }
+ }
+
+ // visits the fields
+ i = readUnsignedShort(u);
+ u += 2;
+ for (; i > 0; --i) {
+ access = readUnsignedShort(u);
+ name = readUTF8(u + 2, c);
+ desc = readUTF8(u + 4, c);
+ // visits the field's attributes and looks for a ConstantValue
+ // attribute
+ int fieldValueItem = 0;
+ signature = null;
+ anns = 0;
+ ianns = 0;
+ cattrs = null;
+
+ j = readUnsignedShort(u + 6);
+ u += 8;
+ for (; j > 0; --j) {
+ attrName = readUTF8(u, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("ConstantValue".equals(attrName)) {
+ fieldValueItem = readUnsignedShort(u + 6);
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 6, c);
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 6;
+ } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 6;
+ } else {
+ attr = readAttribute(attrs,
+ attrName,
+ u + 6,
+ readInt(u + 2),
+ c,
+ -1,
+ null);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ u += 6 + readInt(u + 2);
+ }
+ // visits the field
+ FieldVisitor fv = classVisitor.visitField(access,
+ name,
+ desc,
+ signature,
+ fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
+ // visits the field annotations and attributes
+ if (fv != null) {
+ if (ANNOTATIONS) {
+ for (j = 1; j >= 0; --j) {
+ v = j == 0 ? ianns : anns;
+ if (v != 0) {
+ k = readUnsignedShort(v);
+ v += 2;
+ for (; k > 0; --k) {
+ v = readAnnotationValues(v + 2,
+ c,
+ true,
+ fv.visitAnnotation(readUTF8(v, c), j != 0));
+ }
+ }
+ }
+ }
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ fv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ fv.visitEnd();
+ }
+ }
+
+ // visits the methods
+ i = readUnsignedShort(u);
+ u += 2;
+ for (; i > 0; --i) {
+ int u0 = u + 6;
+ access = readUnsignedShort(u);
+ name = readUTF8(u + 2, c);
+ desc = readUTF8(u + 4, c);
+ signature = null;
+ anns = 0;
+ ianns = 0;
+ int dann = 0;
+ int mpanns = 0;
+ int impanns = 0;
+ cattrs = null;
+ v = 0;
+ w = 0;
+
+ // looks for Code and Exceptions attributes
+ j = readUnsignedShort(u + 6);
+ u += 8;
+ for (; j > 0; --j) {
+ attrName = readUTF8(u, c);
+ int attrSize = readInt(u + 2);
+ u += 6;
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("Code".equals(attrName)) {
+ if (!skipCode) {
+ v = u;
+ }
+ } else if ("Exceptions".equals(attrName)) {
+ w = u;
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u, c);
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u;
+ } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+ dann = u;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u;
+ } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
+ {
+ mpanns = u;
+ } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
+ {
+ impanns = u;
+ } else {
+ attr = readAttribute(attrs,
+ attrName,
+ u,
+ attrSize,
+ c,
+ -1,
+ null);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ u += attrSize;
+ }
+ // reads declared exceptions
+ String[] exceptions;
+ if (w == 0) {
+ exceptions = null;
+ } else {
+ exceptions = new String[readUnsignedShort(w)];
+ w += 2;
+ for (j = 0; j < exceptions.length; ++j) {
+ exceptions[j] = readClass(w, c);
+ w += 2;
+ }
+ }
+
+ // visits the method's code, if any
+ MethodVisitor mv = classVisitor.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+
+ if (mv != null) {
+ /*
+ * if the returned MethodVisitor is in fact a MethodWriter, it
+ * means there is no method adapter between the reader and the
+ * writer. If, in addition, the writer's constant pool was
+ * copied from this reader (mw.cw.cr == this), and the signature
+ * and exceptions of the method have not been changed, then it
+ * is possible to skip all visit events and just copy the
+ * original code of the method to the writer (the access, name
+ * and descriptor can have been changed, this is not important
+ * since they are not copied as is from the reader).
+ */
+ if (WRITER && mv instanceof MethodWriter) {
+ MethodWriter mw = (MethodWriter) mv;
+ if (mw.cw.cr == this) {
+ if (signature == mw.signature) {
+ boolean sameExceptions = false;
+ if (exceptions == null) {
+ sameExceptions = mw.exceptionCount == 0;
+ } else {
+ if (exceptions.length == mw.exceptionCount) {
+ sameExceptions = true;
+ for (j = exceptions.length - 1; j >= 0; --j)
+ {
+ w -= 2;
+ if (mw.exceptions[j] != readUnsignedShort(w))
+ {
+ sameExceptions = false;
+ break;
+ }
+ }
+ }
+ }
+ if (sameExceptions) {
+ /*
+ * we do not copy directly the code into
+ * MethodWriter to save a byte array copy
+ * operation. The real copy will be done in
+ * ClassWriter.toByteArray().
+ */
+ mw.classReaderOffset = u0;
+ mw.classReaderLength = u - u0;
+ continue;
+ }
+ }
+ }
+ }
+
+ if (ANNOTATIONS && dann != 0) {
+ AnnotationVisitor dv = mv.visitAnnotationDefault();
+ readAnnotationValue(dann, c, null, dv);
+ if (dv != null) {
+ dv.visitEnd();
+ }
+ }
+ if (ANNOTATIONS) {
+ for (j = 1; j >= 0; --j) {
+ w = j == 0 ? ianns : anns;
+ if (w != 0) {
+ k = readUnsignedShort(w);
+ w += 2;
+ for (; k > 0; --k) {
+ w = readAnnotationValues(w + 2,
+ c,
+ true,
+ mv.visitAnnotation(readUTF8(w, c), j != 0));
+ }
+ }
+ }
+ }
+ if (ANNOTATIONS && mpanns != 0) {
+ readParameterAnnotations(mpanns, desc, c, true, mv);
+ }
+ if (ANNOTATIONS && impanns != 0) {
+ readParameterAnnotations(impanns, desc, c, false, mv);
+ }
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ mv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ }
+
+ if (mv != null && v != 0) {
+ int maxStack = readUnsignedShort(v);
+ int maxLocals = readUnsignedShort(v + 2);
+ int codeLength = readInt(v + 4);
+ v += 8;
+
+ int codeStart = v;
+ int codeEnd = v + codeLength;
+
+ mv.visitCode();
+
+ // 1st phase: finds the labels
+ int label;
+ Label[] labels = new Label[codeLength + 2];
+ readLabel(codeLength + 1, labels);
+ while (v < codeEnd) {
+ w = v - codeStart;
+ int opcode = b[v] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ v += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ readLabel(w + readShort(v + 1), labels);
+ v += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ readLabel(w + readInt(v + 1), labels);
+ v += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[v + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ v += 6;
+ } else {
+ v += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes*
+ v = v + 4 - (w & 3);
+ // reads instruction
+ readLabel(w + readInt(v), labels);
+ j = readInt(v + 8) - readInt(v + 4) + 1;
+ v += 12;
+ for (; j > 0; --j) {
+ readLabel(w + readInt(v), labels);
+ v += 4;
+ }
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes*
+ v = v + 4 - (w & 3);
+ // reads instruction
+ readLabel(w + readInt(v), labels);
+ j = readInt(v + 4);
+ v += 8;
+ for (; j > 0; --j) {
+ readLabel(w + readInt(v + 4), labels);
+ v += 8;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ v += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ v += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ v += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ v += 4;
+ break;
+ }
+ }
+ // parses the try catch entries
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ Label start = readLabel(readUnsignedShort(v), labels);
+ Label end = readLabel(readUnsignedShort(v + 2), labels);
+ Label handler = readLabel(readUnsignedShort(v + 4), labels);
+ int type = readUnsignedShort(v + 6);
+ if (type == 0) {
+ mv.visitTryCatchBlock(start, end, handler, null);
+ } else {
+ mv.visitTryCatchBlock(start,
+ end,
+ handler,
+ readUTF8(items[type], c));
+ }
+ v += 8;
+ }
+ // parses the local variable, line number tables, and code
+ // attributes
+ int varTable = 0;
+ int varTypeTable = 0;
+ int stackMap = 0;
+ int stackMapSize = 0;
+ int frameCount = 0;
+ int frameMode = 0;
+ int frameOffset = 0;
+ int frameLocalCount = 0;
+ int frameLocalDiff = 0;
+ int frameStackCount = 0;
+ Object[] frameLocal = null;
+ Object[] frameStack = null;
+ boolean zip = true;
+ cattrs = null;
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ attrName = readUTF8(v, c);
+ if ("LocalVariableTable".equals(attrName)) {
+ if (!skipDebug) {
+ varTable = v + 6;
+ k = readUnsignedShort(v + 6);
+ w = v + 8;
+ for (; k > 0; --k) {
+ label = readUnsignedShort(w);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ label += readUnsignedShort(w + 2);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ w += 10;
+ }
+ }
+ } else if ("LocalVariableTypeTable".equals(attrName)) {
+ varTypeTable = v + 6;
+ } else if ("LineNumberTable".equals(attrName)) {
+ if (!skipDebug) {
+ k = readUnsignedShort(v + 6);
+ w = v + 8;
+ for (; k > 0; --k) {
+ label = readUnsignedShort(w);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ labels[label].line = readUnsignedShort(w + 2);
+ w += 4;
+ }
+ }
+ } else if (FRAMES && "StackMapTable".equals(attrName)) {
+ if ((flags & SKIP_FRAMES) == 0) {
+ stackMap = v + 8;
+ stackMapSize = readInt(v + 2);
+ frameCount = readUnsignedShort(v + 6);
+ }
+ /*
+ * here we do not extract the labels corresponding to
+ * the attribute content. This would require a full
+ * parsing of the attribute, which would need to be
+ * repeated in the second phase (see below). Instead the
+ * content of the attribute is read one frame at a time
+ * (i.e. after a frame has been visited, the next frame
+ * is read), and the labels it contains are also
+ * extracted one frame at a time. Thanks to the ordering
+ * of frames, having only a "one frame lookahead" is not
+ * a problem, i.e. it is not possible to see an offset
+ * smaller than the offset of the current insn and for
+ * which no Label exist.
+ */
+ /*
+ * This is not true for UNINITIALIZED type offsets. We
+ * solve this by parsing the stack map table without a
+ * full decoding (see below).
+ */
+ } else if (FRAMES && "StackMap".equals(attrName)) {
+ if ((flags & SKIP_FRAMES) == 0) {
+ stackMap = v + 8;
+ stackMapSize = readInt(v + 2);
+ frameCount = readUnsignedShort(v + 6);
+ zip = false;
+ }
+ /*
+ * IMPORTANT! here we assume that the frames are
+ * ordered, as in the StackMapTable attribute, although
+ * this is not guaranteed by the attribute format.
+ */
+ } else {
+ for (k = 0; k < attrs.length; ++k) {
+ if (attrs[k].type.equals(attrName)) {
+ attr = attrs[k].read(this,
+ v + 6,
+ readInt(v + 2),
+ c,
+ codeStart - 8,
+ labels);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ }
+ }
+ v += 6 + readInt(v + 2);
+ }
+
+ // 2nd phase: visits each instruction
+ if (FRAMES && stackMap != 0) {
+ // creates the very first (implicit) frame from the method
+ // descriptor
+ frameLocal = new Object[maxLocals];
+ frameStack = new Object[maxStack];
+ if (unzip) {
+ int local = 0;
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ("<init>".equals(name)) {
+ frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
+ } else {
+ frameLocal[local++] = readClass(header + 2, c);
+ }
+ }
+ j = 1;
+ loop: while (true) {
+ k = j;
+ switch (desc.charAt(j++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ frameLocal[local++] = Opcodes.INTEGER;
+ break;
+ case 'F':
+ frameLocal[local++] = Opcodes.FLOAT;
+ break;
+ case 'J':
+ frameLocal[local++] = Opcodes.LONG;
+ break;
+ case 'D':
+ frameLocal[local++] = Opcodes.DOUBLE;
+ break;
+ case '[':
+ while (desc.charAt(j) == '[') {
+ ++j;
+ }
+ if (desc.charAt(j) == 'L') {
+ ++j;
+ while (desc.charAt(j) != ';') {
+ ++j;
+ }
+ }
+ frameLocal[local++] = desc.substring(k, ++j);
+ break;
+ case 'L':
+ while (desc.charAt(j) != ';') {
+ ++j;
+ }
+ frameLocal[local++] = desc.substring(k + 1,
+ j++);
+ break;
+ default:
+ break loop;
+ }
+ }
+ frameLocalCount = local;
+ }
+ /*
+ * for the first explicit frame the offset is not
+ * offset_delta + 1 but only offset_delta; setting the
+ * implicit frame offset to -1 allow the use of the
+ * "offset_delta + 1" rule in all cases
+ */
+ frameOffset = -1;
+ /*
+ * Finds labels for UNINITIALIZED frame types. Instead of
+ * decoding each element of the stack map table, we look
+ * for 3 consecutive bytes that "look like" an UNINITIALIZED
+ * type (tag 8, offset within code bounds, NEW instruction
+ * at this offset). We may find false positives (i.e. not
+ * real UNINITIALIZED types), but this should be rare, and
+ * the only consequence will be the creation of an unneeded
+ * label. This is better than creating a label for each NEW
+ * instruction, and faster than fully decoding the whole
+ * stack map table.
+ */
+ for (j = stackMap; j < stackMap + stackMapSize - 2; ++j) {
+ if (b[j] == 8) { // UNINITIALIZED FRAME TYPE
+ k = readUnsignedShort(j + 1);
+ if (k >= 0 && k < codeLength) { // potential offset
+ if ((b[codeStart + k] & 0xFF) == Opcodes.NEW) { // NEW at this offset
+ readLabel(k, labels);
+ }
+ }
+ }
+ }
+ }
+ v = codeStart;
+ Label l;
+ while (v < codeEnd) {
+ w = v - codeStart;
+
+ l = labels[w];
+ if (l != null) {
+ mv.visitLabel(l);
+ if (!skipDebug && l.line > 0) {
+ mv.visitLineNumber(l.line, l);
+ }
+ }
+
+ while (FRAMES && frameLocal != null
+ && (frameOffset == w || frameOffset == -1))
+ {
+ // if there is a frame for this offset,
+ // makes the visitor visit it,
+ // and reads the next frame if there is one.
+ if (!zip || unzip) {
+ mv.visitFrame(Opcodes.F_NEW,
+ frameLocalCount,
+ frameLocal,
+ frameStackCount,
+ frameStack);
+ } else if (frameOffset != -1) {
+ mv.visitFrame(frameMode,
+ frameLocalDiff,
+ frameLocal,
+ frameStackCount,
+ frameStack);
+ }
+
+ if (frameCount > 0) {
+ int tag, delta, n;
+ if (zip) {
+ tag = b[stackMap++] & 0xFF;
+ } else {
+ tag = MethodWriter.FULL_FRAME;
+ frameOffset = -1;
+ }
+ frameLocalDiff = 0;
+ if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
+ {
+ delta = tag;
+ frameMode = Opcodes.F_SAME;
+ frameStackCount = 0;
+ } else if (tag < MethodWriter.RESERVED) {
+ delta = tag
+ - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
+ stackMap = readFrameType(frameStack,
+ 0,
+ stackMap,
+ c,
+ labels);
+ frameMode = Opcodes.F_SAME1;
+ frameStackCount = 1;
+ } else {
+ delta = readUnsignedShort(stackMap);
+ stackMap += 2;
+ if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ {
+ stackMap = readFrameType(frameStack,
+ 0,
+ stackMap,
+ c,
+ labels);
+ frameMode = Opcodes.F_SAME1;
+ frameStackCount = 1;
+ } else if (tag >= MethodWriter.CHOP_FRAME
+ && tag < MethodWriter.SAME_FRAME_EXTENDED)
+ {
+ frameMode = Opcodes.F_CHOP;
+ frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
+ - tag;
+ frameLocalCount -= frameLocalDiff;
+ frameStackCount = 0;
+ } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
+ {
+ frameMode = Opcodes.F_SAME;
+ frameStackCount = 0;
+ } else if (tag < MethodWriter.FULL_FRAME) {
+ j = unzip ? frameLocalCount : 0;
+ for (k = tag
+ - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
+ {
+ stackMap = readFrameType(frameLocal,
+ j++,
+ stackMap,
+ c,
+ labels);
+ }
+ frameMode = Opcodes.F_APPEND;
+ frameLocalDiff = tag
+ - MethodWriter.SAME_FRAME_EXTENDED;
+ frameLocalCount += frameLocalDiff;
+ frameStackCount = 0;
+ } else { // if (tag == FULL_FRAME) {
+ frameMode = Opcodes.F_FULL;
+ n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
+ stackMap += 2;
+ for (j = 0; n > 0; n--) {
+ stackMap = readFrameType(frameLocal,
+ j++,
+ stackMap,
+ c,
+ labels);
+ }
+ n = frameStackCount = readUnsignedShort(stackMap);
+ stackMap += 2;
+ for (j = 0; n > 0; n--) {
+ stackMap = readFrameType(frameStack,
+ j++,
+ stackMap,
+ c,
+ labels);
+ }
+ }
+ }
+ frameOffset += delta + 1;
+ readLabel(frameOffset, labels);
+
+ --frameCount;
+ } else {
+ frameLocal = null;
+ }
+ }
+
+ int opcode = b[v] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ mv.visitInsn(opcode);
+ v += 1;
+ break;
+ case ClassWriter.IMPLVAR_INSN:
+ if (opcode > Opcodes.ISTORE) {
+ opcode -= 59; // ISTORE_0
+ mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
+ opcode & 0x3);
+ } else {
+ opcode -= 26; // ILOAD_0
+ mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
+ opcode & 0x3);
+ }
+ v += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ mv.visitJumpInsn(opcode, labels[w
+ + readShort(v + 1)]);
+ v += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ mv.visitJumpInsn(opcode - 33, labels[w
+ + readInt(v + 1)]);
+ v += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[v + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ mv.visitIincInsn(readUnsignedShort(v + 2),
+ readShort(v + 4));
+ v += 6;
+ } else {
+ mv.visitVarInsn(opcode,
+ readUnsignedShort(v + 2));
+ v += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ v = v + 4 - (w & 3);
+ // reads instruction
+ label = w + readInt(v);
+ int min = readInt(v + 4);
+ int max = readInt(v + 8);
+ v += 12;
+ Label[] table = new Label[max - min + 1];
+ for (j = 0; j < table.length; ++j) {
+ table[j] = labels[w + readInt(v)];
+ v += 4;
+ }
+ mv.visitTableSwitchInsn(min,
+ max,
+ labels[label],
+ table);
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ v = v + 4 - (w & 3);
+ // reads instruction
+ label = w + readInt(v);
+ j = readInt(v + 4);
+ v += 8;
+ int[] keys = new int[j];
+ Label[] values = new Label[j];
+ for (j = 0; j < keys.length; ++j) {
+ keys[j] = readInt(v);
+ values[j] = labels[w + readInt(v + 4)];
+ v += 8;
+ }
+ mv.visitLookupSwitchInsn(labels[label],
+ keys,
+ values);
+ break;
+ case ClassWriter.VAR_INSN:
+ mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
+ v += 2;
+ break;
+ case ClassWriter.SBYTE_INSN:
+ mv.visitIntInsn(opcode, b[v + 1]);
+ v += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ mv.visitIntInsn(opcode, readShort(v + 1));
+ v += 3;
+ break;
+ case ClassWriter.LDC_INSN:
+ mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
+ v += 2;
+ break;
+ case ClassWriter.LDCW_INSN:
+ mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
+ c));
+ v += 3;
+ break;
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.ITFMETH_INSN: {
+ int cpIndex = items[readUnsignedShort(v + 1)];
+ String iowner = readClass(cpIndex, c);
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ String iname = readUTF8(cpIndex, c);
+ String idesc = readUTF8(cpIndex + 2, c);
+ if (opcode < Opcodes.INVOKEVIRTUAL) {
+ mv.visitFieldInsn(opcode, iowner, iname, idesc);
+ } else {
+ mv.visitMethodInsn(opcode, iowner, iname, idesc);
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE) {
+ v += 5;
+ } else {
+ v += 3;
+ }
+ break;
+ }
+ case ClassWriter.INDYMETH_INSN: {
+ int cpIndex = items[readUnsignedShort(v + 1)];
+ int bsmIndex = bootstrapMethods[readUnsignedShort(cpIndex)];
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ String iname = readUTF8(cpIndex, c);
+ String idesc = readUTF8(cpIndex + 2, c);
+
+ int mhIndex = readUnsignedShort(bsmIndex);
+ Handle bsm = (Handle) readConst(mhIndex, c);
+ int bsmArgCount = readUnsignedShort(bsmIndex + 2);
+ Object[] bsmArgs = new Object[bsmArgCount];
+ bsmIndex += 4;
+ for(int a = 0; a < bsmArgCount; a++) {
+ int argIndex = readUnsignedShort(bsmIndex);
+ bsmArgs[a] = readConst(argIndex, c);
+ bsmIndex += 2;
+ }
+ mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
+
+ v += 5;
+ break;
+ }
+ case ClassWriter.TYPE_INSN:
+ mv.visitTypeInsn(opcode, readClass(v + 1, c));
+ v += 3;
+ break;
+ case ClassWriter.IINC_INSN:
+ mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
+ v += 3;
+ break;
+ // case MANA_INSN:
+ default:
+ mv.visitMultiANewArrayInsn(readClass(v + 1, c),
+ b[v + 3] & 0xFF);
+ v += 4;
+ break;
+ }
+ }
+ l = labels[codeEnd - codeStart];
+ if (l != null) {
+ mv.visitLabel(l);
+ }
+ // visits the local variable tables
+ if (!skipDebug && varTable != 0) {
+ int[] typeTable = null;
+ if (varTypeTable != 0) {
+ k = readUnsignedShort(varTypeTable) * 3;
+ w = varTypeTable + 2;
+ typeTable = new int[k];
+ while (k > 0) {
+ typeTable[--k] = w + 6; // signature
+ typeTable[--k] = readUnsignedShort(w + 8); // index
+ typeTable[--k] = readUnsignedShort(w); // start
+ w += 10;
+ }
+ }
+ k = readUnsignedShort(varTable);
+ w = varTable + 2;
+ for (; k > 0; --k) {
+ int start = readUnsignedShort(w);
+ int length = readUnsignedShort(w + 2);
+ int index = readUnsignedShort(w + 8);
+ String vsignature = null;
+ if (typeTable != null) {
+ for (int a = 0; a < typeTable.length; a += 3) {
+ if (typeTable[a] == start
+ && typeTable[a + 1] == index)
+ {
+ vsignature = readUTF8(typeTable[a + 2], c);
+ break;
+ }
+ }
+ }
+ mv.visitLocalVariable(readUTF8(w + 4, c),
+ readUTF8(w + 6, c),
+ vsignature,
+ labels[start],
+ labels[start + length],
+ index);
+ w += 10;
+ }
+ }
+ // visits the other attributes
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ mv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ // visits the max stack and max locals values
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+
+ if (mv != null) {
+ mv.visitEnd();
+ }
+ }
+
+ // visits the end of the class
+ classVisitor.visitEnd();
+ }
+
+ /**
+ * Reads parameter annotations and makes the given visitor visit them.
+ *
+ * @param v start offset in {@link #b b} of the annotations to be read.
+ * @param desc the method descriptor.
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param visible <tt>true</tt> if the annotations to be read are visible
+ * at runtime.
+ * @param mv the visitor that must visit the annotations.
+ */
+ private void readParameterAnnotations(
+ int v,
+ final String desc,
+ final char[] buf,
+ final boolean visible,
+ final MethodVisitor mv)
+ {
+ int i;
+ int n = b[v++] & 0xFF;
+ // workaround for a bug in javac (javac compiler generates a parameter
+ // annotation array whose size is equal to the number of parameters in
+ // the Java source file, while it should generate an array whose size is
+ // equal to the number of parameters in the method descriptor - which
+ // includes the synthetic parameters added by the compiler). This work-
+ // around supposes that the synthetic parameters are the first ones.
+ int synthetics = Type.getArgumentTypes(desc).length - n;
+ AnnotationVisitor av;
+ for (i = 0; i < synthetics; ++i) {
+ // virtual annotation to detect synthetic parameters in MethodWriter
+ av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ for (; i < n + synthetics; ++i) {
+ int j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
+ v = readAnnotationValues(v + 2, buf, true, av);
+ }
+ }
+ }
+
+ /**
+ * Reads the values of an annotation and makes the given visitor visit them.
+ *
+ * @param v the start offset in {@link #b b} of the values to be read
+ * (including the unsigned short that gives the number of values).
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param named if the annotation values are named or not.
+ * @param av the visitor that must visit the values.
+ * @return the end offset of the annotation values.
+ */
+ private int readAnnotationValues(
+ int v,
+ final char[] buf,
+ final boolean named,
+ final AnnotationVisitor av)
+ {
+ int i = readUnsignedShort(v);
+ v += 2;
+ if (named) {
+ for (; i > 0; --i) {
+ v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
+ }
+ } else {
+ for (; i > 0; --i) {
+ v = readAnnotationValue(v, buf, null, av);
+ }
+ }
+ if (av != null) {
+ av.visitEnd();
+ }
+ return v;
+ }
+
+ /**
+ * Reads a value of an annotation and makes the given visitor visit it.
+ *
+ * @param v the start offset in {@link #b b} of the value to be read (<i>not
+ * including the value name constant pool index</i>).
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param name the name of the value to be read.
+ * @param av the visitor that must visit the value.
+ * @return the end offset of the annotation value.
+ */
+ private int readAnnotationValue(
+ int v,
+ final char[] buf,
+ final String name,
+ final AnnotationVisitor av)
+ {
+ int i;
+ if (av == null) {
+ switch (b[v] & 0xFF) {
+ case 'e': // enum_const_value
+ return v + 5;
+ case '@': // annotation_value
+ return readAnnotationValues(v + 3, buf, true, null);
+ case '[': // array_value
+ return readAnnotationValues(v + 1, buf, false, null);
+ default:
+ return v + 3;
+ }
+ }
+ switch (b[v++] & 0xFF) {
+ case 'I': // pointer to CONSTANT_Integer
+ case 'J': // pointer to CONSTANT_Long
+ case 'F': // pointer to CONSTANT_Float
+ case 'D': // pointer to CONSTANT_Double
+ av.visit(name, readConst(readUnsignedShort(v), buf));
+ v += 2;
+ break;
+ case 'B': // pointer to CONSTANT_Byte
+ av.visit(name,
+ new Byte((byte) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 'Z': // pointer to CONSTANT_Boolean
+ av.visit(name, readInt(items[readUnsignedShort(v)]) == 0
+ ? Boolean.FALSE
+ : Boolean.TRUE);
+ v += 2;
+ break;
+ case 'S': // pointer to CONSTANT_Short
+ av.visit(name,
+ new Short((short) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 'C': // pointer to CONSTANT_Char
+ av.visit(name,
+ new Character((char) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 's': // pointer to CONSTANT_Utf8
+ av.visit(name, readUTF8(v, buf));
+ v += 2;
+ break;
+ case 'e': // enum_const_value
+ av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
+ v += 4;
+ break;
+ case 'c': // class_info
+ av.visit(name, Type.getType(readUTF8(v, buf)));
+ v += 2;
+ break;
+ case '@': // annotation_value
+ v = readAnnotationValues(v + 2,
+ buf,
+ true,
+ av.visitAnnotation(name, readUTF8(v, buf)));
+ break;
+ case '[': // array_value
+ int size = readUnsignedShort(v);
+ v += 2;
+ if (size == 0) {
+ return readAnnotationValues(v - 2,
+ buf,
+ false,
+ av.visitArray(name));
+ }
+ switch (this.b[v++] & 0xFF) {
+ case 'B':
+ byte[] bv = new byte[size];
+ for (i = 0; i < size; i++) {
+ bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, bv);
+ --v;
+ break;
+ case 'Z':
+ boolean[] zv = new boolean[size];
+ for (i = 0; i < size; i++) {
+ zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
+ v += 3;
+ }
+ av.visit(name, zv);
+ --v;
+ break;
+ case 'S':
+ short[] sv = new short[size];
+ for (i = 0; i < size; i++) {
+ sv[i] = (short) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, sv);
+ --v;
+ break;
+ case 'C':
+ char[] cv = new char[size];
+ for (i = 0; i < size; i++) {
+ cv[i] = (char) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, cv);
+ --v;
+ break;
+ case 'I':
+ int[] iv = new int[size];
+ for (i = 0; i < size; i++) {
+ iv[i] = readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, iv);
+ --v;
+ break;
+ case 'J':
+ long[] lv = new long[size];
+ for (i = 0; i < size; i++) {
+ lv[i] = readLong(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, lv);
+ --v;
+ break;
+ case 'F':
+ float[] fv = new float[size];
+ for (i = 0; i < size; i++) {
+ fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, fv);
+ --v;
+ break;
+ case 'D':
+ double[] dv = new double[size];
+ for (i = 0; i < size; i++) {
+ dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, dv);
+ --v;
+ break;
+ default:
+ v = readAnnotationValues(v - 3,
+ buf,
+ false,
+ av.visitArray(name));
+ }
+ }
+ return v;
+ }
+
+ private int readFrameType(
+ final Object[] frame,
+ final int index,
+ int v,
+ final char[] buf,
+ final Label[] labels)
+ {
+ int type = b[v++] & 0xFF;
+ switch (type) {
+ case 0:
+ frame[index] = Opcodes.TOP;
+ break;
+ case 1:
+ frame[index] = Opcodes.INTEGER;
+ break;
+ case 2:
+ frame[index] = Opcodes.FLOAT;
+ break;
+ case 3:
+ frame[index] = Opcodes.DOUBLE;
+ break;
+ case 4:
+ frame[index] = Opcodes.LONG;
+ break;
+ case 5:
+ frame[index] = Opcodes.NULL;
+ break;
+ case 6:
+ frame[index] = Opcodes.UNINITIALIZED_THIS;
+ break;
+ case 7: // Object
+ frame[index] = readClass(v, buf);
+ v += 2;
+ break;
+ default: // Uninitialized
+ frame[index] = readLabel(readUnsignedShort(v), labels);
+ v += 2;
+ }
+ return v;
+ }
+
+ /**
+ * Returns the label corresponding to the given offset. The default
+ * implementation of this method creates a label for the given offset if it
+ * has not been already created.
+ *
+ * @param offset a bytecode offset in a method.
+ * @param labels the already created labels, indexed by their offset. If a
+ * label already exists for offset this method must not create a new
+ * one. Otherwise it must store the new label in this array.
+ * @return a non null Label, which must be equal to labels[offset].
+ */
+ protected Label readLabel(int offset, Label[] labels) {
+ if (labels[offset] == null) {
+ labels[offset] = new Label();
+ }
+ return labels[offset];
+ }
+
+ /**
+ * Reads an attribute in {@link #b b}.
+ *
+ * @param attrs prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to the
+ * type of one the prototypes is ignored (i.e. an empty
+ * {@link Attribute} instance is returned).
+ * @param type the type of the attribute.
+ * @param off index of the first byte of the attribute's content in
+ * {@link #b b}. The 6 attribute header bytes, containing the type
+ * and the length of the attribute, are not taken into account here
+ * (they have already been read).
+ * @param len the length of the attribute's content.
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param codeOff index of the first byte of code's attribute content in
+ * {@link #b b}, or -1 if the attribute to be read is not a code
+ * attribute. The 6 attribute header bytes, containing the type and
+ * the length of the attribute, are not taken into account here.
+ * @param labels the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
+ * @return the attribute that has been read, or <tt>null</tt> to skip this
+ * attribute.
+ */
+ private Attribute readAttribute(
+ final Attribute[] attrs,
+ final String type,
+ final int off,
+ final int len,
+ final char[] buf,
+ final int codeOff,
+ final Label[] labels)
+ {
+ for (int i = 0; i < attrs.length; ++i) {
+ if (attrs[i].type.equals(type)) {
+ return attrs[i].read(this, off, len, buf, codeOff, labels);
+ }
+ }
+ return new Attribute(type).read(this, off, len, null, -1, null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: low level parsing
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the number of constant pool items in {@link #b b}.
+ *
+ * @return the number of constant pool items in {@link #b b}.
+ */
+ public int getItemCount() {
+ return items.length;
+ }
+
+ /**
+ * Returns the start index of the constant pool item in {@link #b b}, plus
+ * one. <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param item the index a constant pool item.
+ * @return the start index of the constant pool item in {@link #b b}, plus
+ * one.
+ */
+ public int getItem(final int item) {
+ return items[item];
+ }
+
+ /**
+ * Returns the maximum length of the strings contained in the constant pool
+ * of the class.
+ *
+ * @return the maximum length of the strings contained in the constant pool
+ * of the class.
+ */
+ public int getMaxStringLength() {
+ return maxStringLength;
+ }
+
+ /**
+ * Reads a byte value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readByte(final int index) {
+ return b[index] & 0xFF;
+ }
+
+ /**
+ * Reads an unsigned short value in {@link #b b}. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readUnsignedShort(final int index) {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+ }
+
+ /**
+ * Reads a signed short value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public short readShort(final int index) {
+ byte[] b = this.b;
+ return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+ }
+
+ /**
+ * Reads a signed int value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readInt(final int index) {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+ | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+ }
+
+ /**
+ * Reads a signed long value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public long readLong(final int index) {
+ long l1 = readInt(index);
+ long l0 = readInt(index + 4) & 0xFFFFFFFFL;
+ return (l1 << 32) | l0;
+ }
+
+ /**
+ * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
+ * is intended for {@link Attribute} sub classes, and is normally not needed
+ * by class generators or adapters.</i>
+ *
+ * @param index the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of an UTF8 constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 item.
+ */
+ public String readUTF8(int index, final char[] buf) {
+ int item = readUnsignedShort(index);
+ String s = strings[item];
+ if (s != null) {
+ return s;
+ }
+ index = items[item];
+ return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
+ }
+
+ /**
+ * Reads UTF8 string in {@link #b b}.
+ *
+ * @param index start offset of the UTF8 string to be read.
+ * @param utfLen length of the UTF8 string to be read.
+ * @param buf buffer to be used to read the string. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 string.
+ */
+ private String readUTF(int index, final int utfLen, final char[] buf) {
+ int endIndex = index + utfLen;
+ byte[] b = this.b;
+ int strLen = 0;
+ int c;
+ int st = 0;
+ char cc = 0;
+ while (index < endIndex) {
+ c = b[index++];
+ switch (st) {
+ case 0:
+ c = c & 0xFF;
+ if (c < 0x80) { // 0xxxxxxx
+ buf[strLen++] = (char) c;
+ } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
+ cc = (char) (c & 0x1F);
+ st = 1;
+ } else { // 1110 xxxx 10xx xxxx 10xx xxxx
+ cc = (char) (c & 0x0F);
+ st = 2;
+ }
+ break;
+
+ case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
+ buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
+ st = 0;
+ break;
+
+ case 2: // byte 2 of 3-byte char
+ cc = (char) ((cc << 6) | (c & 0x3F));
+ st = 1;
+ break;
+ }
+ }
+ return new String(buf, 0, strLen);
+ }
+
+ /**
+ * Reads a class constant pool item in {@link #b b}. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param index the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a class constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified class item.
+ */
+ public String readClass(final int index, final char[] buf) {
+ // computes the start index of the CONSTANT_Class item in b
+ // and reads the CONSTANT_Utf8 item designated by
+ // the first two bytes of this CONSTANT_Class item
+ return readUTF8(items[readUnsignedShort(index)], buf);
+ }
+
+ /**
+ * Reads a numeric or string constant pool item in {@link #b b}. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param item the index of a constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
+ * {@link String}, {@link Type} or {@link Handle} corresponding to
+ * the given constant pool item.
+ */
+ public Object readConst(final int item, final char[] buf) {
+ int index = items[item];
+ switch (b[index - 1]) {
+ case ClassWriter.INT:
+ return new Integer(readInt(index));
+ case ClassWriter.FLOAT:
+ return new Float(Float.intBitsToFloat(readInt(index)));
+ case ClassWriter.LONG:
+ return new Long(readLong(index));
+ case ClassWriter.DOUBLE:
+ return new Double(Double.longBitsToDouble(readLong(index)));
+ case ClassWriter.CLASS:
+ return Type.getObjectType(readUTF8(index, buf));
+ case ClassWriter.STR:
+ return readUTF8(index, buf);
+ case ClassWriter.MTYPE:
+ return Type.getMethodType(readUTF8(index, buf));
+
+ //case ClassWriter.HANDLE_BASE + [1..9]:
+ default: {
+ int tag = readByte(index);
+ int[] items = this.items;
+ int cpIndex = items[readUnsignedShort(index + 1)];
+ String owner = readClass(cpIndex, buf);
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ String name = readUTF8(cpIndex, buf);
+ String desc = readUTF8(cpIndex + 2, buf);
+ return new Handle(tag, owner, name, desc);
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/ClassVisitor.java b/src/compiler/scala/tools/asm/ClassVisitor.java
new file mode 100644
index 0000000000..ae38ae0ab9
--- /dev/null
+++ b/src/compiler/scala/tools/asm/ClassVisitor.java
@@ -0,0 +1,277 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A visitor to visit a Java class. The methods of this class must be called
+ * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* ( <tt>visitInnerClass</tt> |
+ * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class ClassVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4}.
+ */
+ protected final int api;
+
+ /**
+ * The class visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ protected ClassVisitor cv;
+
+ /**
+ * Constructs a new {@link ClassVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ public ClassVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link ClassVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param cv the class visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public ClassVisitor(final int api, final ClassVisitor cv) {
+ /*if (api != Opcodes.ASM4) {
+ throw new IllegalArgumentException();
+ }*/
+ this.api = api;
+ this.cv = cv;
+ }
+
+ /**
+ * Visits the header of the class.
+ *
+ * @param version the class version.
+ * @param access the class's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the class is deprecated.
+ * @param name the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param signature the signature of this class. May be <tt>null</tt> if
+ * the class is not a generic one, and does not extend or implement
+ * generic classes or interfaces.
+ * @param superName the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For interfaces,
+ * the super class is {@link Object}. May be <tt>null</tt>, but
+ * only for the {@link Object} class.
+ * @param interfaces the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ */
+ public void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces)
+ {
+ if (cv != null) {
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+ }
+
+ /**
+ * Visits the source of the class.
+ *
+ * @param source the name of the source file from which the class was
+ * compiled. May be <tt>null</tt>.
+ * @param debug additional debug information to compute the correspondance
+ * between source and compiled elements of the class. May be
+ * <tt>null</tt>.
+ */
+ public void visitSource(String source, String debug) {
+ if (cv != null) {
+ cv.visitSource(source, debug);
+ }
+ }
+
+ /**
+ * Visits the enclosing class of the class. This method must be called only
+ * if the class has an enclosing class.
+ *
+ * @param owner internal name of the enclosing class of the class.
+ * @param name the name of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ * @param desc the descriptor of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ */
+ public void visitOuterClass(String owner, String name, String desc) {
+ if (cv != null) {
+ cv.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ /**
+ * Visits an annotation of the class.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (cv != null) {
+ return cv.visitAnnotation(desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a non standard attribute of the class.
+ *
+ * @param attr an attribute.
+ */
+ public void visitAttribute(Attribute attr) {
+ if (cv != null) {
+ cv.visitAttribute(attr);
+ }
+ }
+
+ /**
+ * Visits information about an inner class. This inner class is not
+ * necessarily a member of the class being visited.
+ *
+ * @param name the internal name of an inner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param outerName the internal name of the class to which the inner class
+ * belongs (see {@link Type#getInternalName() getInternalName}). May
+ * be <tt>null</tt> for not member classes.
+ * @param innerName the (simple) name of the inner class inside its
+ * enclosing class. May be <tt>null</tt> for anonymous inner
+ * classes.
+ * @param access the access flags of the inner class as originally declared
+ * in the enclosing class.
+ */
+ public void visitInnerClass(
+ String name,
+ String outerName,
+ String innerName,
+ int access)
+ {
+ if (cv != null) {
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+
+ /**
+ * Visits a field of the class.
+ *
+ * @param access the field's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the field is synthetic and/or
+ * deprecated.
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link Type Type}).
+ * @param signature the field's signature. May be <tt>null</tt> if the
+ * field's type does not use generic types.
+ * @param value the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value, must
+ * be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String} (for <tt>int</tt>,
+ * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+ * respectively). <i>This parameter is only used for static fields</i>.
+ * Its value is ignored for non static fields, which must be
+ * initialized through bytecode instructions in constructors or
+ * methods.
+ * @return a visitor to visit field annotations and attributes, or
+ * <tt>null</tt> if this class visitor is not interested in
+ * visiting these annotations and attributes.
+ */
+ public FieldVisitor visitField(
+ int access,
+ String name,
+ String desc,
+ String signature,
+ Object value)
+ {
+ if (cv != null) {
+ return cv.visitField(access, name, desc, signature, value);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a method of the class. This method <i>must</i> return a new
+ * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
+ * called, i.e., it should not return a previously returned visitor.
+ *
+ * @param access the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type Type}).
+ * @param signature the method's signature. May be <tt>null</tt> if the
+ * method parameters, return type and exceptions do not use generic
+ * types.
+ * @param exceptions the internal names of the method's exception classes
+ * (see {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ * @return an object to visit the byte code of the method, or <tt>null</tt>
+ * if this class visitor is not interested in visiting the code of
+ * this method.
+ */
+ public MethodVisitor visitMethod(
+ int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions)
+ {
+ if (cv != null) {
+ return cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+ return null;
+ }
+
+ /**
+ * Visits the end of the class. This method, which is the last one to be
+ * called, is used to inform the visitor that all the fields and methods of
+ * the class have been visited.
+ */
+ public void visitEnd() {
+ if (cv != null) {
+ cv.visitEnd();
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/ClassWriter.java b/src/compiler/scala/tools/asm/ClassWriter.java
new file mode 100644
index 0000000000..c7a0736b51
--- /dev/null
+++ b/src/compiler/scala/tools/asm/ClassWriter.java
@@ -0,0 +1,1672 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A {@link ClassVisitor} that generates classes in bytecode form. More
+ * precisely this visitor generates a byte array conforming to the Java class
+ * file format. It can be used alone, to generate a Java class "from scratch",
+ * or with one or more {@link ClassReader ClassReader} and adapter class visitor
+ * to generate a modified class from one or more existing Java classes.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassWriter extends ClassVisitor {
+
+ /**
+ * Flag to automatically compute the maximum stack size and the maximum
+ * number of local variables of methods. If this flag is set, then the
+ * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
+ * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
+ * method will be ignored, and computed automatically from the signature and
+ * the bytecode of each method.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_MAXS = 1;
+
+ /**
+ * Flag to automatically compute the stack map frames of methods from
+ * scratch. If this flag is set, then the calls to the
+ * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
+ * frames are recomputed from the methods bytecode. The arguments of the
+ * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
+ * recomputed from the bytecode. In other words, computeFrames implies
+ * computeMaxs.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_FRAMES = 2;
+
+ /**
+ * Pseudo access flag to distinguish between the synthetic attribute and
+ * the synthetic access flag.
+ */
+ static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
+
+ /**
+ * The type of instructions without any argument.
+ */
+ static final int NOARG_INSN = 0;
+
+ /**
+ * The type of instructions with an signed byte argument.
+ */
+ static final int SBYTE_INSN = 1;
+
+ /**
+ * The type of instructions with an signed short argument.
+ */
+ static final int SHORT_INSN = 2;
+
+ /**
+ * The type of instructions with a local variable index argument.
+ */
+ static final int VAR_INSN = 3;
+
+ /**
+ * The type of instructions with an implicit local variable index argument.
+ */
+ static final int IMPLVAR_INSN = 4;
+
+ /**
+ * The type of instructions with a type descriptor argument.
+ */
+ static final int TYPE_INSN = 5;
+
+ /**
+ * The type of field and method invocations instructions.
+ */
+ static final int FIELDORMETH_INSN = 6;
+
+ /**
+ * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction.
+ */
+ static final int ITFMETH_INSN = 7;
+
+ /**
+ * The type of the INVOKEDYNAMIC instruction.
+ */
+ static final int INDYMETH_INSN = 8;
+
+ /**
+ * The type of instructions with a 2 bytes bytecode offset label.
+ */
+ static final int LABEL_INSN = 9;
+
+ /**
+ * The type of instructions with a 4 bytes bytecode offset label.
+ */
+ static final int LABELW_INSN = 10;
+
+ /**
+ * The type of the LDC instruction.
+ */
+ static final int LDC_INSN = 11;
+
+ /**
+ * The type of the LDC_W and LDC2_W instructions.
+ */
+ static final int LDCW_INSN = 12;
+
+ /**
+ * The type of the IINC instruction.
+ */
+ static final int IINC_INSN = 13;
+
+ /**
+ * The type of the TABLESWITCH instruction.
+ */
+ static final int TABL_INSN = 14;
+
+ /**
+ * The type of the LOOKUPSWITCH instruction.
+ */
+ static final int LOOK_INSN = 15;
+
+ /**
+ * The type of the MULTIANEWARRAY instruction.
+ */
+ static final int MANA_INSN = 16;
+
+ /**
+ * The type of the WIDE instruction.
+ */
+ static final int WIDE_INSN = 17;
+
+ /**
+ * The instruction types of all JVM opcodes.
+ */
+ static final byte[] TYPE;
+
+ /**
+ * The type of CONSTANT_Class constant pool items.
+ */
+ static final int CLASS = 7;
+
+ /**
+ * The type of CONSTANT_Fieldref constant pool items.
+ */
+ static final int FIELD = 9;
+
+ /**
+ * The type of CONSTANT_Methodref constant pool items.
+ */
+ static final int METH = 10;
+
+ /**
+ * The type of CONSTANT_InterfaceMethodref constant pool items.
+ */
+ static final int IMETH = 11;
+
+ /**
+ * The type of CONSTANT_String constant pool items.
+ */
+ static final int STR = 8;
+
+ /**
+ * The type of CONSTANT_Integer constant pool items.
+ */
+ static final int INT = 3;
+
+ /**
+ * The type of CONSTANT_Float constant pool items.
+ */
+ static final int FLOAT = 4;
+
+ /**
+ * The type of CONSTANT_Long constant pool items.
+ */
+ static final int LONG = 5;
+
+ /**
+ * The type of CONSTANT_Double constant pool items.
+ */
+ static final int DOUBLE = 6;
+
+ /**
+ * The type of CONSTANT_NameAndType constant pool items.
+ */
+ static final int NAME_TYPE = 12;
+
+ /**
+ * The type of CONSTANT_Utf8 constant pool items.
+ */
+ static final int UTF8 = 1;
+
+ /**
+ * The type of CONSTANT_MethodType constant pool items.
+ */
+ static final int MTYPE = 16;
+
+ /**
+ * The type of CONSTANT_MethodHandle constant pool items.
+ */
+ static final int HANDLE = 15;
+
+ /**
+ * The type of CONSTANT_InvokeDynamic constant pool items.
+ */
+ static final int INDY = 18;
+
+ /**
+ * The base value for all CONSTANT_MethodHandle constant pool items.
+ * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into
+ * 9 different items.
+ */
+ static final int HANDLE_BASE = 20;
+
+ /**
+ * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+ * instead of the constant pool, in order to avoid clashes with normal
+ * constant pool items in the ClassWriter constant pool's hash table.
+ */
+ static final int TYPE_NORMAL = 30;
+
+ /**
+ * Uninitialized type Item stored in the ClassWriter
+ * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+ * avoid clashes with normal constant pool items in the ClassWriter constant
+ * pool's hash table.
+ */
+ static final int TYPE_UNINIT = 31;
+
+ /**
+ * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+ * instead of the constant pool, in order to avoid clashes with normal
+ * constant pool items in the ClassWriter constant pool's hash table.
+ */
+ static final int TYPE_MERGED = 32;
+
+ /**
+ * The type of BootstrapMethods items. These items are stored in a
+ * special class attribute named BootstrapMethods and
+ * not in the constant pool.
+ */
+ static final int BSM = 33;
+
+ /**
+ * The class reader from which this class writer was constructed, if any.
+ */
+ ClassReader cr;
+
+ /**
+ * Minor and major version numbers of the class to be generated.
+ */
+ int version;
+
+ /**
+ * Index of the next item to be added in the constant pool.
+ */
+ int index;
+
+ /**
+ * The constant pool of this class.
+ */
+ final ByteVector pool;
+
+ /**
+ * The constant pool's hash table data.
+ */
+ Item[] items;
+
+ /**
+ * The threshold of the constant pool's hash table.
+ */
+ int threshold;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key2;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key3;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key4;
+
+ /**
+ * A type table used to temporarily store internal names that will not
+ * necessarily be stored in the constant pool. This type table is used by
+ * the control flow and data flow analysis algorithm used to compute stack
+ * map frames from scratch. This array associates to each index <tt>i</tt>
+ * the Item whose index is <tt>i</tt>. All Item objects stored in this
+ * array are also stored in the {@link #items} hash table. These two arrays
+ * allow to retrieve an Item from its index or, conversely, to get the index
+ * of an Item from its value. Each Item stores an internal name in its
+ * {@link Item#strVal1} field.
+ */
+ Item[] typeTable;
+
+ /**
+ * Number of elements in the {@link #typeTable} array.
+ */
+ private short typeCount;
+
+ /**
+ * The access flags of this class.
+ */
+ private int access;
+
+ /**
+ * The constant pool item that contains the internal name of this class.
+ */
+ private int name;
+
+ /**
+ * The internal name of this class.
+ */
+ String thisName;
+
+ /**
+ * The constant pool item that contains the signature of this class.
+ */
+ private int signature;
+
+ /**
+ * The constant pool item that contains the internal name of the super class
+ * of this class.
+ */
+ private int superName;
+
+ /**
+ * Number of interfaces implemented or extended by this class or interface.
+ */
+ private int interfaceCount;
+
+ /**
+ * The interfaces implemented or extended by this class or interface. More
+ * precisely, this array contains the indexes of the constant pool items
+ * that contain the internal names of these interfaces.
+ */
+ private int[] interfaces;
+
+ /**
+ * The index of the constant pool item that contains the name of the source
+ * file from which this class was compiled.
+ */
+ private int sourceFile;
+
+ /**
+ * The SourceDebug attribute of this class.
+ */
+ private ByteVector sourceDebug;
+
+ /**
+ * The constant pool item that contains the name of the enclosing class of
+ * this class.
+ */
+ private int enclosingMethodOwner;
+
+ /**
+ * The constant pool item that contains the name and descriptor of the
+ * enclosing method of this class.
+ */
+ private int enclosingMethod;
+
+ /**
+ * The runtime visible annotations of this class.
+ */
+ private AnnotationWriter anns;
+
+ /**
+ * The runtime invisible annotations of this class.
+ */
+ private AnnotationWriter ianns;
+
+ /**
+ * The non standard attributes of this class.
+ */
+ private Attribute attrs;
+
+ /**
+ * The number of entries in the InnerClasses attribute.
+ */
+ private int innerClassesCount;
+
+ /**
+ * The InnerClasses attribute.
+ */
+ private ByteVector innerClasses;
+
+ /**
+ * The number of entries in the BootstrapMethods attribute.
+ */
+ int bootstrapMethodsCount;
+
+ /**
+ * The BootstrapMethods attribute.
+ */
+ ByteVector bootstrapMethods;
+
+ /**
+ * The fields of this class. These fields are stored in a linked list of
+ * {@link FieldWriter} objects, linked to each other by their
+ * {@link FieldWriter#fv} field. This field stores the first element of
+ * this list.
+ */
+ FieldWriter firstField;
+
+ /**
+ * The fields of this class. These fields are stored in a linked list of
+ * {@link FieldWriter} objects, linked to each other by their
+ * {@link FieldWriter#fv} field. This field stores the last element of
+ * this list.
+ */
+ FieldWriter lastField;
+
+ /**
+ * The methods of this class. These methods are stored in a linked list of
+ * {@link MethodWriter} objects, linked to each other by their
+ * {@link MethodWriter#mv} field. This field stores the first element of
+ * this list.
+ */
+ MethodWriter firstMethod;
+
+ /**
+ * The methods of this class. These methods are stored in a linked list of
+ * {@link MethodWriter} objects, linked to each other by their
+ * {@link MethodWriter#mv} field. This field stores the last element of
+ * this list.
+ */
+ MethodWriter lastMethod;
+
+ /**
+ * <tt>true</tt> if the maximum stack size and number of local variables
+ * must be automatically computed.
+ */
+ private final boolean computeMaxs;
+
+ /**
+ * <tt>true</tt> if the stack map frames must be recomputed from scratch.
+ */
+ private final boolean computeFrames;
+
+ /**
+ * <tt>true</tt> if the stack map tables of this class are invalid. The
+ * {@link MethodWriter#resizeInstructions} method cannot transform existing
+ * stack map tables, and so produces potentially invalid classes when it is
+ * executed. In this case the class is reread and rewritten with the
+ * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
+ * stack map tables when this option is used).
+ */
+ boolean invalidFrames;
+
+ // ------------------------------------------------------------------------
+ // Static initializer
+ // ------------------------------------------------------------------------
+
+ /**
+ * Computes the instruction types of JVM opcodes.
+ */
+ static {
+ int i;
+ byte[] b = new byte[220];
+ String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+ + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
+ + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
+ for (i = 0; i < b.length; ++i) {
+ b[i] = (byte) (s.charAt(i) - 'A');
+ }
+ TYPE = b;
+
+ // code to generate the above string
+ //
+ // // SBYTE_INSN instructions
+ // b[Constants.NEWARRAY] = SBYTE_INSN;
+ // b[Constants.BIPUSH] = SBYTE_INSN;
+ //
+ // // SHORT_INSN instructions
+ // b[Constants.SIPUSH] = SHORT_INSN;
+ //
+ // // (IMPL)VAR_INSN instructions
+ // b[Constants.RET] = VAR_INSN;
+ // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
+ // b[i] = VAR_INSN;
+ // }
+ // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
+ // b[i] = VAR_INSN;
+ // }
+ // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
+ // b[i] = IMPLVAR_INSN;
+ // }
+ // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
+ // b[i] = IMPLVAR_INSN;
+ // }
+ //
+ // // TYPE_INSN instructions
+ // b[Constants.NEW] = TYPE_INSN;
+ // b[Constants.ANEWARRAY] = TYPE_INSN;
+ // b[Constants.CHECKCAST] = TYPE_INSN;
+ // b[Constants.INSTANCEOF] = TYPE_INSN;
+ //
+ // // (Set)FIELDORMETH_INSN instructions
+ // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
+ // b[i] = FIELDORMETH_INSN;
+ // }
+ // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
+ // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN;
+ //
+ // // LABEL(W)_INSN instructions
+ // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
+ // b[i] = LABEL_INSN;
+ // }
+ // b[Constants.IFNULL] = LABEL_INSN;
+ // b[Constants.IFNONNULL] = LABEL_INSN;
+ // b[200] = LABELW_INSN; // GOTO_W
+ // b[201] = LABELW_INSN; // JSR_W
+ // // temporary opcodes used internally by ASM - see Label and
+ // MethodWriter
+ // for (i = 202; i < 220; ++i) {
+ // b[i] = LABEL_INSN;
+ // }
+ //
+ // // LDC(_W) instructions
+ // b[Constants.LDC] = LDC_INSN;
+ // b[19] = LDCW_INSN; // LDC_W
+ // b[20] = LDCW_INSN; // LDC2_W
+ //
+ // // special instructions
+ // b[Constants.IINC] = IINC_INSN;
+ // b[Constants.TABLESWITCH] = TABL_INSN;
+ // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
+ // b[Constants.MULTIANEWARRAY] = MANA_INSN;
+ // b[196] = WIDE_INSN; // WIDE
+ //
+ // for (i = 0; i < b.length; ++i) {
+ // System.err.print((char)('A' + b[i]));
+ // }
+ // System.err.println();
+ }
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassWriter} object.
+ *
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ */
+ public ClassWriter(final int flags) {
+ super(Opcodes.ASM4);
+ index = 1;
+ pool = new ByteVector();
+ items = new Item[256];
+ threshold = (int) (0.75d * items.length);
+ key = new Item();
+ key2 = new Item();
+ key3 = new Item();
+ key4 = new Item();
+ this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
+ this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
+ }
+
+ /**
+ * Constructs a new {@link ClassWriter} object and enables optimizations for
+ * "mostly add" bytecode transformations. These optimizations are the
+ * following:
+ *
+ * <ul> <li>The constant pool from the original class is copied as is in the
+ * new class, which saves time. New constant pool entries will be added at
+ * the end if necessary, but unused constant pool entries <i>won't be
+ * removed</i>.</li> <li>Methods that are not transformed are copied as is
+ * in the new class, directly from the original class bytecode (i.e. without
+ * emitting visit events for all the method instructions), which saves a
+ * <i>lot</i> of time. Untransformed methods are detected by the fact that
+ * the {@link ClassReader} receives {@link MethodVisitor} objects that come
+ * from a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+ * instance).</li> </ul>
+ *
+ * @param classReader the {@link ClassReader} used to read the original
+ * class. It will be used to copy the entire constant pool from the
+ * original class and also to copy other fragments of original
+ * bytecode where applicable.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. <i>These option flags do not affect methods that
+ * are copied as is in the new class. This means that the maximum
+ * stack size nor the stack frames will be computed for these
+ * methods</i>. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ */
+ public ClassWriter(final ClassReader classReader, final int flags) {
+ this(flags);
+ classReader.copyPool(this);
+ this.cr = classReader;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public final void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ this.version = version;
+ this.access = access;
+ this.name = newClass(name);
+ thisName = name;
+ if (ClassReader.SIGNATURES && signature != null) {
+ this.signature = newUTF8(signature);
+ }
+ this.superName = superName == null ? 0 : newClass(superName);
+ if (interfaces != null && interfaces.length > 0) {
+ interfaceCount = interfaces.length;
+ this.interfaces = new int[interfaceCount];
+ for (int i = 0; i < interfaceCount; ++i) {
+ this.interfaces[i] = newClass(interfaces[i]);
+ }
+ }
+ }
+
+ @Override
+ public final void visitSource(final String file, final String debug) {
+ if (file != null) {
+ sourceFile = newUTF8(file);
+ }
+ if (debug != null) {
+ sourceDebug = new ByteVector().putUTF8(debug);
+ }
+ }
+
+ @Override
+ public final void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ enclosingMethodOwner = newClass(owner);
+ if (name != null && desc != null) {
+ enclosingMethod = newNameType(name, desc);
+ }
+ }
+
+ @Override
+ public final AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public final void visitAttribute(final Attribute attr) {
+ attr.next = attrs;
+ attrs = attr;
+ }
+
+ @Override
+ public final void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ if (innerClasses == null) {
+ innerClasses = new ByteVector();
+ }
+ ++innerClassesCount;
+ innerClasses.putShort(name == null ? 0 : newClass(name));
+ innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+ innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+ innerClasses.putShort(access);
+ }
+
+ @Override
+ public final FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ return new FieldWriter(this, access, name, desc, signature, value);
+ }
+
+ @Override
+ public final MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ return new MethodWriter(this,
+ access,
+ name,
+ desc,
+ signature,
+ exceptions,
+ computeMaxs,
+ computeFrames);
+ }
+
+ @Override
+ public final void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Other public methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the bytecode of the class that was build with this class writer.
+ *
+ * @return the bytecode of the class that was build with this class writer.
+ */
+ public byte[] toByteArray() {
+ if (index > Short.MAX_VALUE) {
+ throw new RuntimeException("Class file too large!");
+ }
+ // computes the real size of the bytecode of this class
+ int size = 24 + 2 * interfaceCount;
+ int nbFields = 0;
+ FieldWriter fb = firstField;
+ while (fb != null) {
+ ++nbFields;
+ size += fb.getSize();
+ fb = (FieldWriter) fb.fv;
+ }
+ int nbMethods = 0;
+ MethodWriter mb = firstMethod;
+ while (mb != null) {
+ ++nbMethods;
+ size += mb.getSize();
+ mb = (MethodWriter) mb.mv;
+ }
+ int attributeCount = 0;
+ if (bootstrapMethods != null) { // we put it as first argument in order
+ // to improve a bit ClassReader.copyBootstrapMethods
+ ++attributeCount;
+ size += 8 + bootstrapMethods.length;
+ newUTF8("BootstrapMethods");
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ ++attributeCount;
+ size += 8;
+ newUTF8("Signature");
+ }
+ if (sourceFile != 0) {
+ ++attributeCount;
+ size += 8;
+ newUTF8("SourceFile");
+ }
+ if (sourceDebug != null) {
+ ++attributeCount;
+ size += sourceDebug.length + 4;
+ newUTF8("SourceDebugExtension");
+ }
+ if (enclosingMethodOwner != 0) {
+ ++attributeCount;
+ size += 10;
+ newUTF8("EnclosingMethod");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Deprecated");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Synthetic");
+ }
+ if (innerClasses != null) {
+ ++attributeCount;
+ size += 8 + innerClasses.length;
+ newUTF8("InnerClasses");
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ size += 8 + anns.getSize();
+ newUTF8("RuntimeVisibleAnnotations");
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ size += 8 + ianns.getSize();
+ newUTF8("RuntimeInvisibleAnnotations");
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ size += attrs.getSize(this, null, 0, -1, -1);
+ }
+ size += pool.length;
+ // allocates a byte vector of this size, in order to avoid unnecessary
+ // arraycopy operations in the ByteVector.enlarge() method
+ ByteVector out = new ByteVector(size);
+ out.putInt(0xCAFEBABE).putInt(version);
+ out.putShort(index).putByteArray(pool.data, 0, pool.length);
+ int mask = Opcodes.ACC_DEPRECATED
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ out.putShort(access & ~mask).putShort(name).putShort(superName);
+ out.putShort(interfaceCount);
+ for (int i = 0; i < interfaceCount; ++i) {
+ out.putShort(interfaces[i]);
+ }
+ out.putShort(nbFields);
+ fb = firstField;
+ while (fb != null) {
+ fb.put(out);
+ fb = (FieldWriter) fb.fv;
+ }
+ out.putShort(nbMethods);
+ mb = firstMethod;
+ while (mb != null) {
+ mb.put(out);
+ mb = (MethodWriter) mb.mv;
+ }
+ out.putShort(attributeCount);
+ if (bootstrapMethods != null) { // should be the first class attribute ?
+ out.putShort(newUTF8("BootstrapMethods"));
+ out.putInt(bootstrapMethods.length + 2).putShort(bootstrapMethodsCount);
+ out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
+ }
+ if (sourceFile != 0) {
+ out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
+ }
+ if (sourceDebug != null) {
+ int len = sourceDebug.length - 2;
+ out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
+ out.putByteArray(sourceDebug.data, 2, len);
+ }
+ if (enclosingMethodOwner != 0) {
+ out.putShort(newUTF8("EnclosingMethod")).putInt(4);
+ out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(newUTF8("Deprecated")).putInt(0);
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((version & 0xFFFF) < Opcodes.V1_5 || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ out.putShort(newUTF8("Synthetic")).putInt(0);
+ }
+ if (innerClasses != null) {
+ out.putShort(newUTF8("InnerClasses"));
+ out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
+ out.putByteArray(innerClasses.data, 0, innerClasses.length);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (attrs != null) {
+ attrs.put(this, null, 0, -1, -1, out);
+ }
+ if (invalidFrames) {
+ ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
+ new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
+ return cw.toByteArray();
+ }
+ return out.data;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: constant pool management
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds a number or string constant to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ *
+ * @param cst the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double}, a {@link String} or a
+ * {@link Type}.
+ * @return a new or already existing constant item with the given value.
+ */
+ Item newConstItem(final Object cst) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Byte) {
+ int val = ((Byte) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Character) {
+ int val = ((Character) cst).charValue();
+ return newInteger(val);
+ } else if (cst instanceof Short) {
+ int val = ((Short) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Boolean) {
+ int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+ return newInteger(val);
+ } else if (cst instanceof Float) {
+ float val = ((Float) cst).floatValue();
+ return newFloat(val);
+ } else if (cst instanceof Long) {
+ long val = ((Long) cst).longValue();
+ return newLong(val);
+ } else if (cst instanceof Double) {
+ double val = ((Double) cst).doubleValue();
+ return newDouble(val);
+ } else if (cst instanceof String) {
+ return newString((String) cst);
+ } else if (cst instanceof Type) {
+ Type t = (Type) cst;
+ int s = t.getSort();
+ if (s == Type.ARRAY) {
+ return newClassItem(t.getDescriptor());
+ } else if (s == Type.OBJECT) {
+ return newClassItem(t.getInternalName());
+ } else { // s == Type.METHOD
+ return newMethodTypeItem(t.getDescriptor());
+ }
+ } else if (cst instanceof Handle) {
+ Handle h = (Handle) cst;
+ return newHandleItem(h.tag, h.owner, h.name, h.desc);
+ } else {
+ throw new IllegalArgumentException("value " + cst);
+ }
+ }
+
+ /**
+ * Adds a number or string constant to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param cst the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ * @return the index of a new or already existing constant item with the
+ * given value.
+ */
+ public int newConst(final Object cst) {
+ return newConstItem(cst).index;
+ }
+
+ /**
+ * Adds an UTF8 string to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param value the String value.
+ * @return the index of a new or already existing UTF8 item.
+ */
+ public int newUTF8(final String value) {
+ key.set(UTF8, value, null, null);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(UTF8).putUTF8(value);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds a class reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param value the internal name of the class.
+ * @return a new or already existing class reference item.
+ */
+ Item newClassItem(final String value) {
+ key2.set(CLASS, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(CLASS, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a class reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param value the internal name of the class.
+ * @return the index of a new or already existing class reference item.
+ */
+ public int newClass(final String value) {
+ return newClassItem(value).index;
+ }
+
+ /**
+ * Adds a method type reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param methodDesc method descriptor of the method type.
+ * @return a new or already existing method type reference item.
+ */
+ Item newMethodTypeItem(final String methodDesc) {
+ key2.set(MTYPE, methodDesc, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(MTYPE, newUTF8(methodDesc));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a method type reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param methodDesc method descriptor of the method type.
+ * @return the index of a new or already existing method type reference
+ * item.
+ */
+ public int newMethodType(final String methodDesc) {
+ return newMethodTypeItem(methodDesc).index;
+ }
+
+ /**
+ * Adds a handle to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner the internal name of the field or method owner class.
+ * @param name the name of the field or method.
+ * @param desc the descriptor of the field or method.
+ * @return a new or an already existing method type reference item.
+ */
+ Item newHandleItem(
+ final int tag,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ key4.set(HANDLE_BASE + tag, owner, name, desc);
+ Item result = get(key4);
+ if (result == null) {
+ if (tag <= Opcodes.H_PUTSTATIC) {
+ put112(HANDLE, tag, newField(owner, name, desc));
+ } else {
+ put112(HANDLE, tag, newMethod(owner,
+ name,
+ desc,
+ tag == Opcodes.H_INVOKEINTERFACE));
+ }
+ result = new Item(index++, key4);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a handle to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param tag the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC}, {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner the internal name of the field or method owner class.
+ * @param name the name of the field or method.
+ * @param desc the descriptor of the field or method.
+ * @return the index of a new or already existing method type reference
+ * item.
+ */
+ public int newHandle(
+ final int tag,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ return newHandleItem(tag, owner, name, desc).index;
+ }
+
+ /**
+ * Adds an invokedynamic reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param name name of the invoked method.
+ * @param desc descriptor of the invoke method.
+ * @param bsm the bootstrap method.
+ * @param bsmArgs the bootstrap method constant arguments.
+ *
+ * @return a new or an already existing invokedynamic type reference item.
+ */
+ Item newInvokeDynamicItem(
+ final String name,
+ final String desc,
+ final Handle bsm,
+ final Object... bsmArgs)
+ {
+ // cache for performance
+ ByteVector bootstrapMethods = this.bootstrapMethods;
+ if (bootstrapMethods == null) {
+ bootstrapMethods = this.bootstrapMethods = new ByteVector();
+ }
+
+ int position = bootstrapMethods.length; // record current position
+
+ int hashCode = bsm.hashCode();
+ bootstrapMethods.putShort(newHandle(bsm.tag,
+ bsm.owner,
+ bsm.name,
+ bsm.desc));
+
+ int argsLength = bsmArgs.length;
+ bootstrapMethods.putShort(argsLength);
+
+ for (int i = 0; i < argsLength; i++) {
+ Object bsmArg = bsmArgs[i];
+ hashCode ^= bsmArg.hashCode();
+ bootstrapMethods.putShort(newConst(bsmArg));
+ }
+
+ byte[] data = bootstrapMethods.data;
+ int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments)
+ hashCode &= 0x7FFFFFFF;
+ Item result = items[hashCode % items.length];
+ loop: while (result != null) {
+ if (result.type != BSM || result.hashCode != hashCode) {
+ result = result.next;
+ continue;
+ }
+
+ // because the data encode the size of the argument
+ // we don't need to test if these size are equals
+ int resultPosition = result.intVal;
+ for (int p = 0; p < length; p++) {
+ if (data[position + p] != data[resultPosition + p]) {
+ result = result.next;
+ continue loop;
+ }
+ }
+ break;
+ }
+
+ int bootstrapMethodIndex;
+ if (result != null) {
+ bootstrapMethodIndex = result.index;
+ bootstrapMethods.length = position; // revert to old position
+ } else {
+ bootstrapMethodIndex = bootstrapMethodsCount++;
+ result = new Item(bootstrapMethodIndex);
+ result.set(position, hashCode);
+ put(result);
+ }
+
+ // now, create the InvokeDynamic constant
+ key3.set(name, desc, bootstrapMethodIndex);
+ result = get(key3);
+ if (result == null) {
+ put122(INDY, bootstrapMethodIndex, newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds an invokedynamic reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param name name of the invoked method.
+ * @param desc descriptor of the invoke method.
+ * @param bsm the bootstrap method.
+ * @param bsmArgs the bootstrap method constant arguments.
+ *
+ * @return the index of a new or already existing invokedynamic
+ * reference item.
+ */
+ public int newInvokeDynamic(
+ final String name,
+ final String desc,
+ final Handle bsm,
+ final Object... bsmArgs)
+ {
+ return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
+ }
+
+ /**
+ * Adds a field reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param owner the internal name of the field's owner class.
+ * @param name the field's name.
+ * @param desc the field's descriptor.
+ * @return a new or already existing field reference item.
+ */
+ Item newFieldItem(final String owner, final String name, final String desc)
+ {
+ key3.set(FIELD, owner, name, desc);
+ Item result = get(key3);
+ if (result == null) {
+ put122(FIELD, newClass(owner), newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a field reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param owner the internal name of the field's owner class.
+ * @param name the field's name.
+ * @param desc the field's descriptor.
+ * @return the index of a new or already existing field reference item.
+ */
+ public int newField(final String owner, final String name, final String desc)
+ {
+ return newFieldItem(owner, name, desc).index;
+ }
+
+ /**
+ * Adds a method reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param owner the internal name of the method's owner class.
+ * @param name the method's name.
+ * @param desc the method's descriptor.
+ * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ * @return a new or already existing method reference item.
+ */
+ Item newMethodItem(
+ final String owner,
+ final String name,
+ final String desc,
+ final boolean itf)
+ {
+ int type = itf ? IMETH : METH;
+ key3.set(type, owner, name, desc);
+ Item result = get(key3);
+ if (result == null) {
+ put122(type, newClass(owner), newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a method reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param owner the internal name of the method's owner class.
+ * @param name the method's name.
+ * @param desc the method's descriptor.
+ * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ * @return the index of a new or already existing method reference item.
+ */
+ public int newMethod(
+ final String owner,
+ final String name,
+ final String desc,
+ final boolean itf)
+ {
+ return newMethodItem(owner, name, desc, itf).index;
+ }
+
+ /**
+ * Adds an integer to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item.
+ *
+ * @param value the int value.
+ * @return a new or already existing int item.
+ */
+ Item newInteger(final int value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(INT).putInt(value);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a float to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the float value.
+ * @return a new or already existing float item.
+ */
+ Item newFloat(final float value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(FLOAT).putInt(key.intVal);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a long to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the long value.
+ * @return a new or already existing long item.
+ */
+ Item newLong(final long value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(LONG).putLong(value);
+ result = new Item(index, key);
+ index += 2;
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a double to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the double value.
+ * @return a new or already existing double item.
+ */
+ Item newDouble(final double value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(DOUBLE).putLong(key.longVal);
+ result = new Item(index, key);
+ index += 2;
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a string to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the String value.
+ * @return a new or already existing string item.
+ */
+ private Item newString(final String value) {
+ key2.set(STR, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(STR, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a name and type to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param name a name.
+ * @param desc a type descriptor.
+ * @return the index of a new or already existing name and type item.
+ */
+ public int newNameType(final String name, final String desc) {
+ return newNameTypeItem(name, desc).index;
+ }
+
+ /**
+ * Adds a name and type to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item.
+ *
+ * @param name a name.
+ * @param desc a type descriptor.
+ * @return a new or already existing name and type item.
+ */
+ Item newNameTypeItem(final String name, final String desc) {
+ key2.set(NAME_TYPE, name, desc, null);
+ Item result = get(key2);
+ if (result == null) {
+ put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds the given internal name to {@link #typeTable} and returns its index.
+ * Does nothing if the type table already contains this internal name.
+ *
+ * @param type the internal name to be added to the type table.
+ * @return the index of this internal name in the type table.
+ */
+ int addType(final String type) {
+ key.set(TYPE_NORMAL, type, null, null);
+ Item result = get(key);
+ if (result == null) {
+ result = addType(key);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds the given "uninitialized" type to {@link #typeTable} and returns its
+ * index. This method is used for UNINITIALIZED types, made of an internal
+ * name and a bytecode offset.
+ *
+ * @param type the internal name to be added to the type table.
+ * @param offset the bytecode offset of the NEW instruction that created
+ * this UNINITIALIZED type value.
+ * @return the index of this internal name in the type table.
+ */
+ int addUninitializedType(final String type, final int offset) {
+ key.type = TYPE_UNINIT;
+ key.intVal = offset;
+ key.strVal1 = type;
+ key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
+ Item result = get(key);
+ if (result == null) {
+ result = addType(key);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds the given Item to {@link #typeTable}.
+ *
+ * @param item the value to be added to the type table.
+ * @return the added Item, which a new Item instance with the same value as
+ * the given Item.
+ */
+ private Item addType(final Item item) {
+ ++typeCount;
+ Item result = new Item(typeCount, key);
+ put(result);
+ if (typeTable == null) {
+ typeTable = new Item[16];
+ }
+ if (typeCount == typeTable.length) {
+ Item[] newTable = new Item[2 * typeTable.length];
+ System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
+ typeTable = newTable;
+ }
+ typeTable[typeCount] = result;
+ return result;
+ }
+
+ /**
+ * Returns the index of the common super type of the two given types. This
+ * method calls {@link #getCommonSuperClass} and caches the result in the
+ * {@link #items} hash table to speedup future calls with the same
+ * parameters.
+ *
+ * @param type1 index of an internal name in {@link #typeTable}.
+ * @param type2 index of an internal name in {@link #typeTable}.
+ * @return the index of the common super type of the two given types.
+ */
+ int getMergedType(final int type1, final int type2) {
+ key2.type = TYPE_MERGED;
+ key2.longVal = type1 | (((long) type2) << 32);
+ key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
+ Item result = get(key2);
+ if (result == null) {
+ String t = typeTable[type1].strVal1;
+ String u = typeTable[type2].strVal1;
+ key2.intVal = addType(getCommonSuperClass(t, u));
+ result = new Item((short) 0, key2);
+ put(result);
+ }
+ return result.intVal;
+ }
+
+ /**
+ * Returns the common super type of the two given types. The default
+ * implementation of this method <i>loads<i> the two given classes and uses
+ * the java.lang.Class methods to find the common super class. It can be
+ * overridden to compute this common super type in other ways, in particular
+ * without actually loading any class, or to take into account the class
+ * that is currently being generated by this ClassWriter, which can of
+ * course not be loaded since it is under construction.
+ *
+ * @param type1 the internal name of a class.
+ * @param type2 the internal name of another class.
+ * @return the internal name of the common super class of the two given
+ * classes.
+ */
+ protected String getCommonSuperClass(final String type1, final String type2)
+ {
+ Class<?> c, d;
+ ClassLoader classLoader = getClass().getClassLoader();
+ try {
+ c = Class.forName(type1.replace('/', '.'), false, classLoader);
+ d = Class.forName(type2.replace('/', '.'), false, classLoader);
+ } catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ if (c.isAssignableFrom(d)) {
+ return type1;
+ }
+ if (d.isAssignableFrom(c)) {
+ return type2;
+ }
+ if (c.isInterface() || d.isInterface()) {
+ return "java/lang/Object";
+ } else {
+ do {
+ c = c.getSuperclass();
+ } while (!c.isAssignableFrom(d));
+ return c.getName().replace('.', '/');
+ }
+ }
+
+ /**
+ * Returns the constant pool's hash table item which is equal to the given
+ * item.
+ *
+ * @param key a constant pool item.
+ * @return the constant pool's hash table item which is equal to the given
+ * item, or <tt>null</tt> if there is no such item.
+ */
+ private Item get(final Item key) {
+ Item i = items[key.hashCode % items.length];
+ while (i != null && (i.type != key.type || !key.isEqualTo(i))) {
+ i = i.next;
+ }
+ return i;
+ }
+
+ /**
+ * Puts the given item in the constant pool's hash table. The hash table
+ * <i>must</i> not already contains this item.
+ *
+ * @param i the item to be added to the constant pool's hash table.
+ */
+ private void put(final Item i) {
+ if (index + typeCount > threshold) {
+ int ll = items.length;
+ int nl = ll * 2 + 1;
+ Item[] newItems = new Item[nl];
+ for (int l = ll - 1; l >= 0; --l) {
+ Item j = items[l];
+ while (j != null) {
+ int index = j.hashCode % newItems.length;
+ Item k = j.next;
+ j.next = newItems[index];
+ newItems[index] = j;
+ j = k;
+ }
+ }
+ items = newItems;
+ threshold = (int) (nl * 0.75);
+ }
+ int index = i.hashCode % items.length;
+ i.next = items[index];
+ items[index] = i;
+ }
+
+ /**
+ * Puts one byte and two shorts into the constant pool.
+ *
+ * @param b a byte.
+ * @param s1 a short.
+ * @param s2 another short.
+ */
+ private void put122(final int b, final int s1, final int s2) {
+ pool.put12(b, s1).putShort(s2);
+ }
+
+ /**
+ * Puts two bytes and one short into the constant pool.
+ *
+ * @param b1 a byte.
+ * @param b2 another byte.
+ * @param s a short.
+ */
+ private void put112(final int b1, final int b2, final int s) {
+ pool.put11(b1, b2).putShort(s);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/CustomAttr.java b/src/compiler/scala/tools/asm/CustomAttr.java
new file mode 100644
index 0000000000..5ecfd283d0
--- /dev/null
+++ b/src/compiler/scala/tools/asm/CustomAttr.java
@@ -0,0 +1,20 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2012 LAMP/EPFL
+ */
+
+package scala.tools.asm;
+
+import scala.tools.asm.Attribute;
+
+/**
+ * A subclass of ASM's Attribute for the sole purpose of accessing a protected field there.
+ *
+ */
+public class CustomAttr extends Attribute {
+
+ public CustomAttr(final String type, final byte[] value) {
+ super(type);
+ super.value = value;
+ }
+
+}
diff --git a/src/compiler/scala/tools/asm/Edge.java b/src/compiler/scala/tools/asm/Edge.java
new file mode 100644
index 0000000000..daac1f7bb0
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Edge.java
@@ -0,0 +1,75 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * An edge in the control flow graph of a method body. See {@link Label Label}.
+ *
+ * @author Eric Bruneton
+ */
+class Edge {
+
+ /**
+ * Denotes a normal control flow graph edge.
+ */
+ static final int NORMAL = 0;
+
+ /**
+ * Denotes a control flow graph edge corresponding to an exception handler.
+ * More precisely any {@link Edge} whose {@link #info} is strictly positive
+ * corresponds to an exception handler. The actual value of {@link #info} is
+ * the index, in the {@link ClassWriter} type table, of the exception that
+ * is catched.
+ */
+ static final int EXCEPTION = 0x7FFFFFFF;
+
+ /**
+ * Information about this control flow graph edge. If
+ * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
+ * stack size in the basic block from which this edge originates. This size
+ * is equal to the stack size at the "jump" instruction to which this edge
+ * corresponds, relatively to the stack size at the beginning of the
+ * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
+ * this field is the kind of this control flow graph edge (i.e. NORMAL or
+ * EXCEPTION).
+ */
+ int info;
+
+ /**
+ * The successor block of the basic block from which this edge originates.
+ */
+ Label successor;
+
+ /**
+ * The next edge in the list of successors of the originating basic block.
+ * See {@link Label#successors successors}.
+ */
+ Edge next;
+}
diff --git a/src/compiler/scala/tools/asm/FieldVisitor.java b/src/compiler/scala/tools/asm/FieldVisitor.java
new file mode 100644
index 0000000000..9ac0f6236f
--- /dev/null
+++ b/src/compiler/scala/tools/asm/FieldVisitor.java
@@ -0,0 +1,115 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A visitor to visit a Java field. The methods of this class must be called
+ * in the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class FieldVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4}.
+ */
+ protected final int api;
+
+ /**
+ * The field visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ protected FieldVisitor fv;
+
+ /**
+ * Constructs a new {@link FieldVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ public FieldVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link FieldVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param fv the field visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public FieldVisitor(final int api, final FieldVisitor fv) {
+ /*if (api != Opcodes.ASM4) {
+ throw new IllegalArgumentException();
+ }*/
+ this.api = api;
+ this.fv = fv;
+ }
+
+ /**
+ * Visits an annotation of the field.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (fv != null) {
+ return fv.visitAnnotation(desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a non standard attribute of the field.
+ *
+ * @param attr an attribute.
+ */
+ public void visitAttribute(Attribute attr) {
+ if (fv != null) {
+ fv.visitAttribute(attr);
+ }
+ }
+
+ /**
+ * Visits the end of the field. This method, which is the last one to be
+ * called, is used to inform the visitor that all the annotations and
+ * attributes of the field have been visited.
+ */
+ public void visitEnd() {
+ if (fv != null) {
+ fv.visitEnd();
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/FieldWriter.java b/src/compiler/scala/tools/asm/FieldWriter.java
new file mode 100644
index 0000000000..45ef6d0df3
--- /dev/null
+++ b/src/compiler/scala/tools/asm/FieldWriter.java
@@ -0,0 +1,271 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * An {@link FieldVisitor} that generates Java fields in bytecode form.
+ *
+ * @author Eric Bruneton
+ */
+final class FieldWriter extends FieldVisitor {
+
+ /**
+ * The class writer to which this field must be added.
+ */
+ private final ClassWriter cw;
+
+ /**
+ * Access flags of this field.
+ */
+ private final int access;
+
+ /**
+ * The index of the constant pool item that contains the name of this
+ * method.
+ */
+ private final int name;
+
+ /**
+ * The index of the constant pool item that contains the descriptor of this
+ * field.
+ */
+ private final int desc;
+
+ /**
+ * The index of the constant pool item that contains the signature of this
+ * field.
+ */
+ private int signature;
+
+ /**
+ * The index of the constant pool item that contains the constant value of
+ * this field.
+ */
+ private int value;
+
+ /**
+ * The runtime visible annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter anns;
+
+ /**
+ * The runtime invisible annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ianns;
+
+ /**
+ * The non standard attributes of this field. May be <tt>null</tt>.
+ */
+ private Attribute attrs;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link FieldWriter}.
+ *
+ * @param cw the class writer to which this field must be added.
+ * @param access the field's access flags (see {@link Opcodes}).
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link Type}).
+ * @param signature the field's signature. May be <tt>null</tt>.
+ * @param value the field's constant value. May be <tt>null</tt>.
+ */
+ FieldWriter(
+ final ClassWriter cw,
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ super(Opcodes.ASM4);
+ if (cw.firstField == null) {
+ cw.firstField = this;
+ } else {
+ cw.lastField.fv = this;
+ }
+ cw.lastField = this;
+ this.cw = cw;
+ this.access = access;
+ this.name = cw.newUTF8(name);
+ this.desc = cw.newUTF8(desc);
+ if (ClassReader.SIGNATURES && signature != null) {
+ this.signature = cw.newUTF8(signature);
+ }
+ if (value != null) {
+ this.value = cw.newConstItem(value).index;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the FieldVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ attr.next = attrs;
+ attrs = attr;
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of this field.
+ *
+ * @return the size of this field.
+ */
+ int getSize() {
+ int size = 8;
+ if (value != 0) {
+ cw.newUTF8("ConstantValue");
+ size += 8;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cw.newUTF8("Deprecated");
+ size += 6;
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ cw.newUTF8("Signature");
+ size += 8;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ cw.newUTF8("RuntimeVisibleAnnotations");
+ size += 8 + anns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ cw.newUTF8("RuntimeInvisibleAnnotations");
+ size += 8 + ianns.getSize();
+ }
+ if (attrs != null) {
+ size += attrs.getSize(cw, null, 0, -1, -1);
+ }
+ return size;
+ }
+
+ /**
+ * Puts the content of this field into the given byte vector.
+ *
+ * @param out where the content of this field must be put.
+ */
+ void put(final ByteVector out) {
+ int mask = Opcodes.ACC_DEPRECATED
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ out.putShort(access & ~mask).putShort(name).putShort(desc);
+ int attributeCount = 0;
+ if (value != 0) {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (value != 0) {
+ out.putShort(cw.newUTF8("ConstantValue"));
+ out.putInt(2).putShort(value);
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(cw.newUTF8("Deprecated")).putInt(0);
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ out.putShort(cw.newUTF8("Signature"));
+ out.putInt(2).putShort(signature);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (attrs != null) {
+ attrs.put(cw, null, 0, -1, -1, out);
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/Frame.java b/src/compiler/scala/tools/asm/Frame.java
new file mode 100644
index 0000000000..387b56796d
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Frame.java
@@ -0,0 +1,1435 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * Information about the input and output stack map frames of a basic block.
+ *
+ * @author Eric Bruneton
+ */
+final class Frame {
+
+ /*
+ * Frames are computed in a two steps process: during the visit of each
+ * instruction, the state of the frame at the end of current basic block is
+ * updated by simulating the action of the instruction on the previous state
+ * of this so called "output frame". In visitMaxs, a fix point algorithm is
+ * used to compute the "input frame" of each basic block, i.e. the stack map
+ * frame at the beginning of the basic block, starting from the input frame
+ * of the first basic block (which is computed from the method descriptor),
+ * and by using the previously computed output frames to compute the input
+ * state of the other blocks.
+ *
+ * All output and input frames are stored as arrays of integers. Reference
+ * and array types are represented by an index into a type table (which is
+ * not the same as the constant pool of the class, in order to avoid adding
+ * unnecessary constants in the pool - not all computed frames will end up
+ * being stored in the stack map table). This allows very fast type
+ * comparisons.
+ *
+ * Output stack map frames are computed relatively to the input frame of the
+ * basic block, which is not yet known when output frames are computed. It
+ * is therefore necessary to be able to represent abstract types such as
+ * "the type at position x in the input frame locals" or "the type at
+ * position x from the top of the input frame stack" or even "the type at
+ * position x in the input frame, with y more (or less) array dimensions".
+ * This explains the rather complicated type format used in output frames.
+ *
+ * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
+ * signed number of array dimensions (from -8 to 7). KIND is either BASE,
+ * LOCAL or STACK. BASE is used for types that are not relative to the input
+ * frame. LOCAL is used for types that are relative to the input local
+ * variable types. STACK is used for types that are relative to the input
+ * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
+ * the input local variable types. For STACK types, it is a position
+ * relatively to the top of input frame stack. For BASE types, it is either
+ * one of the constants defined in FrameVisitor, or for OBJECT and
+ * UNINITIALIZED types, a tag and an index in the type table.
+ *
+ * Output frames can contain types of any kind and with a positive or
+ * negative dimension (and even unassigned types, represented by 0 - which
+ * does not correspond to any valid type value). Input frames can only
+ * contain BASE types of positive or null dimension. In all cases the type
+ * table contains only internal type names (array type descriptors are
+ * forbidden - dimensions must be represented through the DIM field).
+ *
+ * The LONG and DOUBLE types are always represented by using two slots (LONG +
+ * TOP or DOUBLE + TOP), for local variable types as well as in the operand
+ * stack. This is necessary to be able to simulate DUPx_y instructions,
+ * whose effect would be dependent on the actual type values if types were
+ * always represented by a single slot in the stack (and this is not
+ * possible, since actual type values are not always known - cf LOCAL and
+ * STACK type kinds).
+ */
+
+ /**
+ * Mask to get the dimension of a frame type. This dimension is a signed
+ * integer between -8 and 7.
+ */
+ static final int DIM = 0xF0000000;
+
+ /**
+ * Constant to be added to a type to get a type with one more dimension.
+ */
+ static final int ARRAY_OF = 0x10000000;
+
+ /**
+ * Constant to be added to a type to get a type with one less dimension.
+ */
+ static final int ELEMENT_OF = 0xF0000000;
+
+ /**
+ * Mask to get the kind of a frame type.
+ *
+ * @see #BASE
+ * @see #LOCAL
+ * @see #STACK
+ */
+ static final int KIND = 0xF000000;
+
+ /**
+ * Flag used for LOCAL and STACK types. Indicates that if this type happens
+ * to be a long or double type (during the computations of input frames),
+ * then it must be set to TOP because the second word of this value has
+ * been reused to store other data in the basic block. Hence the first word
+ * no longer stores a valid long or double value.
+ */
+ static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
+
+ /**
+ * Mask to get the value of a frame type.
+ */
+ static final int VALUE = 0x7FFFFF;
+
+ /**
+ * Mask to get the kind of base types.
+ */
+ static final int BASE_KIND = 0xFF00000;
+
+ /**
+ * Mask to get the value of base types.
+ */
+ static final int BASE_VALUE = 0xFFFFF;
+
+ /**
+ * Kind of the types that are not relative to an input stack map frame.
+ */
+ static final int BASE = 0x1000000;
+
+ /**
+ * Base kind of the base reference types. The BASE_VALUE of such types is an
+ * index into the type table.
+ */
+ static final int OBJECT = BASE | 0x700000;
+
+ /**
+ * Base kind of the uninitialized base types. The BASE_VALUE of such types
+ * in an index into the type table (the Item at that index contains both an
+ * instruction offset and an internal class name).
+ */
+ static final int UNINITIALIZED = BASE | 0x800000;
+
+ /**
+ * Kind of the types that are relative to the local variable types of an
+ * input stack map frame. The value of such types is a local variable index.
+ */
+ private static final int LOCAL = 0x2000000;
+
+ /**
+ * Kind of the the types that are relative to the stack of an input stack
+ * map frame. The value of such types is a position relatively to the top of
+ * this stack.
+ */
+ private static final int STACK = 0x3000000;
+
+ /**
+ * The TOP type. This is a BASE type.
+ */
+ static final int TOP = BASE | 0;
+
+ /**
+ * The BOOLEAN type. This is a BASE type mainly used for array types.
+ */
+ static final int BOOLEAN = BASE | 9;
+
+ /**
+ * The BYTE type. This is a BASE type mainly used for array types.
+ */
+ static final int BYTE = BASE | 10;
+
+ /**
+ * The CHAR type. This is a BASE type mainly used for array types.
+ */
+ static final int CHAR = BASE | 11;
+
+ /**
+ * The SHORT type. This is a BASE type mainly used for array types.
+ */
+ static final int SHORT = BASE | 12;
+
+ /**
+ * The INTEGER type. This is a BASE type.
+ */
+ static final int INTEGER = BASE | 1;
+
+ /**
+ * The FLOAT type. This is a BASE type.
+ */
+ static final int FLOAT = BASE | 2;
+
+ /**
+ * The DOUBLE type. This is a BASE type.
+ */
+ static final int DOUBLE = BASE | 3;
+
+ /**
+ * The LONG type. This is a BASE type.
+ */
+ static final int LONG = BASE | 4;
+
+ /**
+ * The NULL type. This is a BASE type.
+ */
+ static final int NULL = BASE | 5;
+
+ /**
+ * The UNINITIALIZED_THIS type. This is a BASE type.
+ */
+ static final int UNINITIALIZED_THIS = BASE | 6;
+
+ /**
+ * The stack size variation corresponding to each JVM instruction. This
+ * stack variation is equal to the size of the values produced by an
+ * instruction, minus the size of the values consumed by this instruction.
+ */
+ static final int[] SIZE;
+
+ /**
+ * Computes the stack size variation corresponding to each JVM instruction.
+ */
+ static {
+ int i;
+ int[] b = new int[202];
+ String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
+ + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
+ + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
+ + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
+ for (i = 0; i < b.length; ++i) {
+ b[i] = s.charAt(i) - 'E';
+ }
+ SIZE = b;
+
+ // code to generate the above string
+ //
+ // int NA = 0; // not applicable (unused opcode or variable size opcode)
+ //
+ // b = new int[] {
+ // 0, //NOP, // visitInsn
+ // 1, //ACONST_NULL, // -
+ // 1, //ICONST_M1, // -
+ // 1, //ICONST_0, // -
+ // 1, //ICONST_1, // -
+ // 1, //ICONST_2, // -
+ // 1, //ICONST_3, // -
+ // 1, //ICONST_4, // -
+ // 1, //ICONST_5, // -
+ // 2, //LCONST_0, // -
+ // 2, //LCONST_1, // -
+ // 1, //FCONST_0, // -
+ // 1, //FCONST_1, // -
+ // 1, //FCONST_2, // -
+ // 2, //DCONST_0, // -
+ // 2, //DCONST_1, // -
+ // 1, //BIPUSH, // visitIntInsn
+ // 1, //SIPUSH, // -
+ // 1, //LDC, // visitLdcInsn
+ // NA, //LDC_W, // -
+ // NA, //LDC2_W, // -
+ // 1, //ILOAD, // visitVarInsn
+ // 2, //LLOAD, // -
+ // 1, //FLOAD, // -
+ // 2, //DLOAD, // -
+ // 1, //ALOAD, // -
+ // NA, //ILOAD_0, // -
+ // NA, //ILOAD_1, // -
+ // NA, //ILOAD_2, // -
+ // NA, //ILOAD_3, // -
+ // NA, //LLOAD_0, // -
+ // NA, //LLOAD_1, // -
+ // NA, //LLOAD_2, // -
+ // NA, //LLOAD_3, // -
+ // NA, //FLOAD_0, // -
+ // NA, //FLOAD_1, // -
+ // NA, //FLOAD_2, // -
+ // NA, //FLOAD_3, // -
+ // NA, //DLOAD_0, // -
+ // NA, //DLOAD_1, // -
+ // NA, //DLOAD_2, // -
+ // NA, //DLOAD_3, // -
+ // NA, //ALOAD_0, // -
+ // NA, //ALOAD_1, // -
+ // NA, //ALOAD_2, // -
+ // NA, //ALOAD_3, // -
+ // -1, //IALOAD, // visitInsn
+ // 0, //LALOAD, // -
+ // -1, //FALOAD, // -
+ // 0, //DALOAD, // -
+ // -1, //AALOAD, // -
+ // -1, //BALOAD, // -
+ // -1, //CALOAD, // -
+ // -1, //SALOAD, // -
+ // -1, //ISTORE, // visitVarInsn
+ // -2, //LSTORE, // -
+ // -1, //FSTORE, // -
+ // -2, //DSTORE, // -
+ // -1, //ASTORE, // -
+ // NA, //ISTORE_0, // -
+ // NA, //ISTORE_1, // -
+ // NA, //ISTORE_2, // -
+ // NA, //ISTORE_3, // -
+ // NA, //LSTORE_0, // -
+ // NA, //LSTORE_1, // -
+ // NA, //LSTORE_2, // -
+ // NA, //LSTORE_3, // -
+ // NA, //FSTORE_0, // -
+ // NA, //FSTORE_1, // -
+ // NA, //FSTORE_2, // -
+ // NA, //FSTORE_3, // -
+ // NA, //DSTORE_0, // -
+ // NA, //DSTORE_1, // -
+ // NA, //DSTORE_2, // -
+ // NA, //DSTORE_3, // -
+ // NA, //ASTORE_0, // -
+ // NA, //ASTORE_1, // -
+ // NA, //ASTORE_2, // -
+ // NA, //ASTORE_3, // -
+ // -3, //IASTORE, // visitInsn
+ // -4, //LASTORE, // -
+ // -3, //FASTORE, // -
+ // -4, //DASTORE, // -
+ // -3, //AASTORE, // -
+ // -3, //BASTORE, // -
+ // -3, //CASTORE, // -
+ // -3, //SASTORE, // -
+ // -1, //POP, // -
+ // -2, //POP2, // -
+ // 1, //DUP, // -
+ // 1, //DUP_X1, // -
+ // 1, //DUP_X2, // -
+ // 2, //DUP2, // -
+ // 2, //DUP2_X1, // -
+ // 2, //DUP2_X2, // -
+ // 0, //SWAP, // -
+ // -1, //IADD, // -
+ // -2, //LADD, // -
+ // -1, //FADD, // -
+ // -2, //DADD, // -
+ // -1, //ISUB, // -
+ // -2, //LSUB, // -
+ // -1, //FSUB, // -
+ // -2, //DSUB, // -
+ // -1, //IMUL, // -
+ // -2, //LMUL, // -
+ // -1, //FMUL, // -
+ // -2, //DMUL, // -
+ // -1, //IDIV, // -
+ // -2, //LDIV, // -
+ // -1, //FDIV, // -
+ // -2, //DDIV, // -
+ // -1, //IREM, // -
+ // -2, //LREM, // -
+ // -1, //FREM, // -
+ // -2, //DREM, // -
+ // 0, //INEG, // -
+ // 0, //LNEG, // -
+ // 0, //FNEG, // -
+ // 0, //DNEG, // -
+ // -1, //ISHL, // -
+ // -1, //LSHL, // -
+ // -1, //ISHR, // -
+ // -1, //LSHR, // -
+ // -1, //IUSHR, // -
+ // -1, //LUSHR, // -
+ // -1, //IAND, // -
+ // -2, //LAND, // -
+ // -1, //IOR, // -
+ // -2, //LOR, // -
+ // -1, //IXOR, // -
+ // -2, //LXOR, // -
+ // 0, //IINC, // visitIincInsn
+ // 1, //I2L, // visitInsn
+ // 0, //I2F, // -
+ // 1, //I2D, // -
+ // -1, //L2I, // -
+ // -1, //L2F, // -
+ // 0, //L2D, // -
+ // 0, //F2I, // -
+ // 1, //F2L, // -
+ // 1, //F2D, // -
+ // -1, //D2I, // -
+ // 0, //D2L, // -
+ // -1, //D2F, // -
+ // 0, //I2B, // -
+ // 0, //I2C, // -
+ // 0, //I2S, // -
+ // -3, //LCMP, // -
+ // -1, //FCMPL, // -
+ // -1, //FCMPG, // -
+ // -3, //DCMPL, // -
+ // -3, //DCMPG, // -
+ // -1, //IFEQ, // visitJumpInsn
+ // -1, //IFNE, // -
+ // -1, //IFLT, // -
+ // -1, //IFGE, // -
+ // -1, //IFGT, // -
+ // -1, //IFLE, // -
+ // -2, //IF_ICMPEQ, // -
+ // -2, //IF_ICMPNE, // -
+ // -2, //IF_ICMPLT, // -
+ // -2, //IF_ICMPGE, // -
+ // -2, //IF_ICMPGT, // -
+ // -2, //IF_ICMPLE, // -
+ // -2, //IF_ACMPEQ, // -
+ // -2, //IF_ACMPNE, // -
+ // 0, //GOTO, // -
+ // 1, //JSR, // -
+ // 0, //RET, // visitVarInsn
+ // -1, //TABLESWITCH, // visiTableSwitchInsn
+ // -1, //LOOKUPSWITCH, // visitLookupSwitch
+ // -1, //IRETURN, // visitInsn
+ // -2, //LRETURN, // -
+ // -1, //FRETURN, // -
+ // -2, //DRETURN, // -
+ // -1, //ARETURN, // -
+ // 0, //RETURN, // -
+ // NA, //GETSTATIC, // visitFieldInsn
+ // NA, //PUTSTATIC, // -
+ // NA, //GETFIELD, // -
+ // NA, //PUTFIELD, // -
+ // NA, //INVOKEVIRTUAL, // visitMethodInsn
+ // NA, //INVOKESPECIAL, // -
+ // NA, //INVOKESTATIC, // -
+ // NA, //INVOKEINTERFACE, // -
+ // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn
+ // 1, //NEW, // visitTypeInsn
+ // 0, //NEWARRAY, // visitIntInsn
+ // 0, //ANEWARRAY, // visitTypeInsn
+ // 0, //ARRAYLENGTH, // visitInsn
+ // NA, //ATHROW, // -
+ // 0, //CHECKCAST, // visitTypeInsn
+ // 0, //INSTANCEOF, // -
+ // -1, //MONITORENTER, // visitInsn
+ // -1, //MONITOREXIT, // -
+ // NA, //WIDE, // NOT VISITED
+ // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
+ // -1, //IFNULL, // visitJumpInsn
+ // -1, //IFNONNULL, // -
+ // NA, //GOTO_W, // -
+ // NA, //JSR_W, // -
+ // };
+ // for (i = 0; i < b.length; ++i) {
+ // System.err.print((char)('E' + b[i]));
+ // }
+ // System.err.println();
+ }
+
+ /**
+ * The label (i.e. basic block) to which these input and output stack map
+ * frames correspond.
+ */
+ Label owner;
+
+ /**
+ * The input stack map frame locals.
+ */
+ int[] inputLocals;
+
+ /**
+ * The input stack map frame stack.
+ */
+ int[] inputStack;
+
+ /**
+ * The output stack map frame locals.
+ */
+ private int[] outputLocals;
+
+ /**
+ * The output stack map frame stack.
+ */
+ private int[] outputStack;
+
+ /**
+ * Relative size of the output stack. The exact semantics of this field
+ * depends on the algorithm that is used.
+ *
+ * When only the maximum stack size is computed, this field is the size of
+ * the output stack relatively to the top of the input stack.
+ *
+ * When the stack map frames are completely computed, this field is the
+ * actual number of types in {@link #outputStack}.
+ */
+ private int outputStackTop;
+
+ /**
+ * Number of types that are initialized in the basic block.
+ *
+ * @see #initializations
+ */
+ private int initializationCount;
+
+ /**
+ * The types that are initialized in the basic block. A constructor
+ * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
+ * <i>every occurence</i> of this type in the local variables and in the
+ * operand stack. This cannot be done during the first phase of the
+ * algorithm since, during this phase, the local variables and the operand
+ * stack are not completely computed. It is therefore necessary to store the
+ * types on which constructors are invoked in the basic block, in order to
+ * do this replacement during the second phase of the algorithm, where the
+ * frames are fully computed. Note that this array can contain types that
+ * are relative to input locals or to the input stack (see below for the
+ * description of the algorithm).
+ */
+ private int[] initializations;
+
+ /**
+ * Returns the output frame local variable type at the given index.
+ *
+ * @param local the index of the local that must be returned.
+ * @return the output frame local variable type at the given index.
+ */
+ private int get(final int local) {
+ if (outputLocals == null || local >= outputLocals.length) {
+ // this local has never been assigned in this basic block,
+ // so it is still equal to its value in the input frame
+ return LOCAL | local;
+ } else {
+ int type = outputLocals[local];
+ if (type == 0) {
+ // this local has never been assigned in this basic block,
+ // so it is still equal to its value in the input frame
+ type = outputLocals[local] = LOCAL | local;
+ }
+ return type;
+ }
+ }
+
+ /**
+ * Sets the output frame local variable type at the given index.
+ *
+ * @param local the index of the local that must be set.
+ * @param type the value of the local that must be set.
+ */
+ private void set(final int local, final int type) {
+ // creates and/or resizes the output local variables array if necessary
+ if (outputLocals == null) {
+ outputLocals = new int[10];
+ }
+ int n = outputLocals.length;
+ if (local >= n) {
+ int[] t = new int[Math.max(local + 1, 2 * n)];
+ System.arraycopy(outputLocals, 0, t, 0, n);
+ outputLocals = t;
+ }
+ // sets the local variable
+ outputLocals[local] = type;
+ }
+
+ /**
+ * Pushes a new type onto the output frame stack.
+ *
+ * @param type the type that must be pushed.
+ */
+ private void push(final int type) {
+ // creates and/or resizes the output stack array if necessary
+ if (outputStack == null) {
+ outputStack = new int[10];
+ }
+ int n = outputStack.length;
+ if (outputStackTop >= n) {
+ int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
+ System.arraycopy(outputStack, 0, t, 0, n);
+ outputStack = t;
+ }
+ // pushes the type on the output stack
+ outputStack[outputStackTop++] = type;
+ // updates the maximun height reached by the output stack, if needed
+ int top = owner.inputStackTop + outputStackTop;
+ if (top > owner.outputStackMax) {
+ owner.outputStackMax = top;
+ }
+ }
+
+ /**
+ * Pushes a new type onto the output frame stack.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param desc the descriptor of the type to be pushed. Can also be a method
+ * descriptor (in this case this method pushes its return type onto
+ * the output frame stack).
+ */
+ private void push(final ClassWriter cw, final String desc) {
+ int type = type(cw, desc);
+ if (type != 0) {
+ push(type);
+ if (type == LONG || type == DOUBLE) {
+ push(TOP);
+ }
+ }
+ }
+
+ /**
+ * Returns the int encoding of the given type.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param desc a type descriptor.
+ * @return the int encoding of the given type.
+ */
+ private static int type(final ClassWriter cw, final String desc) {
+ String t;
+ int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+ switch (desc.charAt(index)) {
+ case 'V':
+ return 0;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ return INTEGER;
+ case 'F':
+ return FLOAT;
+ case 'J':
+ return LONG;
+ case 'D':
+ return DOUBLE;
+ case 'L':
+ // stores the internal name, not the descriptor!
+ t = desc.substring(index + 1, desc.length() - 1);
+ return OBJECT | cw.addType(t);
+ // case '[':
+ default:
+ // extracts the dimensions and the element type
+ int data;
+ int dims = index + 1;
+ while (desc.charAt(dims) == '[') {
+ ++dims;
+ }
+ switch (desc.charAt(dims)) {
+ case 'Z':
+ data = BOOLEAN;
+ break;
+ case 'C':
+ data = CHAR;
+ break;
+ case 'B':
+ data = BYTE;
+ break;
+ case 'S':
+ data = SHORT;
+ break;
+ case 'I':
+ data = INTEGER;
+ break;
+ case 'F':
+ data = FLOAT;
+ break;
+ case 'J':
+ data = LONG;
+ break;
+ case 'D':
+ data = DOUBLE;
+ break;
+ // case 'L':
+ default:
+ // stores the internal name, not the descriptor
+ t = desc.substring(dims + 1, desc.length() - 1);
+ data = OBJECT | cw.addType(t);
+ }
+ return (dims - index) << 28 | data;
+ }
+ }
+
+ /**
+ * Pops a type from the output frame stack and returns its value.
+ *
+ * @return the type that has been popped from the output frame stack.
+ */
+ private int pop() {
+ if (outputStackTop > 0) {
+ return outputStack[--outputStackTop];
+ } else {
+ // if the output frame stack is empty, pops from the input stack
+ return STACK | -(--owner.inputStackTop);
+ }
+ }
+
+ /**
+ * Pops the given number of types from the output frame stack.
+ *
+ * @param elements the number of types that must be popped.
+ */
+ private void pop(final int elements) {
+ if (outputStackTop >= elements) {
+ outputStackTop -= elements;
+ } else {
+ // if the number of elements to be popped is greater than the number
+ // of elements in the output stack, clear it, and pops the remaining
+ // elements from the input stack.
+ owner.inputStackTop -= elements - outputStackTop;
+ outputStackTop = 0;
+ }
+ }
+
+ /**
+ * Pops a type from the output frame stack.
+ *
+ * @param desc the descriptor of the type to be popped. Can also be a method
+ * descriptor (in this case this method pops the types corresponding
+ * to the method arguments).
+ */
+ private void pop(final String desc) {
+ char c = desc.charAt(0);
+ if (c == '(') {
+ pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
+ } else if (c == 'J' || c == 'D') {
+ pop(2);
+ } else {
+ pop(1);
+ }
+ }
+
+ /**
+ * Adds a new type to the list of types on which a constructor is invoked in
+ * the basic block.
+ *
+ * @param var a type on a which a constructor is invoked.
+ */
+ private void init(final int var) {
+ // creates and/or resizes the initializations array if necessary
+ if (initializations == null) {
+ initializations = new int[2];
+ }
+ int n = initializations.length;
+ if (initializationCount >= n) {
+ int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
+ System.arraycopy(initializations, 0, t, 0, n);
+ initializations = t;
+ }
+ // stores the type to be initialized
+ initializations[initializationCount++] = var;
+ }
+
+ /**
+ * Replaces the given type with the appropriate type if it is one of the
+ * types on which a constructor is invoked in the basic block.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param t a type
+ * @return t or, if t is one of the types on which a constructor is invoked
+ * in the basic block, the type corresponding to this constructor.
+ */
+ private int init(final ClassWriter cw, final int t) {
+ int s;
+ if (t == UNINITIALIZED_THIS) {
+ s = OBJECT | cw.addType(cw.thisName);
+ } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
+ String type = cw.typeTable[t & BASE_VALUE].strVal1;
+ s = OBJECT | cw.addType(type);
+ } else {
+ return t;
+ }
+ for (int j = 0; j < initializationCount; ++j) {
+ int u = initializations[j];
+ int dim = u & DIM;
+ int kind = u & KIND;
+ if (kind == LOCAL) {
+ u = dim + inputLocals[u & VALUE];
+ } else if (kind == STACK) {
+ u = dim + inputStack[inputStack.length - (u & VALUE)];
+ }
+ if (t == u) {
+ return s;
+ }
+ }
+ return t;
+ }
+
+ /**
+ * Initializes the input frame of the first basic block from the method
+ * descriptor.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param access the access flags of the method to which this label belongs.
+ * @param args the formal parameter types of this method.
+ * @param maxLocals the maximum number of local variables of this method.
+ */
+ void initInputFrame(
+ final ClassWriter cw,
+ final int access,
+ final Type[] args,
+ final int maxLocals)
+ {
+ inputLocals = new int[maxLocals];
+ inputStack = new int[0];
+ int i = 0;
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
+ inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
+ } else {
+ inputLocals[i++] = UNINITIALIZED_THIS;
+ }
+ }
+ for (int j = 0; j < args.length; ++j) {
+ int t = type(cw, args[j].getDescriptor());
+ inputLocals[i++] = t;
+ if (t == LONG || t == DOUBLE) {
+ inputLocals[i++] = TOP;
+ }
+ }
+ while (i < maxLocals) {
+ inputLocals[i++] = TOP;
+ }
+ }
+
+ /**
+ * Simulates the action of the given instruction on the output stack frame.
+ *
+ * @param opcode the opcode of the instruction.
+ * @param arg the operand of the instruction, if any.
+ * @param cw the class writer to which this label belongs.
+ * @param item the operand of the instructions, if any.
+ */
+ void execute(
+ final int opcode,
+ final int arg,
+ final ClassWriter cw,
+ final Item item)
+ {
+ int t1, t2, t3, t4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.ILOAD:
+ push(INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.LLOAD:
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.FLOAD:
+ push(FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.DLOAD:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LDC:
+ switch (item.type) {
+ case ClassWriter.INT:
+ push(INTEGER);
+ break;
+ case ClassWriter.LONG:
+ push(LONG);
+ push(TOP);
+ break;
+ case ClassWriter.FLOAT:
+ push(FLOAT);
+ break;
+ case ClassWriter.DOUBLE:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case ClassWriter.CLASS:
+ push(OBJECT | cw.addType("java/lang/Class"));
+ break;
+ case ClassWriter.STR:
+ push(OBJECT | cw.addType("java/lang/String"));
+ break;
+ case ClassWriter.MTYPE:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
+ break;
+ // case ClassWriter.HANDLE_BASE + [1..9]:
+ default:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
+ }
+ break;
+ case Opcodes.ALOAD:
+ push(get(arg));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FALOAD:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ t1 = pop();
+ push(ELEMENT_OF + t1);
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ t1 = pop();
+ set(arg, t1);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ t1 = pop();
+ set(arg, t1);
+ set(arg + 1, TOP);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ t1 = pop();
+ push(t1);
+ push(t1);
+ break;
+ case Opcodes.DUP_X1:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2:
+ t1 = pop();
+ t2 = pop();
+ push(t2);
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X1:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t2);
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ t4 = pop();
+ push(t2);
+ push(t1);
+ push(t4);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.SWAP:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ break;
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.IINC:
+ set(arg, INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new RuntimeException("JSR/RET are not supported with computeFrames option");
+ case Opcodes.GETSTATIC:
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(item.strVal3);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(item.strVal3);
+ pop();
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ pop(item.strVal3);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ t1 = pop();
+ if (opcode == Opcodes.INVOKESPECIAL
+ && item.strVal2.charAt(0) == '<')
+ {
+ init(t1);
+ }
+ }
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.INVOKEDYNAMIC:
+ pop(item.strVal2);
+ push(cw, item.strVal2);
+ break;
+ case Opcodes.NEW:
+ push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (arg) {
+ case Opcodes.T_BOOLEAN:
+ push(ARRAY_OF | BOOLEAN);
+ break;
+ case Opcodes.T_CHAR:
+ push(ARRAY_OF | CHAR);
+ break;
+ case Opcodes.T_BYTE:
+ push(ARRAY_OF | BYTE);
+ break;
+ case Opcodes.T_SHORT:
+ push(ARRAY_OF | SHORT);
+ break;
+ case Opcodes.T_INT:
+ push(ARRAY_OF | INTEGER);
+ break;
+ case Opcodes.T_FLOAT:
+ push(ARRAY_OF | FLOAT);
+ break;
+ case Opcodes.T_DOUBLE:
+ push(ARRAY_OF | DOUBLE);
+ break;
+ // case Opcodes.T_LONG:
+ default:
+ push(ARRAY_OF | LONG);
+ break;
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ String s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, '[' + s);
+ } else {
+ push(ARRAY_OF | OBJECT | cw.addType(s));
+ }
+ break;
+ case Opcodes.CHECKCAST:
+ s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, s);
+ } else {
+ push(OBJECT | cw.addType(s));
+ }
+ break;
+ // case Opcodes.MULTIANEWARRAY:
+ default:
+ pop(arg);
+ push(cw, item.strVal1);
+ break;
+ }
+ }
+
+ /**
+ * Merges the input frame of the given basic block with the input and output
+ * frames of this basic block. Returns <tt>true</tt> if the input frame of
+ * the given label has been changed by this operation.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param frame the basic block whose input frame must be updated.
+ * @param edge the kind of the {@link Edge} between this label and 'label'.
+ * See {@link Edge#info}.
+ * @return <tt>true</tt> if the input frame of the given label has been
+ * changed by this operation.
+ */
+ boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
+ boolean changed = false;
+ int i, s, dim, kind, t;
+
+ int nLocal = inputLocals.length;
+ int nStack = inputStack.length;
+ if (frame.inputLocals == null) {
+ frame.inputLocals = new int[nLocal];
+ changed = true;
+ }
+
+ for (i = 0; i < nLocal; ++i) {
+ if (outputLocals != null && i < outputLocals.length) {
+ s = outputLocals[i];
+ if (s == 0) {
+ t = inputLocals[i];
+ } else {
+ dim = s & DIM;
+ kind = s & KIND;
+ if (kind == BASE) {
+ t = s;
+ } else {
+ if (kind == LOCAL) {
+ t = dim + inputLocals[s & VALUE];
+ } else {
+ t = dim + inputStack[nStack - (s & VALUE)];
+ }
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+ t = TOP;
+ }
+ }
+ }
+ } else {
+ t = inputLocals[i];
+ }
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputLocals, i);
+ }
+
+ if (edge > 0) {
+ for (i = 0; i < nLocal; ++i) {
+ t = inputLocals[i];
+ changed |= merge(cw, t, frame.inputLocals, i);
+ }
+ if (frame.inputStack == null) {
+ frame.inputStack = new int[1];
+ changed = true;
+ }
+ changed |= merge(cw, edge, frame.inputStack, 0);
+ return changed;
+ }
+
+ int nInputStack = inputStack.length + owner.inputStackTop;
+ if (frame.inputStack == null) {
+ frame.inputStack = new int[nInputStack + outputStackTop];
+ changed = true;
+ }
+
+ for (i = 0; i < nInputStack; ++i) {
+ t = inputStack[i];
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputStack, i);
+ }
+ for (i = 0; i < outputStackTop; ++i) {
+ s = outputStack[i];
+ dim = s & DIM;
+ kind = s & KIND;
+ if (kind == BASE) {
+ t = s;
+ } else {
+ if (kind == LOCAL) {
+ t = dim + inputLocals[s & VALUE];
+ } else {
+ t = dim + inputStack[nStack - (s & VALUE)];
+ }
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0 && (t == LONG || t == DOUBLE)) {
+ t = TOP;
+ }
+ }
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputStack, nInputStack + i);
+ }
+ return changed;
+ }
+
+ /**
+ * Merges the type at the given index in the given type array with the given
+ * type. Returns <tt>true</tt> if the type array has been modified by this
+ * operation.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param t the type with which the type array element must be merged.
+ * @param types an array of types.
+ * @param index the index of the type that must be merged in 'types'.
+ * @return <tt>true</tt> if the type array has been modified by this
+ * operation.
+ */
+ private static boolean merge(
+ final ClassWriter cw,
+ int t,
+ final int[] types,
+ final int index)
+ {
+ int u = types[index];
+ if (u == t) {
+ // if the types are equal, merge(u,t)=u, so there is no change
+ return false;
+ }
+ if ((t & ~DIM) == NULL) {
+ if (u == NULL) {
+ return false;
+ }
+ t = NULL;
+ }
+ if (u == 0) {
+ // if types[index] has never been assigned, merge(u,t)=t
+ types[index] = t;
+ return true;
+ }
+ int v;
+ if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
+ // if u is a reference type of any dimension
+ if (t == NULL) {
+ // if t is the NULL type, merge(u,t)=u, so there is no change
+ return false;
+ } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+ if ((u & BASE_KIND) == OBJECT) {
+ // if t is also a reference type, and if u and t have the
+ // same dimension merge(u,t) = dim(t) | common parent of the
+ // element types of u and t
+ v = (t & DIM) | OBJECT
+ | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
+ } else {
+ // if u and t are array types, but not with the same element
+ // type, merge(u,t)=java/lang/Object
+ v = OBJECT | cw.addType("java/lang/Object");
+ }
+ } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
+ // if t is any other reference or array type,
+ // merge(u,t)=java/lang/Object
+ v = OBJECT | cw.addType("java/lang/Object");
+ } else {
+ // if t is any other type, merge(u,t)=TOP
+ v = TOP;
+ }
+ } else if (u == NULL) {
+ // if u is the NULL type, merge(u,t)=t,
+ // or TOP if t is not a reference type
+ v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
+ } else {
+ // if u is any other type, merge(u,t)=TOP whatever t
+ v = TOP;
+ }
+ if (u != v) {
+ types[index] = v;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/Handle.java b/src/compiler/scala/tools/asm/Handle.java
new file mode 100644
index 0000000000..be8f334192
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Handle.java
@@ -0,0 +1,159 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package scala.tools.asm;
+
+/**
+ * A reference to a field or a method.
+ *
+ * @author Remi Forax
+ * @author Eric Bruneton
+ */
+public final class Handle {
+
+ /**
+ * The kind of field or method designated by this Handle. Should be
+ * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ */
+ final int tag;
+
+ /**
+ * The internal name of the field or method designed by this handle.
+ */
+ final String owner;
+
+ /**
+ * The name of the field or method designated by this handle.
+ */
+ final String name;
+
+ /**
+ * The descriptor of the field or method designated by this handle.
+ */
+ final String desc;
+
+ /**
+ * Constructs a new field or method handle.
+ *
+ * @param tag the kind of field or method designated by this Handle. Must be
+ * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner the internal name of the field or method designed by this
+ * handle.
+ * @param name the name of the field or method designated by this handle.
+ * @param desc the descriptor of the field or method designated by this
+ * handle.
+ */
+ public Handle(int tag, String owner, String name, String desc) {
+ this.tag = tag;
+ this.owner = owner;
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Returns the kind of field or method designated by this handle.
+ *
+ * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ */
+ public int getTag() {
+ return tag;
+ }
+
+ /**
+ * Returns the internal name of the field or method designed by this
+ * handle.
+ *
+ * @return the internal name of the field or method designed by this
+ * handle.
+ */
+ public String getOwner() {
+ return owner;
+ }
+
+ /**
+ * Returns the name of the field or method designated by this handle.
+ *
+ * @return the name of the field or method designated by this handle.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the descriptor of the field or method designated by this handle.
+ *
+ * @return the descriptor of the field or method designated by this handle.
+ */
+ public String getDesc() {
+ return desc;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof Handle)) {
+ return false;
+ }
+ Handle h = (Handle) obj;
+ return tag == h.tag && owner.equals(h.owner)
+ && name.equals(h.name) && desc.equals(h.desc);
+ }
+
+ @Override
+ public int hashCode() {
+ return tag + owner.hashCode() * name.hashCode() * desc.hashCode();
+ }
+
+ /**
+ * Returns the textual representation of this handle. The textual
+ * representation is: <pre>owner '.' name desc ' ' '(' tag ')'</pre>. As
+ * this format is unambiguous, it can be parsed if necessary.
+ */
+ @Override
+ public String toString() {
+ return owner + '.' + name + desc + " (" + tag + ')';
+ }
+}
diff --git a/src/compiler/scala/tools/asm/Handler.java b/src/compiler/scala/tools/asm/Handler.java
new file mode 100644
index 0000000000..9e92bb98be
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Handler.java
@@ -0,0 +1,118 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * Information about an exception handler block.
+ *
+ * @author Eric Bruneton
+ */
+class Handler {
+
+ /**
+ * Beginning of the exception handler's scope (inclusive).
+ */
+ Label start;
+
+ /**
+ * End of the exception handler's scope (exclusive).
+ */
+ Label end;
+
+ /**
+ * Beginning of the exception handler's code.
+ */
+ Label handler;
+
+ /**
+ * Internal name of the type of exceptions handled by this handler, or
+ * <tt>null</tt> to catch any exceptions.
+ */
+ String desc;
+
+ /**
+ * Constant pool index of the internal name of the type of exceptions
+ * handled by this handler, or 0 to catch any exceptions.
+ */
+ int type;
+
+ /**
+ * Next exception handler block info.
+ */
+ Handler next;
+
+ /**
+ * Removes the range between start and end from the given exception
+ * handlers.
+ *
+ * @param h an exception handler list.
+ * @param start the start of the range to be removed.
+ * @param end the end of the range to be removed. Maybe null.
+ * @return the exception handler list with the start-end range removed.
+ */
+ static Handler remove(Handler h, Label start, Label end) {
+ if (h == null) {
+ return null;
+ } else {
+ h.next = remove(h.next, start, end);
+ }
+ int hstart = h.start.position;
+ int hend = h.end.position;
+ int s = start.position;
+ int e = end == null ? Integer.MAX_VALUE : end.position;
+ // if [hstart,hend[ and [s,e[ intervals intersect...
+ if (s < hend && e > hstart) {
+ if (s <= hstart) {
+ if (e >= hend) {
+ // [hstart,hend[ fully included in [s,e[, h removed
+ h = h.next;
+ } else {
+ // [hstart,hend[ minus [s,e[ = [e,hend[
+ h.start = end;
+ }
+ } else if (e >= hend) {
+ // [hstart,hend[ minus [s,e[ = [hstart,s[
+ h.end = start;
+ } else {
+ // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
+ Handler g = new Handler();
+ g.start = end;
+ g.end = h.end;
+ g.handler = h.handler;
+ g.desc = h.desc;
+ g.type = h.type;
+ g.next = h.next;
+ h.end = start;
+ h.next = g;
+ }
+ }
+ return h;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/Item.java b/src/compiler/scala/tools/asm/Item.java
new file mode 100644
index 0000000000..021a0b11d3
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Item.java
@@ -0,0 +1,297 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A constant pool item. Constant pool items can be created with the 'newXXX'
+ * methods in the {@link ClassWriter} class.
+ *
+ * @author Eric Bruneton
+ */
+final class Item {
+
+ /**
+ * Index of this item in the constant pool.
+ */
+ int index;
+
+ /**
+ * Type of this constant pool item. A single class is used to represent all
+ * constant pool item types, in order to minimize the bytecode size of this
+ * package. The value of this field is one of {@link ClassWriter#INT},
+ * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
+ * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
+ * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
+ * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
+ * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
+ * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
+ *
+ * MethodHandle constant 9 variations are stored using a range
+ * of 9 values from {@link ClassWriter#HANDLE_BASE} + 1 to
+ * {@link ClassWriter#HANDLE_BASE} + 9.
+ *
+ * Special Item types are used for Items that are stored in the ClassWriter
+ * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+ * avoid clashes with normal constant pool items in the ClassWriter constant
+ * pool's hash table. These special item types are
+ * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
+ * {@link ClassWriter#TYPE_MERGED}.
+ */
+ int type;
+
+ /**
+ * Value of this item, for an integer item.
+ */
+ int intVal;
+
+ /**
+ * Value of this item, for a long item.
+ */
+ long longVal;
+
+ /**
+ * First part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal1;
+
+ /**
+ * Second part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal2;
+
+ /**
+ * Third part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal3;
+
+ /**
+ * The hash code value of this constant pool item.
+ */
+ int hashCode;
+
+ /**
+ * Link to another constant pool item, used for collision lists in the
+ * constant pool's hash table.
+ */
+ Item next;
+
+ /**
+ * Constructs an uninitialized {@link Item}.
+ */
+ Item() {
+ }
+
+ /**
+ * Constructs an uninitialized {@link Item} for constant pool element at
+ * given position.
+ *
+ * @param index index of the item to be constructed.
+ */
+ Item(final int index) {
+ this.index = index;
+ }
+
+ /**
+ * Constructs a copy of the given item.
+ *
+ * @param index index of the item to be constructed.
+ * @param i the item that must be copied into the item to be constructed.
+ */
+ Item(final int index, final Item i) {
+ this.index = index;
+ type = i.type;
+ intVal = i.intVal;
+ longVal = i.longVal;
+ strVal1 = i.strVal1;
+ strVal2 = i.strVal2;
+ strVal3 = i.strVal3;
+ hashCode = i.hashCode;
+ }
+
+ /**
+ * Sets this item to an integer item.
+ *
+ * @param intVal the value of this item.
+ */
+ void set(final int intVal) {
+ this.type = ClassWriter.INT;
+ this.intVal = intVal;
+ this.hashCode = 0x7FFFFFFF & (type + intVal);
+ }
+
+ /**
+ * Sets this item to a long item.
+ *
+ * @param longVal the value of this item.
+ */
+ void set(final long longVal) {
+ this.type = ClassWriter.LONG;
+ this.longVal = longVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+ }
+
+ /**
+ * Sets this item to a float item.
+ *
+ * @param floatVal the value of this item.
+ */
+ void set(final float floatVal) {
+ this.type = ClassWriter.FLOAT;
+ this.intVal = Float.floatToRawIntBits(floatVal);
+ this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+ }
+
+ /**
+ * Sets this item to a double item.
+ *
+ * @param doubleVal the value of this item.
+ */
+ void set(final double doubleVal) {
+ this.type = ClassWriter.DOUBLE;
+ this.longVal = Double.doubleToRawLongBits(doubleVal);
+ this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+ }
+
+ /**
+ * Sets this item to an item that do not hold a primitive value.
+ *
+ * @param type the type of this item.
+ * @param strVal1 first part of the value of this item.
+ * @param strVal2 second part of the value of this item.
+ * @param strVal3 third part of the value of this item.
+ */
+ void set(
+ final int type,
+ final String strVal1,
+ final String strVal2,
+ final String strVal3)
+ {
+ this.type = type;
+ this.strVal1 = strVal1;
+ this.strVal2 = strVal2;
+ this.strVal3 = strVal3;
+ switch (type) {
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+ return;
+ case ClassWriter.NAME_TYPE:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode());
+ return;
+ // ClassWriter.FIELD:
+ // ClassWriter.METH:
+ // ClassWriter.IMETH:
+ // ClassWriter.HANDLE_BASE + 1..9
+ default:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode() * strVal3.hashCode());
+ }
+ }
+
+ /**
+ * Sets the item to an InvokeDynamic item.
+ *
+ * @param name invokedynamic's name.
+ * @param desc invokedynamic's desc.
+ * @param bsmIndex zero based index into the class attribute BootrapMethods.
+ */
+ void set(String name, String desc, int bsmIndex) {
+ this.type = ClassWriter.INDY;
+ this.longVal = bsmIndex;
+ this.strVal1 = name;
+ this.strVal2 = desc;
+ this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
+ * strVal1.hashCode() * strVal2.hashCode());
+ }
+
+ /**
+ * Sets the item to a BootstrapMethod item.
+ *
+ * @param position position in byte in the class attribute BootrapMethods.
+ * @param hashCode hashcode of the item. This hashcode is processed from
+ * the hashcode of the bootstrap method and the hashcode of
+ * all bootstrap arguments.
+ */
+ void set(int position, int hashCode) {
+ this.type = ClassWriter.BSM;
+ this.intVal = position;
+ this.hashCode = hashCode;
+ }
+
+ /**
+ * Indicates if the given item is equal to this one. <i>This method assumes
+ * that the two items have the same {@link #type}</i>.
+ *
+ * @param i the item to be compared to this one. Both items must have the
+ * same {@link #type}.
+ * @return <tt>true</tt> if the given item if equal to this one,
+ * <tt>false</tt> otherwise.
+ */
+ boolean isEqualTo(final Item i) {
+ switch (type) {
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ return i.strVal1.equals(strVal1);
+ case ClassWriter.TYPE_MERGED:
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ return i.longVal == longVal;
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ return i.intVal == intVal;
+ case ClassWriter.TYPE_UNINIT:
+ return i.intVal == intVal && i.strVal1.equals(strVal1);
+ case ClassWriter.NAME_TYPE:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
+ case ClassWriter.INDY:
+ return i.longVal == longVal && i.strVal1.equals(strVal1)
+ && i.strVal2.equals(strVal2);
+
+ // case ClassWriter.FIELD:
+ // case ClassWriter.METH:
+ // case ClassWriter.IMETH:
+ // case ClassWriter.HANDLE_BASE + 1..9
+ default:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
+ && i.strVal3.equals(strVal3);
+ }
+ }
+
+}
diff --git a/src/compiler/scala/tools/asm/Label.java b/src/compiler/scala/tools/asm/Label.java
new file mode 100644
index 0000000000..712c7f251f
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Label.java
@@ -0,0 +1,555 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A label represents a position in the bytecode of a method. Labels are used
+ * for jump, goto, and switch instructions, and for try catch blocks. A label
+ * designates the <i>instruction</i> that is just after. Note however that
+ * there can be other elements between a label and the instruction it
+ * designates (such as other labels, stack map frames, line numbers, etc.).
+ *
+ * @author Eric Bruneton
+ */
+public class Label {
+
+ /**
+ * Indicates if this label is only used for debug attributes. Such a label
+ * is not the start of a basic block, the target of a jump instruction, or
+ * an exception handler. It can be safely ignored in control flow graph
+ * analysis algorithms (for optimization purposes).
+ */
+ static final int DEBUG = 1;
+
+ /**
+ * Indicates if the position of this label is known.
+ */
+ static final int RESOLVED = 2;
+
+ /**
+ * Indicates if this label has been updated, after instruction resizing.
+ */
+ static final int RESIZED = 4;
+
+ /**
+ * Indicates if this basic block has been pushed in the basic block stack.
+ * See {@link MethodWriter#visitMaxs visitMaxs}.
+ */
+ static final int PUSHED = 8;
+
+ /**
+ * Indicates if this label is the target of a jump instruction, or the start
+ * of an exception handler.
+ */
+ static final int TARGET = 16;
+
+ /**
+ * Indicates if a stack map frame must be stored for this label.
+ */
+ static final int STORE = 32;
+
+ /**
+ * Indicates if this label corresponds to a reachable basic block.
+ */
+ static final int REACHABLE = 64;
+
+ /**
+ * Indicates if this basic block ends with a JSR instruction.
+ */
+ static final int JSR = 128;
+
+ /**
+ * Indicates if this basic block ends with a RET instruction.
+ */
+ static final int RET = 256;
+
+ /**
+ * Indicates if this basic block is the start of a subroutine.
+ */
+ static final int SUBROUTINE = 512;
+
+ /**
+ * Indicates if this subroutine basic block has been visited by a
+ * visitSubroutine(null, ...) call.
+ */
+ static final int VISITED = 1024;
+
+ /**
+ * Indicates if this subroutine basic block has been visited by a
+ * visitSubroutine(!null, ...) call.
+ */
+ static final int VISITED2 = 2048;
+
+ /**
+ * Field used to associate user information to a label. Warning: this field
+ * is used by the ASM tree package. In order to use it with the ASM tree
+ * package you must override the {@link
+ * org.objectweb.asm.tree.MethodNode#getLabelNode} method.
+ */
+ public Object info;
+
+ /**
+ * Flags that indicate the status of this label.
+ *
+ * @see #DEBUG
+ * @see #RESOLVED
+ * @see #RESIZED
+ * @see #PUSHED
+ * @see #TARGET
+ * @see #STORE
+ * @see #REACHABLE
+ * @see #JSR
+ * @see #RET
+ */
+ int status;
+
+ /**
+ * The line number corresponding to this label, if known.
+ */
+ int line;
+
+ /**
+ * The position of this label in the code, if known.
+ */
+ int position;
+
+ /**
+ * Number of forward references to this label, times two.
+ */
+ private int referenceCount;
+
+ /**
+ * Informations about forward references. Each forward reference is
+ * described by two consecutive integers in this array: the first one is the
+ * position of the first byte of the bytecode instruction that contains the
+ * forward reference, while the second is the position of the first byte of
+ * the forward reference itself. In fact the sign of the first integer
+ * indicates if this reference uses 2 or 4 bytes, and its absolute value
+ * gives the position of the bytecode instruction. This array is also used
+ * as a bitset to store the subroutines to which a basic block belongs. This
+ * information is needed in {@linked MethodWriter#visitMaxs}, after all
+ * forward references have been resolved. Hence the same array can be used
+ * for both purposes without problems.
+ */
+ private int[] srcAndRefPositions;
+
+ // ------------------------------------------------------------------------
+
+ /*
+ * Fields for the control flow and data flow graph analysis algorithms (used
+ * to compute the maximum stack size or the stack map frames). A control
+ * flow graph contains one node per "basic block", and one edge per "jump"
+ * from one basic block to another. Each node (i.e., each basic block) is
+ * represented by the Label object that corresponds to the first instruction
+ * of this basic block. Each node also stores the list of its successors in
+ * the graph, as a linked list of Edge objects.
+ *
+ * The control flow analysis algorithms used to compute the maximum stack
+ * size or the stack map frames are similar and use two steps. The first
+ * step, during the visit of each instruction, builds information about the
+ * state of the local variables and the operand stack at the end of each
+ * basic block, called the "output frame", <i>relatively</i> to the frame
+ * state at the beginning of the basic block, which is called the "input
+ * frame", and which is <i>unknown</i> during this step. The second step,
+ * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that
+ * computes information about the input frame of each basic block, from the
+ * input state of the first basic block (known from the method signature),
+ * and by the using the previously computed relative output frames.
+ *
+ * The algorithm used to compute the maximum stack size only computes the
+ * relative output and absolute input stack heights, while the algorithm
+ * used to compute stack map frames computes relative output frames and
+ * absolute input frames.
+ */
+
+ /**
+ * Start of the output stack relatively to the input stack. The exact
+ * semantics of this field depends on the algorithm that is used.
+ *
+ * When only the maximum stack size is computed, this field is the number of
+ * elements in the input stack.
+ *
+ * When the stack map frames are completely computed, this field is the
+ * offset of the first output stack element relatively to the top of the
+ * input stack. This offset is always negative or null. A null offset means
+ * that the output stack must be appended to the input stack. A -n offset
+ * means that the first n output stack elements must replace the top n input
+ * stack elements, and that the other elements must be appended to the input
+ * stack.
+ */
+ int inputStackTop;
+
+ /**
+ * Maximum height reached by the output stack, relatively to the top of the
+ * input stack. This maximum is always positive or null.
+ */
+ int outputStackMax;
+
+ /**
+ * Information about the input and output stack map frames of this basic
+ * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}
+ * option is used.
+ */
+ Frame frame;
+
+ /**
+ * The successor of this label, in the order they are visited. This linked
+ * list does not include labels used for debug info only. If
+ * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
+ * does not contain successive labels that denote the same bytecode position
+ * (in this case only the first label appears in this list).
+ */
+ Label successor;
+
+ /**
+ * The successors of this node in the control flow graph. These successors
+ * are stored in a linked list of {@link Edge Edge} objects, linked to each
+ * other by their {@link Edge#next} field.
+ */
+ Edge successors;
+
+ /**
+ * The next basic block in the basic block stack. This stack is used in the
+ * main loop of the fix point algorithm used in the second step of the
+ * control flow analysis algorithms. It is also used in
+ * {@link #visitSubroutine} to avoid using a recursive method.
+ *
+ * @see MethodWriter#visitMaxs
+ */
+ Label next;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new label.
+ */
+ public Label() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods to compute offsets and to manage forward references
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the offset corresponding to this label. This offset is computed
+ * from the start of the method's bytecode. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @return the offset corresponding to this label.
+ * @throws IllegalStateException if this label is not resolved yet.
+ */
+ public int getOffset() {
+ if ((status & RESOLVED) == 0) {
+ throw new IllegalStateException("Label offset position has not been resolved yet");
+ }
+ return position;
+ }
+
+ /**
+ * Puts a reference to this label in the bytecode of a method. If the
+ * position of the label is known, the offset is computed and written
+ * directly. Otherwise, a null offset is written and a new forward reference
+ * is declared for this label.
+ *
+ * @param owner the code writer that calls this method.
+ * @param out the bytecode of the method.
+ * @param source the position of first byte of the bytecode instruction that
+ * contains this label.
+ * @param wideOffset <tt>true</tt> if the reference must be stored in 4
+ * bytes, or <tt>false</tt> if it must be stored with 2 bytes.
+ * @throws IllegalArgumentException if this label has not been created by
+ * the given code writer.
+ */
+ void put(
+ final MethodWriter owner,
+ final ByteVector out,
+ final int source,
+ final boolean wideOffset)
+ {
+ if ((status & RESOLVED) == 0) {
+ if (wideOffset) {
+ addReference(-1 - source, out.length);
+ out.putInt(-1);
+ } else {
+ addReference(source, out.length);
+ out.putShort(-1);
+ }
+ } else {
+ if (wideOffset) {
+ out.putInt(position - source);
+ } else {
+ out.putShort(position - source);
+ }
+ }
+ }
+
+ /**
+ * Adds a forward reference to this label. This method must be called only
+ * for a true forward reference, i.e. only if this label is not resolved
+ * yet. For backward references, the offset of the reference can be, and
+ * must be, computed and stored directly.
+ *
+ * @param sourcePosition the position of the referencing instruction. This
+ * position will be used to compute the offset of this forward
+ * reference.
+ * @param referencePosition the position where the offset for this forward
+ * reference must be stored.
+ */
+ private void addReference(
+ final int sourcePosition,
+ final int referencePosition)
+ {
+ if (srcAndRefPositions == null) {
+ srcAndRefPositions = new int[6];
+ }
+ if (referenceCount >= srcAndRefPositions.length) {
+ int[] a = new int[srcAndRefPositions.length + 6];
+ System.arraycopy(srcAndRefPositions,
+ 0,
+ a,
+ 0,
+ srcAndRefPositions.length);
+ srcAndRefPositions = a;
+ }
+ srcAndRefPositions[referenceCount++] = sourcePosition;
+ srcAndRefPositions[referenceCount++] = referencePosition;
+ }
+
+ /**
+ * Resolves all forward references to this label. This method must be called
+ * when this label is added to the bytecode of the method, i.e. when its
+ * position becomes known. This method fills in the blanks that where left
+ * in the bytecode by each forward reference previously added to this label.
+ *
+ * @param owner the code writer that calls this method.
+ * @param position the position of this label in the bytecode.
+ * @param data the bytecode of the method.
+ * @return <tt>true</tt> if a blank that was left for this label was to
+ * small to store the offset. In such a case the corresponding jump
+ * instruction is replaced with a pseudo instruction (using unused
+ * opcodes) using an unsigned two bytes offset. These pseudo
+ * instructions will need to be replaced with true instructions with
+ * wider offsets (4 bytes instead of 2). This is done in
+ * {@link MethodWriter#resizeInstructions}.
+ * @throws IllegalArgumentException if this label has already been resolved,
+ * or if it has not been created by the given code writer.
+ */
+ boolean resolve(
+ final MethodWriter owner,
+ final int position,
+ final byte[] data)
+ {
+ boolean needUpdate = false;
+ this.status |= RESOLVED;
+ this.position = position;
+ int i = 0;
+ while (i < referenceCount) {
+ int source = srcAndRefPositions[i++];
+ int reference = srcAndRefPositions[i++];
+ int offset;
+ if (source >= 0) {
+ offset = position - source;
+ if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
+ /*
+ * changes the opcode of the jump instruction, in order to
+ * be able to find it later (see resizeInstructions in
+ * MethodWriter). These temporary opcodes are similar to
+ * jump instruction opcodes, except that the 2 bytes offset
+ * is unsigned (and can therefore represent values from 0 to
+ * 65535, which is sufficient since the size of a method is
+ * limited to 65535 bytes).
+ */
+ int opcode = data[reference - 1] & 0xFF;
+ if (opcode <= Opcodes.JSR) {
+ // changes IFEQ ... JSR to opcodes 202 to 217
+ data[reference - 1] = (byte) (opcode + 49);
+ } else {
+ // changes IFNULL and IFNONNULL to opcodes 218 and 219
+ data[reference - 1] = (byte) (opcode + 20);
+ }
+ needUpdate = true;
+ }
+ data[reference++] = (byte) (offset >>> 8);
+ data[reference] = (byte) offset;
+ } else {
+ offset = position + source + 1;
+ data[reference++] = (byte) (offset >>> 24);
+ data[reference++] = (byte) (offset >>> 16);
+ data[reference++] = (byte) (offset >>> 8);
+ data[reference] = (byte) offset;
+ }
+ }
+ return needUpdate;
+ }
+
+ /**
+ * Returns the first label of the series to which this label belongs. For an
+ * isolated label or for the first label in a series of successive labels,
+ * this method returns the label itself. For other labels it returns the
+ * first label of the series.
+ *
+ * @return the first label of the series to which this label belongs.
+ */
+ Label getFirst() {
+ return !ClassReader.FRAMES || frame == null ? this : frame.owner;
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods related to subroutines
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns true is this basic block belongs to the given subroutine.
+ *
+ * @param id a subroutine id.
+ * @return true is this basic block belongs to the given subroutine.
+ */
+ boolean inSubroutine(final long id) {
+ if ((status & Label.VISITED) != 0) {
+ return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if this basic block and the given one belong to a common
+ * subroutine.
+ *
+ * @param block another basic block.
+ * @return true if this basic block and the given one belong to a common
+ * subroutine.
+ */
+ boolean inSameSubroutine(final Label block) {
+ if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {
+ return false;
+ }
+ for (int i = 0; i < srcAndRefPositions.length; ++i) {
+ if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Marks this basic block as belonging to the given subroutine.
+ *
+ * @param id a subroutine id.
+ * @param nbSubroutines the total number of subroutines in the method.
+ */
+ void addToSubroutine(final long id, final int nbSubroutines) {
+ if ((status & VISITED) == 0) {
+ status |= VISITED;
+ srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1];
+ }
+ srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
+ }
+
+ /**
+ * Finds the basic blocks that belong to a given subroutine, and marks these
+ * blocks as belonging to this subroutine. This method follows the control
+ * flow graph to find all the blocks that are reachable from the current
+ * block WITHOUT following any JSR target.
+ *
+ * @param JSR a JSR block that jumps to this subroutine. If this JSR is not
+ * null it is added to the successor of the RET blocks found in the
+ * subroutine.
+ * @param id the id of this subroutine.
+ * @param nbSubroutines the total number of subroutines in the method.
+ */
+ void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)
+ {
+ // user managed stack of labels, to avoid using a recursive method
+ // (recursivity can lead to stack overflow with very large methods)
+ Label stack = this;
+ while (stack != null) {
+ // removes a label l from the stack
+ Label l = stack;
+ stack = l.next;
+ l.next = null;
+
+ if (JSR != null) {
+ if ((l.status & VISITED2) != 0) {
+ continue;
+ }
+ l.status |= VISITED2;
+ // adds JSR to the successors of l, if it is a RET block
+ if ((l.status & RET) != 0) {
+ if (!l.inSameSubroutine(JSR)) {
+ Edge e = new Edge();
+ e.info = l.inputStackTop;
+ e.successor = JSR.successors.successor;
+ e.next = l.successors;
+ l.successors = e;
+ }
+ }
+ } else {
+ // if the l block already belongs to subroutine 'id', continue
+ if (l.inSubroutine(id)) {
+ continue;
+ }
+ // marks the l block as belonging to subroutine 'id'
+ l.addToSubroutine(id, nbSubroutines);
+ }
+ // pushes each successor of l on the stack, except JSR targets
+ Edge e = l.successors;
+ while (e != null) {
+ // if the l block is a JSR block, then 'l.successors.next' leads
+ // to the JSR target (see {@link #visitJumpInsn}) and must
+ // therefore not be followed
+ if ((l.status & Label.JSR) == 0 || e != l.successors.next) {
+ // pushes e.successor on the stack if it not already added
+ if (e.successor.next == null) {
+ e.successor.next = stack;
+ stack = e.successor;
+ }
+ }
+ e = e.next;
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Overriden Object methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns a string representation of this label.
+ *
+ * @return a string representation of this label.
+ */
+ @Override
+ public String toString() {
+ return "L" + System.identityHashCode(this);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/MethodVisitor.java b/src/compiler/scala/tools/asm/MethodVisitor.java
new file mode 100644
index 0000000000..a8a859a6a9
--- /dev/null
+++ b/src/compiler/scala/tools/asm/MethodVisitor.java
@@ -0,0 +1,588 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A visitor to visit a Java method. The methods of this class must be
+ * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (
+ * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
+ * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> |
+ * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt> )* <tt>visitMaxs</tt> ]
+ * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt>
+ * and <tt>visitLabel</tt> methods must be called in the sequential order of
+ * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt>
+ * must be called <i>before</i> the labels passed as arguments have been
+ * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>
+ * methods must be called <i>after</i> the labels passed as arguments have been
+ * visited.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class MethodVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4}.
+ */
+ protected final int api;
+
+ /**
+ * The method visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ protected MethodVisitor mv;
+
+ /**
+ * Constructs a new {@link MethodVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ public MethodVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link MethodVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param mv the method visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public MethodVisitor(final int api, final MethodVisitor mv) {
+ /*if (api != Opcodes.ASM4) {
+ throw new IllegalArgumentException();
+ }*/
+ this.api = api;
+ this.mv = mv;
+ }
+
+ // -------------------------------------------------------------------------
+ // Annotations and non standard attributes
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits the default value of this annotation interface method.
+ *
+ * @return a visitor to the visit the actual default value of this
+ * annotation interface method, or <tt>null</tt> if this visitor
+ * is not interested in visiting this default value. The 'name'
+ * parameters passed to the methods of this annotation visitor are
+ * ignored. Moreover, exacly one visit method must be called on this
+ * annotation visitor, followed by visitEnd.
+ */
+ public AnnotationVisitor visitAnnotationDefault() {
+ if (mv != null) {
+ return mv.visitAnnotationDefault();
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation of this method.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (mv != null) {
+ return mv.visitAnnotation(desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation of a parameter this method.
+ *
+ * @param parameter the parameter index.
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitParameterAnnotation(
+ int parameter,
+ String desc,
+ boolean visible)
+ {
+ if (mv != null) {
+ return mv.visitParameterAnnotation(parameter, desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a non standard attribute of this method.
+ *
+ * @param attr an attribute.
+ */
+ public void visitAttribute(Attribute attr) {
+ if (mv != null) {
+ mv.visitAttribute(attr);
+ }
+ }
+
+ /**
+ * Starts the visit of the method's code, if any (i.e. non abstract method).
+ */
+ public void visitCode() {
+ if (mv != null) {
+ mv.visitCode();
+ }
+ }
+
+ /**
+ * Visits the current state of the local variables and operand stack
+ * elements. This method must(*) be called <i>just before</i> any
+ * instruction <b>i</b> that follows an unconditional branch instruction
+ * such as GOTO or THROW, that is the target of a jump instruction, or that
+ * starts an exception handler block. The visited types must describe the
+ * values of the local variables and of the operand stack elements <i>just
+ * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only
+ * for classes whose version is greater than or equal to
+ * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically
+ * "deltas" from the state of the previous frame (very first frame is
+ * implicitly defined by the method's parameters and access flags): <ul>
+ * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
+ * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}
+ * representing frame with exactly the same locals as the previous frame and
+ * with single value on the stack (<code>nStack</code> is 1 and
+ * <code>stack[0]</code> contains value for the type of the stack item).</li>
+ * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
+ * the same as the locals in the previous frame, except that additional
+ * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
+ * <code>local</code> elements contains values representing added types).</li>
+ * <li>{@link Opcodes#F_CHOP} representing frame with current locals are
+ * the same as the locals in the previous frame, except that the last 1-3
+ * locals are absent and with the empty stack (<code>nLocals</code> is 1,
+ * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame
+ * data.</li> </li> </ul>
+ *
+ * @param type the type of this stack map frame. Must be
+ * {@link Opcodes#F_NEW} for expanded frames, or
+ * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed
+ * frames.
+ * @param nLocal the number of local variables in the visited frame.
+ * @param local the local variable types in this frame. This array must not
+ * be modified. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+ * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+ * represented by a single element). Reference types are represented
+ * by String objects (representing internal names), and uninitialized
+ * types by Label objects (this label designates the NEW instruction
+ * that created this uninitialized value).
+ * @param nStack the number of operand stack elements in the visited frame.
+ * @param stack the operand stack types in this frame. This array must not
+ * be modified. Its content has the same format as the "local" array.
+ * @throws IllegalStateException if a frame is visited just after another
+ * one, without any instruction between the two (unless this frame
+ * is a Opcodes#F_SAME frame, in which case it is silently ignored).
+ */
+ public void visitFrame(
+ int type,
+ int nLocal,
+ Object[] local,
+ int nStack,
+ Object[] stack)
+ {
+ if (mv != null) {
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Normal instructions
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a zero operand instruction.
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is
+ * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
+ * ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0,
+ * FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD,
+ * DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE,
+ * DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP,
+ * DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD,
+ * DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
+ * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL,
+ * LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR,
+ * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
+ * I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
+ * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
+ * MONITORENTER, or MONITOREXIT.
+ */
+ public void visitInsn(int opcode) {
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ }
+
+ /**
+ * Visits an instruction with a single int operand.
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is
+ * either BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand the operand of the instruction to be visited.<br> When
+ * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE
+ * and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value
+ * should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When
+ * opcode is NEWARRAY, operand value should be one of
+ * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+ * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+ * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+ * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+ */
+ public void visitIntInsn(int opcode, int operand) {
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ }
+
+ /**
+ * Visits a local variable instruction. A local variable instruction is an
+ * instruction that loads or stores the value of a local variable.
+ *
+ * @param opcode the opcode of the local variable instruction to be visited.
+ * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
+ * LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var the operand of the instruction to be visited. This operand is
+ * the index of a local variable.
+ */
+ public void visitVarInsn(int opcode, int var) {
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ }
+
+ /**
+ * Visits a type instruction. A type instruction is an instruction that
+ * takes the internal name of a class as parameter.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param type the operand of the instruction to be visited. This operand
+ * must be the internal name of an object or array class (see {@link
+ * Type#getInternalName() getInternalName}).
+ */
+ public void visitTypeInsn(int opcode, String type) {
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ }
+
+ /**
+ * Visits a field instruction. A field instruction is an instruction that
+ * loads or stores the value of a field of an object.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner the internal name of the field's owner class (see {@link
+ * Type#getInternalName() getInternalName}).
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link Type Type}).
+ */
+ public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ /**
+ * Visits a method instruction. A method instruction is an instruction that
+ * invokes a method.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC
+ * or INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName() getInternalName}).
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type Type}).
+ */
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+
+ /**
+ * Visits an invokedynamic instruction.
+ *
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type Type}).
+ * @param bsm the bootstrap method.
+ * @param bsmArgs the bootstrap method constant arguments. Each argument
+ * must be an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String}, {@link Type} or {@link Handle}
+ * value. This method is allowed to modify the content of the array
+ * so a caller should expect that this array may change.
+ */
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
+ if (mv != null) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+ }
+
+ /**
+ * Visits a jump instruction. A jump instruction is an instruction that may
+ * jump to another instruction.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+ * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label the operand of the instruction to be visited. This operand
+ * is a label that designates the instruction to which the jump
+ * instruction may jump.
+ */
+ public void visitJumpInsn(int opcode, Label label) {
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ }
+
+ /**
+ * Visits a label. A label designates the instruction that will be visited
+ * just after it.
+ *
+ * @param label a {@link Label Label} object.
+ */
+ public void visitLabel(Label label) {
+ if (mv != null) {
+ mv.visitLabel(label);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Special instructions
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a LDC instruction. Note that new constant types may be added in
+ * future versions of the Java Virtual Machine. To easily detect new
+ * constant types, implementations of this method should check for
+ * unexpected constant types, like this:
+ * <pre>
+ * if (cst instanceof Integer) {
+ * // ...
+ * } else if (cst instanceof Float) {
+ * // ...
+ * } else if (cst instanceof Long) {
+ * // ...
+ * } else if (cst instanceof Double) {
+ * // ...
+ * } else if (cst instanceof String) {
+ * // ...
+ * } else if (cst instanceof Type) {
+ * int sort = ((Type) cst).getSort();
+ * if (sort == Type.OBJECT) {
+ * // ...
+ * } else if (sort == Type.ARRAY) {
+ * // ...
+ * } else if (sort == Type.METHOD) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }
+ * } else if (cst instanceof Handle) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }</pre>
+ *
+ * @param cst the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double}, a {@link String}, a {@link Type} of OBJECT or ARRAY
+ * sort for <tt>.class</tt> constants, for classes whose version is
+ * 49.0, a {@link Type} of METHOD sort or a {@link Handle} for
+ * MethodType and MethodHandle constants, for classes whose version
+ * is 51.0.
+ */
+ public void visitLdcInsn(Object cst) {
+ if (mv != null) {
+ mv.visitLdcInsn(cst);
+ }
+ }
+
+ /**
+ * Visits an IINC instruction.
+ *
+ * @param var index of the local variable to be incremented.
+ * @param increment amount to increment the local variable by.
+ */
+ public void visitIincInsn(int var, int increment) {
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ }
+
+ /**
+ * Visits a TABLESWITCH instruction.
+ *
+ * @param min the minimum key value.
+ * @param max the maximum key value.
+ * @param dflt beginning of the default handler block.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>min + i</tt> key.
+ */
+ public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ /**
+ * Visits a LOOKUPSWITCH instruction.
+ *
+ * @param dflt beginning of the default handler block.
+ * @param keys the values of the keys.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ */
+ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ /**
+ * Visits a MULTIANEWARRAY instruction.
+ *
+ * @param desc an array type descriptor (see {@link Type Type}).
+ * @param dims number of dimensions of the array to allocate.
+ */
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Exceptions table entries, debug information, max stack and max locals
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a try catch block.
+ *
+ * @param start beginning of the exception handler's scope (inclusive).
+ * @param end end of the exception handler's scope (exclusive).
+ * @param handler beginning of the exception handler's code.
+ * @param type internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for "finally"
+ * blocks).
+ * @throws IllegalArgumentException if one of the labels has already been
+ * visited by this visitor (by the {@link #visitLabel visitLabel}
+ * method).
+ */
+ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ if (mv != null) {
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ /**
+ * Visits a local variable declaration.
+ *
+ * @param name the name of a local variable.
+ * @param desc the type descriptor of this local variable.
+ * @param signature the type signature of this local variable. May be
+ * <tt>null</tt> if the local variable type does not use generic
+ * types.
+ * @param start the first instruction corresponding to the scope of this
+ * local variable (inclusive).
+ * @param end the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index the local variable's index.
+ * @throws IllegalArgumentException if one of the labels has not already
+ * been visited by this visitor (by the
+ * {@link #visitLabel visitLabel} method).
+ */
+ public void visitLocalVariable(
+ String name,
+ String desc,
+ String signature,
+ Label start,
+ Label end,
+ int index)
+ {
+ if (mv != null) {
+ mv.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+ }
+
+ /**
+ * Visits a line number declaration.
+ *
+ * @param line a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start the first instruction corresponding to this line number.
+ * @throws IllegalArgumentException if <tt>start</tt> has not already been
+ * visited by this visitor (by the {@link #visitLabel visitLabel}
+ * method).
+ */
+ public void visitLineNumber(int line, Label start) {
+ if (mv != null) {
+ mv.visitLineNumber(line, start);
+ }
+ }
+
+ /**
+ * Visits the maximum stack size and the maximum number of local variables
+ * of the method.
+ *
+ * @param maxStack maximum stack size of the method.
+ * @param maxLocals maximum number of local variables for the method.
+ */
+ public void visitMaxs(int maxStack, int maxLocals) {
+ if (mv != null) {
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ /**
+ * Visits the end of the method. This method, which is the last one to be
+ * called, is used to inform the visitor that all the annotations and
+ * attributes of the method have been visited.
+ */
+ public void visitEnd() {
+ if (mv != null) {
+ mv.visitEnd();
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/MethodWriter.java b/src/compiler/scala/tools/asm/MethodWriter.java
new file mode 100644
index 0000000000..321bacb6fc
--- /dev/null
+++ b/src/compiler/scala/tools/asm/MethodWriter.java
@@ -0,0 +1,2666 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * A {@link MethodVisitor} that generates methods in bytecode form. Each visit
+ * method of this class appends the bytecode corresponding to the visited
+ * instruction to a byte vector, in the order these methods are called.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+class MethodWriter extends MethodVisitor {
+
+ /**
+ * Pseudo access flag used to denote constructors.
+ */
+ static final int ACC_CONSTRUCTOR = 262144;
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is zero.
+ */
+ static final int SAME_FRAME = 0; // to 63 (0-3f)
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is 1
+ */
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)
+
+ /**
+ * Reserved for future use
+ */
+ static final int RESERVED = 128;
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is 1. Offset is bigger then 63;
+ */
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
+
+ /**
+ * Frame where current locals are the same as the locals in the previous
+ * frame, except that the k last locals are absent. The value of k is given
+ * by the formula 251-frame_type.
+ */
+ static final int CHOP_FRAME = 248; // to 250 (f8-fA)
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is zero. Offset is bigger then 63;
+ */
+ static final int SAME_FRAME_EXTENDED = 251; // fb
+
+ /**
+ * Frame where current locals are the same as the locals in the previous
+ * frame, except that k additional locals are defined. The value of k is
+ * given by the formula frame_type-251.
+ */
+ static final int APPEND_FRAME = 252; // to 254 // fc-fe
+
+ /**
+ * Full frame
+ */
+ static final int FULL_FRAME = 255; // ff
+
+ /**
+ * Indicates that the stack map frames must be recomputed from scratch. In
+ * this case the maximum stack size and number of local variables is also
+ * recomputed from scratch.
+ *
+ * @see #compute
+ */
+ private static final int FRAMES = 0;
+
+ /**
+ * Indicates that the maximum stack size and number of local variables must
+ * be automatically computed.
+ *
+ * @see #compute
+ */
+ private static final int MAXS = 1;
+
+ /**
+ * Indicates that nothing must be automatically computed.
+ *
+ * @see #compute
+ */
+ private static final int NOTHING = 2;
+
+ /**
+ * The class writer to which this method must be added.
+ */
+ final ClassWriter cw;
+
+ /**
+ * Access flags of this method.
+ */
+ private int access;
+
+ /**
+ * The index of the constant pool item that contains the name of this
+ * method.
+ */
+ private final int name;
+
+ /**
+ * The index of the constant pool item that contains the descriptor of this
+ * method.
+ */
+ private final int desc;
+
+ /**
+ * The descriptor of this method.
+ */
+ private final String descriptor;
+
+ /**
+ * The signature of this method.
+ */
+ String signature;
+
+ /**
+ * If not zero, indicates that the code of this method must be copied from
+ * the ClassReader associated to this writer in <code>cw.cr</code>. More
+ * precisely, this field gives the index of the first byte to copied from
+ * <code>cw.cr.b</code>.
+ */
+ int classReaderOffset;
+
+ /**
+ * If not zero, indicates that the code of this method must be copied from
+ * the ClassReader associated to this writer in <code>cw.cr</code>. More
+ * precisely, this field gives the number of bytes to copied from
+ * <code>cw.cr.b</code>.
+ */
+ int classReaderLength;
+
+ /**
+ * Number of exceptions that can be thrown by this method.
+ */
+ int exceptionCount;
+
+ /**
+ * The exceptions that can be thrown by this method. More precisely, this
+ * array contains the indexes of the constant pool items that contain the
+ * internal names of these exception classes.
+ */
+ int[] exceptions;
+
+ /**
+ * The annotation default attribute of this method. May be <tt>null</tt>.
+ */
+ private ByteVector annd;
+
+ /**
+ * The runtime visible annotations of this method. May be <tt>null</tt>.
+ */
+ private AnnotationWriter anns;
+
+ /**
+ * The runtime invisible annotations of this method. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ianns;
+
+ /**
+ * The runtime visible parameter annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter[] panns;
+
+ /**
+ * The runtime invisible parameter annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter[] ipanns;
+
+ /**
+ * The number of synthetic parameters of this method.
+ */
+ private int synthetics;
+
+ /**
+ * The non standard attributes of the method.
+ */
+ private Attribute attrs;
+
+ /**
+ * The bytecode of this method.
+ */
+ private ByteVector code = new ByteVector();
+
+ /**
+ * Maximum stack size of this method.
+ */
+ private int maxStack;
+
+ /**
+ * Maximum number of local variables for this method.
+ */
+ private int maxLocals;
+
+ /**
+ * Number of local variables in the current stack map frame.
+ */
+ private int currentLocals;
+
+ /**
+ * Number of stack map frames in the StackMapTable attribute.
+ */
+ private int frameCount;
+
+ /**
+ * The StackMapTable attribute.
+ */
+ private ByteVector stackMap;
+
+ /**
+ * The offset of the last frame that was written in the StackMapTable
+ * attribute.
+ */
+ private int previousFrameOffset;
+
+ /**
+ * The last frame that was written in the StackMapTable attribute.
+ *
+ * @see #frame
+ */
+ private int[] previousFrame;
+
+ /**
+ * Index of the next element to be added in {@link #frame}.
+ */
+ private int frameIndex;
+
+ /**
+ * The current stack map frame. The first element contains the offset of the
+ * instruction to which the frame corresponds, the second element is the
+ * number of locals and the third one is the number of stack elements. The
+ * local variables start at index 3 and are followed by the operand stack
+ * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =
+ * nStack, frame[3] = nLocal. All types are encoded as integers, with the
+ * same format as the one used in {@link Label}, but limited to BASE types.
+ */
+ private int[] frame;
+
+ /**
+ * Number of elements in the exception handler list.
+ */
+ private int handlerCount;
+
+ /**
+ * The first element in the exception handler list.
+ */
+ private Handler firstHandler;
+
+ /**
+ * The last element in the exception handler list.
+ */
+ private Handler lastHandler;
+
+ /**
+ * Number of entries in the LocalVariableTable attribute.
+ */
+ private int localVarCount;
+
+ /**
+ * The LocalVariableTable attribute.
+ */
+ private ByteVector localVar;
+
+ /**
+ * Number of entries in the LocalVariableTypeTable attribute.
+ */
+ private int localVarTypeCount;
+
+ /**
+ * The LocalVariableTypeTable attribute.
+ */
+ private ByteVector localVarType;
+
+ /**
+ * Number of entries in the LineNumberTable attribute.
+ */
+ private int lineNumberCount;
+
+ /**
+ * The LineNumberTable attribute.
+ */
+ private ByteVector lineNumber;
+
+ /**
+ * The non standard attributes of the method's code.
+ */
+ private Attribute cattrs;
+
+ /**
+ * Indicates if some jump instructions are too small and need to be resized.
+ */
+ private boolean resize;
+
+ /**
+ * The number of subroutines in this method.
+ */
+ private int subroutines;
+
+ // ------------------------------------------------------------------------
+
+ /*
+ * Fields for the control flow graph analysis algorithm (used to compute the
+ * maximum stack size). A control flow graph contains one node per "basic
+ * block", and one edge per "jump" from one basic block to another. Each
+ * node (i.e., each basic block) is represented by the Label object that
+ * corresponds to the first instruction of this basic block. Each node also
+ * stores the list of its successors in the graph, as a linked list of Edge
+ * objects.
+ */
+
+ /**
+ * Indicates what must be automatically computed.
+ *
+ * @see #FRAMES
+ * @see #MAXS
+ * @see #NOTHING
+ */
+ private final int compute;
+
+ /**
+ * A list of labels. This list is the list of basic blocks in the method,
+ * i.e. a list of Label objects linked to each other by their
+ * {@link Label#successor} field, in the order they are visited by
+ * {@link MethodVisitor#visitLabel}, and starting with the first basic block.
+ */
+ private Label labels;
+
+ /**
+ * The previous basic block.
+ */
+ private Label previousBlock;
+
+ /**
+ * The current basic block.
+ */
+ private Label currentBlock;
+
+ /**
+ * The (relative) stack size after the last visited instruction. This size
+ * is relative to the beginning of the current basic block, i.e., the true
+ * stack size after the last visited instruction is equal to the
+ * {@link Label#inputStackTop beginStackSize} of the current basic block
+ * plus <tt>stackSize</tt>.
+ */
+ private int stackSize;
+
+ /**
+ * The (relative) maximum stack size after the last visited instruction.
+ * This size is relative to the beginning of the current basic block, i.e.,
+ * the true maximum stack size after the last visited instruction is equal
+ * to the {@link Label#inputStackTop beginStackSize} of the current basic
+ * block plus <tt>stackSize</tt>.
+ */
+ private int maxStackSize;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link MethodWriter}.
+ *
+ * @param cw the class writer in which the method must be added.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be <tt>null</tt>.
+ * @param exceptions the internal names of the method's exceptions. May be
+ * <tt>null</tt>.
+ * @param computeMaxs <tt>true</tt> if the maximum stack size and number
+ * of local variables must be automatically computed.
+ * @param computeFrames <tt>true</tt> if the stack map tables must be
+ * recomputed from scratch.
+ */
+ MethodWriter(
+ final ClassWriter cw,
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions,
+ final boolean computeMaxs,
+ final boolean computeFrames)
+ {
+ super(Opcodes.ASM4);
+ if (cw.firstMethod == null) {
+ cw.firstMethod = this;
+ } else {
+ cw.lastMethod.mv = this;
+ }
+ cw.lastMethod = this;
+ this.cw = cw;
+ this.access = access;
+ this.name = cw.newUTF8(name);
+ this.desc = cw.newUTF8(desc);
+ this.descriptor = desc;
+ if (ClassReader.SIGNATURES) {
+ this.signature = signature;
+ }
+ if (exceptions != null && exceptions.length > 0) {
+ exceptionCount = exceptions.length;
+ this.exceptions = new int[exceptionCount];
+ for (int i = 0; i < exceptionCount; ++i) {
+ this.exceptions[i] = cw.newClass(exceptions[i]);
+ }
+ }
+ this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
+ if (computeMaxs || computeFrames) {
+ if (computeFrames && "<init>".equals(name)) {
+ this.access |= ACC_CONSTRUCTOR;
+ }
+ // updates maxLocals
+ int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ --size;
+ }
+ maxLocals = size;
+ currentLocals = size;
+ // creates and visits the label for the first basic block
+ labels = new Label();
+ labels.status |= Label.PUSHED;
+ visitLabel(labels);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the MethodVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ annd = new ByteVector();
+ return new AnnotationWriter(cw, false, annd, null, 0);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ if ("Ljava/lang/Synthetic;".equals(desc)) {
+ // workaround for a bug in javac with synthetic parameters
+ // see ClassReader.readParameterAnnotations
+ synthetics = Math.max(synthetics, parameter + 1);
+ return new AnnotationWriter(cw, false, bv, null, 0);
+ }
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ if (panns == null) {
+ panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ aw.next = panns[parameter];
+ panns[parameter] = aw;
+ } else {
+ if (ipanns == null) {
+ ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ aw.next = ipanns[parameter];
+ ipanns[parameter] = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ if (attr.isCodeAttribute()) {
+ attr.next = cattrs;
+ cattrs = attr;
+ } else {
+ attr.next = attrs;
+ attrs = attr;
+ }
+ }
+
+ @Override
+ public void visitCode() {
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ if (!ClassReader.FRAMES || compute == FRAMES) {
+ return;
+ }
+
+ if (type == Opcodes.F_NEW) {
+ currentLocals = nLocal;
+ startFrame(code.length, nLocal, nStack);
+ for (int i = 0; i < nLocal; ++i) {
+ if (local[i] instanceof String) {
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType((String) local[i]);
+ } else if (local[i] instanceof Integer) {
+ frame[frameIndex++] = ((Integer) local[i]).intValue();
+ } else {
+ frame[frameIndex++] = Frame.UNINITIALIZED
+ | cw.addUninitializedType("",
+ ((Label) local[i]).position);
+ }
+ }
+ for (int i = 0; i < nStack; ++i) {
+ if (stack[i] instanceof String) {
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType((String) stack[i]);
+ } else if (stack[i] instanceof Integer) {
+ frame[frameIndex++] = ((Integer) stack[i]).intValue();
+ } else {
+ frame[frameIndex++] = Frame.UNINITIALIZED
+ | cw.addUninitializedType("",
+ ((Label) stack[i]).position);
+ }
+ }
+ endFrame();
+ } else {
+ int delta;
+ if (stackMap == null) {
+ stackMap = new ByteVector();
+ delta = code.length;
+ } else {
+ delta = code.length - previousFrameOffset - 1;
+ if (delta < 0) {
+ if (type == Opcodes.F_SAME) {
+ return;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ switch (type) {
+ case Opcodes.F_FULL:
+ currentLocals = nLocal;
+ stackMap.putByte(FULL_FRAME)
+ .putShort(delta)
+ .putShort(nLocal);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ stackMap.putShort(nStack);
+ for (int i = 0; i < nStack; ++i) {
+ writeFrameType(stack[i]);
+ }
+ break;
+ case Opcodes.F_APPEND:
+ currentLocals += nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
+ .putShort(delta);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ break;
+ case Opcodes.F_CHOP:
+ currentLocals -= nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
+ .putShort(delta);
+ break;
+ case Opcodes.F_SAME:
+ if (delta < 64) {
+ stackMap.putByte(delta);
+ } else {
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ }
+ break;
+ case Opcodes.F_SAME1:
+ if (delta < 64) {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ } else {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ .putShort(delta);
+ }
+ writeFrameType(stack[0]);
+ break;
+ }
+
+ previousFrameOffset = code.length;
+ ++frameCount;
+ }
+
+ maxStack = Math.max(maxStack, nStack);
+ maxLocals = Math.max(maxLocals, currentLocals);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ // adds the instruction to the bytecode of the method
+ code.putByte(opcode);
+ // update currentBlock
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, null, null);
+ } else {
+ // updates current and max stack sizes
+ int size = stackSize + Frame.SIZE[opcode];
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ // if opcode == ATHROW or xRETURN, ends current block (no successor)
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
+ || opcode == Opcodes.ATHROW)
+ {
+ noSuccessor();
+ }
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, operand, null, null);
+ } else if (opcode != Opcodes.NEWARRAY) {
+ // updates current and max stack sizes only for NEWARRAY
+ // (stack size variation = 0 for BIPUSH or SIPUSH)
+ int size = stackSize + 1;
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (opcode == Opcodes.SIPUSH) {
+ code.put12(opcode, operand);
+ } else { // BIPUSH or NEWARRAY
+ code.put11(opcode, operand);
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, var, null, null);
+ } else {
+ // updates current and max stack sizes
+ if (opcode == Opcodes.RET) {
+ // no stack change, but end of current block (no successor)
+ currentBlock.status |= Label.RET;
+ // save 'stackSize' here for future use
+ // (see {@link #findSubroutineSuccessors})
+ currentBlock.inputStackTop = stackSize;
+ noSuccessor();
+ } else { // xLOAD or xSTORE
+ int size = stackSize + Frame.SIZE[opcode];
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ }
+ if (compute != NOTHING) {
+ // updates max locals
+ int n;
+ if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
+ || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)
+ {
+ n = var + 2;
+ } else {
+ n = var + 1;
+ }
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (var < 4 && opcode != Opcodes.RET) {
+ int opt;
+ if (opcode < Opcodes.ISTORE) {
+ /* ILOAD_0 */
+ opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
+ } else {
+ /* ISTORE_0 */
+ opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
+ }
+ code.putByte(opt);
+ } else if (var >= 256) {
+ code.putByte(196 /* WIDE */).put12(opcode, var);
+ } else {
+ code.put11(opcode, var);
+ }
+ if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {
+ visitLabel(new Label());
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ Item i = cw.newClassItem(type);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, code.length, cw, i);
+ } else if (opcode == Opcodes.NEW) {
+ // updates current and max stack sizes only if opcode == NEW
+ // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)
+ int size = stackSize + 1;
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(opcode, i.index);
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ Item i = cw.newFieldItem(owner, name, desc);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, cw, i);
+ } else {
+ int size;
+ // computes the stack size variation
+ char c = desc.charAt(0);
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+ break;
+ case Opcodes.PUTSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+ break;
+ case Opcodes.GETFIELD:
+ size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+ break;
+ // case Constants.PUTFIELD:
+ default:
+ size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+ break;
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(opcode, i.index);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ Item i = cw.newMethodItem(owner, name, desc, itf);
+ int argSize = i.intVal;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, cw, i);
+ } else {
+ /*
+ * computes the stack size variation. In order not to recompute
+ * several times this variation for the same Item, we use the
+ * intVal field of this item to store this variation, once it
+ * has been computed. More precisely this intVal field stores
+ * the sizes of the arguments and of the return value
+ * corresponding to desc.
+ */
+ if (argSize == 0) {
+ // the above sizes have not been computed yet,
+ // so we compute them...
+ argSize = Type.getArgumentsAndReturnSizes(desc);
+ // ... and we save them in order
+ // not to recompute them in the future
+ i.intVal = argSize;
+ }
+ int size;
+ if (opcode == Opcodes.INVOKESTATIC) {
+ size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
+ } else {
+ size = stackSize - (argSize >> 2) + (argSize & 0x03);
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (itf) {
+ if (argSize == 0) {
+ argSize = Type.getArgumentsAndReturnSizes(desc);
+ i.intVal = argSize;
+ }
+ code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
+ } else {
+ code.put12(opcode, i.index);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ final String name,
+ final String desc,
+ final Handle bsm,
+ final Object... bsmArgs)
+ {
+ Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
+ int argSize = i.intVal;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i);
+ } else {
+ /*
+ * computes the stack size variation. In order not to recompute
+ * several times this variation for the same Item, we use the
+ * intVal field of this item to store this variation, once it
+ * has been computed. More precisely this intVal field stores
+ * the sizes of the arguments and of the return value
+ * corresponding to desc.
+ */
+ if (argSize == 0) {
+ // the above sizes have not been computed yet,
+ // so we compute them...
+ argSize = Type.getArgumentsAndReturnSizes(desc);
+ // ... and we save them in order
+ // not to recompute them in the future
+ i.intVal = argSize;
+ }
+ int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
+
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(Opcodes.INVOKEDYNAMIC, i.index);
+ code.putShort(0);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ Label nextInsn = null;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, null, null);
+ // 'label' is the target of a jump instruction
+ label.getFirst().status |= Label.TARGET;
+ // adds 'label' as a successor of this basic block
+ addSuccessor(Edge.NORMAL, label);
+ if (opcode != Opcodes.GOTO) {
+ // creates a Label for the next basic block
+ nextInsn = new Label();
+ }
+ } else {
+ if (opcode == Opcodes.JSR) {
+ if ((label.status & Label.SUBROUTINE) == 0) {
+ label.status |= Label.SUBROUTINE;
+ ++subroutines;
+ }
+ currentBlock.status |= Label.JSR;
+ addSuccessor(stackSize + 1, label);
+ // creates a Label for the next basic block
+ nextInsn = new Label();
+ /*
+ * note that, by construction in this method, a JSR block
+ * has at least two successors in the control flow graph:
+ * the first one leads the next instruction after the JSR,
+ * while the second one leads to the JSR target.
+ */
+ } else {
+ // updates current stack size (max stack size unchanged
+ // because stack size variation always negative in this
+ // case)
+ stackSize += Frame.SIZE[opcode];
+ addSuccessor(stackSize, label);
+ }
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if ((label.status & Label.RESOLVED) != 0
+ && label.position - code.length < Short.MIN_VALUE)
+ {
+ /*
+ * case of a backward jump with an offset < -32768. In this case we
+ * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
+ * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
+ * designates the instruction just after the GOTO_W.
+ */
+ if (opcode == Opcodes.GOTO) {
+ code.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ code.putByte(201); // JSR_W
+ } else {
+ // if the IF instruction is transformed into IFNOT GOTO_W the
+ // next instruction becomes the target of the IFNOT instruction
+ if (nextInsn != null) {
+ nextInsn.status |= Label.TARGET;
+ }
+ code.putByte(opcode <= 166
+ ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ code.putShort(8); // jump offset
+ code.putByte(200); // GOTO_W
+ }
+ label.put(this, code, code.length - 1, true);
+ } else {
+ /*
+ * case of a backward jump with an offset >= -32768, or of a forward
+ * jump with, of course, an unknown offset. In these cases we store
+ * the offset in 2 bytes (which will be increased in
+ * resizeInstructions, if needed).
+ */
+ code.putByte(opcode);
+ label.put(this, code, code.length - 1, false);
+ }
+ if (currentBlock != null) {
+ if (nextInsn != null) {
+ // if the jump instruction is not a GOTO, the next instruction
+ // is also a successor of this instruction. Calling visitLabel
+ // adds the label of this next instruction as a successor of the
+ // current block, and starts a new basic block
+ visitLabel(nextInsn);
+ }
+ if (opcode == Opcodes.GOTO) {
+ noSuccessor();
+ }
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ // resolves previous forward references to label, if any
+ resize |= label.resolve(this, code.length, code.data);
+ // updates currentBlock
+ if ((label.status & Label.DEBUG) != 0) {
+ return;
+ }
+ if (compute == FRAMES) {
+ if (currentBlock != null) {
+ if (label.position == currentBlock.position) {
+ // successive labels, do not start a new basic block
+ currentBlock.status |= (label.status & Label.TARGET);
+ label.frame = currentBlock.frame;
+ return;
+ }
+ // ends current block (with one new successor)
+ addSuccessor(Edge.NORMAL, label);
+ }
+ // begins a new current block
+ currentBlock = label;
+ if (label.frame == null) {
+ label.frame = new Frame();
+ label.frame.owner = label;
+ }
+ // updates the basic block list
+ if (previousBlock != null) {
+ if (label.position == previousBlock.position) {
+ previousBlock.status |= (label.status & Label.TARGET);
+ label.frame = previousBlock.frame;
+ currentBlock = previousBlock;
+ return;
+ }
+ previousBlock.successor = label;
+ }
+ previousBlock = label;
+ } else if (compute == MAXS) {
+ if (currentBlock != null) {
+ // ends current block (with one new successor)
+ currentBlock.outputStackMax = maxStackSize;
+ addSuccessor(stackSize, label);
+ }
+ // begins a new current block
+ currentBlock = label;
+ // resets the relative current and max stack sizes
+ stackSize = 0;
+ maxStackSize = 0;
+ // updates the basic block list
+ if (previousBlock != null) {
+ previousBlock.successor = label;
+ }
+ previousBlock = label;
+ }
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ Item i = cw.newConstItem(cst);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);
+ } else {
+ int size;
+ // computes the stack size variation
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)
+ {
+ size = stackSize + 2;
+ } else {
+ size = stackSize + 1;
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ int index = i.index;
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
+ code.put12(20 /* LDC2_W */, index);
+ } else if (index >= 256) {
+ code.put12(19 /* LDC_W */, index);
+ } else {
+ code.put11(Opcodes.LDC, index);
+ }
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.IINC, var, null, null);
+ }
+ }
+ if (compute != NOTHING) {
+ // updates max locals
+ int n = var + 1;
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if ((var > 255) || (increment > 127) || (increment < -128)) {
+ code.putByte(196 /* WIDE */)
+ .put12(Opcodes.IINC, var)
+ .putShort(increment);
+ } else {
+ code.putByte(Opcodes.IINC).put11(var, increment);
+ }
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label... labels)
+ {
+ // adds the instruction to the bytecode of the method
+ int source = code.length;
+ code.putByte(Opcodes.TABLESWITCH);
+ code.putByteArray(null, 0, (4 - code.length % 4) % 4);
+ dflt.put(this, code, source, true);
+ code.putInt(min).putInt(max);
+ for (int i = 0; i < labels.length; ++i) {
+ labels[i].put(this, code, source, true);
+ }
+ // updates currentBlock
+ visitSwitchInsn(dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ // adds the instruction to the bytecode of the method
+ int source = code.length;
+ code.putByte(Opcodes.LOOKUPSWITCH);
+ code.putByteArray(null, 0, (4 - code.length % 4) % 4);
+ dflt.put(this, code, source, true);
+ code.putInt(labels.length);
+ for (int i = 0; i < labels.length; ++i) {
+ code.putInt(keys[i]);
+ labels[i].put(this, code, source, true);
+ }
+ // updates currentBlock
+ visitSwitchInsn(dflt, labels);
+ }
+
+ private void visitSwitchInsn(final Label dflt, final Label[] labels) {
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);
+ // adds current block successors
+ addSuccessor(Edge.NORMAL, dflt);
+ dflt.getFirst().status |= Label.TARGET;
+ for (int i = 0; i < labels.length; ++i) {
+ addSuccessor(Edge.NORMAL, labels[i]);
+ labels[i].getFirst().status |= Label.TARGET;
+ }
+ } else {
+ // updates current stack size (max stack size unchanged)
+ --stackSize;
+ // adds current block successors
+ addSuccessor(stackSize, dflt);
+ for (int i = 0; i < labels.length; ++i) {
+ addSuccessor(stackSize, labels[i]);
+ }
+ }
+ // ends current block
+ noSuccessor();
+ }
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ Item i = cw.newClassItem(desc);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);
+ } else {
+ // updates current stack size (max stack size unchanged because
+ // stack size variation always negative or null)
+ stackSize += 1 - dims;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ ++handlerCount;
+ Handler h = new Handler();
+ h.start = start;
+ h.end = end;
+ h.handler = handler;
+ h.desc = type;
+ h.type = type != null ? cw.newClass(type) : 0;
+ if (lastHandler == null) {
+ firstHandler = h;
+ } else {
+ lastHandler.next = h;
+ }
+ lastHandler = h;
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ if (signature != null) {
+ if (localVarType == null) {
+ localVarType = new ByteVector();
+ }
+ ++localVarTypeCount;
+ localVarType.putShort(start.position)
+ .putShort(end.position - start.position)
+ .putShort(cw.newUTF8(name))
+ .putShort(cw.newUTF8(signature))
+ .putShort(index);
+ }
+ if (localVar == null) {
+ localVar = new ByteVector();
+ }
+ ++localVarCount;
+ localVar.putShort(start.position)
+ .putShort(end.position - start.position)
+ .putShort(cw.newUTF8(name))
+ .putShort(cw.newUTF8(desc))
+ .putShort(index);
+ if (compute != NOTHING) {
+ // updates max locals
+ char c = desc.charAt(0);
+ int n = index + (c == 'J' || c == 'D' ? 2 : 1);
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ if (lineNumber == null) {
+ lineNumber = new ByteVector();
+ }
+ ++lineNumberCount;
+ lineNumber.putShort(start.position);
+ lineNumber.putShort(line);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (ClassReader.FRAMES && compute == FRAMES) {
+ // completes the control flow graph with exception handler blocks
+ Handler handler = firstHandler;
+ while (handler != null) {
+ Label l = handler.start.getFirst();
+ Label h = handler.handler.getFirst();
+ Label e = handler.end.getFirst();
+ // computes the kind of the edges to 'h'
+ String t = handler.desc == null
+ ? "java/lang/Throwable"
+ : handler.desc;
+ int kind = Frame.OBJECT | cw.addType(t);
+ // h is an exception handler
+ h.status |= Label.TARGET;
+ // adds 'h' as a successor of labels between 'start' and 'end'
+ while (l != e) {
+ // creates an edge to 'h'
+ Edge b = new Edge();
+ b.info = kind;
+ b.successor = h;
+ // adds it to the successors of 'l'
+ b.next = l.successors;
+ l.successors = b;
+ // goes to the next label
+ l = l.successor;
+ }
+ handler = handler.next;
+ }
+
+ // creates and visits the first (implicit) frame
+ Frame f = labels.frame;
+ Type[] args = Type.getArgumentTypes(descriptor);
+ f.initInputFrame(cw, access, args, this.maxLocals);
+ visitFrame(f);
+
+ /*
+ * fix point algorithm: mark the first basic block as 'changed'
+ * (i.e. put it in the 'changed' list) and, while there are changed
+ * basic blocks, choose one, mark it as unchanged, and update its
+ * successors (which can be changed in the process).
+ */
+ int max = 0;
+ Label changed = labels;
+ while (changed != null) {
+ // removes a basic block from the list of changed basic blocks
+ Label l = changed;
+ changed = changed.next;
+ l.next = null;
+ f = l.frame;
+ // a reachable jump target must be stored in the stack map
+ if ((l.status & Label.TARGET) != 0) {
+ l.status |= Label.STORE;
+ }
+ // all visited labels are reachable, by definition
+ l.status |= Label.REACHABLE;
+ // updates the (absolute) maximum stack size
+ int blockMax = f.inputStack.length + l.outputStackMax;
+ if (blockMax > max) {
+ max = blockMax;
+ }
+ // updates the successors of the current basic block
+ Edge e = l.successors;
+ while (e != null) {
+ Label n = e.successor.getFirst();
+ boolean change = f.merge(cw, n.frame, e.info);
+ if (change && n.next == null) {
+ // if n has changed and is not already in the 'changed'
+ // list, adds it to this list
+ n.next = changed;
+ changed = n;
+ }
+ e = e.next;
+ }
+ }
+
+ // visits all the frames that must be stored in the stack map
+ Label l = labels;
+ while (l != null) {
+ f = l.frame;
+ if ((l.status & Label.STORE) != 0) {
+ visitFrame(f);
+ }
+ if ((l.status & Label.REACHABLE) == 0) {
+ // finds start and end of dead basic block
+ Label k = l.successor;
+ int start = l.position;
+ int end = (k == null ? code.length : k.position) - 1;
+ // if non empty basic block
+ if (end >= start) {
+ max = Math.max(max, 1);
+ // replaces instructions with NOP ... NOP ATHROW
+ for (int i = start; i < end; ++i) {
+ code.data[i] = Opcodes.NOP;
+ }
+ code.data[end] = (byte) Opcodes.ATHROW;
+ // emits a frame for this unreachable block
+ startFrame(start, 0, 1);
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType("java/lang/Throwable");
+ endFrame();
+ // removes the start-end range from the exception handlers
+ firstHandler = Handler.remove(firstHandler, l, k);
+ }
+ }
+ l = l.successor;
+ }
+
+ handler = firstHandler;
+ handlerCount = 0;
+ while (handler != null) {
+ handlerCount += 1;
+ handler = handler.next;
+ }
+
+ this.maxStack = max;
+ } else if (compute == MAXS) {
+ // completes the control flow graph with exception handler blocks
+ Handler handler = firstHandler;
+ while (handler != null) {
+ Label l = handler.start;
+ Label h = handler.handler;
+ Label e = handler.end;
+ // adds 'h' as a successor of labels between 'start' and 'end'
+ while (l != e) {
+ // creates an edge to 'h'
+ Edge b = new Edge();
+ b.info = Edge.EXCEPTION;
+ b.successor = h;
+ // adds it to the successors of 'l'
+ if ((l.status & Label.JSR) == 0) {
+ b.next = l.successors;
+ l.successors = b;
+ } else {
+ // if l is a JSR block, adds b after the first two edges
+ // to preserve the hypothesis about JSR block successors
+ // order (see {@link #visitJumpInsn})
+ b.next = l.successors.next.next;
+ l.successors.next.next = b;
+ }
+ // goes to the next label
+ l = l.successor;
+ }
+ handler = handler.next;
+ }
+
+ if (subroutines > 0) {
+ // completes the control flow graph with the RET successors
+ /*
+ * first step: finds the subroutines. This step determines, for
+ * each basic block, to which subroutine(s) it belongs.
+ */
+ // finds the basic blocks that belong to the "main" subroutine
+ int id = 0;
+ labels.visitSubroutine(null, 1, subroutines);
+ // finds the basic blocks that belong to the real subroutines
+ Label l = labels;
+ while (l != null) {
+ if ((l.status & Label.JSR) != 0) {
+ // the subroutine is defined by l's TARGET, not by l
+ Label subroutine = l.successors.next.successor;
+ // if this subroutine has not been visited yet...
+ if ((subroutine.status & Label.VISITED) == 0) {
+ // ...assigns it a new id and finds its basic blocks
+ id += 1;
+ subroutine.visitSubroutine(null, (id / 32L) << 32
+ | (1L << (id % 32)), subroutines);
+ }
+ }
+ l = l.successor;
+ }
+ // second step: finds the successors of RET blocks
+ l = labels;
+ while (l != null) {
+ if ((l.status & Label.JSR) != 0) {
+ Label L = labels;
+ while (L != null) {
+ L.status &= ~Label.VISITED2;
+ L = L.successor;
+ }
+ // the subroutine is defined by l's TARGET, not by l
+ Label subroutine = l.successors.next.successor;
+ subroutine.visitSubroutine(l, 0, subroutines);
+ }
+ l = l.successor;
+ }
+ }
+
+ /*
+ * control flow analysis algorithm: while the block stack is not
+ * empty, pop a block from this stack, update the max stack size,
+ * compute the true (non relative) begin stack size of the
+ * successors of this block, and push these successors onto the
+ * stack (unless they have already been pushed onto the stack).
+ * Note: by hypothesis, the {@link Label#inputStackTop} of the
+ * blocks in the block stack are the true (non relative) beginning
+ * stack sizes of these blocks.
+ */
+ int max = 0;
+ Label stack = labels;
+ while (stack != null) {
+ // pops a block from the stack
+ Label l = stack;
+ stack = stack.next;
+ // computes the true (non relative) max stack size of this block
+ int start = l.inputStackTop;
+ int blockMax = start + l.outputStackMax;
+ // updates the global max stack size
+ if (blockMax > max) {
+ max = blockMax;
+ }
+ // analyzes the successors of the block
+ Edge b = l.successors;
+ if ((l.status & Label.JSR) != 0) {
+ // ignores the first edge of JSR blocks (virtual successor)
+ b = b.next;
+ }
+ while (b != null) {
+ l = b.successor;
+ // if this successor has not already been pushed...
+ if ((l.status & Label.PUSHED) == 0) {
+ // computes its true beginning stack size...
+ l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start
+ + b.info;
+ // ...and pushes it onto the stack
+ l.status |= Label.PUSHED;
+ l.next = stack;
+ stack = l;
+ }
+ b = b.next;
+ }
+ }
+ this.maxStack = Math.max(maxStack, max);
+ } else {
+ this.maxStack = maxStack;
+ this.maxLocals = maxLocals;
+ }
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: control flow analysis algorithm
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds a successor to the {@link #currentBlock currentBlock} block.
+ *
+ * @param info information about the control flow edge to be added.
+ * @param successor the successor block to be added to the current block.
+ */
+ private void addSuccessor(final int info, final Label successor) {
+ // creates and initializes an Edge object...
+ Edge b = new Edge();
+ b.info = info;
+ b.successor = successor;
+ // ...and adds it to the successor list of the currentBlock block
+ b.next = currentBlock.successors;
+ currentBlock.successors = b;
+ }
+
+ /**
+ * Ends the current basic block. This method must be used in the case where
+ * the current basic block does not have any successor.
+ */
+ private void noSuccessor() {
+ if (compute == FRAMES) {
+ Label l = new Label();
+ l.frame = new Frame();
+ l.frame.owner = l;
+ l.resolve(this, code.length, code.data);
+ previousBlock.successor = l;
+ previousBlock = l;
+ } else {
+ currentBlock.outputStackMax = maxStackSize;
+ }
+ currentBlock = null;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: stack map frames
+ // ------------------------------------------------------------------------
+
+ /**
+ * Visits a frame that has been computed from scratch.
+ *
+ * @param f the frame that must be visited.
+ */
+ private void visitFrame(final Frame f) {
+ int i, t;
+ int nTop = 0;
+ int nLocal = 0;
+ int nStack = 0;
+ int[] locals = f.inputLocals;
+ int[] stacks = f.inputStack;
+ // computes the number of locals (ignores TOP types that are just after
+ // a LONG or a DOUBLE, and all trailing TOP types)
+ for (i = 0; i < locals.length; ++i) {
+ t = locals[i];
+ if (t == Frame.TOP) {
+ ++nTop;
+ } else {
+ nLocal += nTop + 1;
+ nTop = 0;
+ }
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ // computes the stack size (ignores TOP types that are just after
+ // a LONG or a DOUBLE)
+ for (i = 0; i < stacks.length; ++i) {
+ t = stacks[i];
+ ++nStack;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ // visits the frame and its content
+ startFrame(f.owner.position, nLocal, nStack);
+ for (i = 0; nLocal > 0; ++i, --nLocal) {
+ t = locals[i];
+ frame[frameIndex++] = t;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ for (i = 0; i < stacks.length; ++i) {
+ t = stacks[i];
+ frame[frameIndex++] = t;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ endFrame();
+ }
+
+ /**
+ * Starts the visit of a stack map frame.
+ *
+ * @param offset the offset of the instruction to which the frame
+ * corresponds.
+ * @param nLocal the number of local variables in the frame.
+ * @param nStack the number of stack elements in the frame.
+ */
+ private void startFrame(final int offset, final int nLocal, final int nStack)
+ {
+ int n = 3 + nLocal + nStack;
+ if (frame == null || frame.length < n) {
+ frame = new int[n];
+ }
+ frame[0] = offset;
+ frame[1] = nLocal;
+ frame[2] = nStack;
+ frameIndex = 3;
+ }
+
+ /**
+ * Checks if the visit of the current frame {@link #frame} is finished, and
+ * if yes, write it in the StackMapTable attribute.
+ */
+ private void endFrame() {
+ if (previousFrame != null) { // do not write the first frame
+ if (stackMap == null) {
+ stackMap = new ByteVector();
+ }
+ writeFrame();
+ ++frameCount;
+ }
+ previousFrame = frame;
+ frame = null;
+ }
+
+ /**
+ * Compress and writes the current frame {@link #frame} in the StackMapTable
+ * attribute.
+ */
+ private void writeFrame() {
+ int clocalsSize = frame[1];
+ int cstackSize = frame[2];
+ if ((cw.version & 0xFFFF) < Opcodes.V1_6) {
+ stackMap.putShort(frame[0]).putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ return;
+ }
+ int localsSize = previousFrame[1];
+ int type = FULL_FRAME;
+ int k = 0;
+ int delta;
+ if (frameCount == 0) {
+ delta = frame[0];
+ } else {
+ delta = frame[0] - previousFrame[0] - 1;
+ }
+ if (cstackSize == 0) {
+ k = clocalsSize - localsSize;
+ switch (k) {
+ case -3:
+ case -2:
+ case -1:
+ type = CHOP_FRAME;
+ localsSize = clocalsSize;
+ break;
+ case 0:
+ type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ type = APPEND_FRAME;
+ break;
+ }
+ } else if (clocalsSize == localsSize && cstackSize == 1) {
+ type = delta < 63
+ ? SAME_LOCALS_1_STACK_ITEM_FRAME
+ : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
+ }
+ if (type != FULL_FRAME) {
+ // verify if locals are the same
+ int l = 3;
+ for (int j = 0; j < localsSize; j++) {
+ if (frame[l] != previousFrame[l]) {
+ type = FULL_FRAME;
+ break;
+ }
+ l++;
+ }
+ }
+ switch (type) {
+ case SAME_FRAME:
+ stackMap.putByte(delta);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ .putShort(delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_FRAME_EXTENDED:
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ break;
+ case CHOP_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ break;
+ case APPEND_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ writeFrameTypes(3 + localsSize, 3 + clocalsSize);
+ break;
+ // case FULL_FRAME:
+ default:
+ stackMap.putByte(FULL_FRAME)
+ .putShort(delta)
+ .putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ }
+ }
+
+ /**
+ * Writes some types of the current frame {@link #frame} into the
+ * StackMapTableAttribute. This method converts types from the format used
+ * in {@link Label} to the format used in StackMapTable attributes. In
+ * particular, it converts type table indexes to constant pool indexes.
+ *
+ * @param start index of the first type in {@link #frame} to write.
+ * @param end index of last type in {@link #frame} to write (exclusive).
+ */
+ private void writeFrameTypes(final int start, final int end) {
+ for (int i = start; i < end; ++i) {
+ int t = frame[i];
+ int d = t & Frame.DIM;
+ if (d == 0) {
+ int v = t & Frame.BASE_VALUE;
+ switch (t & Frame.BASE_KIND) {
+ case Frame.OBJECT:
+ stackMap.putByte(7)
+ .putShort(cw.newClass(cw.typeTable[v].strVal1));
+ break;
+ case Frame.UNINITIALIZED:
+ stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
+ break;
+ default:
+ stackMap.putByte(v);
+ }
+ } else {
+ StringBuffer buf = new StringBuffer();
+ d >>= 28;
+ while (d-- > 0) {
+ buf.append('[');
+ }
+ if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
+ buf.append('L');
+ buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
+ buf.append(';');
+ } else {
+ switch (t & 0xF) {
+ case 1:
+ buf.append('I');
+ break;
+ case 2:
+ buf.append('F');
+ break;
+ case 3:
+ buf.append('D');
+ break;
+ case 9:
+ buf.append('Z');
+ break;
+ case 10:
+ buf.append('B');
+ break;
+ case 11:
+ buf.append('C');
+ break;
+ case 12:
+ buf.append('S');
+ break;
+ default:
+ buf.append('J');
+ }
+ }
+ stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
+ }
+ }
+ }
+
+ private void writeFrameType(final Object type) {
+ if (type instanceof String) {
+ stackMap.putByte(7).putShort(cw.newClass((String) type));
+ } else if (type instanceof Integer) {
+ stackMap.putByte(((Integer) type).intValue());
+ } else {
+ stackMap.putByte(8).putShort(((Label) type).position);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: dump bytecode array
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of the bytecode of this method.
+ *
+ * @return the size of the bytecode of this method.
+ */
+ final int getSize() {
+ if (classReaderOffset != 0) {
+ return 6 + classReaderLength;
+ }
+ if (resize) {
+ // replaces the temporary jump opcodes introduced by Label.resolve.
+ if (ClassReader.RESIZE) {
+ resizeInstructions();
+ } else {
+ throw new RuntimeException("Method code too large!");
+ }
+ }
+ int size = 8;
+ if (code.length > 0) {
+ if (code.length > 65536) {
+ throw new RuntimeException("Method code too large!");
+ }
+ cw.newUTF8("Code");
+ size += 18 + code.length + 8 * handlerCount;
+ if (localVar != null) {
+ cw.newUTF8("LocalVariableTable");
+ size += 8 + localVar.length;
+ }
+ if (localVarType != null) {
+ cw.newUTF8("LocalVariableTypeTable");
+ size += 8 + localVarType.length;
+ }
+ if (lineNumber != null) {
+ cw.newUTF8("LineNumberTable");
+ size += 8 + lineNumber.length;
+ }
+ if (stackMap != null) {
+ boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
+ cw.newUTF8(zip ? "StackMapTable" : "StackMap");
+ size += 8 + stackMap.length;
+ }
+ if (cattrs != null) {
+ size += cattrs.getSize(cw,
+ code.data,
+ code.length,
+ maxStack,
+ maxLocals);
+ }
+ }
+ if (exceptionCount > 0) {
+ cw.newUTF8("Exceptions");
+ size += 8 + 2 * exceptionCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cw.newUTF8("Deprecated");
+ size += 6;
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ cw.newUTF8("Signature");
+ cw.newUTF8(signature);
+ size += 8;
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ cw.newUTF8("AnnotationDefault");
+ size += 6 + annd.length;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ cw.newUTF8("RuntimeVisibleAnnotations");
+ size += 8 + anns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ cw.newUTF8("RuntimeInvisibleAnnotations");
+ size += 8 + ianns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ cw.newUTF8("RuntimeVisibleParameterAnnotations");
+ size += 7 + 2 * (panns.length - synthetics);
+ for (int i = panns.length - 1; i >= synthetics; --i) {
+ size += panns[i] == null ? 0 : panns[i].getSize();
+ }
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ cw.newUTF8("RuntimeInvisibleParameterAnnotations");
+ size += 7 + 2 * (ipanns.length - synthetics);
+ for (int i = ipanns.length - 1; i >= synthetics; --i) {
+ size += ipanns[i] == null ? 0 : ipanns[i].getSize();
+ }
+ }
+ if (attrs != null) {
+ size += attrs.getSize(cw, null, 0, -1, -1);
+ }
+ return size;
+ }
+
+ /**
+ * Puts the bytecode of this method in the given byte vector.
+ *
+ * @param out the byte vector into which the bytecode of this method must be
+ * copied.
+ */
+ final void put(final ByteVector out) {
+ int mask = Opcodes.ACC_DEPRECATED
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / (ClassWriter.ACC_SYNTHETIC_ATTRIBUTE / Opcodes.ACC_SYNTHETIC));
+ out.putShort(access & ~mask).putShort(name).putShort(desc);
+ if (classReaderOffset != 0) {
+ out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
+ return;
+ }
+ int attributeCount = 0;
+ if (code.length > 0) {
+ ++attributeCount;
+ }
+ if (exceptionCount > 0) {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ ++attributeCount;
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (code.length > 0) {
+ int size = 12 + code.length + 8 * handlerCount;
+ if (localVar != null) {
+ size += 8 + localVar.length;
+ }
+ if (localVarType != null) {
+ size += 8 + localVarType.length;
+ }
+ if (lineNumber != null) {
+ size += 8 + lineNumber.length;
+ }
+ if (stackMap != null) {
+ size += 8 + stackMap.length;
+ }
+ if (cattrs != null) {
+ size += cattrs.getSize(cw,
+ code.data,
+ code.length,
+ maxStack,
+ maxLocals);
+ }
+ out.putShort(cw.newUTF8("Code")).putInt(size);
+ out.putShort(maxStack).putShort(maxLocals);
+ out.putInt(code.length).putByteArray(code.data, 0, code.length);
+ out.putShort(handlerCount);
+ if (handlerCount > 0) {
+ Handler h = firstHandler;
+ while (h != null) {
+ out.putShort(h.start.position)
+ .putShort(h.end.position)
+ .putShort(h.handler.position)
+ .putShort(h.type);
+ h = h.next;
+ }
+ }
+ attributeCount = 0;
+ if (localVar != null) {
+ ++attributeCount;
+ }
+ if (localVarType != null) {
+ ++attributeCount;
+ }
+ if (lineNumber != null) {
+ ++attributeCount;
+ }
+ if (stackMap != null) {
+ ++attributeCount;
+ }
+ if (cattrs != null) {
+ attributeCount += cattrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (localVar != null) {
+ out.putShort(cw.newUTF8("LocalVariableTable"));
+ out.putInt(localVar.length + 2).putShort(localVarCount);
+ out.putByteArray(localVar.data, 0, localVar.length);
+ }
+ if (localVarType != null) {
+ out.putShort(cw.newUTF8("LocalVariableTypeTable"));
+ out.putInt(localVarType.length + 2).putShort(localVarTypeCount);
+ out.putByteArray(localVarType.data, 0, localVarType.length);
+ }
+ if (lineNumber != null) {
+ out.putShort(cw.newUTF8("LineNumberTable"));
+ out.putInt(lineNumber.length + 2).putShort(lineNumberCount);
+ out.putByteArray(lineNumber.data, 0, lineNumber.length);
+ }
+ if (stackMap != null) {
+ boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
+ out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap"));
+ out.putInt(stackMap.length + 2).putShort(frameCount);
+ out.putByteArray(stackMap.data, 0, stackMap.length);
+ }
+ if (cattrs != null) {
+ cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
+ }
+ }
+ if (exceptionCount > 0) {
+ out.putShort(cw.newUTF8("Exceptions"))
+ .putInt(2 * exceptionCount + 2);
+ out.putShort(exceptionCount);
+ for (int i = 0; i < exceptionCount; ++i) {
+ out.putShort(exceptions[i]);
+ }
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && ((cw.version & 0xFFFF) < Opcodes.V1_5 || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0))
+ {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(cw.newUTF8("Deprecated")).putInt(0);
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ out.putShort(cw.newUTF8("Signature"))
+ .putInt(2)
+ .putShort(cw.newUTF8(signature));
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ out.putShort(cw.newUTF8("AnnotationDefault"));
+ out.putInt(annd.length);
+ out.putByteArray(annd.data, 0, annd.length);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
+ AnnotationWriter.put(panns, synthetics, out);
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations"));
+ AnnotationWriter.put(ipanns, synthetics, out);
+ }
+ if (attrs != null) {
+ attrs.put(cw, null, 0, -1, -1, out);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
+ // ------------------------------------------------------------------------
+
+ /**
+ * Resizes and replaces the temporary instructions inserted by
+ * {@link Label#resolve} for wide forward jumps, while keeping jump offsets
+ * and instruction addresses consistent. This may require to resize other
+ * existing instructions, or even to introduce new instructions: for
+ * example, increasing the size of an instruction by 2 at the middle of a
+ * method can increases the offset of an IFEQ instruction from 32766 to
+ * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
+ * 32765. This, in turn, may require to increase the size of another jump
+ * instruction, and so on... All these operations are handled automatically
+ * by this method. <p> <i>This method must be called after all the method
+ * that is being built has been visited</i>. In particular, the
+ * {@link Label Label} objects used to construct the method are no longer
+ * valid after this method has been called.
+ */
+ private void resizeInstructions() {
+ byte[] b = code.data; // bytecode of the method
+ int u, v, label; // indexes in b
+ int i, j; // loop indexes
+ /*
+ * 1st step: As explained above, resizing an instruction may require to
+ * resize another one, which may require to resize yet another one, and
+ * so on. The first step of the algorithm consists in finding all the
+ * instructions that need to be resized, without modifying the code.
+ * This is done by the following "fix point" algorithm:
+ *
+ * Parse the code to find the jump instructions whose offset will need
+ * more than 2 bytes to be stored (the future offset is computed from
+ * the current offset and from the number of bytes that will be inserted
+ * or removed between the source and target instructions). For each such
+ * instruction, adds an entry in (a copy of) the indexes and sizes
+ * arrays (if this has not already been done in a previous iteration!).
+ *
+ * If at least one entry has been added during the previous step, go
+ * back to the beginning, otherwise stop.
+ *
+ * In fact the real algorithm is complicated by the fact that the size
+ * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
+ * position in the bytecode (because of padding). In order to ensure the
+ * convergence of the algorithm, the number of bytes to be added or
+ * removed from these instructions is over estimated during the previous
+ * loop, and computed exactly only after the loop is finished (this
+ * requires another pass to parse the bytecode of the method).
+ */
+ int[] allIndexes = new int[0]; // copy of indexes
+ int[] allSizes = new int[0]; // copy of sizes
+ boolean[] resize; // instructions to be resized
+ int newOffset; // future offset of a jump instruction
+
+ resize = new boolean[code.length];
+
+ // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
+ int state = 3;
+ do {
+ if (state == 3) {
+ state = 2;
+ }
+ u = 0;
+ while (u < b.length) {
+ int opcode = b[u] & 0xFF; // opcode of current instruction
+ int insert = 0; // bytes to be added after this instruction
+
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // converts temporary opcodes 202 to 217, 218 and
+ // 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (newOffset < Short.MIN_VALUE
+ || newOffset > Short.MAX_VALUE)
+ {
+ if (!resize[u]) {
+ if (opcode == Opcodes.GOTO
+ || opcode == Opcodes.JSR)
+ {
+ // two additional bytes will be required to
+ // replace this GOTO or JSR instruction with
+ // a GOTO_W or a JSR_W
+ insert = 2;
+ } else {
+ // five additional bytes will be required to
+ // replace this IFxxx <l> instruction with
+ // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+ // is the "opposite" opcode of IFxxx (i.e.,
+ // IFNE for IFEQ) and where <l'> designates
+ // the instruction just after the GOTO_W.
+ insert = 5;
+ }
+ resize[u] = true;
+ }
+ }
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ if (state == 1) {
+ // true number of bytes to be added (or removed)
+ // from this instruction = (future number of padding
+ // bytes - current number of padding byte) -
+ // previously over estimated variation =
+ // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+ // = (-newOffset%4 + u%4) - u%4
+ // = -(newOffset & 3)
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // over estimation of the number of bytes to be
+ // added to this instruction = 3 - current number
+ // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+ insert = u & 3;
+ resize[u] = true;
+ }
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
+ break;
+ case ClassWriter.LOOK_INSN:
+ if (state == 1) {
+ // like TABL_INSN
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // like TABL_INSN
+ insert = u & 3;
+ resize[u] = true;
+ }
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 8 * readInt(b, u + 4) + 8;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ u += 6;
+ } else {
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ u += 5;
+ break;
+ // case ClassWriter.MANA_INSN:
+ default:
+ u += 4;
+ break;
+ }
+ if (insert != 0) {
+ // adds a new (u, insert) entry in the allIndexes and
+ // allSizes arrays
+ int[] newIndexes = new int[allIndexes.length + 1];
+ int[] newSizes = new int[allSizes.length + 1];
+ System.arraycopy(allIndexes,
+ 0,
+ newIndexes,
+ 0,
+ allIndexes.length);
+ System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
+ newIndexes[allIndexes.length] = u;
+ newSizes[allSizes.length] = insert;
+ allIndexes = newIndexes;
+ allSizes = newSizes;
+ if (insert > 0) {
+ state = 3;
+ }
+ }
+ }
+ if (state < 3) {
+ --state;
+ }
+ } while (state != 0);
+
+ // 2nd step:
+ // copies the bytecode of the method into a new bytevector, updates the
+ // offsets, and inserts (or removes) bytes as requested.
+
+ ByteVector newCode = new ByteVector(code.length);
+
+ u = 0;
+ while (u < code.length) {
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ newCode.putByte(opcode);
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // changes temporary opcodes 202 to 217 (inclusive), 218
+ // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (resize[u]) {
+ // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+ // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+ // and where <l'> designates the instruction just after
+ // the GOTO_W.
+ if (opcode == Opcodes.GOTO) {
+ newCode.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ newCode.putByte(201); // JSR_W
+ } else {
+ newCode.putByte(opcode <= 166
+ ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ newCode.putShort(8); // jump offset
+ newCode.putByte(200); // GOTO_W
+ // newOffset now computed from start of GOTO_W
+ newOffset -= 3;
+ }
+ newCode.putInt(newOffset);
+ } else {
+ newCode.putByte(opcode);
+ newCode.putShort(newOffset);
+ }
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ label = u + readInt(b, u + 1);
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ newCode.putByte(opcode);
+ newCode.putInt(newOffset);
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.TABLESWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ j = readInt(b, u) - j + 1;
+ u += 4;
+ newCode.putInt(readInt(b, u - 4));
+ for (; j > 0; --j) {
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.LOOKUPSWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ for (; j > 0; --j) {
+ newCode.putInt(readInt(b, u));
+ u += 4;
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ newCode.putByteArray(b, u, 6);
+ u += 6;
+ } else {
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ newCode.putByteArray(b, u, 2);
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ newCode.putByteArray(b, u, 3);
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ newCode.putByteArray(b, u, 5);
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ break;
+ }
+ }
+
+ // recomputes the stack map frames
+ if (frameCount > 0) {
+ if (compute == FRAMES) {
+ frameCount = 0;
+ stackMap = null;
+ previousFrame = null;
+ frame = null;
+ Frame f = new Frame();
+ f.owner = labels;
+ Type[] args = Type.getArgumentTypes(descriptor);
+ f.initInputFrame(cw, access, args, maxLocals);
+ visitFrame(f);
+ Label l = labels;
+ while (l != null) {
+ /*
+ * here we need the original label position. getNewOffset
+ * must therefore never have been called for this label.
+ */
+ u = l.position - 3;
+ if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))
+ {
+ getNewOffset(allIndexes, allSizes, l);
+ // TODO update offsets in UNINITIALIZED values
+ visitFrame(l.frame);
+ }
+ l = l.successor;
+ }
+ } else {
+ /*
+ * Resizing an existing stack map frame table is really hard.
+ * Not only the table must be parsed to update the offets, but
+ * new frames may be needed for jump instructions that were
+ * inserted by this method. And updating the offsets or
+ * inserting frames can change the format of the following
+ * frames, in case of packed frames. In practice the whole table
+ * must be recomputed. For this the frames are marked as
+ * potentially invalid. This will cause the whole class to be
+ * reread and rewritten with the COMPUTE_FRAMES option (see the
+ * ClassWriter.toByteArray method). This is not very efficient
+ * but is much easier and requires much less code than any other
+ * method I can think of.
+ */
+ cw.invalidFrames = true;
+ }
+ }
+ // updates the exception handler block labels
+ Handler h = firstHandler;
+ while (h != null) {
+ getNewOffset(allIndexes, allSizes, h.start);
+ getNewOffset(allIndexes, allSizes, h.end);
+ getNewOffset(allIndexes, allSizes, h.handler);
+ h = h.next;
+ }
+ // updates the instructions addresses in the
+ // local var and line number tables
+ for (i = 0; i < 2; ++i) {
+ ByteVector bv = i == 0 ? localVar : localVarType;
+ if (bv != null) {
+ b = bv.data;
+ u = 0;
+ while (u < bv.length) {
+ label = readUnsignedShort(b, u);
+ newOffset = getNewOffset(allIndexes, allSizes, 0, label);
+ writeShort(b, u, newOffset);
+ label += readUnsignedShort(b, u + 2);
+ newOffset = getNewOffset(allIndexes, allSizes, 0, label)
+ - newOffset;
+ writeShort(b, u + 2, newOffset);
+ u += 10;
+ }
+ }
+ }
+ if (lineNumber != null) {
+ b = lineNumber.data;
+ u = 0;
+ while (u < lineNumber.length) {
+ writeShort(b, u, getNewOffset(allIndexes,
+ allSizes,
+ 0,
+ readUnsignedShort(b, u)));
+ u += 4;
+ }
+ }
+ // updates the labels of the other attributes
+ Attribute attr = cattrs;
+ while (attr != null) {
+ Label[] labels = attr.getLabels();
+ if (labels != null) {
+ for (i = labels.length - 1; i >= 0; --i) {
+ getNewOffset(allIndexes, allSizes, labels[i]);
+ }
+ }
+ attr = attr.next;
+ }
+
+ // replaces old bytecodes with new ones
+ code = newCode;
+ }
+
+ /**
+ * Reads an unsigned short value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index the start index of the value to be read.
+ * @return the read value.
+ */
+ static int readUnsignedShort(final byte[] b, final int index) {
+ return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+ }
+
+ /**
+ * Reads a signed short value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index the start index of the value to be read.
+ * @return the read value.
+ */
+ static short readShort(final byte[] b, final int index) {
+ return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+ }
+
+ /**
+ * Reads a signed int value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index the start index of the value to be read.
+ * @return the read value.
+ */
+ static int readInt(final byte[] b, final int index) {
+ return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+ | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+ }
+
+ /**
+ * Writes a short value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index where the first byte of the short value must be written.
+ * @param s the value to be written in the given byte array.
+ */
+ static void writeShort(final byte[] b, final int index, final int s) {
+ b[index] = (byte) (s >>> 8);
+ b[index + 1] = (byte) s;
+ }
+
+ /**
+ * Computes the future value of a bytecode offset. <p> Note: it is possible
+ * to have several entries for the same instruction in the <tt>indexes</tt>
+ * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')
+ * are equivalent to a single entry (index=a,size=b+b').
+ *
+ * @param indexes current positions of the instructions to be resized. Each
+ * instruction must be designated by the index of its <i>last</i>
+ * byte, plus one (or, in other words, by the index of the <i>first</i>
+ * byte of the <i>next</i> instruction).
+ * @param sizes the number of bytes to be <i>added</i> to the above
+ * instructions. More precisely, for each i < <tt>len</tt>,
+ * <tt>sizes</tt>[i] bytes will be added at the end of the
+ * instruction designated by <tt>indexes</tt>[i] or, if
+ * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
+ * bytes of the instruction will be removed (the instruction size
+ * <i>must not</i> become negative or null).
+ * @param begin index of the first byte of the source instruction.
+ * @param end index of the first byte of the target instruction.
+ * @return the future value of the given bytecode offset.
+ */
+ static int getNewOffset(
+ final int[] indexes,
+ final int[] sizes,
+ final int begin,
+ final int end)
+ {
+ int offset = end - begin;
+ for (int i = 0; i < indexes.length; ++i) {
+ if (begin < indexes[i] && indexes[i] <= end) {
+ // forward jump
+ offset += sizes[i];
+ } else if (end < indexes[i] && indexes[i] <= begin) {
+ // backward jump
+ offset -= sizes[i];
+ }
+ }
+ return offset;
+ }
+
+ /**
+ * Updates the offset of the given label.
+ *
+ * @param indexes current positions of the instructions to be resized. Each
+ * instruction must be designated by the index of its <i>last</i>
+ * byte, plus one (or, in other words, by the index of the <i>first</i>
+ * byte of the <i>next</i> instruction).
+ * @param sizes the number of bytes to be <i>added</i> to the above
+ * instructions. More precisely, for each i < <tt>len</tt>,
+ * <tt>sizes</tt>[i] bytes will be added at the end of the
+ * instruction designated by <tt>indexes</tt>[i] or, if
+ * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
+ * bytes of the instruction will be removed (the instruction size
+ * <i>must not</i> become negative or null).
+ * @param label the label whose offset must be updated.
+ */
+ static void getNewOffset(
+ final int[] indexes,
+ final int[] sizes,
+ final Label label)
+ {
+ if ((label.status & Label.RESIZED) == 0) {
+ label.position = getNewOffset(indexes, sizes, 0, label.position);
+ label.status |= Label.RESIZED;
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/Opcodes.java b/src/compiler/scala/tools/asm/Opcodes.java
new file mode 100644
index 0000000000..809e5ae590
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Opcodes.java
@@ -0,0 +1,358 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+/**
+ * Defines the JVM opcodes, access flags and array type codes. This interface
+ * does not define all the JVM opcodes because some opcodes are automatically
+ * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
+ * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
+ * opcodes are therefore not defined in this interface. Likewise for LDC,
+ * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
+ * JSR_W.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public interface Opcodes {
+
+ // ASM API versions
+
+ int ASM4 = 4 << 16 | 0 << 8 | 0;
+
+ // versions
+
+ int V1_1 = 3 << 16 | 45;
+ int V1_2 = 0 << 16 | 46;
+ int V1_3 = 0 << 16 | 47;
+ int V1_4 = 0 << 16 | 48;
+ int V1_5 = 0 << 16 | 49;
+ int V1_6 = 0 << 16 | 50;
+ int V1_7 = 0 << 16 | 51;
+
+ // access flags
+
+ int ACC_PUBLIC = 0x0001; // class, field, method
+ int ACC_PRIVATE = 0x0002; // class, field, method
+ int ACC_PROTECTED = 0x0004; // class, field, method
+ int ACC_STATIC = 0x0008; // field, method
+ int ACC_FINAL = 0x0010; // class, field, method
+ int ACC_SUPER = 0x0020; // class
+ int ACC_SYNCHRONIZED = 0x0020; // method
+ int ACC_VOLATILE = 0x0040; // field
+ int ACC_BRIDGE = 0x0040; // method
+ int ACC_VARARGS = 0x0080; // method
+ int ACC_TRANSIENT = 0x0080; // field
+ int ACC_NATIVE = 0x0100; // method
+ int ACC_INTERFACE = 0x0200; // class
+ int ACC_ABSTRACT = 0x0400; // class, method
+ int ACC_STRICT = 0x0800; // method
+ int ACC_SYNTHETIC = 0x1000; // class, field, method
+ int ACC_ANNOTATION = 0x2000; // class
+ int ACC_ENUM = 0x4000; // class(?) field inner
+
+ // ASM specific pseudo access flags
+
+ int ACC_DEPRECATED = 0x20000; // class, field, method
+
+ // types for NEWARRAY
+
+ int T_BOOLEAN = 4;
+ int T_CHAR = 5;
+ int T_FLOAT = 6;
+ int T_DOUBLE = 7;
+ int T_BYTE = 8;
+ int T_SHORT = 9;
+ int T_INT = 10;
+ int T_LONG = 11;
+
+ // tags for Handle
+
+ int H_GETFIELD = 1;
+ int H_GETSTATIC = 2;
+ int H_PUTFIELD = 3;
+ int H_PUTSTATIC = 4;
+ int H_INVOKEVIRTUAL = 5;
+ int H_INVOKESTATIC = 6;
+ int H_INVOKESPECIAL = 7;
+ int H_NEWINVOKESPECIAL = 8;
+ int H_INVOKEINTERFACE = 9;
+
+ // stack map frame types
+
+ /**
+ * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
+ */
+ int F_NEW = -1;
+
+ /**
+ * Represents a compressed frame with complete frame data.
+ */
+ int F_FULL = 0;
+
+ /**
+ * Represents a compressed frame where locals are the same as the locals in
+ * the previous frame, except that additional 1-3 locals are defined, and
+ * with an empty stack.
+ */
+ int F_APPEND = 1;
+
+ /**
+ * Represents a compressed frame where locals are the same as the locals in
+ * the previous frame, except that the last 1-3 locals are absent and with
+ * an empty stack.
+ */
+ int F_CHOP = 2;
+
+ /**
+ * Represents a compressed frame with exactly the same locals as the
+ * previous frame and with an empty stack.
+ */
+ int F_SAME = 3;
+
+ /**
+ * Represents a compressed frame with exactly the same locals as the
+ * previous frame and with a single value on the stack.
+ */
+ int F_SAME1 = 4;
+
+ Integer TOP = new Integer(0);
+ Integer INTEGER = new Integer(1);
+ Integer FLOAT = new Integer(2);
+ Integer DOUBLE = new Integer(3);
+ Integer LONG = new Integer(4);
+ Integer NULL = new Integer(5);
+ Integer UNINITIALIZED_THIS = new Integer(6);
+
+ // opcodes // visit method (- = idem)
+
+ int NOP = 0; // visitInsn
+ int ACONST_NULL = 1; // -
+ int ICONST_M1 = 2; // -
+ int ICONST_0 = 3; // -
+ int ICONST_1 = 4; // -
+ int ICONST_2 = 5; // -
+ int ICONST_3 = 6; // -
+ int ICONST_4 = 7; // -
+ int ICONST_5 = 8; // -
+ int LCONST_0 = 9; // -
+ int LCONST_1 = 10; // -
+ int FCONST_0 = 11; // -
+ int FCONST_1 = 12; // -
+ int FCONST_2 = 13; // -
+ int DCONST_0 = 14; // -
+ int DCONST_1 = 15; // -
+ int BIPUSH = 16; // visitIntInsn
+ int SIPUSH = 17; // -
+ int LDC = 18; // visitLdcInsn
+ // int LDC_W = 19; // -
+ // int LDC2_W = 20; // -
+ int ILOAD = 21; // visitVarInsn
+ int LLOAD = 22; // -
+ int FLOAD = 23; // -
+ int DLOAD = 24; // -
+ int ALOAD = 25; // -
+ // int ILOAD_0 = 26; // -
+ // int ILOAD_1 = 27; // -
+ // int ILOAD_2 = 28; // -
+ // int ILOAD_3 = 29; // -
+ // int LLOAD_0 = 30; // -
+ // int LLOAD_1 = 31; // -
+ // int LLOAD_2 = 32; // -
+ // int LLOAD_3 = 33; // -
+ // int FLOAD_0 = 34; // -
+ // int FLOAD_1 = 35; // -
+ // int FLOAD_2 = 36; // -
+ // int FLOAD_3 = 37; // -
+ // int DLOAD_0 = 38; // -
+ // int DLOAD_1 = 39; // -
+ // int DLOAD_2 = 40; // -
+ // int DLOAD_3 = 41; // -
+ // int ALOAD_0 = 42; // -
+ // int ALOAD_1 = 43; // -
+ // int ALOAD_2 = 44; // -
+ // int ALOAD_3 = 45; // -
+ int IALOAD = 46; // visitInsn
+ int LALOAD = 47; // -
+ int FALOAD = 48; // -
+ int DALOAD = 49; // -
+ int AALOAD = 50; // -
+ int BALOAD = 51; // -
+ int CALOAD = 52; // -
+ int SALOAD = 53; // -
+ int ISTORE = 54; // visitVarInsn
+ int LSTORE = 55; // -
+ int FSTORE = 56; // -
+ int DSTORE = 57; // -
+ int ASTORE = 58; // -
+ // int ISTORE_0 = 59; // -
+ // int ISTORE_1 = 60; // -
+ // int ISTORE_2 = 61; // -
+ // int ISTORE_3 = 62; // -
+ // int LSTORE_0 = 63; // -
+ // int LSTORE_1 = 64; // -
+ // int LSTORE_2 = 65; // -
+ // int LSTORE_3 = 66; // -
+ // int FSTORE_0 = 67; // -
+ // int FSTORE_1 = 68; // -
+ // int FSTORE_2 = 69; // -
+ // int FSTORE_3 = 70; // -
+ // int DSTORE_0 = 71; // -
+ // int DSTORE_1 = 72; // -
+ // int DSTORE_2 = 73; // -
+ // int DSTORE_3 = 74; // -
+ // int ASTORE_0 = 75; // -
+ // int ASTORE_1 = 76; // -
+ // int ASTORE_2 = 77; // -
+ // int ASTORE_3 = 78; // -
+ int IASTORE = 79; // visitInsn
+ int LASTORE = 80; // -
+ int FASTORE = 81; // -
+ int DASTORE = 82; // -
+ int AASTORE = 83; // -
+ int BASTORE = 84; // -
+ int CASTORE = 85; // -
+ int SASTORE = 86; // -
+ int POP = 87; // -
+ int POP2 = 88; // -
+ int DUP = 89; // -
+ int DUP_X1 = 90; // -
+ int DUP_X2 = 91; // -
+ int DUP2 = 92; // -
+ int DUP2_X1 = 93; // -
+ int DUP2_X2 = 94; // -
+ int SWAP = 95; // -
+ int IADD = 96; // -
+ int LADD = 97; // -
+ int FADD = 98; // -
+ int DADD = 99; // -
+ int ISUB = 100; // -
+ int LSUB = 101; // -
+ int FSUB = 102; // -
+ int DSUB = 103; // -
+ int IMUL = 104; // -
+ int LMUL = 105; // -
+ int FMUL = 106; // -
+ int DMUL = 107; // -
+ int IDIV = 108; // -
+ int LDIV = 109; // -
+ int FDIV = 110; // -
+ int DDIV = 111; // -
+ int IREM = 112; // -
+ int LREM = 113; // -
+ int FREM = 114; // -
+ int DREM = 115; // -
+ int INEG = 116; // -
+ int LNEG = 117; // -
+ int FNEG = 118; // -
+ int DNEG = 119; // -
+ int ISHL = 120; // -
+ int LSHL = 121; // -
+ int ISHR = 122; // -
+ int LSHR = 123; // -
+ int IUSHR = 124; // -
+ int LUSHR = 125; // -
+ int IAND = 126; // -
+ int LAND = 127; // -
+ int IOR = 128; // -
+ int LOR = 129; // -
+ int IXOR = 130; // -
+ int LXOR = 131; // -
+ int IINC = 132; // visitIincInsn
+ int I2L = 133; // visitInsn
+ int I2F = 134; // -
+ int I2D = 135; // -
+ int L2I = 136; // -
+ int L2F = 137; // -
+ int L2D = 138; // -
+ int F2I = 139; // -
+ int F2L = 140; // -
+ int F2D = 141; // -
+ int D2I = 142; // -
+ int D2L = 143; // -
+ int D2F = 144; // -
+ int I2B = 145; // -
+ int I2C = 146; // -
+ int I2S = 147; // -
+ int LCMP = 148; // -
+ int FCMPL = 149; // -
+ int FCMPG = 150; // -
+ int DCMPL = 151; // -
+ int DCMPG = 152; // -
+ int IFEQ = 153; // visitJumpInsn
+ int IFNE = 154; // -
+ int IFLT = 155; // -
+ int IFGE = 156; // -
+ int IFGT = 157; // -
+ int IFLE = 158; // -
+ int IF_ICMPEQ = 159; // -
+ int IF_ICMPNE = 160; // -
+ int IF_ICMPLT = 161; // -
+ int IF_ICMPGE = 162; // -
+ int IF_ICMPGT = 163; // -
+ int IF_ICMPLE = 164; // -
+ int IF_ACMPEQ = 165; // -
+ int IF_ACMPNE = 166; // -
+ int GOTO = 167; // -
+ int JSR = 168; // -
+ int RET = 169; // visitVarInsn
+ int TABLESWITCH = 170; // visiTableSwitchInsn
+ int LOOKUPSWITCH = 171; // visitLookupSwitch
+ int IRETURN = 172; // visitInsn
+ int LRETURN = 173; // -
+ int FRETURN = 174; // -
+ int DRETURN = 175; // -
+ int ARETURN = 176; // -
+ int RETURN = 177; // -
+ int GETSTATIC = 178; // visitFieldInsn
+ int PUTSTATIC = 179; // -
+ int GETFIELD = 180; // -
+ int PUTFIELD = 181; // -
+ int INVOKEVIRTUAL = 182; // visitMethodInsn
+ int INVOKESPECIAL = 183; // -
+ int INVOKESTATIC = 184; // -
+ int INVOKEINTERFACE = 185; // -
+ int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
+ int NEW = 187; // visitTypeInsn
+ int NEWARRAY = 188; // visitIntInsn
+ int ANEWARRAY = 189; // visitTypeInsn
+ int ARRAYLENGTH = 190; // visitInsn
+ int ATHROW = 191; // -
+ int CHECKCAST = 192; // visitTypeInsn
+ int INSTANCEOF = 193; // -
+ int MONITORENTER = 194; // visitInsn
+ int MONITOREXIT = 195; // -
+ // int WIDE = 196; // NOT VISITED
+ int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
+ int IFNULL = 198; // visitJumpInsn
+ int IFNONNULL = 199; // -
+ // int GOTO_W = 200; // -
+ // int JSR_W = 201; // -
+}
diff --git a/src/compiler/scala/tools/asm/Type.java b/src/compiler/scala/tools/asm/Type.java
new file mode 100644
index 0000000000..bf1107182a
--- /dev/null
+++ b/src/compiler/scala/tools/asm/Type.java
@@ -0,0 +1,865 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * A Java field or method type. This class can be used to make it easier to
+ * manipulate type and method descriptors.
+ *
+ * @author Eric Bruneton
+ * @author Chris Nokleberg
+ */
+public class Type {
+
+ /**
+ * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int VOID = 0;
+
+ /**
+ * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int BOOLEAN = 1;
+
+ /**
+ * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int CHAR = 2;
+
+ /**
+ * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int BYTE = 3;
+
+ /**
+ * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int SHORT = 4;
+
+ /**
+ * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int INT = 5;
+
+ /**
+ * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int FLOAT = 6;
+
+ /**
+ * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int LONG = 7;
+
+ /**
+ * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int DOUBLE = 8;
+
+ /**
+ * The sort of array reference types. See {@link #getSort getSort}.
+ */
+ public static final int ARRAY = 9;
+
+ /**
+ * The sort of object reference types. See {@link #getSort getSort}.
+ */
+ public static final int OBJECT = 10;
+
+ /**
+ * The sort of method types. See {@link #getSort getSort}.
+ */
+ public static final int METHOD = 11;
+
+ /**
+ * The <tt>void</tt> type.
+ */
+ public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)
+ | (5 << 16) | (0 << 8) | 0, 1);
+
+ /**
+ * The <tt>boolean</tt> type.
+ */
+ public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24)
+ | (0 << 16) | (5 << 8) | 1, 1);
+
+ /**
+ * The <tt>char</tt> type.
+ */
+ public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24)
+ | (0 << 16) | (6 << 8) | 1, 1);
+
+ /**
+ * The <tt>byte</tt> type.
+ */
+ public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24)
+ | (0 << 16) | (5 << 8) | 1, 1);
+
+ /**
+ * The <tt>short</tt> type.
+ */
+ public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24)
+ | (0 << 16) | (7 << 8) | 1, 1);
+
+ /**
+ * The <tt>int</tt> type.
+ */
+ public static final Type INT_TYPE = new Type(INT, null, ('I' << 24)
+ | (0 << 16) | (0 << 8) | 1, 1);
+
+ /**
+ * The <tt>float</tt> type.
+ */
+ public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24)
+ | (2 << 16) | (2 << 8) | 1, 1);
+
+ /**
+ * The <tt>long</tt> type.
+ */
+ public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24)
+ | (1 << 16) | (1 << 8) | 2, 1);
+
+ /**
+ * The <tt>double</tt> type.
+ */
+ public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24)
+ | (3 << 16) | (3 << 8) | 2, 1);
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * The sort of this Java type.
+ */
+ private final int sort;
+
+ /**
+ * A buffer containing the internal name of this Java type. This field is
+ * only used for reference types.
+ */
+ private final char[] buf;
+
+ /**
+ * The offset of the internal name of this Java type in {@link #buf buf} or,
+ * for primitive types, the size, descriptor and getOpcode offsets for this
+ * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset
+ * for IALOAD or IASTORE, byte 3 the offset for all other instructions).
+ */
+ private final int off;
+
+ /**
+ * The length of the internal name of this Java type.
+ */
+ private final int len;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a reference type.
+ *
+ * @param sort the sort of the reference type to be constructed.
+ * @param buf a buffer containing the descriptor of the previous type.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @param len the length of this descriptor.
+ */
+ private Type(final int sort, final char[] buf, final int off, final int len)
+ {
+ this.sort = sort;
+ this.buf = buf;
+ this.off = off;
+ this.len = len;
+ }
+
+ /**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param typeDescriptor a field or method type descriptor.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+ public static Type getType(final String typeDescriptor) {
+ return getType(typeDescriptor.toCharArray(), 0);
+ }
+
+ /**
+ * Returns the Java type corresponding to the given internal name.
+ *
+ * @param internalName an internal name.
+ * @return the Java type corresponding to the given internal name.
+ */
+ public static Type getObjectType(final String internalName) {
+ char[] buf = internalName.toCharArray();
+ return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
+ }
+
+ /**
+ * Returns the Java type corresponding to the given method descriptor.
+ * Equivalent to <code>Type.getType(methodDescriptor)</code>.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java type corresponding to the given method descriptor.
+ */
+ public static Type getMethodType(final String methodDescriptor) {
+ return getType(methodDescriptor.toCharArray(), 0);
+ }
+
+ /**
+ * Returns the Java method type corresponding to the given argument and
+ * return types.
+ *
+ * @param returnType the return type of the method.
+ * @param argumentTypes the argument types of the method.
+ * @return the Java type corresponding to the given argument and return types.
+ */
+ public static Type getMethodType(final Type returnType, final Type... argumentTypes) {
+ return getType(getMethodDescriptor(returnType, argumentTypes));
+ }
+
+ /**
+ * Returns the Java type corresponding to the given class.
+ *
+ * @param c a class.
+ * @return the Java type corresponding to the given class.
+ */
+ public static Type getType(final Class<?> c) {
+ if (c.isPrimitive()) {
+ if (c == Integer.TYPE) {
+ return INT_TYPE;
+ } else if (c == Void.TYPE) {
+ return VOID_TYPE;
+ } else if (c == Boolean.TYPE) {
+ return BOOLEAN_TYPE;
+ } else if (c == Byte.TYPE) {
+ return BYTE_TYPE;
+ } else if (c == Character.TYPE) {
+ return CHAR_TYPE;
+ } else if (c == Short.TYPE) {
+ return SHORT_TYPE;
+ } else if (c == Double.TYPE) {
+ return DOUBLE_TYPE;
+ } else if (c == Float.TYPE) {
+ return FLOAT_TYPE;
+ } else /* if (c == Long.TYPE) */{
+ return LONG_TYPE;
+ }
+ } else {
+ return getType(getDescriptor(c));
+ }
+ }
+
+ /**
+ * Returns the Java method type corresponding to the given constructor.
+ *
+ * @param c a {@link Constructor Constructor} object.
+ * @return the Java method type corresponding to the given constructor.
+ */
+ public static Type getType(final Constructor<?> c) {
+ return getType(getConstructorDescriptor(c));
+ }
+
+ /**
+ * Returns the Java method type corresponding to the given method.
+ *
+ * @param m a {@link Method Method} object.
+ * @return the Java method type corresponding to the given method.
+ */
+ public static Type getType(final Method m) {
+ return getType(getMethodDescriptor(m));
+ }
+
+ /**
+ * Returns the Java types corresponding to the argument types of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java types corresponding to the argument types of the given
+ * method descriptor.
+ */
+ public static Type[] getArgumentTypes(final String methodDescriptor) {
+ char[] buf = methodDescriptor.toCharArray();
+ int off = 1;
+ int size = 0;
+ while (true) {
+ char car = buf[off++];
+ if (car == ')') {
+ break;
+ } else if (car == 'L') {
+ while (buf[off++] != ';') {
+ }
+ ++size;
+ } else if (car != '[') {
+ ++size;
+ }
+ }
+ Type[] args = new Type[size];
+ off = 1;
+ size = 0;
+ while (buf[off] != ')') {
+ args[size] = getType(buf, off);
+ off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
+ size += 1;
+ }
+ return args;
+ }
+
+ /**
+ * Returns the Java types corresponding to the argument types of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java types corresponding to the argument types of the given
+ * method.
+ */
+ public static Type[] getArgumentTypes(final Method method) {
+ Class<?>[] classes = method.getParameterTypes();
+ Type[] types = new Type[classes.length];
+ for (int i = classes.length - 1; i >= 0; --i) {
+ types[i] = getType(classes[i]);
+ }
+ return types;
+ }
+
+ /**
+ * Returns the Java type corresponding to the return type of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java type corresponding to the return type of the given
+ * method descriptor.
+ */
+ public static Type getReturnType(final String methodDescriptor) {
+ char[] buf = methodDescriptor.toCharArray();
+ return getType(buf, methodDescriptor.indexOf(')') + 1);
+ }
+
+ /**
+ * Returns the Java type corresponding to the return type of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java type corresponding to the return type of the given
+ * method.
+ */
+ public static Type getReturnType(final Method method) {
+ return getType(method.getReturnType());
+ }
+
+ /**
+ * Computes the size of the arguments and of the return value of a method.
+ *
+ * @param desc the descriptor of a method.
+ * @return the size of the arguments of the method (plus one for the
+ * implicit this argument), argSize, and the size of its return
+ * value, retSize, packed into a single int i =
+ * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
+ * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
+ */
+ public static int getArgumentsAndReturnSizes(final String desc) {
+ int n = 1;
+ int c = 1;
+ while (true) {
+ char car = desc.charAt(c++);
+ if (car == ')') {
+ car = desc.charAt(c);
+ return n << 2
+ | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
+ } else if (car == 'L') {
+ while (desc.charAt(c++) != ';') {
+ }
+ n += 1;
+ } else if (car == '[') {
+ while ((car = desc.charAt(c)) == '[') {
+ ++c;
+ }
+ if (car == 'D' || car == 'J') {
+ n -= 1;
+ }
+ } else if (car == 'D' || car == 'J') {
+ n += 2;
+ } else {
+ n += 1;
+ }
+ }
+ }
+
+ /**
+ * Returns the Java type corresponding to the given type descriptor. For
+ * method descriptors, buf is supposed to contain nothing more than the
+ * descriptor itself.
+ *
+ * @param buf a buffer containing a type descriptor.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+ private static Type getType(final char[] buf, final int off) {
+ int len;
+ switch (buf[off]) {
+ case 'V':
+ return VOID_TYPE;
+ case 'Z':
+ return BOOLEAN_TYPE;
+ case 'C':
+ return CHAR_TYPE;
+ case 'B':
+ return BYTE_TYPE;
+ case 'S':
+ return SHORT_TYPE;
+ case 'I':
+ return INT_TYPE;
+ case 'F':
+ return FLOAT_TYPE;
+ case 'J':
+ return LONG_TYPE;
+ case 'D':
+ return DOUBLE_TYPE;
+ case '[':
+ len = 1;
+ while (buf[off + len] == '[') {
+ ++len;
+ }
+ if (buf[off + len] == 'L') {
+ ++len;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ }
+ return new Type(ARRAY, buf, off, len + 1);
+ case 'L':
+ len = 1;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ return new Type(OBJECT, buf, off + 1, len - 1);
+ // case '(':
+ default:
+ return new Type(METHOD, buf, 0, buf.length);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the sort of this Java type.
+ *
+ * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
+ * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
+ * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
+ * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY},
+ * {@link #OBJECT OBJECT} or {@link #METHOD METHOD}.
+ */
+ public int getSort() {
+ return sort;
+ }
+
+ /**
+ * Returns the number of dimensions of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return the number of dimensions of this array type.
+ */
+ public int getDimensions() {
+ int i = 1;
+ while (buf[off + i] == '[') {
+ ++i;
+ }
+ return i;
+ }
+
+ /**
+ * Returns the type of the elements of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return Returns the type of the elements of this array type.
+ */
+ public Type getElementType() {
+ return getType(buf, off + getDimensions());
+ }
+
+ /**
+ * Returns the binary name of the class corresponding to this type. This
+ * method must not be used on method types.
+ *
+ * @return the binary name of the class corresponding to this type.
+ */
+ public String getClassName() {
+ switch (sort) {
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuffer b = new StringBuffer(getElementType().getClassName());
+ for (int i = getDimensions(); i > 0; --i) {
+ b.append("[]");
+ }
+ return b.toString();
+ case OBJECT:
+ return new String(buf, off, len).replace('/', '.');
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the internal name of the class corresponding to this object or
+ * array type. The internal name of a class is its fully qualified name (as
+ * returned by Class.getName(), where '.' are replaced by '/'. This method
+ * should only be used for an object or array type.
+ *
+ * @return the internal name of the class corresponding to this object type.
+ */
+ public String getInternalName() {
+ return new String(buf, off, len);
+ }
+
+ /**
+ * Returns the argument types of methods of this type. This method should
+ * only be used for method types.
+ *
+ * @return the argument types of methods of this type.
+ */
+ public Type[] getArgumentTypes() {
+ return getArgumentTypes(getDescriptor());
+ }
+
+ /**
+ * Returns the return type of methods of this type. This method should only
+ * be used for method types.
+ *
+ * @return the return type of methods of this type.
+ */
+ public Type getReturnType() {
+ return getReturnType(getDescriptor());
+ }
+
+ /**
+ * Returns the size of the arguments and of the return value of methods of
+ * this type. This method should only be used for method types.
+ *
+ * @return the size of the arguments (plus one for the implicit this
+ * argument), argSize, and the size of the return value, retSize,
+ * packed into a single int i = <tt>(argSize << 2) | retSize</tt>
+ * (argSize is therefore equal to <tt>i >> 2</tt>, and retSize to
+ * <tt>i & 0x03</tt>).
+ */
+ public int getArgumentsAndReturnSizes() {
+ return getArgumentsAndReturnSizes(getDescriptor());
+ }
+
+ // ------------------------------------------------------------------------
+ // Conversion to type descriptors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the descriptor corresponding to this Java type.
+ *
+ * @return the descriptor corresponding to this Java type.
+ */
+ public String getDescriptor() {
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given argument and return
+ * types.
+ *
+ * @param returnType the return type of the method.
+ * @param argumentTypes the argument types of the method.
+ * @return the descriptor corresponding to the given argument and return
+ * types.
+ */
+ public static String getMethodDescriptor(
+ final Type returnType,
+ final Type... argumentTypes)
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < argumentTypes.length; ++i) {
+ argumentTypes[i].getDescriptor(buf);
+ }
+ buf.append(')');
+ returnType.getDescriptor(buf);
+ return buf.toString();
+ }
+
+ /**
+ * Appends the descriptor corresponding to this Java type to the given
+ * string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ */
+ private void getDescriptor(final StringBuffer buf) {
+ if (this.buf == null) {
+ // descriptor is in byte 3 of 'off' for primitive types (buf == null)
+ buf.append((char) ((off & 0xFF000000) >>> 24));
+ } else if (sort == OBJECT) {
+ buf.append('L');
+ buf.append(this.buf, off, len);
+ buf.append(';');
+ } else { // sort == ARRAY || sort == METHOD
+ buf.append(this.buf, off, len);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Direct conversion from classes to type descriptors,
+ // without intermediate Type objects
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the internal name of the given class. The internal name of a
+ * class is its fully qualified name, as returned by Class.getName(), where
+ * '.' are replaced by '/'.
+ *
+ * @param c an object or array class.
+ * @return the internal name of the given class.
+ */
+ public static String getInternalName(final Class<?> c) {
+ return c.getName().replace('.', '/');
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given Java type.
+ *
+ * @param c an object class, a primitive class or an array class.
+ * @return the descriptor corresponding to the given class.
+ */
+ public static String getDescriptor(final Class<?> c) {
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf, c);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given constructor.
+ *
+ * @param c a {@link Constructor Constructor} object.
+ * @return the descriptor of the given constructor.
+ */
+ public static String getConstructorDescriptor(final Constructor<?> c) {
+ Class<?>[] parameters = c.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < parameters.length; ++i) {
+ getDescriptor(buf, parameters[i]);
+ }
+ return buf.append(")V").toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given method.
+ *
+ * @param m a {@link Method Method} object.
+ * @return the descriptor of the given method.
+ */
+ public static String getMethodDescriptor(final Method m) {
+ Class<?>[] parameters = m.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < parameters.length; ++i) {
+ getDescriptor(buf, parameters[i]);
+ }
+ buf.append(')');
+ getDescriptor(buf, m.getReturnType());
+ return buf.toString();
+ }
+
+ /**
+ * Appends the descriptor of the given class to the given string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ * @param c the class whose descriptor must be computed.
+ */
+ private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
+ Class<?> d = c;
+ while (true) {
+ if (d.isPrimitive()) {
+ char car;
+ if (d == Integer.TYPE) {
+ car = 'I';
+ } else if (d == Void.TYPE) {
+ car = 'V';
+ } else if (d == Boolean.TYPE) {
+ car = 'Z';
+ } else if (d == Byte.TYPE) {
+ car = 'B';
+ } else if (d == Character.TYPE) {
+ car = 'C';
+ } else if (d == Short.TYPE) {
+ car = 'S';
+ } else if (d == Double.TYPE) {
+ car = 'D';
+ } else if (d == Float.TYPE) {
+ car = 'F';
+ } else /* if (d == Long.TYPE) */{
+ car = 'J';
+ }
+ buf.append(car);
+ return;
+ } else if (d.isArray()) {
+ buf.append('[');
+ d = d.getComponentType();
+ } else {
+ buf.append('L');
+ String name = d.getName();
+ int len = name.length();
+ for (int i = 0; i < len; ++i) {
+ char car = name.charAt(i);
+ buf.append(car == '.' ? '/' : car);
+ }
+ buf.append(';');
+ return;
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Corresponding size and opcodes
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of values of this type. This method must not be used for
+ * method types.
+ *
+ * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
+ * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
+ */
+ public int getSize() {
+ // the size is in byte 0 of 'off' for primitive types (buf == null)
+ return buf == null ? (off & 0xFF) : 1;
+ }
+
+ /**
+ * Returns a JVM instruction opcode adapted to this Java type. This method
+ * must not be used for method types.
+ *
+ * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
+ * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
+ * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+ * @return an opcode that is similar to the given opcode, but adapted to
+ * this Java type. For example, if this type is <tt>float</tt> and
+ * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
+ */
+ public int getOpcode(final int opcode) {
+ if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
+ // the offset for IALOAD or IASTORE is in byte 1 of 'off' for
+ // primitive types (buf == null)
+ return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);
+ } else {
+ // the offset for other instructions is in byte 2 of 'off' for
+ // primitive types (buf == null)
+ return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Equals, hashCode and toString
+ // ------------------------------------------------------------------------
+
+ /**
+ * Tests if the given object is equal to this type.
+ *
+ * @param o the object to be compared to this type.
+ * @return <tt>true</tt> if the given object is equal to this type.
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Type)) {
+ return false;
+ }
+ Type t = (Type) o;
+ if (sort != t.sort) {
+ return false;
+ }
+ if (sort >= ARRAY) {
+ if (len != t.len) {
+ return false;
+ }
+ for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
+ if (buf[i] != t.buf[j]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns a hash code value for this type.
+ *
+ * @return a hash code value for this type.
+ */
+ @Override
+ public int hashCode() {
+ int hc = 13 * sort;
+ if (sort >= ARRAY) {
+ for (int i = off, end = i + len; i < end; i++) {
+ hc = 17 * (hc + buf[i]);
+ }
+ }
+ return hc;
+ }
+
+ /**
+ * Returns a string representation of this type.
+ *
+ * @return the descriptor of this type.
+ */
+ @Override
+ public String toString() {
+ return getDescriptor();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/signature/SignatureReader.java b/src/compiler/scala/tools/asm/signature/SignatureReader.java
new file mode 100644
index 0000000000..22e6427e63
--- /dev/null
+++ b/src/compiler/scala/tools/asm/signature/SignatureReader.java
@@ -0,0 +1,229 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.signature;
+
+/**
+ * A type signature parser to make a signature visitor visit an existing
+ * signature.
+ *
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureReader {
+
+ /**
+ * The signature to be read.
+ */
+ private final String signature;
+
+ /**
+ * Constructs a {@link SignatureReader} for the given signature.
+ *
+ * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
+ * or <i>FieldTypeSignature</i>.
+ */
+ public SignatureReader(final String signature) {
+ this.signature = signature;
+ }
+
+ /**
+ * Makes the given visitor visit the signature of this
+ * {@link SignatureReader}. This signature is the one specified in the
+ * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+ * method is intended to be called on a {@link SignatureReader} that was
+ * created using a <i>ClassSignature</i> (such as the
+ * <code>signature</code> parameter of the
+ * {@link org.objectweb.asm.ClassVisitor#visit ClassVisitor.visit} method)
+ * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
+ * parameter of the
+ * {@link org.objectweb.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
+ * method).
+ *
+ * @param v the visitor that must visit this signature.
+ */
+ public void accept(final SignatureVisitor v) {
+ String signature = this.signature;
+ int len = signature.length();
+ int pos;
+ char c;
+
+ if (signature.charAt(0) == '<') {
+ pos = 2;
+ do {
+ int end = signature.indexOf(':', pos);
+ v.visitFormalTypeParameter(signature.substring(pos - 1, end));
+ pos = end + 1;
+
+ c = signature.charAt(pos);
+ if (c == 'L' || c == '[' || c == 'T') {
+ pos = parseType(signature, pos, v.visitClassBound());
+ }
+
+ while ((c = signature.charAt(pos++)) == ':') {
+ pos = parseType(signature, pos, v.visitInterfaceBound());
+ }
+ } while (c != '>');
+ } else {
+ pos = 0;
+ }
+
+ if (signature.charAt(pos) == '(') {
+ pos++;
+ while (signature.charAt(pos) != ')') {
+ pos = parseType(signature, pos, v.visitParameterType());
+ }
+ pos = parseType(signature, pos + 1, v.visitReturnType());
+ while (pos < len) {
+ pos = parseType(signature, pos + 1, v.visitExceptionType());
+ }
+ } else {
+ pos = parseType(signature, pos, v.visitSuperclass());
+ while (pos < len) {
+ pos = parseType(signature, pos, v.visitInterface());
+ }
+ }
+ }
+
+ /**
+ * Makes the given visitor visit the signature of this
+ * {@link SignatureReader}. This signature is the one specified in the
+ * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+ * method is intended to be called on a {@link SignatureReader} that was
+ * created using a <i>FieldTypeSignature</i>, such as the
+ * <code>signature</code> parameter of the
+ * {@link org.objectweb.asm.ClassVisitor#visitField
+ * ClassVisitor.visitField} or {@link
+ * org.objectweb.asm.MethodVisitor#visitLocalVariable
+ * MethodVisitor.visitLocalVariable} methods.
+ *
+ * @param v the visitor that must visit this signature.
+ */
+ public void acceptType(final SignatureVisitor v) {
+ parseType(this.signature, 0, v);
+ }
+
+ /**
+ * Parses a field type signature and makes the given visitor visit it.
+ *
+ * @param signature a string containing the signature that must be parsed.
+ * @param pos index of the first character of the signature to parsed.
+ * @param v the visitor that must visit this signature.
+ * @return the index of the first character after the parsed signature.
+ */
+ private static int parseType(
+ final String signature,
+ int pos,
+ final SignatureVisitor v)
+ {
+ char c;
+ int start, end;
+ boolean visited, inner;
+ String name;
+
+ switch (c = signature.charAt(pos++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ case 'V':
+ v.visitBaseType(c);
+ return pos;
+
+ case '[':
+ return parseType(signature, pos, v.visitArrayType());
+
+ case 'T':
+ end = signature.indexOf(';', pos);
+ v.visitTypeVariable(signature.substring(pos, end));
+ return end + 1;
+
+ default: // case 'L':
+ start = pos;
+ visited = false;
+ inner = false;
+ for (;;) {
+ switch (c = signature.charAt(pos++)) {
+ case '.':
+ case ';':
+ if (!visited) {
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ }
+ if (c == ';') {
+ v.visitEnd();
+ return pos;
+ }
+ start = pos;
+ visited = false;
+ inner = true;
+ break;
+
+ case '<':
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ visited = true;
+ top: for (;;) {
+ switch (c = signature.charAt(pos)) {
+ case '>':
+ break top;
+ case '*':
+ ++pos;
+ v.visitTypeArgument();
+ break;
+ case '+':
+ case '-':
+ pos = parseType(signature,
+ pos + 1,
+ v.visitTypeArgument(c));
+ break;
+ default:
+ pos = parseType(signature,
+ pos,
+ v.visitTypeArgument('='));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/signature/SignatureVisitor.java b/src/compiler/scala/tools/asm/signature/SignatureVisitor.java
new file mode 100644
index 0000000000..2fc364e374
--- /dev/null
+++ b/src/compiler/scala/tools/asm/signature/SignatureVisitor.java
@@ -0,0 +1,228 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.signature;
+
+import scala.tools.asm.Opcodes;
+
+/**
+ * A visitor to visit a generic signature. The methods of this interface must be
+ * called in one of the three following orders (the last one is the only valid
+ * order for a {@link SignatureVisitor} that is returned by a method of this
+ * interface): <ul> <li><i>ClassSignature</i> = (
+ * <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>?
+ * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt>
+ * <tt>visitInterface</tt>* )</li>
+ * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>?
+ * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*
+ * <tt>visitReturnType</tt>
+ * <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =
+ * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |
+ * <tt>visitArrayType</tt> | (
+ * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*
+ * <tt>visitEnd</tt> ) )</li> </ul>
+ *
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public abstract class SignatureVisitor {
+
+ /**
+ * Wildcard for an "extends" type argument.
+ */
+ public final static char EXTENDS = '+';
+
+ /**
+ * Wildcard for a "super" type argument.
+ */
+ public final static char SUPER = '-';
+
+ /**
+ * Wildcard for a normal type argument.
+ */
+ public final static char INSTANCEOF = '=';
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4}.
+ */
+ protected final int api;
+
+ /**
+ * Constructs a new {@link SignatureVisitor}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ public SignatureVisitor(final int api) {
+ this.api = api;
+ }
+
+ /**
+ * Visits a formal type parameter.
+ *
+ * @param name the name of the formal parameter.
+ */
+ public void visitFormalTypeParameter(String name) {
+ }
+
+ /**
+ * Visits the class bound of the last visited formal type parameter.
+ *
+ * @return a non null visitor to visit the signature of the class bound.
+ */
+ public SignatureVisitor visitClassBound() {
+ return this;
+ }
+
+ /**
+ * Visits an interface bound of the last visited formal type parameter.
+ *
+ * @return a non null visitor to visit the signature of the interface bound.
+ */
+ public SignatureVisitor visitInterfaceBound() {
+ return this;
+ }
+
+ /**
+ * Visits the type of the super class.
+ *
+ * @return a non null visitor to visit the signature of the super class
+ * type.
+ */
+ public SignatureVisitor visitSuperclass() {
+ return this;
+ }
+
+ /**
+ * Visits the type of an interface implemented by the class.
+ *
+ * @return a non null visitor to visit the signature of the interface type.
+ */
+ public SignatureVisitor visitInterface() {
+ return this;
+ }
+
+ /**
+ * Visits the type of a method parameter.
+ *
+ * @return a non null visitor to visit the signature of the parameter type.
+ */
+ public SignatureVisitor visitParameterType() {
+ return this;
+ }
+
+ /**
+ * Visits the return type of the method.
+ *
+ * @return a non null visitor to visit the signature of the return type.
+ */
+ public SignatureVisitor visitReturnType() {
+ return this;
+ }
+
+ /**
+ * Visits the type of a method exception.
+ *
+ * @return a non null visitor to visit the signature of the exception type.
+ */
+ public SignatureVisitor visitExceptionType() {
+ return this;
+ }
+
+ /**
+ * Visits a signature corresponding to a primitive type.
+ *
+ * @param descriptor the descriptor of the primitive type, or 'V' for
+ * <tt>void</tt>.
+ */
+ public void visitBaseType(char descriptor) {
+ }
+
+ /**
+ * Visits a signature corresponding to a type variable.
+ *
+ * @param name the name of the type variable.
+ */
+ public void visitTypeVariable(String name) {
+ }
+
+ /**
+ * Visits a signature corresponding to an array type.
+ *
+ * @return a non null visitor to visit the signature of the array element
+ * type.
+ */
+ public SignatureVisitor visitArrayType() {
+ return this;
+ }
+
+ /**
+ * Starts the visit of a signature corresponding to a class or interface
+ * type.
+ *
+ * @param name the internal name of the class or interface.
+ */
+ public void visitClassType(String name) {
+ }
+
+ /**
+ * Visits an inner class.
+ *
+ * @param name the local name of the inner class in its enclosing class.
+ */
+ public void visitInnerClassType(String name) {
+ }
+
+ /**
+ * Visits an unbounded type argument of the last visited class or inner
+ * class type.
+ */
+ public void visitTypeArgument() {
+ }
+
+ /**
+ * Visits a type argument of the last visited class or inner class type.
+ *
+ * @param wildcard '+', '-' or '='.
+ * @return a non null visitor to visit the signature of the type argument.
+ */
+ public SignatureVisitor visitTypeArgument(char wildcard) {
+ return this;
+ }
+
+ /**
+ * Ends the visit of a signature corresponding to a class or interface type.
+ */
+ public void visitEnd() {
+ }
+}
diff --git a/src/compiler/scala/tools/asm/signature/SignatureWriter.java b/src/compiler/scala/tools/asm/signature/SignatureWriter.java
new file mode 100644
index 0000000000..a59fdfde2b
--- /dev/null
+++ b/src/compiler/scala/tools/asm/signature/SignatureWriter.java
@@ -0,0 +1,227 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.signature;
+
+import scala.tools.asm.Opcodes;
+
+/**
+ * A signature visitor that generates signatures in string format.
+ *
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureWriter extends SignatureVisitor {
+
+ /**
+ * Buffer used to construct the signature.
+ */
+ private final StringBuffer buf = new StringBuffer();
+
+ /**
+ * Indicates if the signature contains formal type parameters.
+ */
+ private boolean hasFormals;
+
+ /**
+ * Indicates if the signature contains method parameter types.
+ */
+ private boolean hasParameters;
+
+ /**
+ * Stack used to keep track of class types that have arguments. Each element
+ * of this stack is a boolean encoded in one bit. The top of the stack is
+ * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+ * /2.
+ */
+ private int argumentStack;
+
+ /**
+ * Constructs a new {@link SignatureWriter} object.
+ */
+ public SignatureWriter() {
+ super(Opcodes.ASM4);
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the SignatureVisitor interface
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (!hasFormals) {
+ hasFormals = true;
+ buf.append('<');
+ }
+ buf.append(name);
+ buf.append(':');
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ buf.append(':');
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ endFormals();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ endFormals();
+ if (!hasParameters) {
+ hasParameters = true;
+ buf.append('(');
+ }
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ endFormals();
+ if (!hasParameters) {
+ buf.append('(');
+ }
+ buf.append(')');
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ buf.append('^');
+ return this;
+ }
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ buf.append(descriptor);
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ buf.append('T');
+ buf.append(name);
+ buf.append(';');
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ buf.append('[');
+ return this;
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ buf.append('L');
+ buf.append(name);
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ endArguments();
+ buf.append('.');
+ buf.append(name);
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ buf.append('<');
+ }
+ buf.append('*');
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ buf.append('<');
+ }
+ if (wildcard != '=') {
+ buf.append(wildcard);
+ }
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ endArguments();
+ buf.append(';');
+ }
+
+ /**
+ * Returns the signature that was built by this signature writer.
+ *
+ * @return the signature that was built by this signature writer.
+ */
+ @Override
+ public String toString() {
+ return buf.toString();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Ends the formal type parameters section of the signature.
+ */
+ private void endFormals() {
+ if (hasFormals) {
+ hasFormals = false;
+ buf.append('>');
+ }
+ }
+
+ /**
+ * Ends the type arguments of a class or inner class type.
+ */
+ private void endArguments() {
+ if (argumentStack % 2 != 0) {
+ buf.append('>');
+ }
+ argumentStack /= 2;
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/AbstractInsnNode.java b/src/compiler/scala/tools/asm/tree/AbstractInsnNode.java
new file mode 100644
index 0000000000..471f842ffc
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/AbstractInsnNode.java
@@ -0,0 +1,238 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.List;
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a bytecode instruction. <i>An instruction can appear
+ * at most once in at most one {@link InsnList} at a time</i>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class AbstractInsnNode {
+
+ /**
+ * The type of {@link InsnNode} instructions.
+ */
+ public static final int INSN = 0;
+
+ /**
+ * The type of {@link IntInsnNode} instructions.
+ */
+ public static final int INT_INSN = 1;
+
+ /**
+ * The type of {@link VarInsnNode} instructions.
+ */
+ public static final int VAR_INSN = 2;
+
+ /**
+ * The type of {@link TypeInsnNode} instructions.
+ */
+ public static final int TYPE_INSN = 3;
+
+ /**
+ * The type of {@link FieldInsnNode} instructions.
+ */
+ public static final int FIELD_INSN = 4;
+
+ /**
+ * The type of {@link MethodInsnNode} instructions.
+ */
+ public static final int METHOD_INSN = 5;
+
+ /**
+ * The type of {@link InvokeDynamicInsnNode} instructions.
+ */
+ public static final int INVOKE_DYNAMIC_INSN = 6;
+
+ /**
+ * The type of {@link JumpInsnNode} instructions.
+ */
+ public static final int JUMP_INSN = 7;
+
+ /**
+ * The type of {@link LabelNode} "instructions".
+ */
+ public static final int LABEL = 8;
+
+ /**
+ * The type of {@link LdcInsnNode} instructions.
+ */
+ public static final int LDC_INSN = 9;
+
+ /**
+ * The type of {@link IincInsnNode} instructions.
+ */
+ public static final int IINC_INSN = 10;
+
+ /**
+ * The type of {@link TableSwitchInsnNode} instructions.
+ */
+ public static final int TABLESWITCH_INSN = 11;
+
+ /**
+ * The type of {@link LookupSwitchInsnNode} instructions.
+ */
+ public static final int LOOKUPSWITCH_INSN = 12;
+
+ /**
+ * The type of {@link MultiANewArrayInsnNode} instructions.
+ */
+ public static final int MULTIANEWARRAY_INSN = 13;
+
+ /**
+ * The type of {@link FrameNode} "instructions".
+ */
+ public static final int FRAME = 14;
+
+ /**
+ * The type of {@link LineNumberNode} "instructions".
+ */
+ public static final int LINE = 15;
+
+ /**
+ * The opcode of this instruction.
+ */
+ protected int opcode;
+
+ /**
+ * Previous instruction in the list to which this instruction belongs.
+ */
+ AbstractInsnNode prev;
+
+ /**
+ * Next instruction in the list to which this instruction belongs.
+ */
+ AbstractInsnNode next;
+
+ /**
+ * Index of this instruction in the list to which it belongs. The value of
+ * this field is correct only when {@link InsnList#cache} is not null. A
+ * value of -1 indicates that this instruction does not belong to any
+ * {@link InsnList}.
+ */
+ int index;
+
+ /**
+ * Constructs a new {@link AbstractInsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed.
+ */
+ protected AbstractInsnNode(final int opcode) {
+ this.opcode = opcode;
+ this.index = -1;
+ }
+
+ /**
+ * Returns the opcode of this instruction.
+ *
+ * @return the opcode of this instruction.
+ */
+ public int getOpcode() {
+ return opcode;
+ }
+
+ /**
+ * Returns the type of this instruction.
+ *
+ * @return the type of this instruction, i.e. one the constants defined in
+ * this class.
+ */
+ public abstract int getType();
+
+ /**
+ * Returns the previous instruction in the list to which this instruction
+ * belongs, if any.
+ *
+ * @return the previous instruction in the list to which this instruction
+ * belongs, if any. May be <tt>null</tt>.
+ */
+ public AbstractInsnNode getPrevious() {
+ return prev;
+ }
+
+ /**
+ * Returns the next instruction in the list to which this instruction
+ * belongs, if any.
+ *
+ * @return the next instruction in the list to which this instruction
+ * belongs, if any. May be <tt>null</tt>.
+ */
+ public AbstractInsnNode getNext() {
+ return next;
+ }
+
+ /**
+ * Makes the given code visitor visit this instruction.
+ *
+ * @param cv a code visitor.
+ */
+ public abstract void accept(final MethodVisitor cv);
+
+ /**
+ * Returns a copy of this instruction.
+ *
+ * @param labels a map from LabelNodes to cloned LabelNodes.
+ * @return a copy of this instruction. The returned instruction does not
+ * belong to any {@link InsnList}.
+ */
+ public abstract AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels);
+
+ /**
+ * Returns the clone of the given label.
+ *
+ * @param label a label.
+ * @param map a map from LabelNodes to cloned LabelNodes.
+ * @return the clone of the given label.
+ */
+ static LabelNode clone(final LabelNode label, final Map<LabelNode, LabelNode> map) {
+ return map.get(label);
+ }
+
+ /**
+ * Returns the clones of the given labels.
+ *
+ * @param labels a list of labels.
+ * @param map a map from LabelNodes to cloned LabelNodes.
+ * @return the clones of the given labels.
+ */
+ static LabelNode[] clone(final List<LabelNode> labels, final Map<LabelNode, LabelNode> map) {
+ LabelNode[] clones = new LabelNode[labels.size()];
+ for (int i = 0; i < clones.length; ++i) {
+ clones[i] = map.get(labels.get(i));
+ }
+ return clones;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/AnnotationNode.java b/src/compiler/scala/tools/asm/tree/AnnotationNode.java
new file mode 100644
index 0000000000..9f132550e6
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/AnnotationNode.java
@@ -0,0 +1,224 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents an annotationn.
+ *
+ * @author Eric Bruneton
+ */
+public class AnnotationNode extends AnnotationVisitor {
+
+ /**
+ * The class descriptor of the annotation class.
+ */
+ public String desc;
+
+ /**
+ * The name value pairs of this annotation. Each name value pair is stored
+ * as two consecutive elements in the list. The name is a {@link String},
+ * and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
+ * {@link Short}, {@link Integer}, {@link Long}, {@link Float},
+ * {@link Double}, {@link String} or {@link org.objectweb.asm.Type}, or an
+ * two elements String array (for enumeration values), a
+ * {@link AnnotationNode}, or a {@link List} of values of one of the
+ * preceding types. The list may be <tt>null</tt> if there is no name
+ * value pair.
+ */
+ public List<Object> values;
+
+ /**
+ * Constructs a new {@link AnnotationNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #AnnotationNode(int, String)} version.
+ *
+ * @param desc the class descriptor of the annotation class.
+ */
+ public AnnotationNode(final String desc) {
+ this(Opcodes.ASM4, desc);
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param desc the class descriptor of the annotation class.
+ */
+ public AnnotationNode(final int api, final String desc) {
+ super(api);
+ this.desc = desc;
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode} to visit an array value.
+ *
+ * @param values where the visited values must be stored.
+ */
+ AnnotationNode(final List<Object> values) {
+ super(Opcodes.ASM4);
+ this.values = values;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ values.add(value);
+ }
+
+ @Override
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ values.add(new String[] { desc, value });
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ AnnotationNode annotation = new AnnotationNode(desc);
+ values.add(annotation);
+ return annotation;
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ if (values == null) {
+ values = new ArrayList<Object>(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ List<Object> array = new ArrayList<Object>();
+ values.add(array);
+ return new AnnotationNode(array);
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that this annotation node is compatible with the given ASM API
+ * version. This methods checks that this node, and all its nodes
+ * recursively, do not contain elements that were introduced in more recent
+ * versions of the ASM API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ */
+ public void check(final int api) {
+ // nothing to do
+ }
+
+ /**
+ * Makes the given visitor visit this annotation.
+ *
+ * @param av an annotation visitor. Maybe <tt>null</tt>.
+ */
+ public void accept(final AnnotationVisitor av) {
+ if (av != null) {
+ if (values != null) {
+ for (int i = 0; i < values.size(); i += 2) {
+ String name = (String) values.get(i);
+ Object value = values.get(i + 1);
+ accept(av, name, value);
+ }
+ }
+ av.visitEnd();
+ }
+ }
+
+ /**
+ * Makes the given visitor visit a given annotation value.
+ *
+ * @param av an annotation visitor. Maybe <tt>null</tt>.
+ * @param name the value name.
+ * @param value the actual value.
+ */
+ static void accept(
+ final AnnotationVisitor av,
+ final String name,
+ final Object value)
+ {
+ if (av != null) {
+ if (value instanceof String[]) {
+ String[] typeconst = (String[]) value;
+ av.visitEnum(name, typeconst[0], typeconst[1]);
+ } else if (value instanceof AnnotationNode) {
+ AnnotationNode an = (AnnotationNode) value;
+ an.accept(av.visitAnnotation(name, an.desc));
+ } else if (value instanceof List) {
+ AnnotationVisitor v = av.visitArray(name);
+ List<?> array = (List<?>) value;
+ for (int j = 0; j < array.size(); ++j) {
+ accept(v, null, array.get(j));
+ }
+ v.visitEnd();
+ } else {
+ av.visit(name, value);
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/ClassNode.java b/src/compiler/scala/tools/asm/tree/ClassNode.java
new file mode 100644
index 0000000000..64effae698
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/ClassNode.java
@@ -0,0 +1,371 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.ClassVisitor;
+import scala.tools.asm.FieldVisitor;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents a class.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassNode extends ClassVisitor {
+
+ /**
+ * The class version.
+ */
+ public int version;
+
+ /**
+ * The class's access flags (see {@link org.objectweb.asm.Opcodes}). This
+ * field also indicates if the class is deprecated.
+ */
+ public int access;
+
+ /**
+ * The internal name of the class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ */
+ public String name;
+
+ /**
+ * The signature of the class. Mayt be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The internal of name of the super class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). For
+ * interfaces, the super class is {@link Object}. May be <tt>null</tt>,
+ * but only for the {@link Object} class.
+ */
+ public String superName;
+
+ /**
+ * The internal names of the class's interfaces (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). This
+ * list is a list of {@link String} objects.
+ */
+ public List<String> interfaces;
+
+ /**
+ * The name of the source file from which this class was compiled. May be
+ * <tt>null</tt>.
+ */
+ public String sourceFile;
+
+ /**
+ * Debug information to compute the correspondance between source and
+ * compiled elements of the class. May be <tt>null</tt>.
+ */
+ public String sourceDebug;
+
+ /**
+ * The internal name of the enclosing class of the class. May be
+ * <tt>null</tt>.
+ */
+ public String outerClass;
+
+ /**
+ * The name of the method that contains the class, or <tt>null</tt> if the
+ * class is not enclosed in a method.
+ */
+ public String outerMethod;
+
+ /**
+ * The descriptor of the method that contains the class, or <tt>null</tt>
+ * if the class is not enclosed in a method.
+ */
+ public String outerMethodDesc;
+
+ /**
+ * The runtime visible annotations of this class. This list is a list of
+ * {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label visible
+ */
+ public List<AnnotationNode> visibleAnnotations;
+
+ /**
+ * The runtime invisible annotations of this class. This list is a list of
+ * {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label invisible
+ */
+ public List<AnnotationNode> invisibleAnnotations;
+
+ /**
+ * The non standard attributes of this class. This list is a list of
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
+ */
+ public List<Attribute> attrs;
+
+ /**
+ * Informations about the inner classes of this class. This list is a list
+ * of {@link InnerClassNode} objects.
+ *
+ * @associates org.objectweb.asm.tree.InnerClassNode
+ */
+ public List<InnerClassNode> innerClasses;
+
+ /**
+ * The fields of this class. This list is a list of {@link FieldNode}
+ * objects.
+ *
+ * @associates org.objectweb.asm.tree.FieldNode
+ */
+ public List<FieldNode> fields;
+
+ /**
+ * The methods of this class. This list is a list of {@link MethodNode}
+ * objects.
+ *
+ * @associates org.objectweb.asm.tree.MethodNode
+ */
+ public List<MethodNode> methods;
+
+ /**
+ * Constructs a new {@link ClassNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #ClassNode(int)}
+ * version.
+ */
+ public ClassNode() {
+ this(Opcodes.ASM4);
+ }
+
+ /**
+ * Constructs a new {@link ClassNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ public ClassNode(final int api) {
+ super(api);
+ this.interfaces = new ArrayList<String>();
+ this.innerClasses = new ArrayList<InnerClassNode>();
+ this.fields = new ArrayList<FieldNode>();
+ this.methods = new ArrayList<MethodNode>();
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ this.version = version;
+ this.access = access;
+ this.name = name;
+ this.signature = signature;
+ this.superName = superName;
+ if (interfaces != null) {
+ this.interfaces.addAll(Arrays.asList(interfaces));
+ }
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ sourceFile = file;
+ sourceDebug = debug;
+ }
+
+ @Override
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ outerClass = owner;
+ outerMethod = name;
+ outerMethodDesc = desc;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationNode an = new AnnotationNode(desc);
+ if (visible) {
+ if (visibleAnnotations == null) {
+ visibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ visibleAnnotations.add(an);
+ } else {
+ if (invisibleAnnotations == null) {
+ invisibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ if (attrs == null) {
+ attrs = new ArrayList<Attribute>(1);
+ }
+ attrs.add(attr);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ InnerClassNode icn = new InnerClassNode(name,
+ outerName,
+ innerName,
+ access);
+ innerClasses.add(icn);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ FieldNode fn = new FieldNode(access, name, desc, signature, value);
+ fields.add(fn);
+ return fn;
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ MethodNode mn = new MethodNode(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+ methods.add(mn);
+ return mn;
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept method
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that this class node is compatible with the given ASM API version.
+ * This methods checks that this node, and all its nodes recursively, do not
+ * contain elements that were introduced in more recent versions of the ASM
+ * API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ */
+ public void check(final int api) {
+ // nothing to do
+ }
+
+ /**
+ * Makes the given class visitor visit this class.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ // visits header
+ String[] interfaces = new String[this.interfaces.size()];
+ this.interfaces.toArray(interfaces);
+ cv.visit(version, access, name, signature, superName, interfaces);
+ // visits source
+ if (sourceFile != null || sourceDebug != null) {
+ cv.visitSource(sourceFile, sourceDebug);
+ }
+ // visits outer class
+ if (outerClass != null) {
+ cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
+ }
+ // visits attributes
+ int i, n;
+ n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = visibleAnnotations.get(i);
+ an.accept(cv.visitAnnotation(an.desc, true));
+ }
+ n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = invisibleAnnotations.get(i);
+ an.accept(cv.visitAnnotation(an.desc, false));
+ }
+ n = attrs == null ? 0 : attrs.size();
+ for (i = 0; i < n; ++i) {
+ cv.visitAttribute(attrs.get(i));
+ }
+ // visits inner classes
+ for (i = 0; i < innerClasses.size(); ++i) {
+ innerClasses.get(i).accept(cv);
+ }
+ // visits fields
+ for (i = 0; i < fields.size(); ++i) {
+ fields.get(i).accept(cv);
+ }
+ // visits methods
+ for (i = 0; i < methods.size(); ++i) {
+ methods.get(i).accept(cv);
+ }
+ // visits end
+ cv.visitEnd();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/FieldInsnNode.java b/src/compiler/scala/tools/asm/tree/FieldInsnNode.java
new file mode 100644
index 0000000000..6b7a6a142a
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/FieldInsnNode.java
@@ -0,0 +1,106 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a field instruction. A field instruction is an
+ * instruction that loads or stores the value of a field of an object.
+ *
+ * @author Eric Bruneton
+ */
+public class FieldInsnNode extends AbstractInsnNode {
+
+ /**
+ * The internal name of the field's owner class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ */
+ public String owner;
+
+ /**
+ * The field's name.
+ */
+ public String name;
+
+ /**
+ * The field's descriptor (see {@link org.objectweb.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Constructs a new {@link FieldInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner the internal name of the field's owner class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link org.objectweb.asm.Type}).
+ */
+ public FieldInsnNode(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ super(opcode);
+ this.owner = owner;
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be GETSTATIC,
+ * PUTSTATIC, GETFIELD or PUTFIELD.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ @Override
+ public int getType() {
+ return FIELD_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor cv) {
+ cv.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new FieldInsnNode(opcode, owner, name, desc);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/FieldNode.java b/src/compiler/scala/tools/asm/tree/FieldNode.java
new file mode 100644
index 0000000000..9a1e17033c
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/FieldNode.java
@@ -0,0 +1,243 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.ClassVisitor;
+import scala.tools.asm.FieldVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents a field.
+ *
+ * @author Eric Bruneton
+ */
+public class FieldNode extends FieldVisitor {
+
+ /**
+ * The field's access flags (see {@link org.objectweb.asm.Opcodes}). This
+ * field also indicates if the field is synthetic and/or deprecated.
+ */
+ public int access;
+
+ /**
+ * The field's name.
+ */
+ public String name;
+
+ /**
+ * The field's descriptor (see {@link org.objectweb.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * The field's signature. May be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The field's initial value. This field, which may be <tt>null</tt> if
+ * the field does not have an initial value, must be an {@link Integer}, a
+ * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
+ */
+ public Object value;
+
+ /**
+ * The runtime visible annotations of this field. This list is a list of
+ * {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label visible
+ */
+ public List<AnnotationNode> visibleAnnotations;
+
+ /**
+ * The runtime invisible annotations of this field. This list is a list of
+ * {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label invisible
+ */
+ public List<AnnotationNode> invisibleAnnotations;
+
+ /**
+ * The non standard attributes of this field. This list is a list of
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
+ */
+ public List<Attribute> attrs;
+
+ /**
+ * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #FieldNode(int, int, String, String, String, Object)} version.
+ *
+ * @param access the field's access flags (see
+ * {@link org.objectweb.asm.Opcodes}). This parameter also indicates
+ * if the field is synthetic and/or deprecated.
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link org.objectweb.asm.Type
+ * Type}).
+ * @param signature the field's signature.
+ * @param value the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value, must be
+ * an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
+ */
+ public FieldNode(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ this(Opcodes.ASM4, access, name, desc, signature, value);
+ }
+
+ /**
+ * Constructs a new {@link FieldNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #FieldNode(int, int, String, String, String, Object)} version.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param access the field's access flags (see
+ * {@link org.objectweb.asm.Opcodes}). This parameter also indicates
+ * if the field is synthetic and/or deprecated.
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link org.objectweb.asm.Type
+ * Type}).
+ * @param signature the field's signature.
+ * @param value the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value, must be
+ * an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
+ */
+ public FieldNode(
+ final int api,
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ super(api);
+ this.access = access;
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.value = value;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the FieldVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationNode an = new AnnotationNode(desc);
+ if (visible) {
+ if (visibleAnnotations == null) {
+ visibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ visibleAnnotations.add(an);
+ } else {
+ if (invisibleAnnotations == null) {
+ invisibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ if (attrs == null) {
+ attrs = new ArrayList<Attribute>(1);
+ }
+ attrs.add(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that this field node is compatible with the given ASM API version.
+ * This methods checks that this node, and all its nodes recursively, do not
+ * contain elements that were introduced in more recent versions of the ASM
+ * API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ */
+ public void check(final int api) {
+ // nothing to do
+ }
+
+ /**
+ * Makes the given class visitor visit this field.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
+ if (fv == null) {
+ return;
+ }
+ int i, n;
+ n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = visibleAnnotations.get(i);
+ an.accept(fv.visitAnnotation(an.desc, true));
+ }
+ n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = invisibleAnnotations.get(i);
+ an.accept(fv.visitAnnotation(an.desc, false));
+ }
+ n = attrs == null ? 0 : attrs.size();
+ for (i = 0; i < n; ++i) {
+ fv.visitAttribute(attrs.get(i));
+ }
+ fv.visitEnd();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/FrameNode.java b/src/compiler/scala/tools/asm/tree/FrameNode.java
new file mode 100644
index 0000000000..66825de0ac
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/FrameNode.java
@@ -0,0 +1,211 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents a stack map frame. These nodes are pseudo instruction
+ * nodes in order to be inserted in an instruction list. In fact these nodes
+ * must(*) be inserted <i>just before</i> any instruction node <b>i</b> that
+ * follows an unconditionnal branch instruction such as GOTO or THROW, that is
+ * the target of a jump instruction, or that starts an exception handler block.
+ * The stack map frame types must describe the values of the local variables and
+ * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
+ * <br> (*) this is mandatory only for classes whose version is greater than or
+ * equal to {@link Opcodes#V1_6 V1_6}.
+ *
+ * @author Eric Bruneton
+ */
+public class FrameNode extends AbstractInsnNode {
+
+ /**
+ * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
+ * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
+ */
+ public int type;
+
+ /**
+ * The types of the local variables of this stack map frame. Elements of
+ * this list can be Integer, String or LabelNode objects (for primitive,
+ * reference and uninitialized types respectively - see
+ * {@link MethodVisitor}).
+ */
+ public List<Object> local;
+
+ /**
+ * The types of the operand stack elements of this stack map frame. Elements
+ * of this list can be Integer, String or LabelNode objects (for primitive,
+ * reference and uninitialized types respectively - see
+ * {@link MethodVisitor}).
+ */
+ public List<Object> stack;
+
+ private FrameNode() {
+ super(-1);
+ }
+
+ /**
+ * Constructs a new {@link FrameNode}.
+ *
+ * @param type the type of this frame. Must be {@link Opcodes#F_NEW} for
+ * expanded frames, or {@link Opcodes#F_FULL},
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
+ * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_SAME1} for compressed frames.
+ * @param nLocal number of local variables of this stack map frame.
+ * @param local the types of the local variables of this stack map frame.
+ * Elements of this list can be Integer, String or LabelNode objects
+ * (for primitive, reference and uninitialized types respectively -
+ * see {@link MethodVisitor}).
+ * @param nStack number of operand stack elements of this stack map frame.
+ * @param stack the types of the operand stack elements of this stack map
+ * frame. Elements of this list can be Integer, String or LabelNode
+ * objects (for primitive, reference and uninitialized types
+ * respectively - see {@link MethodVisitor}).
+ */
+ public FrameNode(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ super(-1);
+ this.type = type;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ this.local = asList(nLocal, local);
+ this.stack = asList(nStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ this.local = asList(nLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ this.local = Arrays.asList(new Object[nLocal]);
+ break;
+ case Opcodes.F_SAME:
+ break;
+ case Opcodes.F_SAME1:
+ this.stack = asList(1, stack);
+ break;
+ }
+ }
+
+ @Override
+ public int getType() {
+ return FRAME;
+ }
+
+ /**
+ * Makes the given visitor visit this stack map frame.
+ *
+ * @param mv a method visitor.
+ */
+ @Override
+ public void accept(final MethodVisitor mv) {
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mv.visitFrame(type,
+ local.size(),
+ asArray(local),
+ stack.size(),
+ asArray(stack));
+ break;
+ case Opcodes.F_APPEND:
+ mv.visitFrame(type, local.size(), asArray(local), 0, null);
+ break;
+ case Opcodes.F_CHOP:
+ mv.visitFrame(type, local.size(), null, 0, null);
+ break;
+ case Opcodes.F_SAME:
+ mv.visitFrame(type, 0, null, 0, null);
+ break;
+ case Opcodes.F_SAME1:
+ mv.visitFrame(type, 0, null, 1, asArray(stack));
+ break;
+ }
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ FrameNode clone = new FrameNode();
+ clone.type = type;
+ if (local != null) {
+ clone.local = new ArrayList<Object>();
+ for (int i = 0; i < local.size(); ++i) {
+ Object l = local.get(i);
+ if (l instanceof LabelNode) {
+ l = labels.get(l);
+ }
+ clone.local.add(l);
+ }
+ }
+ if (stack != null) {
+ clone.stack = new ArrayList<Object>();
+ for (int i = 0; i < stack.size(); ++i) {
+ Object s = stack.get(i);
+ if (s instanceof LabelNode) {
+ s = labels.get(s);
+ }
+ clone.stack.add(s);
+ }
+ }
+ return clone;
+ }
+
+ // ------------------------------------------------------------------------
+
+ private static List<Object> asList(final int n, final Object[] o) {
+ return Arrays.asList(o).subList(0, n);
+ }
+
+ private static Object[] asArray(final List<Object> l) {
+ Object[] objs = new Object[l.size()];
+ for (int i = 0; i < objs.length; ++i) {
+ Object o = l.get(i);
+ if (o instanceof LabelNode) {
+ o = ((LabelNode) o).getLabel();
+ }
+ objs[i] = o;
+ }
+ return objs;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/IincInsnNode.java b/src/compiler/scala/tools/asm/tree/IincInsnNode.java
new file mode 100644
index 0000000000..75ac40884d
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/IincInsnNode.java
@@ -0,0 +1,80 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents an IINC instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class IincInsnNode extends AbstractInsnNode {
+
+ /**
+ * Index of the local variable to be incremented.
+ */
+ public int var;
+
+ /**
+ * Amount to increment the local variable by.
+ */
+ public int incr;
+
+ /**
+ * Constructs a new {@link IincInsnNode}.
+ *
+ * @param var index of the local variable to be incremented.
+ * @param incr increment amount to increment the local variable by.
+ */
+ public IincInsnNode(final int var, final int incr) {
+ super(Opcodes.IINC);
+ this.var = var;
+ this.incr = incr;
+ }
+
+ @Override
+ public int getType() {
+ return IINC_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitIincInsn(var, incr);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new IincInsnNode(var, incr);
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/InnerClassNode.java b/src/compiler/scala/tools/asm/tree/InnerClassNode.java
new file mode 100644
index 0000000000..4579488921
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/InnerClassNode.java
@@ -0,0 +1,101 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import scala.tools.asm.ClassVisitor;
+
+/**
+ * A node that represents an inner class.
+ *
+ * @author Eric Bruneton
+ */
+public class InnerClassNode {
+
+ /**
+ * The internal name of an inner class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ */
+ public String name;
+
+ /**
+ * The internal name of the class to which the inner class belongs (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}). May
+ * be <tt>null</tt>.
+ */
+ public String outerName;
+
+ /**
+ * The (simple) name of the inner class inside its enclosing class. May be
+ * <tt>null</tt> for anonymous inner classes.
+ */
+ public String innerName;
+
+ /**
+ * The access flags of the inner class as originally declared in the
+ * enclosing class.
+ */
+ public int access;
+
+ /**
+ * Constructs a new {@link InnerClassNode}.
+ *
+ * @param name the internal name of an inner class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ * @param outerName the internal name of the class to which the inner class
+ * belongs (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ * May be <tt>null</tt>.
+ * @param innerName the (simple) name of the inner class inside its
+ * enclosing class. May be <tt>null</tt> for anonymous inner
+ * classes.
+ * @param access the access flags of the inner class as originally declared
+ * in the enclosing class.
+ */
+ public InnerClassNode(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ this.name = name;
+ this.outerName = outerName;
+ this.innerName = innerName;
+ this.access = access;
+ }
+
+ /**
+ * Makes the given class visitor visit this inner class.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/InsnList.java b/src/compiler/scala/tools/asm/tree/InsnList.java
new file mode 100644
index 0000000000..dedd3bba73
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/InsnList.java
@@ -0,0 +1,578 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A doubly linked list of {@link AbstractInsnNode} objects. <i>This
+ * implementation is not thread safe</i>.
+ */
+public class InsnList {
+
+ /**
+ * The number of instructions in this list.
+ */
+ private int size;
+
+ /**
+ * The first instruction in this list. May be <tt>null</tt>.
+ */
+ private AbstractInsnNode first;
+
+ /**
+ * The last instruction in this list. May be <tt>null</tt>.
+ */
+ private AbstractInsnNode last;
+
+ /**
+ * A cache of the instructions of this list. This cache is used to improve
+ * the performance of the {@link #get} method.
+ */
+ AbstractInsnNode[] cache;
+
+ /**
+ * Returns the number of instructions in this list.
+ *
+ * @return the number of instructions in this list.
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Returns the first instruction in this list.
+ *
+ * @return the first instruction in this list, or <tt>null</tt> if the
+ * list is empty.
+ */
+ public AbstractInsnNode getFirst() {
+ return first;
+ }
+
+ /**
+ * Returns the last instruction in this list.
+ *
+ * @return the last instruction in this list, or <tt>null</tt> if the list
+ * is empty.
+ */
+ public AbstractInsnNode getLast() {
+ return last;
+ }
+
+ /**
+ * Returns the instruction whose index is given. This method builds a cache
+ * of the instructions in this list to avoid scanning the whole list each
+ * time it is called. Once the cache is built, this method run in constant
+ * time. This cache is invalidated by all the methods that modify the list.
+ *
+ * @param index the index of the instruction that must be returned.
+ * @return the instruction whose index is given.
+ * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
+ */
+ public AbstractInsnNode get(final int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return cache[index];
+ }
+
+ /**
+ * Returns <tt>true</tt> if the given instruction belongs to this list.
+ * This method always scans the instructions of this list until it finds the
+ * given instruction or reaches the end of the list.
+ *
+ * @param insn an instruction.
+ * @return <tt>true</tt> if the given instruction belongs to this list.
+ */
+ public boolean contains(final AbstractInsnNode insn) {
+ AbstractInsnNode i = first;
+ while (i != null && i != insn) {
+ i = i.next;
+ }
+ return i != null;
+ }
+
+ /**
+ * Returns the index of the given instruction in this list. This method
+ * builds a cache of the instruction indexes to avoid scanning the whole
+ * list each time it is called. Once the cache is built, this method run in
+ * constant time. The cache is invalidated by all the methods that modify
+ * the list.
+ *
+ * @param insn an instruction <i>of this list</i>.
+ * @return the index of the given instruction in this list. <i>The result of
+ * this method is undefined if the given instruction does not belong
+ * to this list</i>. Use {@link #contains contains} to test if an
+ * instruction belongs to an instruction list or not.
+ */
+ public int indexOf(final AbstractInsnNode insn) {
+ if (cache == null) {
+ cache = toArray();
+ }
+ return insn.index;
+ }
+
+ /**
+ * Makes the given visitor visit all of the instructions in this list.
+ *
+ * @param mv the method visitor that must visit the instructions.
+ */
+ public void accept(final MethodVisitor mv) {
+ AbstractInsnNode insn = first;
+ while (insn != null) {
+ insn.accept(mv);
+ insn = insn.next;
+ }
+ }
+
+ /**
+ * Returns an iterator over the instructions in this list.
+ *
+ * @return an iterator over the instructions in this list.
+ */
+ public ListIterator<AbstractInsnNode> iterator() {
+ return iterator(0);
+ }
+
+ /**
+ * Returns an iterator over the instructions in this list.
+ *
+ * @return an iterator over the instructions in this list.
+ */
+ @SuppressWarnings("unchecked")
+ public ListIterator<AbstractInsnNode> iterator(int index) {
+ return new InsnListIterator(index);
+ }
+
+ /**
+ * Returns an array containing all of the instructions in this list.
+ *
+ * @return an array containing all of the instructions in this list.
+ */
+ public AbstractInsnNode[] toArray() {
+ int i = 0;
+ AbstractInsnNode elem = first;
+ AbstractInsnNode[] insns = new AbstractInsnNode[size];
+ while (elem != null) {
+ insns[i] = elem;
+ elem.index = i++;
+ elem = elem.next;
+ }
+ return insns;
+ }
+
+ /**
+ * Replaces an instruction of this list with another instruction.
+ *
+ * @param location an instruction <i>of this list</i>.
+ * @param insn another instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
+ */
+ public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ AbstractInsnNode next = location.next;
+ insn.next = next;
+ if (next != null) {
+ next.prev = insn;
+ } else {
+ last = insn;
+ }
+ AbstractInsnNode prev = location.prev;
+ insn.prev = prev;
+ if (prev != null) {
+ prev.next = insn;
+ } else {
+ first = insn;
+ }
+ if (cache != null) {
+ int index = location.index;
+ cache[index] = insn;
+ insn.index = index;
+ } else {
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+ location.index = -1; // i no longer belongs to an InsnList
+ location.prev = null;
+ location.next = null;
+ }
+
+ /**
+ * Adds the given instruction to the end of this list.
+ *
+ * @param insn an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
+ */
+ public void add(final AbstractInsnNode insn) {
+ ++size;
+ if (last == null) {
+ first = insn;
+ last = insn;
+ } else {
+ last.next = insn;
+ insn.prev = last;
+ }
+ last = insn;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Adds the given instructions to the end of this list.
+ *
+ * @param insns an instruction list, which is cleared during the process.
+ * This list must be different from 'this'.
+ */
+ public void add(final InsnList insns) {
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ if (last == null) {
+ first = insns.first;
+ last = insns.last;
+ } else {
+ AbstractInsnNode elem = insns.first;
+ last.next = elem;
+ elem.prev = last;
+ last = insns.last;
+ }
+ cache = null;
+ insns.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction at the begining of this list.
+ *
+ * @param insn an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
+ */
+ public void insert(final AbstractInsnNode insn) {
+ ++size;
+ if (first == null) {
+ first = insn;
+ last = insn;
+ } else {
+ first.prev = insn;
+ insn.next = first;
+ }
+ first = insn;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Inserts the given instructions at the begining of this list.
+ *
+ * @param insns an instruction list, which is cleared during the process.
+ * This list must be different from 'this'.
+ */
+ public void insert(final InsnList insns) {
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ if (first == null) {
+ first = insns.first;
+ last = insns.last;
+ } else {
+ AbstractInsnNode elem = insns.last;
+ first.prev = elem;
+ elem.next = first;
+ first = insns.first;
+ }
+ cache = null;
+ insns.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction after the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> after which insn must be
+ * inserted.
+ * @param insn the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
+ */
+ public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ ++size;
+ AbstractInsnNode next = location.next;
+ if (next == null) {
+ last = insn;
+ } else {
+ next.prev = insn;
+ }
+ location.next = insn;
+ insn.next = next;
+ insn.prev = location;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Inserts the given instructions after the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> after which the
+ * instructions must be inserted.
+ * @param insns the instruction list to be inserted, which is cleared during
+ * the process. This list must be different from 'this'.
+ */
+ public void insert(final AbstractInsnNode location, final InsnList insns) {
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ AbstractInsnNode ifirst = insns.first;
+ AbstractInsnNode ilast = insns.last;
+ AbstractInsnNode next = location.next;
+ if (next == null) {
+ last = ilast;
+ } else {
+ next.prev = ilast;
+ }
+ location.next = ifirst;
+ ilast.next = next;
+ ifirst.prev = location;
+ cache = null;
+ insns.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction before the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> before which insn must be
+ * inserted.
+ * @param insn the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
+ */
+ public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ ++size;
+ AbstractInsnNode prev = location.prev;
+ if (prev == null) {
+ first = insn;
+ } else {
+ prev.next = insn;
+ }
+ location.prev = insn;
+ insn.next = location;
+ insn.prev = prev;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Inserts the given instructions before the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> before which the instructions
+ * must be inserted.
+ * @param insns the instruction list to be inserted, which is cleared during
+ * the process. This list must be different from 'this'.
+ */
+ public void insertBefore(final AbstractInsnNode location, final InsnList insns) {
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ AbstractInsnNode ifirst = insns.first;
+ AbstractInsnNode ilast = insns.last;
+ AbstractInsnNode prev = location .prev;
+ if (prev == null) {
+ first = ifirst;
+ } else {
+ prev.next = ifirst;
+ }
+ location .prev = ilast;
+ ilast.next = location ;
+ ifirst.prev = prev;
+ cache = null;
+ insns.removeAll(false);
+ }
+
+
+
+ /**
+ * Removes the given instruction from this list.
+ *
+ * @param insn the instruction <i>of this list</i> that must be removed.
+ */
+ public void remove(final AbstractInsnNode insn) {
+ --size;
+ AbstractInsnNode next = insn.next;
+ AbstractInsnNode prev = insn.prev;
+ if (next == null) {
+ if (prev == null) {
+ first = null;
+ last = null;
+ } else {
+ prev.next = null;
+ last = prev;
+ }
+ } else {
+ if (prev == null) {
+ first = next;
+ next.prev = null;
+ } else {
+ prev.next = next;
+ next.prev = prev;
+ }
+ }
+ cache = null;
+ insn.index = -1; // insn no longer belongs to an InsnList
+ insn.prev = null;
+ insn.next = null;
+ }
+
+ /**
+ * Removes all of the instructions of this list.
+ *
+ * @param mark if the instructions must be marked as no longer belonging to
+ * any {@link InsnList}.
+ */
+ void removeAll(final boolean mark) {
+ if (mark) {
+ AbstractInsnNode insn = first;
+ while (insn != null) {
+ AbstractInsnNode next = insn.next;
+ insn.index = -1; // insn no longer belongs to an InsnList
+ insn.prev = null;
+ insn.next = null;
+ insn = next;
+ }
+ }
+ size = 0;
+ first = null;
+ last = null;
+ cache = null;
+ }
+
+ /**
+ * Removes all of the instructions of this list.
+ */
+ public void clear() {
+ removeAll(false);
+ }
+
+ /**
+ * Reset all labels in the instruction list. This method should be called
+ * before reusing same instructions list between several
+ * <code>ClassWriter</code>s.
+ */
+ public void resetLabels() {
+ AbstractInsnNode insn = first;
+ while (insn != null) {
+ if (insn instanceof LabelNode) {
+ ((LabelNode) insn).resetLabel();
+ }
+ insn = insn.next;
+ }
+ }
+
+ // this class is not generified because it will create bridges
+ private final class InsnListIterator implements ListIterator/*<AbstractInsnNode>*/ {
+
+ AbstractInsnNode next;
+
+ AbstractInsnNode prev;
+
+ InsnListIterator(int index) {
+ if(index==size()) {
+ next = null;
+ prev = getLast();
+ } else {
+ next = get(index);
+ prev = next.prev;
+ }
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public Object next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ AbstractInsnNode result = next;
+ prev = result;
+ next = result.next;
+ return result;
+ }
+
+ public void remove() {
+ InsnList.this.remove(prev);
+ prev = prev.prev;
+ }
+
+ public boolean hasPrevious() {
+ return prev != null;
+ }
+
+ public Object previous() {
+ AbstractInsnNode result = prev;
+ next = result;
+ prev = result.prev;
+ return result;
+ }
+
+ public int nextIndex() {
+ if (next == null) {
+ return size();
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return next.index;
+ }
+
+ public int previousIndex() {
+ if (prev == null) {
+ return -1;
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return prev.index;
+ }
+
+ public void add(Object o) {
+ InsnList.this.insertBefore(next, (AbstractInsnNode) o);
+ prev = (AbstractInsnNode) o;
+ }
+
+ public void set(Object o) {
+ InsnList.this.set(next.prev, (AbstractInsnNode) o);
+ prev = (AbstractInsnNode) o;
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/InsnNode.java b/src/compiler/scala/tools/asm/tree/InsnNode.java
new file mode 100644
index 0000000000..d4664d23c2
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/InsnNode.java
@@ -0,0 +1,84 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a zero operand instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class InsnNode extends AbstractInsnNode {
+
+ /**
+ * Constructs a new {@link InsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed. This
+ * opcode must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
+ * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
+ * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
+ * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE,
+ * FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2,
+ * DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD,
+ * FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+ * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG,
+ * ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR,
+ * LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
+ * I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
+ * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
+ * MONITORENTER, or MONITOREXIT.
+ */
+ public InsnNode(final int opcode) {
+ super(opcode);
+ }
+
+ @Override
+ public int getType() {
+ return INSN;
+ }
+
+ /**
+ * Makes the given visitor visit this instruction.
+ *
+ * @param mv a method visitor.
+ */
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitInsn(opcode);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new InsnNode(opcode);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/IntInsnNode.java b/src/compiler/scala/tools/asm/tree/IntInsnNode.java
new file mode 100644
index 0000000000..b61270c786
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/IntInsnNode.java
@@ -0,0 +1,84 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents an instruction with a single int operand.
+ *
+ * @author Eric Bruneton
+ */
+public class IntInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction.
+ */
+ public int operand;
+
+ /**
+ * Constructs a new {@link IntInsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed. This
+ * opcode must be BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand the operand of the instruction to be constructed.
+ */
+ public IntInsnNode(final int opcode, final int operand) {
+ super(opcode);
+ this.operand = operand;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be BIPUSH,
+ * SIPUSH or NEWARRAY.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ @Override
+ public int getType() {
+ return INT_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitIntInsn(opcode, operand);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new IntInsnNode(opcode, operand);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/InvokeDynamicInsnNode.java b/src/compiler/scala/tools/asm/tree/InvokeDynamicInsnNode.java
new file mode 100644
index 0000000000..d993b5a054
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/InvokeDynamicInsnNode.java
@@ -0,0 +1,100 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.Handle;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents an invokedynamic instruction.
+ *
+ * @author Remi Forax
+ */
+public class InvokeDynamicInsnNode extends AbstractInsnNode {
+
+ /**
+ * Invokedynamic name.
+ */
+ public String name;
+
+ /**
+ * Invokedynamic descriptor.
+ */
+ public String desc;
+
+ /**
+ * Bootstrap method
+ */
+ public Handle bsm;
+
+ /**
+ * Bootstrap constant arguments
+ */
+ public Object[] bsmArgs;
+
+ /**
+ * Constructs a new {@link InvokeDynamicInsnNode}.
+ *
+ * @param name invokedynamic name.
+ * @param desc invokedynamic descriptor (see {@link org.objectweb.asm.Type}).
+ * @param bsm the bootstrap method.
+ * @param bsmArgs the boostrap constant arguments.
+ */
+ public InvokeDynamicInsnNode(
+ final String name,
+ final String desc,
+ final Handle bsm,
+ final Object... bsmArgs)
+ {
+ super(Opcodes.INVOKEDYNAMIC);
+ this.name = name;
+ this.desc = desc;
+ this.bsm = bsm;
+ this.bsmArgs = bsmArgs;
+ }
+
+ @Override
+ public int getType() {
+ return INVOKE_DYNAMIC_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/JumpInsnNode.java b/src/compiler/scala/tools/asm/tree/JumpInsnNode.java
new file mode 100644
index 0000000000..339ebbd2d0
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/JumpInsnNode.java
@@ -0,0 +1,92 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a jump instruction. A jump instruction is an
+ * instruction that may jump to another instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class JumpInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction. This operand is a label that designates
+ * the instruction to which this instruction may jump.
+ */
+ public LabelNode label;
+
+ /**
+ * Constructs a new {@link JumpInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+ * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label the operand of the instruction to be constructed. This
+ * operand is a label that designates the instruction to which the
+ * jump instruction may jump.
+ */
+ public JumpInsnNode(final int opcode, final LabelNode label) {
+ super(opcode);
+ this.label = label;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE,
+ * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
+ * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR,
+ * IFNULL or IFNONNULL.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ @Override
+ public int getType() {
+ return JUMP_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitJumpInsn(opcode, label.getLabel());
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new JumpInsnNode(opcode, clone(label, labels));
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/LabelNode.java b/src/compiler/scala/tools/asm/tree/LabelNode.java
new file mode 100644
index 0000000000..523a8d6442
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/LabelNode.java
@@ -0,0 +1,78 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.Label;
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * An {@link AbstractInsnNode} that encapsulates a {@link Label}.
+ */
+public class LabelNode extends AbstractInsnNode {
+
+ private Label label;
+
+ public LabelNode() {
+ super(-1);
+ }
+
+ public LabelNode(final Label label) {
+ super(-1);
+ this.label = label;
+ }
+
+ @Override
+ public int getType() {
+ return LABEL;
+ }
+
+ public Label getLabel() {
+ if (label == null) {
+ label = new Label();
+ }
+ return label;
+ }
+
+ @Override
+ public void accept(final MethodVisitor cv) {
+ cv.visitLabel(getLabel());
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return labels.get(this);
+ }
+
+ public void resetLabel() {
+ label = null;
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/LdcInsnNode.java b/src/compiler/scala/tools/asm/tree/LdcInsnNode.java
new file mode 100644
index 0000000000..f8d115acd5
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/LdcInsnNode.java
@@ -0,0 +1,77 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents an LDC instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class LdcInsnNode extends AbstractInsnNode {
+
+ /**
+ * The constant to be loaded on the stack. This parameter must be a non null
+ * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a
+ * {@link String} or a {@link org.objectweb.asm.Type}.
+ */
+ public Object cst;
+
+ /**
+ * Constructs a new {@link LdcInsnNode}.
+ *
+ * @param cst the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
+ */
+ public LdcInsnNode(final Object cst) {
+ super(Opcodes.LDC);
+ this.cst = cst;
+ }
+
+ @Override
+ public int getType() {
+ return LDC_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitLdcInsn(cst);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new LdcInsnNode(cst);
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/LineNumberNode.java b/src/compiler/scala/tools/asm/tree/LineNumberNode.java
new file mode 100644
index 0000000000..acc83c8d30
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/LineNumberNode.java
@@ -0,0 +1,82 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a line number declaration. These nodes are pseudo
+ * instruction nodes in order to be inserted in an instruction list.
+ *
+ * @author Eric Bruneton
+ */
+public class LineNumberNode extends AbstractInsnNode {
+
+ /**
+ * A line number. This number refers to the source file from which the class
+ * was compiled.
+ */
+ public int line;
+
+ /**
+ * The first instruction corresponding to this line number.
+ */
+ public LabelNode start;
+
+ /**
+ * Constructs a new {@link LineNumberNode}.
+ *
+ * @param line a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start the first instruction corresponding to this line number.
+ */
+ public LineNumberNode(final int line, final LabelNode start) {
+ super(-1);
+ this.line = line;
+ this.start = start;
+ }
+
+ @Override
+ public int getType() {
+ return LINE;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitLineNumber(line, start.getLabel());
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new LineNumberNode(line, clone(start, labels));
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/LocalVariableNode.java b/src/compiler/scala/tools/asm/tree/LocalVariableNode.java
new file mode 100644
index 0000000000..51cbd3ca00
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/LocalVariableNode.java
@@ -0,0 +1,115 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a local variable declaration.
+ *
+ * @author Eric Bruneton
+ */
+public class LocalVariableNode {
+
+ /**
+ * The name of a local variable.
+ */
+ public String name;
+
+ /**
+ * The type descriptor of this local variable.
+ */
+ public String desc;
+
+ /**
+ * The signature of this local variable. May be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The first instruction corresponding to the scope of this local variable
+ * (inclusive).
+ */
+ public LabelNode start;
+
+ /**
+ * The last instruction corresponding to the scope of this local variable
+ * (exclusive).
+ */
+ public LabelNode end;
+
+ /**
+ * The local variable's index.
+ */
+ public int index;
+
+ /**
+ * Constructs a new {@link LocalVariableNode}.
+ *
+ * @param name the name of a local variable.
+ * @param desc the type descriptor of this local variable.
+ * @param signature the signature of this local variable. May be
+ * <tt>null</tt>.
+ * @param start the first instruction corresponding to the scope of this
+ * local variable (inclusive).
+ * @param end the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index the local variable's index.
+ */
+ public LocalVariableNode(
+ final String name,
+ final String desc,
+ final String signature,
+ final LabelNode start,
+ final LabelNode end,
+ final int index)
+ {
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.start = start;
+ this.end = end;
+ this.index = index;
+ }
+
+ /**
+ * Makes the given visitor visit this local variable declaration.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitLocalVariable(name,
+ desc,
+ signature,
+ start.getLabel(),
+ end.getLabel(),
+ index);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/LookupSwitchInsnNode.java b/src/compiler/scala/tools/asm/tree/LookupSwitchInsnNode.java
new file mode 100644
index 0000000000..6d0f971c29
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/LookupSwitchInsnNode.java
@@ -0,0 +1,116 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import scala.tools.asm.Label;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents a LOOKUPSWITCH instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class LookupSwitchInsnNode extends AbstractInsnNode {
+
+ /**
+ * Beginning of the default handler block.
+ */
+ public LabelNode dflt;
+
+ /**
+ * The values of the keys. This list is a list of {@link Integer} objects.
+ */
+ public List<Integer> keys;
+
+ /**
+ * Beginnings of the handler blocks. This list is a list of
+ * {@link LabelNode} objects.
+ */
+ public List<LabelNode> labels;
+
+ /**
+ * Constructs a new {@link LookupSwitchInsnNode}.
+ *
+ * @param dflt beginning of the default handler block.
+ * @param keys the values of the keys.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ */
+ public LookupSwitchInsnNode(
+ final LabelNode dflt,
+ final int[] keys,
+ final LabelNode[] labels)
+ {
+ super(Opcodes.LOOKUPSWITCH);
+ this.dflt = dflt;
+ this.keys = new ArrayList<Integer>(keys == null ? 0 : keys.length);
+ this.labels = new ArrayList<LabelNode>(labels == null ? 0 : labels.length);
+ if (keys != null) {
+ for (int i = 0; i < keys.length; ++i) {
+ this.keys.add(new Integer(keys[i]));
+ }
+ }
+ if (labels != null) {
+ this.labels.addAll(Arrays.asList(labels));
+ }
+ }
+
+ @Override
+ public int getType() {
+ return LOOKUPSWITCH_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ int[] keys = new int[this.keys.size()];
+ for (int i = 0; i < keys.length; ++i) {
+ keys[i] = this.keys.get(i).intValue();
+ }
+ Label[] labels = new Label[this.labels.size()];
+ for (int i = 0; i < labels.length; ++i) {
+ labels[i] = this.labels.get(i).getLabel();
+ }
+ mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
+ labels), null, clone(this.labels, labels));
+ clone.keys.addAll(keys);
+ return clone;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/MethodInsnNode.java b/src/compiler/scala/tools/asm/tree/MethodInsnNode.java
new file mode 100644
index 0000000000..c3036bc6b4
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/MethodInsnNode.java
@@ -0,0 +1,107 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a method instruction. A method instruction is an
+ * instruction that invokes a method.
+ *
+ * @author Eric Bruneton
+ */
+public class MethodInsnNode extends AbstractInsnNode {
+
+ /**
+ * The internal name of the method's owner class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ */
+ public String owner;
+
+ /**
+ * The method's name.
+ */
+ public String name;
+
+ /**
+ * The method's descriptor (see {@link org.objectweb.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Constructs a new {@link MethodInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see
+ * {@link org.objectweb.asm.Type#getInternalName() getInternalName}).
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link org.objectweb.asm.Type}).
+ */
+ public MethodInsnNode(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ super(opcode);
+ this.owner = owner;
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ @Override
+ public int getType() {
+ return METHOD_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new MethodInsnNode(opcode, owner, name, desc);
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/MethodNode.java b/src/compiler/scala/tools/asm/tree/MethodNode.java
new file mode 100644
index 0000000000..70ec39e058
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/MethodNode.java
@@ -0,0 +1,645 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.ClassVisitor;
+import scala.tools.asm.Handle;
+import scala.tools.asm.Label;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+
+/**
+ * A node that represents a method.
+ *
+ * @author Eric Bruneton
+ */
+public class MethodNode extends MethodVisitor {
+
+ /**
+ * The method's access flags (see {@link Opcodes}). This field also
+ * indicates if the method is synthetic and/or deprecated.
+ */
+ public int access;
+
+ /**
+ * The method's name.
+ */
+ public String name;
+
+ /**
+ * The method's descriptor (see {@link Type}).
+ */
+ public String desc;
+
+ /**
+ * The method's signature. May be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). This list is a list of
+ * {@link String} objects.
+ */
+ public List<String> exceptions;
+
+ /**
+ * The runtime visible annotations of this method. This list is a list of
+ * {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label visible
+ */
+ public List<AnnotationNode> visibleAnnotations;
+
+ /**
+ * The runtime invisible annotations of this method. This list is a list of
+ * {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label invisible
+ */
+ public List<AnnotationNode> invisibleAnnotations;
+
+ /**
+ * The non standard attributes of this method. This list is a list of
+ * {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.Attribute
+ */
+ public List<Attribute> attrs;
+
+ /**
+ * The default value of this annotation interface method. This field must be
+ * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
+ * {@link Integer}, {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link Type}, or an two elements String array (for
+ * enumeration values), a {@link AnnotationNode}, or a {@link List} of
+ * values of one of the preceding types. May be <tt>null</tt>.
+ */
+ public Object annotationDefault;
+
+ /**
+ * The runtime visible parameter annotations of this method. These lists are
+ * lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label invisible parameters
+ */
+ public List<AnnotationNode>[] visibleParameterAnnotations;
+
+ /**
+ * The runtime invisible parameter annotations of this method. These lists
+ * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.objectweb.asm.tree.AnnotationNode
+ * @label visible parameters
+ */
+ public List<AnnotationNode>[] invisibleParameterAnnotations;
+
+ /**
+ * The instructions of this method. This list is a list of
+ * {@link AbstractInsnNode} objects.
+ *
+ * @associates org.objectweb.asm.tree.AbstractInsnNode
+ * @label instructions
+ */
+ public InsnList instructions;
+
+ /**
+ * The try catch blocks of this method. This list is a list of
+ * {@link TryCatchBlockNode} objects.
+ *
+ * @associates org.objectweb.asm.tree.TryCatchBlockNode
+ */
+ public List<TryCatchBlockNode> tryCatchBlocks;
+
+ /**
+ * The maximum stack size of this method.
+ */
+ public int maxStack;
+
+ /**
+ * The maximum number of local variables of this method.
+ */
+ public int maxLocals;
+
+ /**
+ * The local variables of this method. This list is a list of
+ * {@link LocalVariableNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.objectweb.asm.tree.LocalVariableNode
+ */
+ public List<LocalVariableNode> localVariables;
+
+ /**
+ * If the accept method has been called on this object.
+ */
+ private boolean visited;
+
+ /**
+ * Constructs an uninitialized {@link MethodNode}. <i>Subclasses must not
+ * use this constructor</i>. Instead, they must use the
+ * {@link #MethodNode(int)} version.
+ */
+ public MethodNode() {
+ this(Opcodes.ASM4);
+ }
+
+ /**
+ * Constructs an uninitialized {@link MethodNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ public MethodNode(final int api) {
+ super(api);
+ this.instructions = new InsnList();
+ }
+
+ /**
+ * Constructs a new {@link MethodNode}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #MethodNode(int, int, String, String, String, String[])} version.
+ *
+ * @param access the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be <tt>null</tt>.
+ * @param exceptions the internal names of the method's exception classes
+ * (see {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ */
+ public MethodNode(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ this(Opcodes.ASM4, access, name, desc, signature, exceptions);
+ }
+
+ /**
+ * Constructs a new {@link MethodNode}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param access the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be <tt>null</tt>.
+ * @param exceptions the internal names of the method's exception classes
+ * (see {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ */
+ public MethodNode(
+ final int api,
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ super(api);
+ this.access = access;
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.exceptions = new ArrayList<String>(exceptions == null
+ ? 0
+ : exceptions.length);
+ boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
+ if (!isAbstract) {
+ this.localVariables = new ArrayList<LocalVariableNode>(5);
+ }
+ this.tryCatchBlocks = new ArrayList<TryCatchBlockNode>();
+ if (exceptions != null) {
+ this.exceptions.addAll(Arrays.asList(exceptions));
+ }
+ this.instructions = new InsnList();
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the MethodVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new AnnotationNode(new ArrayList<Object>(0) {
+ @Override
+ public boolean add(final Object o) {
+ annotationDefault = o;
+ return super.add(o);
+ }
+ });
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationNode an = new AnnotationNode(desc);
+ if (visible) {
+ if (visibleAnnotations == null) {
+ visibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ visibleAnnotations.add(an);
+ } else {
+ if (invisibleAnnotations == null) {
+ invisibleAnnotations = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleAnnotations.add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationNode an = new AnnotationNode(desc);
+ if (visible) {
+ if (visibleParameterAnnotations == null) {
+ int params = Type.getArgumentTypes(this.desc).length;
+ visibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ }
+ if (visibleParameterAnnotations[parameter] == null) {
+ visibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ }
+ visibleParameterAnnotations[parameter].add(an);
+ } else {
+ if (invisibleParameterAnnotations == null) {
+ int params = Type.getArgumentTypes(this.desc).length;
+ invisibleParameterAnnotations = (List<AnnotationNode>[])new List<?>[params];
+ }
+ if (invisibleParameterAnnotations[parameter] == null) {
+ invisibleParameterAnnotations[parameter] = new ArrayList<AnnotationNode>(1);
+ }
+ invisibleParameterAnnotations[parameter].add(an);
+ }
+ return an;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ if (attrs == null) {
+ attrs = new ArrayList<Attribute>(1);
+ }
+ attrs.add(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ instructions.add(new FrameNode(type, nLocal, local == null
+ ? null
+ : getLabelNodes(local), nStack, stack == null
+ ? null
+ : getLabelNodes(stack)));
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ instructions.add(new InsnNode(opcode));
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ instructions.add(new IntInsnNode(opcode, operand));
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ instructions.add(new VarInsnNode(opcode, var));
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ instructions.add(new TypeInsnNode(opcode, type));
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ instructions.add(new FieldInsnNode(opcode, owner, name, desc));
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ instructions.add(new MethodInsnNode(opcode, owner, name, desc));
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ String name,
+ String desc,
+ Handle bsm,
+ Object... bsmArgs)
+ {
+ instructions.add(new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs));
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ instructions.add(new JumpInsnNode(opcode, getLabelNode(label)));
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ instructions.add(getLabelNode(label));
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ instructions.add(new LdcInsnNode(cst));
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ instructions.add(new IincInsnNode(var, increment));
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label... labels)
+ {
+ instructions.add(new TableSwitchInsnNode(min,
+ max,
+ getLabelNode(dflt),
+ getLabelNodes(labels)));
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt),
+ keys,
+ getLabelNodes(labels)));
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ instructions.add(new MultiANewArrayInsnNode(desc, dims));
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
+ getLabelNode(end),
+ getLabelNode(handler),
+ type));
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ localVariables.add(new LocalVariableNode(name,
+ desc,
+ signature,
+ getLabelNode(start),
+ getLabelNode(end),
+ index));
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ instructions.add(new LineNumberNode(line, getLabelNode(start)));
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ this.maxStack = maxStack;
+ this.maxLocals = maxLocals;
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ /**
+ * Returns the LabelNode corresponding to the given Label. Creates a new
+ * LabelNode if necessary. The default implementation of this method uses
+ * the {@link Label#info} field to store associations between labels and
+ * label nodes.
+ *
+ * @param l a Label.
+ * @return the LabelNode corresponding to l.
+ */
+ protected LabelNode getLabelNode(final Label l) {
+ if (!(l.info instanceof LabelNode)) {
+ l.info = new LabelNode(l);
+ }
+ return (LabelNode) l.info;
+ }
+
+ private LabelNode[] getLabelNodes(final Label[] l) {
+ LabelNode[] nodes = new LabelNode[l.length];
+ for (int i = 0; i < l.length; ++i) {
+ nodes[i] = getLabelNode(l[i]);
+ }
+ return nodes;
+ }
+
+ private Object[] getLabelNodes(final Object[] objs) {
+ Object[] nodes = new Object[objs.length];
+ for (int i = 0; i < objs.length; ++i) {
+ Object o = objs[i];
+ if (o instanceof Label) {
+ o = getLabelNode((Label) o);
+ }
+ nodes[i] = o;
+ }
+ return nodes;
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept method
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that this method node is compatible with the given ASM API
+ * version. This methods checks that this node, and all its nodes
+ * recursively, do not contain elements that were introduced in more recent
+ * versions of the ASM API than the given version.
+ *
+ * @param api an ASM API version. Must be one of {@link Opcodes#ASM4}.
+ */
+ public void check(final int api) {
+ // nothing to do
+ }
+
+ /**
+ * Makes the given class visitor visit this method.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ String[] exceptions = new String[this.exceptions.size()];
+ this.exceptions.toArray(exceptions);
+ MethodVisitor mv = cv.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+ if (mv != null) {
+ accept(mv);
+ }
+ }
+
+ /**
+ * Makes the given method visitor visit this method.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ // visits the method attributes
+ int i, j, n;
+ if (annotationDefault != null) {
+ AnnotationVisitor av = mv.visitAnnotationDefault();
+ AnnotationNode.accept(av, null, annotationDefault);
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = visibleAnnotations.get(i);
+ an.accept(mv.visitAnnotation(an.desc, true));
+ }
+ n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = invisibleAnnotations.get(i);
+ an.accept(mv.visitAnnotation(an.desc, false));
+ }
+ n = visibleParameterAnnotations == null
+ ? 0
+ : visibleParameterAnnotations.length;
+ for (i = 0; i < n; ++i) {
+ List<?> l = visibleParameterAnnotations[i];
+ if (l == null) {
+ continue;
+ }
+ for (j = 0; j < l.size(); ++j) {
+ AnnotationNode an = (AnnotationNode) l.get(j);
+ an.accept(mv.visitParameterAnnotation(i, an.desc, true));
+ }
+ }
+ n = invisibleParameterAnnotations == null
+ ? 0
+ : invisibleParameterAnnotations.length;
+ for (i = 0; i < n; ++i) {
+ List<?> l = invisibleParameterAnnotations[i];
+ if (l == null) {
+ continue;
+ }
+ for (j = 0; j < l.size(); ++j) {
+ AnnotationNode an = (AnnotationNode) l.get(j);
+ an.accept(mv.visitParameterAnnotation(i, an.desc, false));
+ }
+ }
+ if (visited) {
+ instructions.resetLabels();
+ }
+ n = attrs == null ? 0 : attrs.size();
+ for (i = 0; i < n; ++i) {
+ mv.visitAttribute(attrs.get(i));
+ }
+ // visits the method's code
+ if (instructions.size() > 0) {
+ mv.visitCode();
+ // visits try catch blocks
+ n = tryCatchBlocks == null ? 0 : tryCatchBlocks.size();
+ for (i = 0; i < n; ++i) {
+ tryCatchBlocks.get(i).accept(mv);
+ }
+ // visits instructions
+ instructions.accept(mv);
+ // visits local variables
+ n = localVariables == null ? 0 : localVariables.size();
+ for (i = 0; i < n; ++i) {
+ localVariables.get(i).accept(mv);
+ }
+ // visits maxs
+ mv.visitMaxs(maxStack, maxLocals);
+ visited = true;
+ }
+ mv.visitEnd();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/MultiANewArrayInsnNode.java b/src/compiler/scala/tools/asm/tree/MultiANewArrayInsnNode.java
new file mode 100644
index 0000000000..9dfba77335
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/MultiANewArrayInsnNode.java
@@ -0,0 +1,81 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents a MULTIANEWARRAY instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class MultiANewArrayInsnNode extends AbstractInsnNode {
+
+ /**
+ * An array type descriptor (see {@link org.objectweb.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Number of dimensions of the array to allocate.
+ */
+ public int dims;
+
+ /**
+ * Constructs a new {@link MultiANewArrayInsnNode}.
+ *
+ * @param desc an array type descriptor (see {@link org.objectweb.asm.Type}).
+ * @param dims number of dimensions of the array to allocate.
+ */
+ public MultiANewArrayInsnNode(final String desc, final int dims) {
+ super(Opcodes.MULTIANEWARRAY);
+ this.desc = desc;
+ this.dims = dims;
+ }
+
+ @Override
+ public int getType() {
+ return MULTIANEWARRAY_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new MultiANewArrayInsnNode(desc, dims);
+ }
+
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/TableSwitchInsnNode.java b/src/compiler/scala/tools/asm/tree/TableSwitchInsnNode.java
new file mode 100644
index 0000000000..929ad9b32b
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/TableSwitchInsnNode.java
@@ -0,0 +1,115 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import scala.tools.asm.Label;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A node that represents a TABLESWITCH instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class TableSwitchInsnNode extends AbstractInsnNode {
+
+ /**
+ * The minimum key value.
+ */
+ public int min;
+
+ /**
+ * The maximum key value.
+ */
+ public int max;
+
+ /**
+ * Beginning of the default handler block.
+ */
+ public LabelNode dflt;
+
+ /**
+ * Beginnings of the handler blocks. This list is a list of
+ * {@link LabelNode} objects.
+ */
+ public List<LabelNode> labels;
+
+ /**
+ * Constructs a new {@link TableSwitchInsnNode}.
+ *
+ * @param min the minimum key value.
+ * @param max the maximum key value.
+ * @param dflt beginning of the default handler block.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>min + i</tt> key.
+ */
+ public TableSwitchInsnNode(
+ final int min,
+ final int max,
+ final LabelNode dflt,
+ final LabelNode... labels)
+ {
+ super(Opcodes.TABLESWITCH);
+ this.min = min;
+ this.max = max;
+ this.dflt = dflt;
+ this.labels = new ArrayList<LabelNode>();
+ if (labels != null) {
+ this.labels.addAll(Arrays.asList(labels));
+ }
+ }
+
+ @Override
+ public int getType() {
+ return TABLESWITCH_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ Label[] labels = new Label[this.labels.size()];
+ for (int i = 0; i < labels.length; ++i) {
+ labels[i] = this.labels.get(i).getLabel();
+ }
+ mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new TableSwitchInsnNode(min,
+ max,
+ clone(dflt, labels),
+ clone(this.labels, labels));
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/TryCatchBlockNode.java b/src/compiler/scala/tools/asm/tree/TryCatchBlockNode.java
new file mode 100644
index 0000000000..375b4cfcb9
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/TryCatchBlockNode.java
@@ -0,0 +1,94 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a try catch block.
+ *
+ * @author Eric Bruneton
+ */
+public class TryCatchBlockNode {
+
+ /**
+ * Beginning of the exception handler's scope (inclusive).
+ */
+ public LabelNode start;
+
+ /**
+ * End of the exception handler's scope (exclusive).
+ */
+ public LabelNode end;
+
+ /**
+ * Beginning of the exception handler's code.
+ */
+ public LabelNode handler;
+
+ /**
+ * Internal name of the type of exceptions handled by the handler. May be
+ * <tt>null</tt> to catch any exceptions (for "finally" blocks).
+ */
+ public String type;
+
+ /**
+ * Constructs a new {@link TryCatchBlockNode}.
+ *
+ * @param start beginning of the exception handler's scope (inclusive).
+ * @param end end of the exception handler's scope (exclusive).
+ * @param handler beginning of the exception handler's code.
+ * @param type internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for "finally"
+ * blocks).
+ */
+ public TryCatchBlockNode(
+ final LabelNode start,
+ final LabelNode end,
+ final LabelNode handler,
+ final String type)
+ {
+ this.start = start;
+ this.end = end;
+ this.handler = handler;
+ this.type = type;
+ }
+
+ /**
+ * Makes the given visitor visit this try catch block.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null
+ ? null
+ : handler.getLabel(), type);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/TypeInsnNode.java b/src/compiler/scala/tools/asm/tree/TypeInsnNode.java
new file mode 100644
index 0000000000..0b2666c498
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/TypeInsnNode.java
@@ -0,0 +1,87 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a type instruction. A type instruction is an
+ * instruction that takes a type descriptor as parameter.
+ *
+ * @author Eric Bruneton
+ */
+public class TypeInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction. This operand is an internal name (see
+ * {@link org.objectweb.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Constructs a new {@link TypeInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param desc the operand of the instruction to be constructed. This
+ * operand is an internal name (see {@link org.objectweb.asm.Type}).
+ */
+ public TypeInsnNode(final int opcode, final String desc) {
+ super(opcode);
+ this.desc = desc;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ @Override
+ public int getType() {
+ return TYPE_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitTypeInsn(opcode, desc);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new TypeInsnNode(opcode, desc);
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/VarInsnNode.java b/src/compiler/scala/tools/asm/tree/VarInsnNode.java
new file mode 100644
index 0000000000..89f572db59
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/VarInsnNode.java
@@ -0,0 +1,90 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree;
+
+import java.util.Map;
+
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A node that represents a local variable instruction. A local variable
+ * instruction is an instruction that loads or stores the value of a local
+ * variable.
+ *
+ * @author Eric Bruneton
+ */
+public class VarInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction. This operand is the index of a local
+ * variable.
+ */
+ public int var;
+
+ /**
+ * Constructs a new {@link VarInsnNode}.
+ *
+ * @param opcode the opcode of the local variable instruction to be
+ * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+ * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var the operand of the instruction to be constructed. This operand
+ * is the index of a local variable.
+ */
+ public VarInsnNode(final int opcode, final int var) {
+ super(opcode);
+ this.var = var;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be ILOAD,
+ * LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
+ * or RET.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ @Override
+ public int getType() {
+ return VAR_INSN;
+ }
+
+ @Override
+ public void accept(final MethodVisitor mv) {
+ mv.visitVarInsn(opcode, var);
+ }
+
+ @Override
+ public AbstractInsnNode clone(final Map<LabelNode, LabelNode> labels) {
+ return new VarInsnNode(opcode, var);
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/analysis/Analyzer.java b/src/compiler/scala/tools/asm/tree/analysis/Analyzer.java
new file mode 100644
index 0000000000..df387b0b8e
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/Analyzer.java
@@ -0,0 +1,549 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.AbstractInsnNode;
+import scala.tools.asm.tree.IincInsnNode;
+import scala.tools.asm.tree.InsnList;
+import scala.tools.asm.tree.JumpInsnNode;
+import scala.tools.asm.tree.LabelNode;
+import scala.tools.asm.tree.LookupSwitchInsnNode;
+import scala.tools.asm.tree.MethodNode;
+import scala.tools.asm.tree.TableSwitchInsnNode;
+import scala.tools.asm.tree.TryCatchBlockNode;
+import scala.tools.asm.tree.VarInsnNode;
+
+/**
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
+ * RET instructions are valid.</i>
+ *
+ * @param <V> type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public class Analyzer<V extends Value> implements Opcodes {
+
+ private final Interpreter<V> interpreter;
+
+ private int n;
+
+ private InsnList insns;
+
+ private List<TryCatchBlockNode>[] handlers;
+
+ private Frame<V>[] frames;
+
+ private Subroutine[] subroutines;
+
+ private boolean[] queued;
+
+ private int[] queue;
+
+ private int top;
+
+ /**
+ * Constructs a new {@link Analyzer}.
+ *
+ * @param interpreter the interpreter to be used to symbolically interpret
+ * the bytecode instructions.
+ */
+ public Analyzer(final Interpreter<V> interpreter) {
+ this.interpreter = interpreter;
+ }
+
+ /**
+ * Analyzes the given method.
+ *
+ * @param owner the internal name of the class to which the method belongs.
+ * @param m the method to be analyzed.
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if and only if the corresponding
+ * instruction cannot be reached (dead code).
+ * @throws AnalyzerException if a problem occurs during the analysis.
+ */
+ public Frame<V>[] analyze(final String owner, final MethodNode m)
+ throws AnalyzerException
+ {
+ if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+ frames = (Frame<V>[])new Frame<?>[0];
+ return frames;
+ }
+ n = m.instructions.size();
+ insns = m.instructions;
+ handlers = (List<TryCatchBlockNode>[])new List<?>[n];
+ frames = (Frame<V>[])new Frame<?>[n];
+ subroutines = new Subroutine[n];
+ queued = new boolean[n];
+ queue = new int[n];
+ top = 0;
+
+ // computes exception handlers for each instruction
+ for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+ TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
+ int begin = insns.indexOf(tcb.start);
+ int end = insns.indexOf(tcb.end);
+ for (int j = begin; j < end; ++j) {
+ List<TryCatchBlockNode> insnHandlers = handlers[j];
+ if (insnHandlers == null) {
+ insnHandlers = new ArrayList<TryCatchBlockNode>();
+ handlers[j] = insnHandlers;
+ }
+ insnHandlers.add(tcb);
+ }
+ }
+
+ // computes the subroutine for each instruction:
+ Subroutine main = new Subroutine(null, m.maxLocals, null);
+ List<AbstractInsnNode> subroutineCalls = new ArrayList<AbstractInsnNode>();
+ Map<LabelNode, Subroutine> subroutineHeads = new HashMap<LabelNode, Subroutine>();
+ findSubroutine(0, main, subroutineCalls);
+ while (!subroutineCalls.isEmpty()) {
+ JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
+ Subroutine sub = subroutineHeads.get(jsr.label);
+ if (sub == null) {
+ sub = new Subroutine(jsr.label, m.maxLocals, jsr);
+ subroutineHeads.put(jsr.label, sub);
+ findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+ } else {
+ sub.callers.add(jsr);
+ }
+ }
+ for (int i = 0; i < n; ++i) {
+ if (subroutines[i] != null && subroutines[i].start == null) {
+ subroutines[i] = null;
+ }
+ }
+
+ // initializes the data structures for the control flow analysis
+ Frame<V> current = newFrame(m.maxLocals, m.maxStack);
+ Frame<V> handler = newFrame(m.maxLocals, m.maxStack);
+ current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
+ Type[] args = Type.getArgumentTypes(m.desc);
+ int local = 0;
+ if ((m.access & ACC_STATIC) == 0) {
+ Type ctype = Type.getObjectType(owner);
+ current.setLocal(local++, interpreter.newValue(ctype));
+ }
+ for (int i = 0; i < args.length; ++i) {
+ current.setLocal(local++, interpreter.newValue(args[i]));
+ if (args[i].getSize() == 2) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ }
+ while (local < m.maxLocals) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ merge(0, current, null);
+
+ init(owner, m);
+
+ // control flow analysis
+ while (top > 0) {
+ int insn = queue[--top];
+ Frame<V> f = frames[insn];
+ Subroutine subroutine = subroutines[insn];
+ queued[insn] = false;
+
+ AbstractInsnNode insnNode = null;
+ try {
+ insnNode = m.instructions.get(insn);
+ int insnOpcode = insnNode.getOpcode();
+ int insnType = insnNode.getType();
+
+ if (insnType == AbstractInsnNode.LABEL
+ || insnType == AbstractInsnNode.LINE
+ || insnType == AbstractInsnNode.FRAME)
+ {
+ merge(insn + 1, f, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ } else {
+ current.init(f).execute(insnNode, interpreter);
+ subroutine = subroutine == null ? null : subroutine.copy();
+
+ if (insnNode instanceof JumpInsnNode) {
+ JumpInsnNode j = (JumpInsnNode) insnNode;
+ if (insnOpcode != GOTO && insnOpcode != JSR) {
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ int jump = insns.indexOf(j.label);
+ if (insnOpcode == JSR) {
+ merge(jump, current, new Subroutine(j.label,
+ m.maxLocals,
+ j));
+ } else {
+ merge(jump, current, subroutine);
+ }
+ newControlFlowEdge(insn, jump);
+ } else if (insnNode instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(lsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < lsi.labels.size(); ++j) {
+ LabelNode label = lsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnNode instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(tsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < tsi.labels.size(); ++j) {
+ LabelNode label = tsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnOpcode == RET) {
+ if (subroutine == null) {
+ throw new AnalyzerException(insnNode, "RET instruction outside of a sub routine");
+ }
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ JumpInsnNode caller = subroutine.callers.get(i);
+ int call = insns.indexOf(caller);
+ if (frames[call] != null) {
+ merge(call + 1,
+ frames[call],
+ current,
+ subroutines[call],
+ subroutine.access);
+ newControlFlowEdge(insn, call + 1);
+ }
+ }
+ } else if (insnOpcode != ATHROW
+ && (insnOpcode < IRETURN || insnOpcode > RETURN))
+ {
+ if (subroutine != null) {
+ if (insnNode instanceof VarInsnNode) {
+ int var = ((VarInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ if (insnOpcode == LLOAD || insnOpcode == DLOAD
+ || insnOpcode == LSTORE
+ || insnOpcode == DSTORE)
+ {
+ subroutine.access[var + 1] = true;
+ }
+ } else if (insnNode instanceof IincInsnNode) {
+ int var = ((IincInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ }
+ }
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ }
+
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ Type type;
+ if (tcb.type == null) {
+ type = Type.getObjectType("java/lang/Throwable");
+ } else {
+ type = Type.getObjectType(tcb.type);
+ }
+ int jump = insns.indexOf(tcb.handler);
+ if (newControlFlowExceptionEdge(insn, tcb)) {
+ handler.init(f);
+ handler.clearStack();
+ handler.push(interpreter.newValue(type));
+ merge(jump, handler, subroutine);
+ }
+ }
+ }
+ } catch (AnalyzerException e) {
+ throw new AnalyzerException(e.node, "Error at instruction " + insn
+ + ": " + e.getMessage(), e);
+ } catch (Exception e) {
+ throw new AnalyzerException(insnNode, "Error at instruction " + insn
+ + ": " + e.getMessage(), e);
+ }
+ }
+
+ return frames;
+ }
+
+ private void findSubroutine(int insn, final Subroutine sub, final List<AbstractInsnNode> calls)
+ throws AnalyzerException
+ {
+ while (true) {
+ if (insn < 0 || insn >= n) {
+ throw new AnalyzerException(null, "Execution can fall off end of the code");
+ }
+ if (subroutines[insn] != null) {
+ return;
+ }
+ subroutines[insn] = sub.copy();
+ AbstractInsnNode node = insns.get(insn);
+
+ // calls findSubroutine recursively on normal successors
+ if (node instanceof JumpInsnNode) {
+ if (node.getOpcode() == JSR) {
+ // do not follow a JSR, it leads to another subroutine!
+ calls.add(node);
+ } else {
+ JumpInsnNode jnode = (JumpInsnNode) node;
+ findSubroutine(insns.indexOf(jnode.label), sub, calls);
+ }
+ } else if (node instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
+ for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = tsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ } else if (node instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
+ for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = lsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ }
+
+ // calls findSubroutine recursively on exception handler successors
+ List<TryCatchBlockNode> insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = insnHandlers.get(i);
+ findSubroutine(insns.indexOf(tcb.handler), sub, calls);
+ }
+ }
+
+ // if insn does not falls through to the next instruction, return.
+ switch (node.getOpcode()) {
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ return;
+ }
+ insn++;
+ }
+ }
+
+ /**
+ * Returns the symbolic stack frame for each instruction of the last
+ * recently analyzed method.
+ *
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if the corresponding instruction
+ * cannot be reached, or if an error occured during the analysis of
+ * the method.
+ */
+ public Frame<V>[] getFrames() {
+ return frames;
+ }
+
+ /**
+ * Returns the exception handlers for the given instruction.
+ *
+ * @param insn the index of an instruction of the last recently analyzed
+ * method.
+ * @return a list of {@link TryCatchBlockNode} objects.
+ */
+ public List<TryCatchBlockNode> getHandlers(final int insn) {
+ return handlers[insn];
+ }
+
+ /**
+ * Initializes this analyzer. This method is called just before the
+ * execution of control flow analysis loop in #analyze. The default
+ * implementation of this method does nothing.
+ *
+ * @param owner the internal name of the class to which the method belongs.
+ * @param m the method to be analyzed.
+ * @throws AnalyzerException if a problem occurs.
+ */
+ protected void init(String owner, MethodNode m) throws AnalyzerException {
+ }
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals the maximum number of local variables of the frame.
+ * @param nStack the maximum stack size of the frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final int nLocals, final int nStack) {
+ return new Frame<V>(nLocals, nStack);
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src a frame.
+ * @return the created frame.
+ */
+ protected Frame<V> newFrame(final Frame<? extends V> src) {
+ return new Frame<V>(src);
+ }
+
+ /**
+ * Creates a control flow graph edge. The default implementation of this
+ * method does nothing. It can be overriden in order to construct the
+ * control flow graph of a method (this method is called by the
+ * {@link #analyze analyze} method during its visit of the method's code).
+ *
+ * @param insn an instruction index.
+ * @param successor index of a successor instruction.
+ */
+ protected void newControlFlowEdge(final int insn, final int successor) {
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method does nothing. It can be
+ * overridden in order to construct the control flow graph of a method (this
+ * method is called by the {@link #analyze analyze} method during its visit
+ * of the method's code).
+ *
+ * @param insn an instruction index.
+ * @param successor index of a successor instruction.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method always returns true.
+ */
+ protected boolean newControlFlowExceptionEdge(
+ final int insn,
+ final int successor)
+ {
+ return true;
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}. It can be overridden in order to
+ * construct the control flow graph of a method (this method is called by
+ * the {@link #analyze analyze} method during its visit of the method's
+ * code).
+ *
+ * @param insn an instruction index.
+ * @param tcb TryCatchBlockNode corresponding to this edge.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method delegates to
+ * {@link #newControlFlowExceptionEdge(int, int)
+ * newControlFlowExceptionEdge(int, int)}.
+ */
+ protected boolean newControlFlowExceptionEdge(
+ final int insn,
+ final TryCatchBlockNode tcb)
+ {
+ return newControlFlowExceptionEdge(insn, insns.indexOf(tcb.handler));
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void merge(
+ final int insn,
+ final Frame<V> frame,
+ final Subroutine subroutine) throws AnalyzerException
+ {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(frame);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(frame, interpreter);
+ }
+
+ if (oldSubroutine == null) {
+ if (subroutine != null) {
+ subroutines[insn] = subroutine.copy();
+ changes = true;
+ }
+ } else {
+ if (subroutine != null) {
+ changes |= oldSubroutine.merge(subroutine);
+ }
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+
+ private void merge(
+ final int insn,
+ final Frame<V> beforeJSR,
+ final Frame<V> afterRET,
+ final Subroutine subroutineBeforeJSR,
+ final boolean[] access) throws AnalyzerException
+ {
+ Frame<V> oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ afterRET.merge(beforeJSR, access);
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(afterRET);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(afterRET, interpreter);
+ }
+
+ if (oldSubroutine != null && subroutineBeforeJSR != null) {
+ changes |= oldSubroutine.merge(subroutineBeforeJSR);
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/AnalyzerException.java b/src/compiler/scala/tools/asm/tree/analysis/AnalyzerException.java
new file mode 100644
index 0000000000..a89bb3513f
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/AnalyzerException.java
@@ -0,0 +1,64 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import scala.tools.asm.tree.AbstractInsnNode;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ *
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+ public final AbstractInsnNode node;
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg) {
+ super(msg);
+ this.node = node;
+ }
+
+ public AnalyzerException(final AbstractInsnNode node, final String msg, final Throwable exception) {
+ super(msg, exception);
+ this.node = node;
+ }
+
+ public AnalyzerException(
+ final AbstractInsnNode node,
+ final String msg,
+ final Object expected,
+ final Value encountered)
+ {
+ super((msg == null ? "Expected " : msg + ": expected ") + expected
+ + ", but found " + encountered);
+ this.node = node;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/BasicInterpreter.java b/src/compiler/scala/tools/asm/tree/analysis/BasicInterpreter.java
new file mode 100644
index 0000000000..64ddcc11e6
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/BasicInterpreter.java
@@ -0,0 +1,365 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.List;
+
+import scala.tools.asm.Handle;
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.AbstractInsnNode;
+import scala.tools.asm.tree.FieldInsnNode;
+import scala.tools.asm.tree.IntInsnNode;
+import scala.tools.asm.tree.InvokeDynamicInsnNode;
+import scala.tools.asm.tree.LdcInsnNode;
+import scala.tools.asm.tree.MethodInsnNode;
+import scala.tools.asm.tree.MultiANewArrayInsnNode;
+import scala.tools.asm.tree.TypeInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter extends Interpreter<BasicValue> implements
+ Opcodes
+{
+
+ public BasicInterpreter() {
+ super(ASM4);
+ }
+
+ protected BasicInterpreter(final int api) {
+ super(api);
+ }
+
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ switch (type.getSort()) {
+ case Type.VOID:
+ return null;
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ return BasicValue.INT_VALUE;
+ case Type.FLOAT:
+ return BasicValue.FLOAT_VALUE;
+ case Type.LONG:
+ return BasicValue.LONG_VALUE;
+ case Type.DOUBLE:
+ return BasicValue.DOUBLE_VALUE;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ return BasicValue.REFERENCE_VALUE;
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ @Override
+ public BasicValue newOperation(final AbstractInsnNode insn)
+ throws AnalyzerException
+ {
+ switch (insn.getOpcode()) {
+ case ACONST_NULL:
+ return newValue(Type.getObjectType("null"));
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ return BasicValue.INT_VALUE;
+ case LCONST_0:
+ case LCONST_1:
+ return BasicValue.LONG_VALUE;
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ return BasicValue.FLOAT_VALUE;
+ case DCONST_0:
+ case DCONST_1:
+ return BasicValue.DOUBLE_VALUE;
+ case BIPUSH:
+ case SIPUSH:
+ return BasicValue.INT_VALUE;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ if (cst instanceof Integer) {
+ return BasicValue.INT_VALUE;
+ } else if (cst instanceof Float) {
+ return BasicValue.FLOAT_VALUE;
+ } else if (cst instanceof Long) {
+ return BasicValue.LONG_VALUE;
+ } else if (cst instanceof Double) {
+ return BasicValue.DOUBLE_VALUE;
+ } else if (cst instanceof String) {
+ return newValue(Type.getObjectType("java/lang/String"));
+ } else if (cst instanceof Type) {
+ int sort = ((Type) cst).getSort();
+ if (sort == Type.OBJECT || sort == Type.ARRAY) {
+ return newValue(Type.getObjectType("java/lang/Class"));
+ } else if (sort == Type.METHOD) {
+ return newValue(Type.getObjectType("java/lang/invoke/MethodType"));
+ } else {
+ throw new IllegalArgumentException("Illegal LDC constant " + cst);
+ }
+ } else if (cst instanceof Handle) {
+ return newValue(Type.getObjectType("java/lang/invoke/MethodHandle"));
+ } else {
+ throw new IllegalArgumentException("Illegal LDC constant " + cst);
+ }
+ case JSR:
+ return BasicValue.RETURNADDRESS_VALUE;
+ case GETSTATIC:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEW:
+ return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException
+ {
+ return value;
+ }
+
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException
+ {
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case L2I:
+ case F2I:
+ case D2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ return BasicValue.INT_VALUE;
+ case FNEG:
+ case I2F:
+ case L2F:
+ case D2F:
+ return BasicValue.FLOAT_VALUE;
+ case LNEG:
+ case I2L:
+ case F2L:
+ case D2L:
+ return BasicValue.LONG_VALUE;
+ case DNEG:
+ case I2D:
+ case L2D:
+ case F2D:
+ return BasicValue.DOUBLE_VALUE;
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case PUTSTATIC:
+ return null;
+ case GETFIELD:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEWARRAY:
+ switch (((IntInsnNode) insn).operand) {
+ case T_BOOLEAN:
+ return newValue(Type.getType("[Z"));
+ case T_CHAR:
+ return newValue(Type.getType("[C"));
+ case T_BYTE:
+ return newValue(Type.getType("[B"));
+ case T_SHORT:
+ return newValue(Type.getType("[S"));
+ case T_INT:
+ return newValue(Type.getType("[I"));
+ case T_FLOAT:
+ return newValue(Type.getType("[F"));
+ case T_DOUBLE:
+ return newValue(Type.getType("[D"));
+ case T_LONG:
+ return newValue(Type.getType("[J"));
+ default:
+ throw new AnalyzerException(insn, "Invalid array type");
+ }
+ case ANEWARRAY:
+ String desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getType("[" + Type.getObjectType(desc)));
+ case ARRAYLENGTH:
+ return BasicValue.INT_VALUE;
+ case ATHROW:
+ return null;
+ case CHECKCAST:
+ desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getObjectType(desc));
+ case INSTANCEOF:
+ return BasicValue.INT_VALUE;
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue binaryOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value1,
+ final BasicValue value2) throws AnalyzerException
+ {
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ case BALOAD:
+ case CALOAD:
+ case SALOAD:
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ return BasicValue.INT_VALUE;
+ case FALOAD:
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ return BasicValue.FLOAT_VALUE;
+ case LALOAD:
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ return BasicValue.LONG_VALUE;
+ case DALOAD:
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ return BasicValue.DOUBLE_VALUE;
+ case AALOAD:
+ return BasicValue.REFERENCE_VALUE;
+ case LCMP:
+ case FCMPL:
+ case FCMPG:
+ case DCMPL:
+ case DCMPG:
+ return BasicValue.INT_VALUE;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case PUTFIELD:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ @Override
+ public BasicValue ternaryOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value1,
+ final BasicValue value2,
+ final BasicValue value3) throws AnalyzerException
+ {
+ return null;
+ }
+
+ @Override
+ public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values)
+ throws AnalyzerException
+ {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+ } else if (opcode == INVOKEDYNAMIC){
+ return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
+ } else {
+ return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+ }
+ }
+
+ @Override
+ public void returnOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value,
+ final BasicValue expected) throws AnalyzerException
+ {
+ }
+
+ @Override
+ public BasicValue merge(final BasicValue v, final BasicValue w) {
+ if (!v.equals(w)) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/BasicValue.java b/src/compiler/scala/tools/asm/tree/analysis/BasicValue.java
new file mode 100644
index 0000000000..6c449db9b0
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/BasicValue.java
@@ -0,0 +1,108 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import scala.tools.asm.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type system.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ *
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+ public static final BasicValue UNINITIALIZED_VALUE = new BasicValue(null);
+
+ public static final BasicValue INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+ public static final BasicValue FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+ public static final BasicValue LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+ public static final BasicValue DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE);
+
+ public static final BasicValue REFERENCE_VALUE = new BasicValue(Type.getObjectType("java/lang/Object"));
+
+ public static final BasicValue RETURNADDRESS_VALUE = new BasicValue(Type.VOID_TYPE);
+
+ private final Type type;
+
+ public BasicValue(final Type type) {
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public int getSize() {
+ return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+ }
+
+ public boolean isReference() {
+ return type != null
+ && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+ }
+
+ @Override
+ public boolean equals(final Object value) {
+ if (value == this) {
+ return true;
+ } else if (value instanceof BasicValue) {
+ if (type == null) {
+ return ((BasicValue) value).type == null;
+ } else {
+ return type.equals(((BasicValue) value).type);
+ }
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return type == null ? 0 : type.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ if (this == UNINITIALIZED_VALUE) {
+ return ".";
+ } else if (this == RETURNADDRESS_VALUE) {
+ return "A";
+ } else if (this == REFERENCE_VALUE) {
+ return "R";
+ } else {
+ return type.getDescriptor();
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/BasicVerifier.java b/src/compiler/scala/tools/asm/tree/analysis/BasicVerifier.java
new file mode 100644
index 0000000000..9297dd9294
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/BasicVerifier.java
@@ -0,0 +1,459 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.List;
+
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.AbstractInsnNode;
+import scala.tools.asm.tree.FieldInsnNode;
+import scala.tools.asm.tree.InvokeDynamicInsnNode;
+import scala.tools.asm.tree.MethodInsnNode;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+ public BasicVerifier() {
+ super(ASM4);
+ }
+
+ protected BasicVerifier(final int api) {
+ super(api);
+ }
+
+ @Override
+ public BasicValue copyOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException
+ {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case ILOAD:
+ case ISTORE:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FLOAD:
+ case FSTORE:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LLOAD:
+ case LSTORE:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DLOAD:
+ case DSTORE:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case ALOAD:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn,
+ null,
+ "an object reference",
+ value);
+ }
+ return value;
+ case ASTORE:
+ if (!value.isReference()
+ && !BasicValue.RETURNADDRESS_VALUE.equals(value))
+ {
+ throw new AnalyzerException(insn,
+ null,
+ "an object reference or a return address",
+ value);
+ }
+ return value;
+ default:
+ return value;
+ }
+ if (!expected.equals(value)) {
+ throw new AnalyzerException(insn, null, expected, value);
+ }
+ return value;
+ }
+
+ @Override
+ public BasicValue unaryOperation(final AbstractInsnNode insn, final BasicValue value)
+ throws AnalyzerException
+ {
+ BasicValue expected;
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case I2F:
+ case I2L:
+ case I2D:
+ case I2B:
+ case I2C:
+ case I2S:
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case NEWARRAY:
+ case ANEWARRAY:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FNEG:
+ case F2I:
+ case F2L:
+ case F2D:
+ case FRETURN:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LNEG:
+ case L2I:
+ case L2F:
+ case L2D:
+ case LRETURN:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DNEG:
+ case D2I:
+ case D2F:
+ case D2L:
+ case DRETURN:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case GETFIELD:
+ expected = newValue(Type.getObjectType(((FieldInsnNode) insn).owner));
+ break;
+ case CHECKCAST:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn,
+ null,
+ "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARRAYLENGTH:
+ if (!isArrayValue(value)) {
+ throw new AnalyzerException(insn,
+ null,
+ "an array reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARETURN:
+ case ATHROW:
+ case INSTANCEOF:
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ if (!value.isReference()) {
+ throw new AnalyzerException(insn,
+ null,
+ "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case PUTSTATIC:
+ expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn, null, expected, value);
+ }
+ return super.unaryOperation(insn, value);
+ }
+
+ @Override
+ public BasicValue binaryOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value1,
+ final BasicValue value2) throws AnalyzerException
+ {
+ BasicValue expected1;
+ BasicValue expected2;
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ expected1 = newValue(Type.getType("[I"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case BALOAD:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case CALOAD:
+ expected1 = newValue(Type.getType("[C"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case SALOAD:
+ expected1 = newValue(Type.getType("[S"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case LALOAD:
+ expected1 = newValue(Type.getType("[J"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FALOAD:
+ expected1 = newValue(Type.getType("[F"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DALOAD:
+ expected1 = newValue(Type.getType("[D"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case AALOAD:
+ expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ expected1 = BasicValue.INT_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL:
+ case FCMPG:
+ expected1 = BasicValue.FLOAT_VALUE;
+ expected2 = BasicValue.FLOAT_VALUE;
+ break;
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case LCMP:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.LONG_VALUE;
+ break;
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ case DCMPL:
+ case DCMPG:
+ expected1 = BasicValue.DOUBLE_VALUE;
+ expected2 = BasicValue.DOUBLE_VALUE;
+ break;
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ expected1 = BasicValue.REFERENCE_VALUE;
+ expected2 = BasicValue.REFERENCE_VALUE;
+ break;
+ case PUTFIELD:
+ FieldInsnNode fin = (FieldInsnNode) insn;
+ expected1 = newValue(Type.getObjectType(fin.owner));
+ expected2 = newValue(Type.getType(fin.desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(insn, "First argument", expected1, value1);
+ } else if (!isSubTypeOf(value2, expected2)) {
+ throw new AnalyzerException(insn, "Second argument", expected2, value2);
+ }
+ if (insn.getOpcode() == AALOAD) {
+ return getElementValue(value1);
+ } else {
+ return super.binaryOperation(insn, value1, value2);
+ }
+ }
+
+ @Override
+ public BasicValue ternaryOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value1,
+ final BasicValue value2,
+ final BasicValue value3) throws AnalyzerException
+ {
+ BasicValue expected1;
+ BasicValue expected3;
+ switch (insn.getOpcode()) {
+ case IASTORE:
+ expected1 = newValue(Type.getType("[I"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case BASTORE:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case CASTORE:
+ expected1 = newValue(Type.getType("[C"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case SASTORE:
+ expected1 = newValue(Type.getType("[S"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case LASTORE:
+ expected1 = newValue(Type.getType("[J"));
+ expected3 = BasicValue.LONG_VALUE;
+ break;
+ case FASTORE:
+ expected1 = newValue(Type.getType("[F"));
+ expected3 = BasicValue.FLOAT_VALUE;
+ break;
+ case DASTORE:
+ expected1 = newValue(Type.getType("[D"));
+ expected3 = BasicValue.DOUBLE_VALUE;
+ break;
+ case AASTORE:
+ expected1 = value1;
+ expected3 = BasicValue.REFERENCE_VALUE;
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException(insn, "First argument", "a " + expected1
+ + " array reference", value1);
+ } else if (!BasicValue.INT_VALUE.equals(value2)) {
+ throw new AnalyzerException(insn, "Second argument",
+ BasicValue.INT_VALUE,
+ value2);
+ } else if (!isSubTypeOf(value3, expected3)) {
+ throw new AnalyzerException(insn, "Third argument", expected3, value3);
+ }
+ return null;
+ }
+
+ @Override
+ public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values)
+ throws AnalyzerException
+ {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ for (int i = 0; i < values.size(); ++i) {
+ if (!BasicValue.INT_VALUE.equals(values.get(i))) {
+ throw new AnalyzerException(insn,
+ null,
+ BasicValue.INT_VALUE,
+ values.get(i));
+ }
+ }
+ } else {
+ int i = 0;
+ int j = 0;
+ if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
+ Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+ if (!isSubTypeOf(values.get(i++), newValue(owner))) {
+ throw new AnalyzerException(insn, "Method owner",
+ newValue(owner),
+ values.get(0));
+ }
+ }
+ String desc = (opcode == INVOKEDYNAMIC)?
+ ((InvokeDynamicInsnNode) insn).desc:
+ ((MethodInsnNode) insn).desc;
+ Type[] args = Type.getArgumentTypes(desc);
+ while (i < values.size()) {
+ BasicValue expected = newValue(args[j++]);
+ BasicValue encountered = values.get(i++);
+ if (!isSubTypeOf(encountered, expected)) {
+ throw new AnalyzerException(insn,
+ "Argument " + j,
+ expected,
+ encountered);
+ }
+ }
+ }
+ return super.naryOperation(insn, values);
+ }
+
+ @Override
+ public void returnOperation(
+ final AbstractInsnNode insn,
+ final BasicValue value,
+ final BasicValue expected) throws AnalyzerException
+ {
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(insn,
+ "Incompatible return type",
+ expected,
+ value);
+ }
+ }
+
+ protected boolean isArrayValue(final BasicValue value) {
+ return value.isReference();
+ }
+
+ protected BasicValue getElementValue(final BasicValue objectArrayValue)
+ throws AnalyzerException
+ {
+ return BasicValue.REFERENCE_VALUE;
+ }
+
+ protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
+ return value.equals(expected);
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/Frame.java b/src/compiler/scala/tools/asm/tree/analysis/Frame.java
new file mode 100644
index 0000000000..fe19c2c9ae
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/Frame.java
@@ -0,0 +1,709 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.AbstractInsnNode;
+import scala.tools.asm.tree.IincInsnNode;
+import scala.tools.asm.tree.InvokeDynamicInsnNode;
+import scala.tools.asm.tree.MethodInsnNode;
+import scala.tools.asm.tree.MultiANewArrayInsnNode;
+import scala.tools.asm.tree.VarInsnNode;
+
+/**
+ * A symbolic execution stack frame. A stack frame contains a set of local
+ * variable slots, and an operand stack. Warning: long and double values are
+ * represented by <i>two</i> slots in local variables, and by <i>one</i> slot
+ * in the operand stack.
+ *
+ * @param <V> type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public class Frame<V extends Value> {
+
+ /**
+ * The expected return type of the analyzed method, or <tt>null</tt> if the
+ * method returns void.
+ */
+ private V returnValue;
+
+ /**
+ * The local variables and operand stack of this frame.
+ */
+ private V[] values;
+
+ /**
+ * The number of local variables of this frame.
+ */
+ private int locals;
+
+ /**
+ * The number of elements in the operand stack.
+ */
+ private int top;
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals the maximum number of local variables of the frame.
+ * @param nStack the maximum stack size of the frame.
+ */
+ public Frame(final int nLocals, final int nStack) {
+ this.values = (V[]) new Value[nLocals + nStack];
+ this.locals = nLocals;
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src a frame.
+ */
+ public Frame(final Frame<? extends V> src) {
+ this(src.locals, src.values.length - src.locals);
+ init(src);
+ }
+
+ /**
+ * Copies the state of the given frame into this frame.
+ *
+ * @param src a frame.
+ * @return this frame.
+ */
+ public Frame<V> init(final Frame<? extends V> src) {
+ returnValue = src.returnValue;
+ System.arraycopy(src.values, 0, values, 0, values.length);
+ top = src.top;
+ return this;
+ }
+
+ /**
+ * Sets the expected return type of the analyzed method.
+ *
+ * @param v the expected return type of the analyzed method, or
+ * <tt>null</tt> if the method returns void.
+ */
+ public void setReturn(final V v) {
+ returnValue = v;
+ }
+
+ /**
+ * Returns the maximum number of local variables of this frame.
+ *
+ * @return the maximum number of local variables of this frame.
+ */
+ public int getLocals() {
+ return locals;
+ }
+
+ /**
+ * Returns the value of the given local variable.
+ *
+ * @param i a local variable index.
+ * @return the value of the given local variable.
+ * @throws IndexOutOfBoundsException if the variable does not exist.
+ */
+ public V getLocal(final int i) throws IndexOutOfBoundsException {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException("Trying to access an inexistant local variable");
+ }
+ return values[i];
+ }
+
+ /**
+ * Sets the value of the given local variable.
+ *
+ * @param i a local variable index.
+ * @param value the new value of this local variable.
+ * @throws IndexOutOfBoundsException if the variable does not exist.
+ */
+ public void setLocal(final int i, final V value)
+ throws IndexOutOfBoundsException
+ {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException("Trying to access an inexistant local variable "+i);
+ }
+ values[i] = value;
+ }
+
+ /**
+ * Returns the number of values in the operand stack of this frame. Long and
+ * double values are treated as single values.
+ *
+ * @return the number of values in the operand stack of this frame.
+ */
+ public int getStackSize() {
+ return top;
+ }
+
+ /**
+ * Returns the value of the given operand stack slot.
+ *
+ * @param i the index of an operand stack slot.
+ * @return the value of the given operand stack slot.
+ * @throws IndexOutOfBoundsException if the operand stack slot does not
+ * exist.
+ */
+ public V getStack(final int i) throws IndexOutOfBoundsException {
+ return values[i + locals];
+ }
+
+ /**
+ * Clears the operand stack of this frame.
+ */
+ public void clearStack() {
+ top = 0;
+ }
+
+ /**
+ * Pops a value from the operand stack of this frame.
+ *
+ * @return the value that has been popped from the stack.
+ * @throws IndexOutOfBoundsException if the operand stack is empty.
+ */
+ public V pop() throws IndexOutOfBoundsException {
+ if (top == 0) {
+ throw new IndexOutOfBoundsException("Cannot pop operand off an empty stack.");
+ }
+ return values[--top + locals];
+ }
+
+ /**
+ * Pushes a value into the operand stack of this frame.
+ *
+ * @param value the value that must be pushed into the stack.
+ * @throws IndexOutOfBoundsException if the operand stack is full.
+ */
+ public void push(final V value) throws IndexOutOfBoundsException {
+ if (top + locals >= values.length) {
+ throw new IndexOutOfBoundsException("Insufficient maximum stack size.");
+ }
+ values[top++ + locals] = value;
+ }
+
+ public void execute(
+ final AbstractInsnNode insn,
+ final Interpreter<V> interpreter) throws AnalyzerException
+ {
+ V value1, value2, value3, value4;
+ List<V> values;
+ int var;
+
+ switch (insn.getOpcode()) {
+ case Opcodes.NOP:
+ break;
+ case Opcodes.ACONST_NULL:
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.LDC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.LLOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.DLOAD:
+ case Opcodes.ALOAD:
+ push(interpreter.copyOperation(insn,
+ getLocal(((VarInsnNode) insn).var)));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.LALOAD:
+ case Opcodes.FALOAD:
+ case Opcodes.DALOAD:
+ case Opcodes.AALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.LSTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.DSTORE:
+ case Opcodes.ASTORE:
+ value1 = interpreter.copyOperation(insn, pop());
+ var = ((VarInsnNode) insn).var;
+ setLocal(var, value1);
+ if (value1.getSize() == 2) {
+ setLocal(var + 1, interpreter.newValue(null));
+ }
+ if (var > 0) {
+ Value local = getLocal(var - 1);
+ if (local != null && local.getSize() == 2) {
+ setLocal(var - 1, interpreter.newValue(null));
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.LASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.DASTORE:
+ case Opcodes.AASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ value3 = pop();
+ value2 = pop();
+ value1 = pop();
+ interpreter.ternaryOperation(insn, value1, value2, value3);
+ break;
+ case Opcodes.POP:
+ if (pop().getSize() == 2) {
+ throw new AnalyzerException(insn, "Illegal use of POP");
+ }
+ break;
+ case Opcodes.POP2:
+ if (pop().getSize() == 1) {
+ if (pop().getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of POP2");
+ }
+ }
+ break;
+ case Opcodes.DUP:
+ value1 = pop();
+ if (value1.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP");
+ }
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.DUP_X1:
+ value1 = pop();
+ value2 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of DUP_X1");
+ }
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ case Opcodes.DUP_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP_X2");
+ case Opcodes.DUP2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(value2);
+ push(value1);
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ } else {
+ push(value1);
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2");
+ case Opcodes.DUP2_X1:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X1");
+ case Opcodes.DUP2_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ value4 = pop();
+ if (value4.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value4);
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(value3);
+ push(value2);
+ push(value1);
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(value2);
+ push(value1);
+ break;
+ }
+ }
+ throw new AnalyzerException(insn, "Illegal use of DUP2_X2");
+ case Opcodes.SWAP:
+ value2 = pop();
+ value1 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException(insn, "Illegal use of SWAP");
+ }
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.IADD:
+ case Opcodes.LADD:
+ case Opcodes.FADD:
+ case Opcodes.DADD:
+ case Opcodes.ISUB:
+ case Opcodes.LSUB:
+ case Opcodes.FSUB:
+ case Opcodes.DSUB:
+ case Opcodes.IMUL:
+ case Opcodes.LMUL:
+ case Opcodes.FMUL:
+ case Opcodes.DMUL:
+ case Opcodes.IDIV:
+ case Opcodes.LDIV:
+ case Opcodes.FDIV:
+ case Opcodes.DDIV:
+ case Opcodes.IREM:
+ case Opcodes.LREM:
+ case Opcodes.FREM:
+ case Opcodes.DREM:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ISHL:
+ case Opcodes.LSHL:
+ case Opcodes.ISHR:
+ case Opcodes.LSHR:
+ case Opcodes.IUSHR:
+ case Opcodes.LUSHR:
+ case Opcodes.IAND:
+ case Opcodes.LAND:
+ case Opcodes.IOR:
+ case Opcodes.LOR:
+ case Opcodes.IXOR:
+ case Opcodes.LXOR:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IINC:
+ var = ((IincInsnNode) insn).var;
+ setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
+ break;
+ case Opcodes.I2L:
+ case Opcodes.I2F:
+ case Opcodes.I2D:
+ case Opcodes.L2I:
+ case Opcodes.L2F:
+ case Opcodes.L2D:
+ case Opcodes.F2I:
+ case Opcodes.F2L:
+ case Opcodes.F2D:
+ case Opcodes.D2I:
+ case Opcodes.D2L:
+ case Opcodes.D2F:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.GOTO:
+ break;
+ case Opcodes.JSR:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.RET:
+ break;
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ case Opcodes.ARETURN:
+ value1 = pop();
+ interpreter.unaryOperation(insn, value1);
+ interpreter.returnOperation(insn, value1, returnValue);
+ break;
+ case Opcodes.RETURN:
+ if (returnValue != null) {
+ throw new AnalyzerException(insn, "Incompatible return type");
+ }
+ break;
+ case Opcodes.GETSTATIC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.PUTSTATIC:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.GETFIELD:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.PUTFIELD:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE: {
+ values = new ArrayList<V>();
+ String desc = ((MethodInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+ values.add(0, pop());
+ }
+ if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
+ values.add(0, pop());
+ }
+ if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, values);
+ } else {
+ push(interpreter.naryOperation(insn, values));
+ }
+ break;
+ }
+ case Opcodes.INVOKEDYNAMIC: {
+ values = new ArrayList<V>();
+ String desc = ((InvokeDynamicInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+ values.add(0, pop());
+ }
+ if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, values);
+ } else {
+ push(interpreter.naryOperation(insn, values));
+ }
+ break;
+ }
+ case Opcodes.NEW:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.NEWARRAY:
+ case Opcodes.ANEWARRAY:
+ case Opcodes.ARRAYLENGTH:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ATHROW:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.CHECKCAST:
+ case Opcodes.INSTANCEOF:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ values = new ArrayList<V>();
+ for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
+ values.add(0, pop());
+ }
+ push(interpreter.naryOperation(insn, values));
+ break;
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ default:
+ throw new RuntimeException("Illegal opcode "+insn.getOpcode());
+ }
+ }
+
+ /**
+ * Merges this frame with the given frame.
+ *
+ * @param frame a frame.
+ * @param interpreter the interpreter used to merge values.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ * @throws AnalyzerException if the frames have incompatible sizes.
+ */
+ public boolean merge(final Frame<? extends V> frame, final Interpreter<V> interpreter)
+ throws AnalyzerException
+ {
+ if (top != frame.top) {
+ throw new AnalyzerException(null, "Incompatible stack heights");
+ }
+ boolean changes = false;
+ for (int i = 0; i < locals + top; ++i) {
+ V v = interpreter.merge(values[i], frame.values[i]);
+ if (v != values[i]) {
+ values[i] = v;
+ changes = true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Merges this frame with the given frame (case of a RET instruction).
+ *
+ * @param frame a frame
+ * @param access the local variables that have been accessed by the
+ * subroutine to which the RET instruction corresponds.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ */
+ public boolean merge(final Frame<? extends V> frame, final boolean[] access) {
+ boolean changes = false;
+ for (int i = 0; i < locals; ++i) {
+ if (!access[i] && !values[i].equals(frame.values[i])) {
+ values[i] = frame.values[i];
+ changes = true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Returns a string representation of this frame.
+ *
+ * @return a string representation of this frame.
+ */
+ @Override
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < getLocals(); ++i) {
+ b.append(getLocal(i));
+ }
+ b.append(' ');
+ for (int i = 0; i < getStackSize(); ++i) {
+ b.append(getStack(i).toString());
+ }
+ return b.toString();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/Interpreter.java b/src/compiler/scala/tools/asm/tree/analysis/Interpreter.java
new file mode 100644
index 0000000000..930c8f4af8
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/Interpreter.java
@@ -0,0 +1,204 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.List;
+
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.AbstractInsnNode;
+
+/**
+ * A semantic bytecode interpreter. More precisely, this interpreter only
+ * manages the computation of values from other values: it does not manage the
+ * transfer of values to or from the stack, and to or from the local variables.
+ * This separation allows a generic bytecode {@link Analyzer} to work with
+ * various semantic interpreters, without needing to duplicate the code to
+ * simulate the transfer of values.
+ *
+ * @param <V> type of the Value used for the analysis.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class Interpreter<V extends Value> {
+
+ protected final int api;
+
+ protected Interpreter(final int api) {
+ this.api = api;
+ }
+
+ /**
+ * Creates a new value that represents the given type.
+ *
+ * Called for method parameters (including <code>this</code>),
+ * exception handler variable and with <code>null</code> type
+ * for variables reserved by long and double types.
+ *
+ * @param type a primitive or reference type, or <tt>null</tt> to
+ * represent an uninitialized value.
+ * @return a value that represents the given type. The size of the returned
+ * value must be equal to the size of the given type.
+ */
+ public abstract V newValue(Type type);
+
+ /**
+ * Interprets a bytecode instruction without arguments. This method is
+ * called for the following opcodes:
+ *
+ * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,
+ * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,
+ * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ public abstract V newOperation(AbstractInsnNode insn)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction that moves a value on the stack or to
+ * or from local variables. This method is called for the following opcodes:
+ *
+ * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
+ * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the value that must be moved by the instruction.
+ * @return the result of the interpretation of the given instruction. The
+ * returned value must be <tt>equal</tt> to the given value.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ public abstract V copyOperation(AbstractInsnNode insn, V value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a single argument. This method is
+ * called for the following opcodes:
+ *
+ * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
+ * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
+ * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
+ * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
+ * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ public abstract V unaryOperation(AbstractInsnNode insn, V value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with two arguments. This method is
+ * called for the following opcodes:
+ *
+ * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
+ * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+ * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
+ * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
+ * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value1 the first argument of the instruction to be interpreted.
+ * @param value2 the second argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ public abstract V binaryOperation(AbstractInsnNode insn, V value1, V value2)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with three arguments. This method is
+ * called for the following opcodes:
+ *
+ * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value1 the first argument of the instruction to be interpreted.
+ * @param value2 the second argument of the instruction to be interpreted.
+ * @param value3 the third argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ public abstract V ternaryOperation(
+ AbstractInsnNode insn,
+ V value1,
+ V value2,
+ V value3) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a variable number of arguments.
+ * This method is called for the following opcodes:
+ *
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
+ * MULTIANEWARRAY and INVOKEDYNAMIC
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param values the arguments of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ public abstract V naryOperation(
+ AbstractInsnNode insn,
+ List< ? extends V> values) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode return instruction. This method is called for the
+ * following opcodes:
+ *
+ * IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the argument of the instruction to be interpreted.
+ * @param expected the expected return type of the analyzed method.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ public abstract void returnOperation(
+ AbstractInsnNode insn,
+ V value,
+ V expected) throws AnalyzerException;
+
+ /**
+ * Merges two values. The merge operation must return a value that
+ * represents both values (for instance, if the two values are two types,
+ * the merged value must be a common super type of the two types. If the two
+ * values are integer intervals, the merged value must be an interval that
+ * contains the previous ones. Likewise for other types of values).
+ *
+ * @param v a value.
+ * @param w another value.
+ * @return the merged value. If the merged value is equal to <tt>v</tt>,
+ * this method <i>must</i> return <tt>v</tt>.
+ */
+ public abstract V merge(V v, V w);
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/SimpleVerifier.java b/src/compiler/scala/tools/asm/tree/analysis/SimpleVerifier.java
new file mode 100644
index 0000000000..c4f515d328
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/SimpleVerifier.java
@@ -0,0 +1,329 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.List;
+
+import scala.tools.asm.Type;
+
+/**
+ * An extended {@link BasicVerifier} that performs more precise verifications.
+ * This verifier computes exact class types, instead of using a single "object
+ * reference" type (as done in the {@link BasicVerifier}).
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class SimpleVerifier extends BasicVerifier {
+
+ /**
+ * The class that is verified.
+ */
+ private final Type currentClass;
+
+ /**
+ * The super class of the class that is verified.
+ */
+ private final Type currentSuperClass;
+
+ /**
+ * The interfaces implemented by the class that is verified.
+ */
+ private final List<Type> currentClassInterfaces;
+
+ /**
+ * If the class that is verified is an interface.
+ */
+ private final boolean isInterface;
+
+ /**
+ * The loader to use for referenced classes.
+ */
+ private ClassLoader loader = getClass().getClassLoader();
+
+ /**
+ * Constructs a new {@link SimpleVerifier}.
+ */
+ public SimpleVerifier() {
+ this(null, null, false);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass the class that is verified.
+ * @param currentSuperClass the super class of the class that is verified.
+ * @param isInterface if the class that is verified is an interface.
+ */
+ public SimpleVerifier(
+ final Type currentClass,
+ final Type currentSuperClass,
+ final boolean isInterface)
+ {
+ this(currentClass, currentSuperClass, null, isInterface);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass the class that is verified.
+ * @param currentSuperClass the super class of the class that is verified.
+ * @param currentClassInterfaces the interfaces implemented by the class
+ * that is verified.
+ * @param isInterface if the class that is verified is an interface.
+ */
+ public SimpleVerifier(
+ final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces,
+ final boolean isInterface)
+ {
+ this(ASM4,
+ currentClass,
+ currentSuperClass,
+ currentClassInterfaces,
+ isInterface);
+ }
+
+ protected SimpleVerifier(
+ final int api,
+ final Type currentClass,
+ final Type currentSuperClass,
+ final List<Type> currentClassInterfaces,
+ final boolean isInterface)
+ {
+ super(api);
+ this.currentClass = currentClass;
+ this.currentSuperClass = currentSuperClass;
+ this.currentClassInterfaces = currentClassInterfaces;
+ this.isInterface = isInterface;
+ }
+
+ /**
+ * Set the <code>ClassLoader</code> which will be used to load referenced
+ * classes. This is useful if you are verifying multiple interdependent
+ * classes.
+ *
+ * @param loader a <code>ClassLoader</code> to use
+ */
+ public void setClassLoader(final ClassLoader loader) {
+ this.loader = loader;
+ }
+
+ @Override
+ public BasicValue newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+
+ boolean isArray = type.getSort() == Type.ARRAY;
+ if (isArray) {
+ switch (type.getElementType().getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ return new BasicValue(type);
+ }
+ }
+
+ BasicValue v = super.newValue(type);
+ if (BasicValue.REFERENCE_VALUE.equals(v)) {
+ if (isArray) {
+ v = newValue(type.getElementType());
+ String desc = v.getType().getDescriptor();
+ for (int i = 0; i < type.getDimensions(); ++i) {
+ desc = '[' + desc;
+ }
+ v = new BasicValue(Type.getType(desc));
+ } else {
+ v = new BasicValue(type);
+ }
+ }
+ return v;
+ }
+
+ @Override
+ protected boolean isArrayValue(final BasicValue value) {
+ Type t = value.getType();
+ return t != null
+ && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+ }
+
+ @Override
+ protected BasicValue getElementValue(final BasicValue objectArrayValue)
+ throws AnalyzerException
+ {
+ Type arrayType = objectArrayValue.getType();
+ if (arrayType != null) {
+ if (arrayType.getSort() == Type.ARRAY) {
+ return newValue(Type.getType(arrayType.getDescriptor()
+ .substring(1)));
+ } else if ("Lnull;".equals(arrayType.getDescriptor())) {
+ return objectArrayValue;
+ }
+ }
+ throw new Error("Internal error");
+ }
+
+ @Override
+ protected boolean isSubTypeOf(final BasicValue value, final BasicValue expected) {
+ Type expectedType = expected.getType();
+ Type type = value.getType();
+ switch (expectedType.getSort()) {
+ case Type.INT:
+ case Type.FLOAT:
+ case Type.LONG:
+ case Type.DOUBLE:
+ return type.equals(expectedType);
+ case Type.ARRAY:
+ case Type.OBJECT:
+ if ("Lnull;".equals(type.getDescriptor())) {
+ return true;
+ } else if (type.getSort() == Type.OBJECT
+ || type.getSort() == Type.ARRAY)
+ {
+ return isAssignableFrom(expectedType, type);
+ } else {
+ return false;
+ }
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ @Override
+ public BasicValue merge(final BasicValue v, final BasicValue w) {
+ if (!v.equals(w)) {
+ Type t = v.getType();
+ Type u = w.getType();
+ if (t != null
+ && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY))
+ {
+ if (u != null
+ && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY))
+ {
+ if ("Lnull;".equals(t.getDescriptor())) {
+ return w;
+ }
+ if ("Lnull;".equals(u.getDescriptor())) {
+ return v;
+ }
+ if (isAssignableFrom(t, u)) {
+ return v;
+ }
+ if (isAssignableFrom(u, t)) {
+ return w;
+ }
+ // TODO case of array classes of the same dimension
+ // TODO should we look also for a common super interface?
+ // problem: there may be several possible common super
+ // interfaces
+ do {
+ if (t == null || isInterface(t)) {
+ return BasicValue.REFERENCE_VALUE;
+ }
+ t = getSuperClass(t);
+ if (isAssignableFrom(t, u)) {
+ return newValue(t);
+ }
+ } while (true);
+ }
+ }
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+
+ protected boolean isInterface(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return isInterface;
+ }
+ return getClass(t).isInterface();
+ }
+
+ protected Type getSuperClass(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return currentSuperClass;
+ }
+ Class<?> c = getClass(t).getSuperclass();
+ return c == null ? null : Type.getType(c);
+ }
+
+ protected boolean isAssignableFrom(final Type t, final Type u) {
+ if (t.equals(u)) {
+ return true;
+ }
+ if (currentClass != null && t.equals(currentClass)) {
+ if (getSuperClass(u) == null) {
+ return false;
+ } else {
+ if (isInterface) {
+ return u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY;
+ }
+ return isAssignableFrom(t, getSuperClass(u));
+ }
+ }
+ if (currentClass != null && u.equals(currentClass)) {
+ if (isAssignableFrom(t, currentSuperClass)) {
+ return true;
+ }
+ if (currentClassInterfaces != null) {
+ for (int i = 0; i < currentClassInterfaces.size(); ++i) {
+ Type v = currentClassInterfaces.get(i);
+ if (isAssignableFrom(t, v)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ Class<?> tc = getClass(t);
+ if (tc.isInterface()) {
+ tc = Object.class;
+ }
+ return tc.isAssignableFrom(getClass(u));
+ }
+
+ protected Class<?> getClass(final Type t) {
+ try {
+ if (t.getSort() == Type.ARRAY) {
+ return Class.forName(t.getDescriptor().replace('/', '.'),
+ false,
+ loader);
+ }
+ return Class.forName(t.getClassName(), false, loader);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/SmallSet.java b/src/compiler/scala/tools/asm/tree/analysis/SmallSet.java
new file mode 100644
index 0000000000..205878d18c
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/SmallSet.java
@@ -0,0 +1,134 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.AbstractSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A set of at most two elements.
+ *
+ * @author Eric Bruneton
+ */
+class SmallSet<E> extends AbstractSet<E> implements Iterator<E> {
+
+ // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+
+ E e1, e2;
+
+ static final <T> Set<T> emptySet() {
+ return new SmallSet<T>(null, null);
+ }
+
+ SmallSet(final E e1, final E e2) {
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of inherited abstract methods
+ // -------------------------------------------------------------------------
+
+ @Override
+ public Iterator<E> iterator() {
+ return new SmallSet<E>(e1, e2);
+ }
+
+ @Override
+ public int size() {
+ return e1 == null ? 0 : (e2 == null ? 1 : 2);
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of the Iterator interface
+ // -------------------------------------------------------------------------
+
+ public boolean hasNext() {
+ return e1 != null;
+ }
+
+ public E next() {
+ if (e1 == null) {
+ throw new NoSuchElementException();
+ }
+ E e = e1;
+ e1 = e2;
+ e2 = null;
+ return e;
+ }
+
+ public void remove() {
+ }
+
+ // -------------------------------------------------------------------------
+ // Utility methods
+ // -------------------------------------------------------------------------
+
+ Set<E> union(final SmallSet<E> s) {
+ if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {
+ return this; // if the two sets are equal, return this
+ }
+ if (s.e1 == null) {
+ return this; // if s is empty, return this
+ }
+ if (e1 == null) {
+ return s; // if this is empty, return s
+ }
+ if (s.e2 == null) { // s contains exactly one element
+ if (e2 == null) {
+ return new SmallSet<E>(e1, s.e1); // necessarily e1 != s.e1
+ } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this
+ return this;
+ }
+ }
+ if (e2 == null) { // this contains exactly one element
+ // if (s.e2 == null) { // cannot happen
+ // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
+ // } else
+ if (e1 == s.e1 || e1 == s.e2) { // this in included in s
+ return s;
+ }
+ }
+ // here we know that there are at least 3 distinct elements
+ HashSet<E> r = new HashSet<E>(4);
+ r.add(e1);
+ if (e2 != null) {
+ r.add(e2);
+ }
+ r.add(s.e1);
+ if (s.e2 != null) {
+ r.add(s.e2);
+ }
+ return r;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/SourceInterpreter.java b/src/compiler/scala/tools/asm/tree/analysis/SourceInterpreter.java
new file mode 100644
index 0000000000..067200b51e
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/SourceInterpreter.java
@@ -0,0 +1,206 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.AbstractInsnNode;
+import scala.tools.asm.tree.FieldInsnNode;
+import scala.tools.asm.tree.InvokeDynamicInsnNode;
+import scala.tools.asm.tree.LdcInsnNode;
+import scala.tools.asm.tree.MethodInsnNode;
+
+/**
+ * An {@link Interpreter} for {@link SourceValue} values.
+ *
+ * @author Eric Bruneton
+ */
+public class SourceInterpreter extends Interpreter<SourceValue> implements
+ Opcodes
+{
+
+ public SourceInterpreter() {
+ super(ASM4);
+ }
+
+ protected SourceInterpreter(final int api) {
+ super(api);
+ }
+
+ @Override
+ public SourceValue newValue(final Type type) {
+ if (type == Type.VOID_TYPE) {
+ return null;
+ }
+ return new SourceValue(type == null ? 1 : type.getSize());
+ }
+
+ @Override
+ public SourceValue newOperation(final AbstractInsnNode insn) {
+ int size;
+ switch (insn.getOpcode()) {
+ case LCONST_0:
+ case LCONST_1:
+ case DCONST_0:
+ case DCONST_1:
+ size = 2;
+ break;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ size = cst instanceof Long || cst instanceof Double ? 2 : 1;
+ break;
+ case GETSTATIC:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ }
+ return new SourceValue(size, insn);
+ }
+
+ @Override
+ public SourceValue copyOperation(final AbstractInsnNode insn, final SourceValue value) {
+ return new SourceValue(value.getSize(), insn);
+ }
+
+ @Override
+ public SourceValue unaryOperation(final AbstractInsnNode insn, final SourceValue value)
+ {
+ int size;
+ switch (insn.getOpcode()) {
+ case LNEG:
+ case DNEG:
+ case I2L:
+ case I2D:
+ case L2D:
+ case F2L:
+ case F2D:
+ case D2L:
+ size = 2;
+ break;
+ case GETFIELD:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ }
+ return new SourceValue(size, insn);
+ }
+
+ @Override
+ public SourceValue binaryOperation(
+ final AbstractInsnNode insn,
+ final SourceValue value1,
+ final SourceValue value2)
+ {
+ int size;
+ switch (insn.getOpcode()) {
+ case LALOAD:
+ case DALOAD:
+ case LADD:
+ case DADD:
+ case LSUB:
+ case DSUB:
+ case LMUL:
+ case DMUL:
+ case LDIV:
+ case DDIV:
+ case LREM:
+ case DREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ size = 2;
+ break;
+ default:
+ size = 1;
+ }
+ return new SourceValue(size, insn);
+ }
+
+ @Override
+ public SourceValue ternaryOperation(
+ final AbstractInsnNode insn,
+ final SourceValue value1,
+ final SourceValue value2,
+ final SourceValue value3)
+ {
+ return new SourceValue(1, insn);
+ }
+
+ @Override
+ public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) {
+ int size;
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ size = 1;
+ } else {
+ String desc = (opcode == INVOKEDYNAMIC)?
+ ((InvokeDynamicInsnNode) insn).desc:
+ ((MethodInsnNode) insn).desc;
+ size = Type.getReturnType(desc).getSize();
+ }
+ return new SourceValue(size, insn);
+ }
+
+ @Override
+ public void returnOperation(
+ final AbstractInsnNode insn,
+ final SourceValue value,
+ final SourceValue expected)
+ {
+ }
+
+ @Override
+ public SourceValue merge(final SourceValue d, final SourceValue w) {
+ if (d.insns instanceof SmallSet && w.insns instanceof SmallSet) {
+ Set<AbstractInsnNode> s = ((SmallSet<AbstractInsnNode>) d.insns).union((SmallSet<AbstractInsnNode>) w.insns);
+ if (s == d.insns && d.size == w.size) {
+ return d;
+ } else {
+ return new SourceValue(Math.min(d.size, w.size), s);
+ }
+ }
+ if (d.size != w.size || !d.insns.containsAll(w.insns)) {
+ HashSet<AbstractInsnNode> s = new HashSet<AbstractInsnNode>();
+ s.addAll(d.insns);
+ s.addAll(w.insns);
+ return new SourceValue(Math.min(d.size, w.size), s);
+ }
+ return d;
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/SourceValue.java b/src/compiler/scala/tools/asm/tree/analysis/SourceValue.java
new file mode 100644
index 0000000000..57ff212fb2
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/SourceValue.java
@@ -0,0 +1,97 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.Set;
+
+import scala.tools.asm.tree.AbstractInsnNode;
+
+/**
+ * A {@link Value} that is represented by its type in a two types type system.
+ * This type system distinguishes the ONEWORD and TWOWORDS types.
+ *
+ * @author Eric Bruneton
+ */
+public class SourceValue implements Value {
+
+ /**
+ * The size of this value.
+ */
+ public final int size;
+
+ /**
+ * The instructions that can produce this value. For example, for the Java
+ * code below, the instructions that can produce the value of <tt>i</tt>
+ * at line 5 are the txo ISTORE instructions at line 1 and 3:
+ *
+ * <pre>
+ * 1: i = 0;
+ * 2: if (...) {
+ * 3: i = 1;
+ * 4: }
+ * 5: return i;
+ * </pre>
+ *
+ * This field is a set of {@link AbstractInsnNode} objects.
+ */
+ public final Set<AbstractInsnNode> insns;
+
+ public SourceValue(final int size) {
+ this(size, SmallSet.<AbstractInsnNode>emptySet());
+ }
+
+ public SourceValue(final int size, final AbstractInsnNode insn) {
+ this.size = size;
+ this.insns = new SmallSet<AbstractInsnNode>(insn, null);
+ }
+
+ public SourceValue(final int size, final Set<AbstractInsnNode> insns) {
+ this.size = size;
+ this.insns = insns;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ @Override
+ public boolean equals(final Object value) {
+ if (!(value instanceof SourceValue)) {
+ return false;
+ }
+ SourceValue v = (SourceValue) value;
+ return size == v.size && insns.equals(v.insns);
+ }
+
+ @Override
+ public int hashCode() {
+ return insns.hashCode();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/tree/analysis/Subroutine.java b/src/compiler/scala/tools/asm/tree/analysis/Subroutine.java
new file mode 100644
index 0000000000..038880ddcd
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/Subroutine.java
@@ -0,0 +1,93 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import scala.tools.asm.tree.JumpInsnNode;
+import scala.tools.asm.tree.LabelNode;
+
+/**
+ * A method subroutine (corresponds to a JSR instruction).
+ *
+ * @author Eric Bruneton
+ */
+class Subroutine {
+
+ LabelNode start;
+
+ boolean[] access;
+
+ List<JumpInsnNode> callers;
+
+ private Subroutine() {
+ }
+
+ Subroutine(
+ final LabelNode start,
+ final int maxLocals,
+ final JumpInsnNode caller)
+ {
+ this.start = start;
+ this.access = new boolean[maxLocals];
+ this.callers = new ArrayList<JumpInsnNode>();
+ callers.add(caller);
+ }
+
+ public Subroutine copy() {
+ Subroutine result = new Subroutine();
+ result.start = start;
+ result.access = new boolean[access.length];
+ System.arraycopy(access, 0, result.access, 0, access.length);
+ result.callers = new ArrayList<JumpInsnNode>(callers);
+ return result;
+ }
+
+ public boolean merge(final Subroutine subroutine) throws AnalyzerException {
+ boolean changes = false;
+ for (int i = 0; i < access.length; ++i) {
+ if (subroutine.access[i] && !access[i]) {
+ access[i] = true;
+ changes = true;
+ }
+ }
+ if (subroutine.start == start) {
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ JumpInsnNode caller = subroutine.callers.get(i);
+ if (!callers.contains(caller)) {
+ callers.add(caller);
+ changes = true;
+ }
+ }
+ }
+ return changes;
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/asm/tree/analysis/Value.java b/src/compiler/scala/tools/asm/tree/analysis/Value.java
new file mode 100644
index 0000000000..1edf475ce7
--- /dev/null
+++ b/src/compiler/scala/tools/asm/tree/analysis/Value.java
@@ -0,0 +1,45 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.tree.analysis;
+
+/**
+ * An immutable symbolic value for semantic interpretation of bytecode.
+ *
+ * @author Eric Bruneton
+ */
+public interface Value {
+
+ /**
+ * Returns the size of this value in words.
+ *
+ * @return either 1 or 2.
+ */
+ int getSize();
+}
diff --git a/src/compiler/scala/tools/asm/util/ASMifiable.java b/src/compiler/scala/tools/asm/util/ASMifiable.java
new file mode 100644
index 0000000000..6a31dd508f
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/ASMifiable.java
@@ -0,0 +1,53 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.util.Map;
+
+import scala.tools.asm.Label;
+
+/**
+ * An {@link org.objectweb.asm.Attribute Attribute} that can print the ASM code
+ * to create an equivalent attribute.
+ *
+ * @author Eugene Kuleshov
+ */
+public interface ASMifiable {
+
+ /**
+ * Prints the ASM code to create an attribute equal to this attribute.
+ *
+ * @param buf a buffer used for printing Java code.
+ * @param varName name of the variable in a printed code used to store
+ * attribute instance.
+ * @param labelNames map of label instances to their names.
+ */
+ void asmify(StringBuffer buf, String varName, Map<Label, String> labelNames);
+}
diff --git a/src/compiler/scala/tools/asm/util/ASMifier.java b/src/compiler/scala/tools/asm/util/ASMifier.java
new file mode 100644
index 0000000000..5967c877d1
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/ASMifier.java
@@ -0,0 +1,1238 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import scala.tools.asm.Attribute;
+import scala.tools.asm.ClassReader;
+import scala.tools.asm.Handle;
+import scala.tools.asm.Label;
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+
+/**
+ * A {@link Printer} that prints the ASM code to generate the classes if visits.
+ *
+ * @author Eric Bruneton
+ */
+public class ASMifier extends Printer {
+
+ /**
+ * The name of the visitor variable in the produced code.
+ */
+ protected final String name;
+
+ /**
+ * Identifier of the annotation visitor variable in the produced code.
+ */
+ protected final int id;
+
+ /**
+ * The label names. This map associates String values to Label keys. It is
+ * used only in ASMifierMethodVisitor.
+ */
+ protected Map<Label, String> labelNames;
+
+ /**
+ * Pseudo access flag used to distinguish class access flags.
+ */
+ private static final int ACCESS_CLASS = 262144;
+
+ /**
+ * Pseudo access flag used to distinguish field access flags.
+ */
+ private static final int ACCESS_FIELD = 524288;
+
+ /**
+ * Pseudo access flag used to distinguish inner class flags.
+ */
+ private static final int ACCESS_INNER = 1048576;
+
+ /**
+ * Constructs a new {@link ASMifier}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the
+ * {@link #ASMifier(int, String, int)} version.
+ */
+ public ASMifier() {
+ this(Opcodes.ASM4, "cw", 0);
+ }
+
+ /**
+ * Constructs a new {@link ASMifier}.
+ *
+ * @param api the ASM API version implemented by this class. Must be one of
+ * {@link Opcodes#ASM4}.
+ * @param name the name of the visitor variable in the produced code.
+ * @param id identifier of the annotation visitor variable in the produced
+ * code.
+ */
+ protected ASMifier(final int api, final String name, final int id) {
+ super(api);
+ this.name = name;
+ this.id = id;
+ }
+
+ /**
+ * Prints the ASM source code to generate the given class to the standard
+ * output. <p> Usage: ASMifier [-debug] &lt;binary
+ * class name or class file name&gt;
+ *
+ * @param args the command line arguments.
+ *
+ * @throws Exception if the class cannot be found, or if an IO exception
+ * occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err.println("Prints the ASM code to generate the given class.");
+ System.err.println("Usage: ASMifier [-debug] "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1)
+ {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new TraceClassVisitor(null,
+ new ASMifier(),
+ new PrintWriter(System.out)), flags);
+ }
+
+ // ------------------------------------------------------------------------
+ // Classes
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ String simpleName;
+ int n = name.lastIndexOf('/');
+ if (n == -1) {
+ simpleName = name;
+ } else {
+ text.add("package asm." + name.substring(0, n).replace('/', '.')
+ + ";\n");
+ simpleName = name.substring(n + 1);
+ }
+ text.add("import java.util.*;\n");
+ text.add("import org.objectweb.asm.*;\n");
+ text.add("import org.objectweb.asm.attrs.*;\n");
+ text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
+ text.add("public static byte[] dump () throws Exception {\n\n");
+ text.add("ClassWriter cw = new ClassWriter(0);\n");
+ text.add("FieldVisitor fv;\n");
+ text.add("MethodVisitor mv;\n");
+ text.add("AnnotationVisitor av0;\n\n");
+
+ buf.setLength(0);
+ buf.append("cw.visit(");
+ switch (version) {
+ case Opcodes.V1_1:
+ buf.append("V1_1");
+ break;
+ case Opcodes.V1_2:
+ buf.append("V1_2");
+ break;
+ case Opcodes.V1_3:
+ buf.append("V1_3");
+ break;
+ case Opcodes.V1_4:
+ buf.append("V1_4");
+ break;
+ case Opcodes.V1_5:
+ buf.append("V1_5");
+ break;
+ case Opcodes.V1_6:
+ buf.append("V1_6");
+ break;
+ case Opcodes.V1_7:
+ buf.append("V1_7");
+ break;
+ default:
+ buf.append(version);
+ break;
+ }
+ buf.append(", ");
+ appendAccess(access | ACCESS_CLASS);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendConstant(superName);
+ buf.append(", ");
+ if (interfaces != null && interfaces.length > 0) {
+ buf.append("new String[] {");
+ for (int i = 0; i < interfaces.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendConstant(interfaces[i]);
+ }
+ buf.append(" }");
+ } else {
+ buf.append("null");
+ }
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ buf.setLength(0);
+ buf.append("cw.visitSource(");
+ appendConstant(file);
+ buf.append(", ");
+ appendConstant(debug);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append("cw.visitOuterClass(");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public ASMifier visitClassAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ buf.setLength(0);
+ buf.append("cw.visitInnerClass(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(outerName);
+ buf.append(", ");
+ appendConstant(innerName);
+ buf.append(", ");
+ appendAccess(access | ACCESS_INNER);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public ASMifier visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("fv = cw.visitField(");
+ appendAccess(access | ACCESS_FIELD);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendConstant(value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("fv", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public ASMifier visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("mv = cw.visitMethod(");
+ appendAccess(access);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ if (exceptions != null && exceptions.length > 0) {
+ buf.append("new String[] {");
+ for (int i = 0; i < exceptions.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendConstant(exceptions[i]);
+ }
+ buf.append(" }");
+ } else {
+ buf.append("null");
+ }
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("mv", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public void visitClassEnd() {
+ text.add("cw.visitEnd();\n\n");
+ text.add("return cw.toByteArray();\n");
+ text.add("}\n");
+ text.add("}\n");
+ }
+
+ // ------------------------------------------------------------------------
+ // Annotations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visit(");
+ appendConstant(buf, name);
+ buf.append(", ");
+ appendConstant(buf, value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visitEnum(");
+ appendConstant(buf, name);
+ buf.append(", ");
+ appendConstant(buf, desc);
+ buf.append(", ");
+ appendConstant(buf, value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public ASMifier visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+ buf.append(id).append(".visitAnnotation(");
+ appendConstant(buf, name);
+ buf.append(", ");
+ appendConstant(buf, desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", id + 1);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public ASMifier visitArray(final String name) {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+ buf.append(id).append(".visitArray(");
+ appendConstant(buf, name);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", id + 1);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ @Override
+ public ASMifier visitFieldAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ buf.setLength(0);
+ buf.append(name).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public ASMifier visitAnnotationDefault() {
+ buf.setLength(0);
+ buf.append("{\n")
+ .append("av0 = ")
+ .append(name)
+ .append(".visitAnnotationDefault();\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public ASMifier visitMethodAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public ASMifier visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append("{\n")
+ .append("av0 = ").append(name).append(".visitParameterAnnotation(")
+ .append(parameter)
+ .append(", ");
+ appendConstant(desc);
+ buf.append(", ").append(visible).append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ text.add(name + ".visitCode();\n");
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ buf.setLength(0);
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ declareFrameTypes(nLocal, local);
+ declareFrameTypes(nStack, stack);
+ if (type == Opcodes.F_NEW) {
+ buf.append(name).append(".visitFrame(Opcodes.F_NEW, ");
+ } else {
+ buf.append(name).append(".visitFrame(Opcodes.F_FULL, ");
+ }
+ buf.append(nLocal).append(", new Object[] {");
+ appendFrameTypes(nLocal, local);
+ buf.append("}, ").append(nStack).append(", new Object[] {");
+ appendFrameTypes(nStack, stack);
+ buf.append('}');
+ break;
+ case Opcodes.F_APPEND:
+ declareFrameTypes(nLocal, local);
+ buf.append(name).append(".visitFrame(Opcodes.F_APPEND,")
+ .append(nLocal)
+ .append(", new Object[] {");
+ appendFrameTypes(nLocal, local);
+ buf.append("}, 0, null");
+ break;
+ case Opcodes.F_CHOP:
+ buf.append(name).append(".visitFrame(Opcodes.F_CHOP,")
+ .append(nLocal)
+ .append(", null, 0, null");
+ break;
+ case Opcodes.F_SAME:
+ buf.append(name).append(".visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+ break;
+ case Opcodes.F_SAME1:
+ declareFrameTypes(1, stack);
+ buf.append(name).append(".visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
+ appendFrameTypes(1, stack);
+ buf.append('}');
+ break;
+ }
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ buf.setLength(0);
+ buf.append(name).append(".visitInsn(").append(OPCODES[opcode]).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ buf.setLength(0);
+ buf.append(name)
+ .append(".visitIntInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(opcode == Opcodes.NEWARRAY
+ ? TYPES[operand]
+ : Integer.toString(operand))
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ buf.setLength(0);
+ buf.append(name)
+ .append(".visitVarInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(var)
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ buf.setLength(0);
+ buf.append(name).append(".visitTypeInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(type);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitFieldInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitMethodInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ String name,
+ String desc,
+ Handle bsm,
+ Object... bsmArgs)
+ {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitInvokeDynamicInsn(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(bsm);
+ buf.append(", new Object[]{");
+ for (int i = 0; i < bsmArgs.length; ++i) {
+ appendConstant(bsmArgs[i]);
+ if (i != bsmArgs.length - 1) {
+ buf.append(", ");
+ }
+ }
+ buf.append("});\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ buf.setLength(0);
+ declareLabel(label);
+ buf.append(name).append(".visitJumpInsn(").append(OPCODES[opcode]).append(", ");
+ appendLabel(label);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ buf.setLength(0);
+ declareLabel(label);
+ buf.append(name).append(".visitLabel(");
+ appendLabel(label);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ buf.setLength(0);
+ buf.append(name).append(".visitLdcInsn(");
+ appendConstant(cst);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ buf.setLength(0);
+ buf.append(name)
+ .append(".visitIincInsn(")
+ .append(var)
+ .append(", ")
+ .append(increment)
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label... labels)
+ {
+ buf.setLength(0);
+ for (int i = 0; i < labels.length; ++i) {
+ declareLabel(labels[i]);
+ }
+ declareLabel(dflt);
+
+ buf.append(name)
+ .append(".visitTableSwitchInsn(")
+ .append(min)
+ .append(", ")
+ .append(max)
+ .append(", ");
+ appendLabel(dflt);
+ buf.append(", new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ buf.append(" });\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ buf.setLength(0);
+ for (int i = 0; i < labels.length; ++i) {
+ declareLabel(labels[i]);
+ }
+ declareLabel(dflt);
+
+ buf.append(name).append(".visitLookupSwitchInsn(");
+ appendLabel(dflt);
+ buf.append(", new int[] {");
+ for (int i = 0; i < keys.length; ++i) {
+ buf.append(i == 0 ? " " : ", ").append(keys[i]);
+ }
+ buf.append(" }, new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ buf.append(" });\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ buf.setLength(0);
+ buf.append(name).append(".visitMultiANewArrayInsn(");
+ appendConstant(desc);
+ buf.append(", ").append(dims).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ buf.setLength(0);
+ declareLabel(start);
+ declareLabel(end);
+ declareLabel(handler);
+ buf.append(name).append(".visitTryCatchBlock(");
+ appendLabel(start);
+ buf.append(", ");
+ appendLabel(end);
+ buf.append(", ");
+ appendLabel(handler);
+ buf.append(", ");
+ appendConstant(type);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ buf.setLength(0);
+ buf.append(this.name).append(".visitLocalVariable(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendLabel(start);
+ buf.append(", ");
+ appendLabel(end);
+ buf.append(", ").append(index).append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ buf.setLength(0);
+ buf.append(name).append(".visitLineNumber(").append(line).append(", ");
+ appendLabel(start);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ buf.setLength(0);
+ buf.append(name)
+ .append(".visitMaxs(")
+ .append(maxStack)
+ .append(", ")
+ .append(maxLocals)
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ buf.setLength(0);
+ buf.append(name).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Common methods
+ // ------------------------------------------------------------------------
+
+ public ASMifier visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append("{\n")
+ .append("av0 = ")
+ .append(name)
+ .append(".visitAnnotation(");
+ appendConstant(desc);
+ buf.append(", ").append(visible).append(");\n");
+ text.add(buf.toString());
+ ASMifier a = createASMifier("av", 0);
+ text.add(a.getText());
+ text.add("}\n");
+ return a;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append("// ATTRIBUTE ").append(attr.type).append('\n');
+ if (attr instanceof ASMifiable) {
+ if (labelNames == null) {
+ labelNames = new HashMap<Label, String>();
+ }
+ buf.append("{\n");
+ ((ASMifiable) attr).asmify(buf, "attr", labelNames);
+ buf.append(name).append(".visitAttribute(attr);\n");
+ buf.append("}\n");
+ }
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ protected ASMifier createASMifier(final String name, final int id) {
+ return new ASMifier(Opcodes.ASM4, name, id);
+ }
+
+ /**
+ * Appends a string representation of the given access modifiers to {@link
+ * #buf buf}.
+ *
+ * @param access some access modifiers.
+ */
+ void appendAccess(final int access) {
+ boolean first = true;
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ buf.append("ACC_PUBLIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ buf.append("ACC_PRIVATE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ buf.append("ACC_PROTECTED");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_FINAL");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_STATIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ if ((access & ACCESS_CLASS) == 0) {
+ buf.append("ACC_SYNCHRONIZED");
+ } else {
+ buf.append("ACC_SUPER");
+ }
+ first = false;
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0
+ && (access & ACCESS_FIELD) != 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_VOLATILE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_BRIDGE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_VARARGS");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0
+ && (access & ACCESS_FIELD) != 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_TRANSIENT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_NATIVE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0
+ && ((access & ACCESS_CLASS) != 0
+ || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0))
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ENUM");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ANNOTATION) != 0
+ && ((access & ACCESS_CLASS) != 0 || (access & ACCESS_INNER) != 0))
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ANNOTATION");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ABSTRACT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_INTERFACE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_STRICT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_SYNTHETIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_DEPRECATED");
+ first = false;
+ }
+ if (first) {
+ buf.append('0');
+ }
+ }
+
+ /**
+ * Appends a string representation of the given constant to the given
+ * buffer.
+ *
+ * @param cst an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double} or {@link String} object. May be <tt>null</tt>.
+ */
+ protected void appendConstant(final Object cst) {
+ appendConstant(buf, cst);
+ }
+
+ /**
+ * Appends a string representation of the given constant to the given
+ * buffer.
+ *
+ * @param buf a string buffer.
+ * @param cst an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double} or {@link String} object. May be <tt>null</tt>.
+ */
+ static void appendConstant(final StringBuffer buf, final Object cst) {
+ if (cst == null) {
+ buf.append("null");
+ } else if (cst instanceof String) {
+ appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append("Type.getType(\"");
+ buf.append(((Type) cst).getDescriptor());
+ buf.append("\")");
+ } else if (cst instanceof Handle) {
+ buf.append("new Handle(");
+ Handle h = (Handle) cst;
+ buf.append("Opcodes.").append(HANDLE_TAG[h.getTag()]).append(", \"");
+ buf.append(h.getOwner()).append("\", \"");
+ buf.append(h.getName()).append("\", \"");
+ buf.append(h.getDesc()).append("\")");
+ } else if (cst instanceof Byte) {
+ buf.append("new Byte((byte)").append(cst).append(')');
+ } else if (cst instanceof Boolean) {
+ buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE" : "Boolean.FALSE");
+ } else if (cst instanceof Short) {
+ buf.append("new Short((short)").append(cst).append(')');
+ } else if (cst instanceof Character) {
+ int c = ((Character) cst).charValue();
+ buf.append("new Character((char)").append(c).append(')');
+ } else if (cst instanceof Integer) {
+ buf.append("new Integer(").append(cst).append(')');
+ } else if (cst instanceof Float) {
+ buf.append("new Float(\"").append(cst).append("\")");
+ } else if (cst instanceof Long) {
+ buf.append("new Long(").append(cst).append("L)");
+ } else if (cst instanceof Double) {
+ buf.append("new Double(\"").append(cst).append("\")");
+ } else if (cst instanceof byte[]) {
+ byte[] v = (byte[]) cst;
+ buf.append("new byte[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof boolean[]) {
+ boolean[] v = (boolean[]) cst;
+ buf.append("new boolean[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof short[]) {
+ short[] v = (short[]) cst;
+ buf.append("new short[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof char[]) {
+ char[] v = (char[]) cst;
+ buf.append("new char[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",")
+ .append("(char)")
+ .append((int) v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof int[]) {
+ int[] v = (int[]) cst;
+ buf.append("new int[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof long[]) {
+ long[] v = (long[]) cst;
+ buf.append("new long[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('L');
+ }
+ buf.append('}');
+ } else if (cst instanceof float[]) {
+ float[] v = (float[]) cst;
+ buf.append("new float[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('f');
+ }
+ buf.append('}');
+ } else if (cst instanceof double[]) {
+ double[] v = (double[]) cst;
+ buf.append("new double[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('d');
+ }
+ buf.append('}');
+ }
+ }
+
+ private void declareFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (o[i] instanceof Label) {
+ declareLabel((Label) o[i]);
+ }
+ }
+ }
+
+ private void appendFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (i > 0) {
+ buf.append(", ");
+ }
+ if (o[i] instanceof String) {
+ appendConstant(o[i]);
+ } else if (o[i] instanceof Integer) {
+ switch (((Integer) o[i]).intValue()) {
+ case 0:
+ buf.append("Opcodes.TOP");
+ break;
+ case 1:
+ buf.append("Opcodes.INTEGER");
+ break;
+ case 2:
+ buf.append("Opcodes.FLOAT");
+ break;
+ case 3:
+ buf.append("Opcodes.DOUBLE");
+ break;
+ case 4:
+ buf.append("Opcodes.LONG");
+ break;
+ case 5:
+ buf.append("Opcodes.NULL");
+ break;
+ case 6:
+ buf.append("Opcodes.UNINITIALIZED_THIS");
+ break;
+ }
+ } else {
+ appendLabel((Label) o[i]);
+ }
+ }
+ }
+
+ /**
+ * Appends a declaration of the given label to {@link #buf buf}. This
+ * declaration is of the form "Label lXXX = new Label();". Does nothing if
+ * the given label has already been declared.
+ *
+ * @param l a label.
+ */
+ protected void declareLabel(final Label l) {
+ if (labelNames == null) {
+ labelNames = new HashMap<Label, String>();
+ }
+ String name = labelNames.get(l);
+ if (name == null) {
+ name = "l" + labelNames.size();
+ labelNames.put(l, name);
+ buf.append("Label ").append(name).append(" = new Label();\n");
+ }
+ }
+
+ /**
+ * Appends the name of the given label to {@link #buf buf}. The given label
+ * <i>must</i> already have a name. One way to ensure this is to always
+ * call {@link #declareLabel declared} before calling this method.
+ *
+ * @param l a label.
+ */
+ protected void appendLabel(final Label l) {
+ buf.append(labelNames.get(l));
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/CheckAnnotationAdapter.java b/src/compiler/scala/tools/asm/util/CheckAnnotationAdapter.java
new file mode 100644
index 0000000000..8030c14f2e
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/CheckAnnotationAdapter.java
@@ -0,0 +1,142 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckAnnotationAdapter extends AnnotationVisitor {
+
+ private final boolean named;
+
+ private boolean end;
+
+ public CheckAnnotationAdapter(final AnnotationVisitor av) {
+ this(av, true);
+ }
+
+ CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {
+ super(Opcodes.ASM4, av);
+ this.named = named;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ checkEnd();
+ checkName(name);
+ if (!(value instanceof Byte || value instanceof Boolean
+ || value instanceof Character || value instanceof Short
+ || value instanceof Integer || value instanceof Long
+ || value instanceof Float || value instanceof Double
+ || value instanceof String || value instanceof Type
+ || value instanceof byte[] || value instanceof boolean[]
+ || value instanceof char[] || value instanceof short[]
+ || value instanceof int[] || value instanceof long[]
+ || value instanceof float[] || value instanceof double[]))
+ {
+ throw new IllegalArgumentException("Invalid annotation value");
+ }
+ if (value instanceof Type) {
+ int sort = ((Type) value).getSort();
+ if (sort != Type.OBJECT && sort != Type.ARRAY) {
+ throw new IllegalArgumentException("Invalid annotation value");
+ }
+ }
+ if (av != null) {
+ av.visit(name, value);
+ }
+ }
+
+ @Override
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ checkEnd();
+ checkName(name);
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (value == null) {
+ throw new IllegalArgumentException("Invalid enum value");
+ }
+ if (av != null) {
+ av.visitEnum(name, desc, value);
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ checkEnd();
+ checkName(name);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(av == null
+ ? null
+ : av.visitAnnotation(name, desc));
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ checkEnd();
+ checkName(name);
+ return new CheckAnnotationAdapter(av == null
+ ? null
+ : av.visitArray(name), false);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
+ }
+ }
+
+ private void checkName(final String name) {
+ if (named && name == null) {
+ throw new IllegalArgumentException("Annotation value name must not be null");
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/CheckClassAdapter.java b/src/compiler/scala/tools/asm/util/CheckClassAdapter.java
new file mode 100644
index 0000000000..a455322531
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/CheckClassAdapter.java
@@ -0,0 +1,603 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.ClassReader;
+import scala.tools.asm.ClassVisitor;
+import scala.tools.asm.FieldVisitor;
+import scala.tools.asm.Label;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.ClassNode;
+import scala.tools.asm.tree.MethodNode;
+import scala.tools.asm.tree.analysis.Analyzer;
+import scala.tools.asm.tree.analysis.BasicValue;
+import scala.tools.asm.tree.analysis.Frame;
+import scala.tools.asm.tree.analysis.SimpleVerifier;
+
+/**
+ * A {@link ClassVisitor} that checks that its methods are properly used. More
+ * precisely this class adapter checks each method call individually, based
+ * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
+ * of method calls. For example, the invalid sequence
+ * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
+ * "i", "D", null)</tt>
+ * will <i>not</i> be detected by this class adapter.
+ *
+ * <p><code>CheckClassAdapter</code> can be also used to verify bytecode
+ * transformations in order to make sure transformed bytecode is sane. For
+ * example:
+ *
+ * <pre>
+ * InputStream is = ...; // get bytes for the source class
+ * ClassReader cr = new ClassReader(is);
+ * ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
+ * ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));
+ * cr.accept(cv, 0);
+ *
+ * StringWriter sw = new StringWriter();
+ * PrintWriter pw = new PrintWriter(sw);
+ * CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
+ * assertTrue(sw.toString(), sw.toString().length()==0);
+ * </pre>
+ *
+ * Above code runs transformed bytecode trough the
+ * <code>CheckClassAdapter</code>. It won't be exactly the same verification
+ * as JVM does, but it run data flow analysis for the code of each method and
+ * checks that expectations are met for each method instruction.
+ *
+ * <p>If method bytecode has errors, assertion text will show the erroneous
+ * instruction number and dump of the failed method with information about
+ * locals and stack slot for each instruction. For example (format is -
+ * insnNumber locals : stack):
+ *
+ * <pre>
+ * org.objectweb.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
+ * at org.objectweb.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
+ * at org.objectweb.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)
+ * ...
+ * remove()V
+ * 00000 LinkedBlockingQueue$Itr . . . . . . . . :
+ * ICONST_0
+ * 00001 LinkedBlockingQueue$Itr . . . . . . . . : I
+ * ISTORE 2
+ * 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
+ * ...
+ *
+ * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
+ * ILOAD 1
+ * 00072 <b>?</b>
+ * INVOKESPECIAL java/lang/Integer.<init> (I)V
+ * ...
+ * </pre>
+ *
+ * In the above output you can see that variable 1 loaded by
+ * <code>ILOAD 1</code> instruction at position <code>00071</code> is not
+ * initialized. You can also see that at the beginning of the method (code
+ * inserted by the transformation) variable 2 is initialized.
+ *
+ * <p>Note that when used like that, <code>CheckClassAdapter.verify()</code>
+ * can trigger additional class loading, because it is using
+ * <code>SimpleVerifier</code>.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckClassAdapter extends ClassVisitor {
+
+ /**
+ * The class version number.
+ */
+ private int version;
+
+ /**
+ * <tt>true</tt> if the visit method has been called.
+ */
+ private boolean start;
+
+ /**
+ * <tt>true</tt> if the visitSource method has been called.
+ */
+ private boolean source;
+
+ /**
+ * <tt>true</tt> if the visitOuterClass method has been called.
+ */
+ private boolean outer;
+
+ /**
+ * <tt>true</tt> if the visitEnd method has been called.
+ */
+ private boolean end;
+
+ /**
+ * The already visited labels. This map associate Integer values to Label
+ * keys.
+ */
+ private Map<Label, Integer> labels;
+
+ /**
+ * <tt>true</tt> if the method code must be checked with a BasicVerifier.
+ */
+ private boolean checkDataFlow;
+
+ /**
+ * Checks a given class. <p> Usage: CheckClassAdapter &lt;binary
+ * class name or class file name&gt;
+ *
+ * @param args the command line arguments.
+ *
+ * @throws Exception if the class cannot be found, or if an IO exception
+ * occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ if (args.length != 1) {
+ System.err.println("Verifies the given class.");
+ System.err.println("Usage: CheckClassAdapter "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[0].endsWith(".class")) {
+ cr = new ClassReader(new FileInputStream(args[0]));
+ } else {
+ cr = new ClassReader(args[0]);
+ }
+
+ verify(cr, false, new PrintWriter(System.err));
+ }
+
+ /**
+ * Checks a given class.
+ *
+ * @param cr a <code>ClassReader</code> that contains bytecode for the
+ * analysis.
+ * @param loader a <code>ClassLoader</code> which will be used to load
+ * referenced classes. This is useful if you are verifiying multiple
+ * interdependent classes.
+ * @param dump true if bytecode should be printed out not only when errors
+ * are found.
+ * @param pw write where results going to be printed
+ */
+ public static void verify(
+ final ClassReader cr,
+ final ClassLoader loader,
+ final boolean dump,
+ final PrintWriter pw)
+ {
+ ClassNode cn = new ClassNode();
+ cr.accept(new CheckClassAdapter(cn, false), ClassReader.SKIP_DEBUG);
+
+ Type syperType = cn.superName == null
+ ? null
+ : Type.getObjectType(cn.superName);
+ List<MethodNode> methods = cn.methods;
+
+ List<Type> interfaces = new ArrayList<Type>();
+ for (Iterator<String> i = cn.interfaces.iterator(); i.hasNext();) {
+ interfaces.add(Type.getObjectType(i.next().toString()));
+ }
+
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodNode method = methods.get(i);
+ SimpleVerifier verifier = new SimpleVerifier(Type.getObjectType(cn.name),
+ syperType,
+ interfaces,
+ (cn.access & Opcodes.ACC_INTERFACE) != 0);
+ Analyzer<BasicValue> a = new Analyzer<BasicValue>(verifier);
+ if (loader != null) {
+ verifier.setClassLoader(loader);
+ }
+ try {
+ a.analyze(cn.name, method);
+ if (!dump) {
+ continue;
+ }
+ } catch (Exception e) {
+ e.printStackTrace(pw);
+ }
+ printAnalyzerResult(method, a, pw);
+ }
+ pw.flush();
+ }
+
+ /**
+ * Checks a given class
+ *
+ * @param cr a <code>ClassReader</code> that contains bytecode for the
+ * analysis.
+ * @param dump true if bytecode should be printed out not only when errors
+ * are found.
+ * @param pw write where results going to be printed
+ */
+ public static void verify(
+ final ClassReader cr,
+ final boolean dump,
+ final PrintWriter pw)
+ {
+ verify(cr, null, dump, pw);
+ }
+
+ static void printAnalyzerResult(
+ MethodNode method,
+ Analyzer<BasicValue> a,
+ final PrintWriter pw)
+ {
+ Frame<BasicValue>[] frames = a.getFrames();
+ Textifier t = new Textifier();
+ TraceMethodVisitor mv = new TraceMethodVisitor(t);
+
+ pw.println(method.name + method.desc);
+ for (int j = 0; j < method.instructions.size(); ++j) {
+ method.instructions.get(j).accept(mv);
+
+ StringBuffer s = new StringBuffer();
+ Frame<BasicValue> f = frames[j];
+ if (f == null) {
+ s.append('?');
+ } else {
+ for (int k = 0; k < f.getLocals(); ++k) {
+ s.append(getShortName(f.getLocal(k).toString()))
+ .append(' ');
+ }
+ s.append(" : ");
+ for (int k = 0; k < f.getStackSize(); ++k) {
+ s.append(getShortName(f.getStack(k).toString()))
+ .append(' ');
+ }
+ }
+ while (s.length() < method.maxStack + method.maxLocals + 1) {
+ s.append(' ');
+ }
+ pw.print(Integer.toString(j + 100000).substring(1));
+ pw.print(" " + s + " : " + t.text.get(t.text.size() - 1));
+ }
+ for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
+ method.tryCatchBlocks.get(j).accept(mv);
+ pw.print(" " + t.text.get(t.text.size() - 1));
+ }
+ pw.println();
+ }
+
+ private static String getShortName(final String name) {
+ int n = name.lastIndexOf('/');
+ int k = name.length();
+ if (name.charAt(k - 1) == ';') {
+ k--;
+ }
+ return n == -1 ? name : name.substring(n + 1, k);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @param cv the class visitor to which this adapter must delegate calls.
+ */
+ public CheckClassAdapter(final ClassVisitor cv) {
+ this(cv, true);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckClassAdapter(int, ClassVisitor, boolean)} version.
+ *
+ * @param cv the class visitor to which this adapter must delegate calls.
+ * @param checkDataFlow <tt>true</tt> to perform basic data flow checks, or
+ * <tt>false</tt> to not perform any data flow check (see
+ * {@link CheckMethodAdapter}). This option requires valid maxLocals
+ * and maxStack values.
+ */
+ public CheckClassAdapter(final ClassVisitor cv, final boolean checkDataFlow)
+ {
+ this(Opcodes.ASM4, cv, checkDataFlow);
+ }
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param cv the class visitor to which this adapter must delegate calls.
+ * @param checkDataFlow <tt>true</tt> to perform basic data flow checks, or
+ * <tt>false</tt> to not perform any data flow check (see
+ * {@link CheckMethodAdapter}). This option requires valid maxLocals
+ * and maxStack values.
+ */
+ protected CheckClassAdapter(
+ final int api,
+ final ClassVisitor cv,
+ final boolean checkDataFlow)
+ {
+ super(api, cv);
+ this.labels = new HashMap<Label, Integer>();
+ this.checkDataFlow = checkDataFlow;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ if (start) {
+ throw new IllegalStateException("visit must be called only once");
+ }
+ start = true;
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
+ + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+ + Opcodes.ACC_DEPRECATED
+ + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ if (name == null || !name.endsWith("package-info")) {
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ }
+ if ("java/lang/Object".equals(name)) {
+ if (superName != null) {
+ throw new IllegalArgumentException("The super class name of the Object class must be 'null'");
+ }
+ } else {
+ CheckMethodAdapter.checkInternalName(superName, "super class name");
+ }
+ if (signature != null) {
+ CheckMethodAdapter.checkClassSignature(signature);
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!"java/lang/Object".equals(superName)) {
+ throw new IllegalArgumentException("The super class name of interfaces must be 'java/lang/Object'");
+ }
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ CheckMethodAdapter.checkInternalName(interfaces[i],
+ "interface name at index " + i);
+ }
+ }
+ this.version = version;
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ checkState();
+ if (source) {
+ throw new IllegalStateException("visitSource can be called only once.");
+ }
+ source = true;
+ super.visitSource(file, debug);
+ }
+
+ @Override
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ checkState();
+ if (outer) {
+ throw new IllegalStateException("visitOuterClass can be called only once.");
+ }
+ outer = true;
+ if (owner == null) {
+ throw new IllegalArgumentException("Illegal outer class owner");
+ }
+ if (desc != null) {
+ CheckMethodAdapter.checkMethodDesc(desc);
+ }
+ super.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ checkState();
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ if (outerName != null) {
+ CheckMethodAdapter.checkInternalName(outerName, "outer class name");
+ }
+ if (innerName != null) {
+ CheckMethodAdapter.checkIdentifier(innerName, "inner class name");
+ }
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
+ + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED
+ + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ CheckMethodAdapter.checkUnqualifiedName(version, name, "field name");
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (signature != null) {
+ CheckMethodAdapter.checkFieldSignature(signature);
+ }
+ if (value != null) {
+ CheckMethodAdapter.checkConstant(value);
+ }
+ FieldVisitor av = super.visitField(access, name, desc, signature, value);
+ return new CheckFieldAdapter(av);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
+ + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
+ + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED
+ + 0x40000); // ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ CheckMethodAdapter.checkMethodIdentifier(version, name, "method name");
+ CheckMethodAdapter.checkMethodDesc(desc);
+ if (signature != null) {
+ CheckMethodAdapter.checkMethodSignature(signature);
+ }
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; ++i) {
+ CheckMethodAdapter.checkInternalName(exceptions[i],
+ "exception name at index " + i);
+ }
+ }
+ CheckMethodAdapter cma;
+ if (checkDataFlow) {
+ cma = new CheckMethodAdapter(access,
+ name,
+ desc,
+ super.visitMethod(access, name, desc, signature, exceptions),
+ labels);
+ } else {
+ cma = new CheckMethodAdapter(super.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions), labels);
+ }
+ cma.version = version;
+ return cma;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ checkState();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkState();
+ if (attr == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkState();
+ end = true;
+ super.visitEnd();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that the visit method has been called and that visitEnd has not
+ * been called.
+ */
+ private void checkState() {
+ if (!start) {
+ throw new IllegalStateException("Cannot visit member before visit has been called.");
+ }
+ if (end) {
+ throw new IllegalStateException("Cannot visit member after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks that the given access flags do not contain invalid flags. This
+ * method also checks that mutually incompatible flags are not set
+ * simultaneously.
+ *
+ * @param access the access flags to be checked
+ * @param possibleAccess the valid access flags.
+ */
+ static void checkAccess(final int access, final int possibleAccess) {
+ if ((access & ~possibleAccess) != 0) {
+ throw new IllegalArgumentException("Invalid access flags: "
+ + access);
+ }
+ int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
+ int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
+ int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
+ if (pub + pri + pro > 1) {
+ throw new IllegalArgumentException("public private and protected are mutually exclusive: "
+ + access);
+ }
+ int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
+ int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
+ if (fin + abs > 1) {
+ throw new IllegalArgumentException("final and abstract are mutually exclusive: "
+ + access);
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/CheckFieldAdapter.java b/src/compiler/scala/tools/asm/util/CheckFieldAdapter.java
new file mode 100644
index 0000000000..bdcbe14b16
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/CheckFieldAdapter.java
@@ -0,0 +1,97 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.FieldVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A {@link FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter extends FieldVisitor {
+
+ private boolean end;
+
+ /**
+ * Constructs a new {@link CheckFieldAdapter}. <i>Subclasses must not use
+ * this constructor</i>. Instead, they must use the
+ * {@link #CheckFieldAdapter(int, FieldVisitor)} version.
+ *
+ * @param fv the field visitor to which this adapter must delegate calls.
+ */
+ public CheckFieldAdapter(final FieldVisitor fv) {
+ this(Opcodes.ASM4, fv);
+ }
+
+ /**
+ * Constructs a new {@link CheckFieldAdapter}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param fv the field visitor to which this adapter must delegate calls.
+ */
+ protected CheckFieldAdapter(final int api, final FieldVisitor fv) {
+ super(api, fv);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ checkEnd();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEnd();
+ if (attr == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ super.visitEnd();
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/CheckMethodAdapter.java b/src/compiler/scala/tools/asm/util/CheckMethodAdapter.java
new file mode 100644
index 0000000000..7549765421
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/CheckMethodAdapter.java
@@ -0,0 +1,1668 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.Handle;
+import scala.tools.asm.Label;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+import scala.tools.asm.tree.MethodNode;
+import scala.tools.asm.tree.analysis.Analyzer;
+import scala.tools.asm.tree.analysis.BasicValue;
+import scala.tools.asm.tree.analysis.BasicVerifier;
+
+/**
+ * A {@link MethodVisitor} that checks that its methods are properly used. More
+ * precisely this method adapter checks each instruction individually, i.e.,
+ * each visit method checks some preconditions based <i>only</i> on its
+ * arguments - such as the fact that the given opcode is correct for a given
+ * visit method. This adapter can also perform some basic data flow checks (more
+ * precisely those that can be performed without the full class hierarchy - see
+ * {@link org.objectweb.asm.tree.analysis.BasicVerifier}). For instance in a
+ * method whose signature is <tt>void m ()</tt>, the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will be detected if the data flow
+ * checks are enabled. These checks are enabled by using the
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)} constructor.
+ * They are not performed if any other constructor is used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodVisitor {
+
+ /**
+ * The class version number.
+ */
+ public int version;
+
+ /**
+ * <tt>true</tt> if the visitCode method has been called.
+ */
+ private boolean startCode;
+
+ /**
+ * <tt>true</tt> if the visitMaxs method has been called.
+ */
+ private boolean endCode;
+
+ /**
+ * <tt>true</tt> if the visitEnd method has been called.
+ */
+ private boolean endMethod;
+
+ /**
+ * Number of visited instructions.
+ */
+ private int insnCount;
+
+ /**
+ * The already visited labels. This map associate Integer values to pseudo
+ * code offsets.
+ */
+ private final Map<Label, Integer> labels;
+
+ /**
+ * The labels used in this method. Every used label must be visited with
+ * visitLabel before the end of the method (i.e. should be in #labels).
+ */
+ private Set<Label> usedLabels;
+
+ /**
+ * The exception handler ranges. Each pair of list element contains the
+ * start and end labels of an exception handler block.
+ */
+ private List<Label> handlers;
+
+ /**
+ * Code of the visit method to be used for each opcode.
+ */
+ private static final int[] TYPE;
+
+ /**
+ * The Label.status field.
+ */
+ private static Field labelStatusField;
+
+ static {
+ String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
+ + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+ + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
+ + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+ TYPE = new int[s.length()];
+ for (int i = 0; i < TYPE.length; ++i) {
+ TYPE[i] = s.charAt(i) - 'A' - 1;
+ }
+ }
+
+ // code to generate the above string
+ // public static void main (String[] args) {
+ // int[] TYPE = new int[] {
+ // 0, //NOP
+ // 0, //ACONST_NULL
+ // 0, //ICONST_M1
+ // 0, //ICONST_0
+ // 0, //ICONST_1
+ // 0, //ICONST_2
+ // 0, //ICONST_3
+ // 0, //ICONST_4
+ // 0, //ICONST_5
+ // 0, //LCONST_0
+ // 0, //LCONST_1
+ // 0, //FCONST_0
+ // 0, //FCONST_1
+ // 0, //FCONST_2
+ // 0, //DCONST_0
+ // 0, //DCONST_1
+ // 1, //BIPUSH
+ // 1, //SIPUSH
+ // 7, //LDC
+ // -1, //LDC_W
+ // -1, //LDC2_W
+ // 2, //ILOAD
+ // 2, //LLOAD
+ // 2, //FLOAD
+ // 2, //DLOAD
+ // 2, //ALOAD
+ // -1, //ILOAD_0
+ // -1, //ILOAD_1
+ // -1, //ILOAD_2
+ // -1, //ILOAD_3
+ // -1, //LLOAD_0
+ // -1, //LLOAD_1
+ // -1, //LLOAD_2
+ // -1, //LLOAD_3
+ // -1, //FLOAD_0
+ // -1, //FLOAD_1
+ // -1, //FLOAD_2
+ // -1, //FLOAD_3
+ // -1, //DLOAD_0
+ // -1, //DLOAD_1
+ // -1, //DLOAD_2
+ // -1, //DLOAD_3
+ // -1, //ALOAD_0
+ // -1, //ALOAD_1
+ // -1, //ALOAD_2
+ // -1, //ALOAD_3
+ // 0, //IALOAD
+ // 0, //LALOAD
+ // 0, //FALOAD
+ // 0, //DALOAD
+ // 0, //AALOAD
+ // 0, //BALOAD
+ // 0, //CALOAD
+ // 0, //SALOAD
+ // 2, //ISTORE
+ // 2, //LSTORE
+ // 2, //FSTORE
+ // 2, //DSTORE
+ // 2, //ASTORE
+ // -1, //ISTORE_0
+ // -1, //ISTORE_1
+ // -1, //ISTORE_2
+ // -1, //ISTORE_3
+ // -1, //LSTORE_0
+ // -1, //LSTORE_1
+ // -1, //LSTORE_2
+ // -1, //LSTORE_3
+ // -1, //FSTORE_0
+ // -1, //FSTORE_1
+ // -1, //FSTORE_2
+ // -1, //FSTORE_3
+ // -1, //DSTORE_0
+ // -1, //DSTORE_1
+ // -1, //DSTORE_2
+ // -1, //DSTORE_3
+ // -1, //ASTORE_0
+ // -1, //ASTORE_1
+ // -1, //ASTORE_2
+ // -1, //ASTORE_3
+ // 0, //IASTORE
+ // 0, //LASTORE
+ // 0, //FASTORE
+ // 0, //DASTORE
+ // 0, //AASTORE
+ // 0, //BASTORE
+ // 0, //CASTORE
+ // 0, //SASTORE
+ // 0, //POP
+ // 0, //POP2
+ // 0, //DUP
+ // 0, //DUP_X1
+ // 0, //DUP_X2
+ // 0, //DUP2
+ // 0, //DUP2_X1
+ // 0, //DUP2_X2
+ // 0, //SWAP
+ // 0, //IADD
+ // 0, //LADD
+ // 0, //FADD
+ // 0, //DADD
+ // 0, //ISUB
+ // 0, //LSUB
+ // 0, //FSUB
+ // 0, //DSUB
+ // 0, //IMUL
+ // 0, //LMUL
+ // 0, //FMUL
+ // 0, //DMUL
+ // 0, //IDIV
+ // 0, //LDIV
+ // 0, //FDIV
+ // 0, //DDIV
+ // 0, //IREM
+ // 0, //LREM
+ // 0, //FREM
+ // 0, //DREM
+ // 0, //INEG
+ // 0, //LNEG
+ // 0, //FNEG
+ // 0, //DNEG
+ // 0, //ISHL
+ // 0, //LSHL
+ // 0, //ISHR
+ // 0, //LSHR
+ // 0, //IUSHR
+ // 0, //LUSHR
+ // 0, //IAND
+ // 0, //LAND
+ // 0, //IOR
+ // 0, //LOR
+ // 0, //IXOR
+ // 0, //LXOR
+ // 8, //IINC
+ // 0, //I2L
+ // 0, //I2F
+ // 0, //I2D
+ // 0, //L2I
+ // 0, //L2F
+ // 0, //L2D
+ // 0, //F2I
+ // 0, //F2L
+ // 0, //F2D
+ // 0, //D2I
+ // 0, //D2L
+ // 0, //D2F
+ // 0, //I2B
+ // 0, //I2C
+ // 0, //I2S
+ // 0, //LCMP
+ // 0, //FCMPL
+ // 0, //FCMPG
+ // 0, //DCMPL
+ // 0, //DCMPG
+ // 6, //IFEQ
+ // 6, //IFNE
+ // 6, //IFLT
+ // 6, //IFGE
+ // 6, //IFGT
+ // 6, //IFLE
+ // 6, //IF_ICMPEQ
+ // 6, //IF_ICMPNE
+ // 6, //IF_ICMPLT
+ // 6, //IF_ICMPGE
+ // 6, //IF_ICMPGT
+ // 6, //IF_ICMPLE
+ // 6, //IF_ACMPEQ
+ // 6, //IF_ACMPNE
+ // 6, //GOTO
+ // 6, //JSR
+ // 2, //RET
+ // 9, //TABLESWITCH
+ // 10, //LOOKUPSWITCH
+ // 0, //IRETURN
+ // 0, //LRETURN
+ // 0, //FRETURN
+ // 0, //DRETURN
+ // 0, //ARETURN
+ // 0, //RETURN
+ // 4, //GETSTATIC
+ // 4, //PUTSTATIC
+ // 4, //GETFIELD
+ // 4, //PUTFIELD
+ // 5, //INVOKEVIRTUAL
+ // 5, //INVOKESPECIAL
+ // 5, //INVOKESTATIC
+ // 5, //INVOKEINTERFACE
+ // -1, //INVOKEDYNAMIC
+ // 3, //NEW
+ // 1, //NEWARRAY
+ // 3, //ANEWARRAY
+ // 0, //ARRAYLENGTH
+ // 0, //ATHROW
+ // 3, //CHECKCAST
+ // 3, //INSTANCEOF
+ // 0, //MONITORENTER
+ // 0, //MONITOREXIT
+ // -1, //WIDE
+ // 11, //MULTIANEWARRAY
+ // 6, //IFNULL
+ // 6, //IFNONNULL
+ // -1, //GOTO_W
+ // -1 //JSR_W
+ // };
+ // for (int i = 0; i < TYPE.length; ++i) {
+ // System.out.print((char)(TYPE[i] + 1 + 'A'));
+ // }
+ // System.out.println();
+ // }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use
+ * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param mv the method visitor to which this adapter must delegate calls.
+ */
+ public CheckMethodAdapter(final MethodVisitor mv) {
+ this(mv, new HashMap<Label, Integer>());
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ * <i>Subclasses must not use this constructor</i>. Instead, they must use
+ * the {@link #CheckMethodAdapter(int, MethodVisitor, Map)} version.
+ *
+ * @param mv the method visitor to which this adapter must delegate calls.
+ * @param labels a map of already visited labels (in other methods).
+ */
+ public CheckMethodAdapter(
+ final MethodVisitor mv,
+ final Map<Label, Integer> labels)
+ {
+ this(Opcodes.ASM4, mv, labels);
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will not perform any data flow check (see
+ * {@link #CheckMethodAdapter(int,String,String,MethodVisitor,Map)}).
+ *
+ * @param mv the method visitor to which this adapter must delegate calls.
+ * @param labels a map of already visited labels (in other methods).
+ */
+ protected CheckMethodAdapter(
+ final int api,
+ final MethodVisitor mv,
+ final Map<Label, Integer> labels)
+ {
+ super(api, mv);
+ this.labels = labels;
+ this.usedLabels = new HashSet<Label>();
+ this.handlers = new ArrayList<Label>();
+ }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object. This method adapter
+ * will perform basic data flow checks. For instance in a method whose
+ * signature is <tt>void m ()</tt>, the invalid instruction IRETURN, or the
+ * invalid sequence IADD L2I will be detected.
+ *
+ * @param access the method's access flags.
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type Type}).
+ * @param cmv the method visitor to which this adapter must delegate calls.
+ * @param labels a map of already visited labels (in other methods).
+ */
+ public CheckMethodAdapter(
+ final int access,
+ final String name,
+ final String desc,
+ final MethodVisitor cmv,
+ final Map<Label, Integer> labels)
+ {
+ this(new MethodNode(access, name, desc, null, null) {
+ @Override
+ public void visitEnd() {
+ Analyzer<BasicValue> a = new Analyzer<BasicValue>(new BasicVerifier());
+ try {
+ a.analyze("dummy", this);
+ } catch (Exception e) {
+ if (e instanceof IndexOutOfBoundsException
+ && maxLocals == 0 && maxStack == 0)
+ {
+ throw new RuntimeException("Data flow checking option requires valid, non zero maxLocals and maxStack values.");
+ }
+ e.printStackTrace();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw, true);
+ CheckClassAdapter.printAnalyzerResult(this, a, pw);
+ pw.close();
+ throw new RuntimeException(e.getMessage() + ' '
+ + sw.toString());
+ }
+ accept(cmv);
+ }
+ },
+ labels);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitAnnotation(desc, visible));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ checkEndMethod();
+ return new CheckAnnotationAdapter(super.visitAnnotationDefault(), false);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(super.visitParameterAnnotation(parameter,
+ desc,
+ visible));
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ checkEndMethod();
+ if (attr == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
+ }
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitCode() {
+ startCode = true;
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ int mLocal;
+ int mStack;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mLocal = Integer.MAX_VALUE;
+ mStack = Integer.MAX_VALUE;
+ break;
+
+ case Opcodes.F_SAME:
+ mLocal = 0;
+ mStack = 0;
+ break;
+
+ case Opcodes.F_SAME1:
+ mLocal = 0;
+ mStack = 1;
+ break;
+
+ case Opcodes.F_APPEND:
+ case Opcodes.F_CHOP:
+ mLocal = 3;
+ mStack = 0;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Invalid frame type " + type);
+ }
+
+ if (nLocal > mLocal) {
+ throw new IllegalArgumentException("Invalid nLocal=" + nLocal
+ + " for frame type " + type);
+ }
+ if (nStack > mStack) {
+ throw new IllegalArgumentException("Invalid nStack=" + nStack
+ + " for frame type " + type);
+ }
+
+ if (type != Opcodes.F_CHOP) {
+ if (nLocal > 0 && (local == null || local.length < nLocal)) {
+ throw new IllegalArgumentException("Array local[] is shorter than nLocal");
+ }
+ for (int i = 0; i < nLocal; ++i) {
+ checkFrameValue(local[i]);
+ }
+ }
+ if (nStack > 0 && (stack == null || stack.length < nStack)) {
+ throw new IllegalArgumentException("Array stack[] is shorter than nStack");
+ }
+ for (int i = 0; i < nStack; ++i) {
+ checkFrameValue(stack[i]);
+ }
+
+ super.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 0);
+ super.visitInsn(opcode);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 1);
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ checkSignedByte(operand, "Invalid operand");
+ break;
+ case Opcodes.SIPUSH:
+ checkSignedShort(operand, "Invalid operand");
+ break;
+ // case Constants.NEWARRAY:
+ default:
+ if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+ throw new IllegalArgumentException("Invalid operand (must be an array type code T_...): "
+ + operand);
+ }
+ }
+ super.visitIntInsn(opcode, operand);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 2);
+ checkUnsignedShort(var, "Invalid variable index");
+ super.visitVarInsn(opcode, var);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 3);
+ checkInternalName(type, "type");
+ if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+ throw new IllegalArgumentException("NEW cannot be used to create arrays: "
+ + type);
+ }
+ super.visitTypeInsn(opcode, type);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 4);
+ checkInternalName(owner, "owner");
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ super.visitFieldInsn(opcode, owner, name, desc);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 5);
+ checkMethodIdentifier(version, name, "name");
+ checkInternalName(owner, "owner");
+ checkMethodDesc(desc);
+ super.visitMethodInsn(opcode, owner, name, desc);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ String name,
+ String desc,
+ Handle bsm,
+ Object... bsmArgs)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkMethodIdentifier(version, name, "name");
+ checkMethodDesc(desc);
+ if (bsm.getTag() != Opcodes.H_INVOKESTATIC
+ && bsm.getTag() != Opcodes.H_NEWINVOKESPECIAL)
+ {
+ throw new IllegalArgumentException("invalid handle tag "
+ + bsm.getTag());
+ }
+ for (int i = 0; i < bsmArgs.length; i++) {
+ checkLDCConstant(bsmArgs[i]);
+ }
+ super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 6);
+ checkLabel(label, false, "label");
+ checkNonDebugLabel(label);
+ super.visitJumpInsn(opcode, label);
+ usedLabels.add(label);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(label, false, "label");
+ if (labels.get(label) != null) {
+ throw new IllegalArgumentException("Already visited label");
+ }
+ labels.put(label, new Integer(insnCount));
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ checkStartCode();
+ checkEndCode();
+ checkLDCConstant(cst);
+ super.visitLdcInsn(cst);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(var, "Invalid variable index");
+ checkSignedShort(increment, "Invalid increment");
+ super.visitIincInsn(var, increment);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label... labels)
+ {
+ checkStartCode();
+ checkEndCode();
+ if (max < min) {
+ throw new IllegalArgumentException("Max = " + max
+ + " must be greater than or equal to min = " + min);
+ }
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (labels == null || labels.length != max - min + 1) {
+ throw new IllegalArgumentException("There must be max - min + 1 labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ checkEndCode();
+ checkStartCode();
+ checkLabel(dflt, false, "default label");
+ checkNonDebugLabel(dflt);
+ if (keys == null || labels == null || keys.length != labels.length) {
+ throw new IllegalArgumentException("There must be the same number of keys and labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ checkNonDebugLabel(labels[i]);
+ }
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ usedLabels.add(dflt);
+ for (int i = 0; i < labels.length; ++i) {
+ usedLabels.add(labels[i]);
+ }
+ ++insnCount;
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ checkStartCode();
+ checkEndCode();
+ checkDesc(desc, false);
+ if (desc.charAt(0) != '[') {
+ throw new IllegalArgumentException("Invalid descriptor (must be an array type descriptor): "
+ + desc);
+ }
+ if (dims < 1) {
+ throw new IllegalArgumentException("Invalid dimensions (must be greater than 0): "
+ + dims);
+ }
+ if (dims > desc.lastIndexOf('[') + 1) {
+ throw new IllegalArgumentException("Invalid dimensions (must not be greater than dims(desc)): "
+ + dims);
+ }
+ super.visitMultiANewArrayInsn(desc, dims);
+ ++insnCount;
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(start, false, "start label");
+ checkLabel(end, false, "end label");
+ checkLabel(handler, false, "handler label");
+ checkNonDebugLabel(start);
+ checkNonDebugLabel(end);
+ checkNonDebugLabel(handler);
+ if (labels.get(start) != null || labels.get(end) != null
+ || labels.get(handler) != null)
+ {
+ throw new IllegalStateException("Try catch blocks must be visited before their labels");
+ }
+ if (type != null) {
+ checkInternalName(type, "type");
+ }
+ super.visitTryCatchBlock(start, end, handler, type);
+ handlers.add(start);
+ handlers.add(end);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkUnqualifiedName(version, name, "name");
+ checkDesc(desc, false);
+ checkLabel(start, true, "start label");
+ checkLabel(end, true, "end label");
+ checkUnsignedShort(index, "Invalid variable index");
+ int s = labels.get(start).intValue();
+ int e = labels.get(end).intValue();
+ if (e < s) {
+ throw new IllegalArgumentException("Invalid start and end labels (end must be greater than start)");
+ }
+ super.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(line, "Invalid line number");
+ checkLabel(start, true, "start label");
+ super.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ checkStartCode();
+ checkEndCode();
+ endCode = true;
+ for (Label l : usedLabels) {
+ if (labels.get(l) == null) {
+ throw new IllegalStateException("Undefined label used");
+ }
+ }
+ for (int i = 0; i < handlers.size(); ) {
+ Integer start = labels.get(handlers.get(i++));
+ Integer end = labels.get(handlers.get(i++));
+ if (start == null || end == null) {
+ throw new IllegalStateException("Undefined try catch block labels");
+ }
+ if (end.intValue() <= start.intValue()) {
+ throw new IllegalStateException("Emty try catch block handler range");
+ }
+ }
+ checkUnsignedShort(maxStack, "Invalid max stack");
+ checkUnsignedShort(maxLocals, "Invalid max locals");
+ super.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ checkEndMethod();
+ endMethod = true;
+ super.visitEnd();
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Checks that the visitCode method has been called.
+ */
+ void checkStartCode() {
+ if (!startCode) {
+ throw new IllegalStateException("Cannot visit instructions before visitCode has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitMaxs method has not been called.
+ */
+ void checkEndCode() {
+ if (endCode) {
+ throw new IllegalStateException("Cannot visit instructions after visitMaxs has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitEnd method has not been called.
+ */
+ void checkEndMethod() {
+ if (endMethod) {
+ throw new IllegalStateException("Cannot visit elements after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks a stack frame value.
+ *
+ * @param value the value to be checked.
+ */
+ void checkFrameValue(final Object value) {
+ if (value == Opcodes.TOP || value == Opcodes.INTEGER
+ || value == Opcodes.FLOAT || value == Opcodes.LONG
+ || value == Opcodes.DOUBLE || value == Opcodes.NULL
+ || value == Opcodes.UNINITIALIZED_THIS)
+ {
+ return;
+ }
+ if (value instanceof String) {
+ checkInternalName((String) value, "Invalid stack frame value");
+ return;
+ }
+ if (!(value instanceof Label)) {
+ throw new IllegalArgumentException("Invalid stack frame value: "
+ + value);
+ } else {
+ usedLabels.add((Label) value);
+ }
+ }
+
+ /**
+ * Checks that the type of the given opcode is equal to the given type.
+ *
+ * @param opcode the opcode to be checked.
+ * @param type the expected opcode type.
+ */
+ static void checkOpcode(final int opcode, final int type) {
+ if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
+ throw new IllegalArgumentException("Invalid opcode: " + opcode);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed byte.
+ *
+ * @param value the value to be checked.
+ * @param msg an message to be used in case of error.
+ */
+ static void checkSignedByte(final int value, final String msg) {
+ if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed byte): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed short.
+ *
+ * @param value the value to be checked.
+ * @param msg an message to be used in case of error.
+ */
+ static void checkSignedShort(final int value, final String msg) {
+ if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an unsigned short.
+ *
+ * @param value the value to be checked.
+ * @param msg an message to be used in case of error.
+ */
+ static void checkUnsignedShort(final int value, final String msg) {
+ if (value < 0 || value > 65535) {
+ throw new IllegalArgumentException(msg
+ + " (must be an unsigned short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an {@link Integer}, a{@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ *
+ * @param cst the value to be checked.
+ */
+ static void checkConstant(final Object cst) {
+ if (!(cst instanceof Integer) && !(cst instanceof Float)
+ && !(cst instanceof Long) && !(cst instanceof Double)
+ && !(cst instanceof String))
+ {
+ throw new IllegalArgumentException("Invalid constant: " + cst);
+ }
+ }
+
+ void checkLDCConstant(final Object cst) {
+ if (cst instanceof Type) {
+ int s = ((Type) cst).getSort();
+ if (s != Type.OBJECT && s != Type.ARRAY && s != Type.METHOD) {
+ throw new IllegalArgumentException("Illegal LDC constant value");
+ }
+ if (s != Type.METHOD && (version & 0xFFFF) < Opcodes.V1_5) {
+ throw new IllegalArgumentException("ldc of a constant class requires at least version 1.5");
+ }
+ if (s == Type.METHOD && (version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException("ldc of a method type requires at least version 1.7");
+ }
+ } else if (cst instanceof Handle) {
+ if ((version & 0xFFFF) < Opcodes.V1_7) {
+ throw new IllegalArgumentException("ldc of a handle requires at least version 1.7");
+ }
+ int tag = ((Handle) cst).getTag();
+ if (tag < Opcodes.H_GETFIELD || tag > Opcodes.H_INVOKEINTERFACE) {
+ throw new IllegalArgumentException("invalid handle tag "
+ + tag);
+ }
+ } else {
+ checkConstant(cst);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid unqualified name.
+ *
+ * @param version the class version.
+ * @param name the string to be checked.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkUnqualifiedName(
+ int version,
+ final String name,
+ final String msg)
+ {
+ if ((version & 0xFFFF) < Opcodes.V1_5) {
+ checkIdentifier(name, msg);
+ } else {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param name the string to be checked.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final String msg) {
+ checkIdentifier(name, 0, -1, msg);
+ }
+
+ /**
+ * Checks that the given substring is a valid Java identifier.
+ *
+ * @param name the string to be checked.
+ * @param start index of the first character of the identifier (inclusive).
+ * @param end index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkIdentifier(
+ final String name,
+ final int start,
+ final int end,
+ final String msg)
+ {
+ if (name == null || (end == -1 ? name.length() <= start : end <= start))
+ {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(start))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ int max = end == -1 ? name.length() : end;
+ for (int i = start + 1; i < max; ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier or is equal to
+ * '&lt;init&gt;' or '&lt;clinit&gt;'.
+ *
+ * @param version the class version.
+ * @param name the string to be checked.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkMethodIdentifier(
+ int version,
+ final String name,
+ final String msg)
+ {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if ("<init>".equals(name) || "<clinit>".equals(name)) {
+ return;
+ }
+ if ((version & 0xFFFF) >= Opcodes.V1_5) {
+ for (int i = 0; i < name.length(); ++i) {
+ if (".;[/<>".indexOf(name.charAt(i)) != -1) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid unqualified name): " + name);
+ }
+ }
+ return;
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+ throw new IllegalArgumentException("Invalid "
+ + msg
+ + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ for (int i = 1; i < name.length(); ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException("Invalid "
+ + msg
+ + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid internal class name.
+ *
+ * @param name the string to be checked.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (name.charAt(0) == '[') {
+ checkDesc(name, false);
+ } else {
+ checkInternalName(name, 0, -1, msg);
+ }
+ }
+
+ /**
+ * Checks that the given substring is a valid internal class name.
+ *
+ * @param name the string to be checked.
+ * @param start index of the first character of the identifier (inclusive).
+ * @param end index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkInternalName(
+ final String name,
+ final int start,
+ final int end,
+ final String msg)
+ {
+ int max = end == -1 ? name.length() : end;
+ try {
+ int begin = start;
+ int slash;
+ do {
+ slash = name.indexOf('/', begin + 1);
+ if (slash == -1 || slash > max) {
+ slash = max;
+ }
+ checkIdentifier(name, begin, slash, null);
+ begin = slash + 1;
+ } while (slash != max);
+ } catch (IllegalArgumentException _) {
+ throw new IllegalArgumentException("Invalid "
+ + msg
+ + " (must be a fully qualified class name in internal form): "
+ + name);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid type descriptor.
+ *
+ * @param desc the string to be checked.
+ * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
+ */
+ static void checkDesc(final String desc, final boolean canBeVoid) {
+ int end = checkDesc(desc, 0, canBeVoid);
+ if (end != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that a the given substring is a valid type descriptor.
+ *
+ * @param desc the string to be checked.
+ * @param start index of the first character of the identifier (inclusive).
+ * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
+ * @return the index of the last character of the type decriptor, plus one.
+ */
+ static int checkDesc(
+ final String desc,
+ final int start,
+ final boolean canBeVoid)
+ {
+ if (desc == null || start >= desc.length()) {
+ throw new IllegalArgumentException("Invalid type descriptor (must not be null or empty)");
+ }
+ int index;
+ switch (desc.charAt(start)) {
+ case 'V':
+ if (canBeVoid) {
+ return start + 1;
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return start + 1;
+ case '[':
+ index = start + 1;
+ while (index < desc.length() && desc.charAt(index) == '[') {
+ ++index;
+ }
+ if (index < desc.length()) {
+ return checkDesc(desc, index, false);
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'L':
+ index = desc.indexOf(';', start);
+ if (index == -1 || index - start < 2) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ try {
+ checkInternalName(desc, start + 1, index, null);
+ } catch (IllegalArgumentException _) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ return index + 1;
+ default:
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid method descriptor.
+ *
+ * @param desc the string to be checked.
+ */
+ static void checkMethodDesc(final String desc) {
+ if (desc == null || desc.length() == 0) {
+ throw new IllegalArgumentException("Invalid method descriptor (must not be null or empty)");
+ }
+ if (desc.charAt(0) != '(' || desc.length() < 3) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ int start = 1;
+ if (desc.charAt(start) != ')') {
+ do {
+ if (desc.charAt(start) == 'V') {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ start = checkDesc(desc, start, false);
+ } while (start < desc.length() && desc.charAt(start) != ')');
+ }
+ start = checkDesc(desc, start + 1, true);
+ if (start != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks a class signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ static void checkClassSignature(final String signature) {
+ // ClassSignature:
+ // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkClassTypeSignature(signature, pos);
+ while (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ static void checkMethodSignature(final String signature) {
+ // MethodTypeSignature:
+ // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
+ // ^ClassTypeSignature | ^TypeVariableSignature )*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkChar('(', signature, pos);
+ while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkTypeSignature(signature, pos);
+ }
+ pos = checkChar(')', signature, pos);
+ if (getChar(signature, pos) == 'V') {
+ ++pos;
+ } else {
+ pos = checkTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == '^') {
+ ++pos;
+ if (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ } else {
+ pos = checkTypeVariableSignature(signature, pos);
+ }
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a field signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ static void checkFieldSignature(final String signature) {
+ int pos = checkFieldTypeSignature(signature, 0);
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks the formal type parameters of a class or method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameters(final String signature, int pos)
+ {
+ // FormalTypeParameters:
+ // < FormalTypeParameter+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkFormalTypeParameter(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkFormalTypeParameter(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a formal type parameter of a class or method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameter(final String signature, int pos)
+ {
+ // FormalTypeParameter:
+ // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
+
+ pos = checkIdentifier(signature, pos);
+ pos = checkChar(':', signature, pos);
+ if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkFieldTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == ':') {
+ pos = checkFieldTypeSignature(signature, pos + 1);
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a field type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFieldTypeSignature(final String signature, int pos)
+ {
+ // FieldTypeSignature:
+ // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
+ //
+ // ArrayTypeSignature:
+ // [ TypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'L':
+ return checkClassTypeSignature(signature, pos);
+ case '[':
+ return checkTypeSignature(signature, pos + 1);
+ default:
+ return checkTypeVariableSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkClassTypeSignature(final String signature, int pos)
+ {
+ // ClassTypeSignature:
+ // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
+ // TypeArguments? )* ;
+
+ pos = checkChar('L', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ while (getChar(signature, pos) == '/') {
+ pos = checkIdentifier(signature, pos + 1);
+ }
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ while (getChar(signature, pos) == '.') {
+ pos = checkIdentifier(signature, pos + 1);
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ }
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks the type arguments in a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArguments(final String signature, int pos) {
+ // TypeArguments:
+ // < TypeArgument+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkTypeArgument(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkTypeArgument(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a type argument in a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArgument(final String signature, int pos) {
+ // TypeArgument:
+ // * | ( ( + | - )? FieldTypeSignature )
+
+ char c = getChar(signature, pos);
+ if (c == '*') {
+ return pos + 1;
+ } else if (c == '+' || c == '-') {
+ pos++;
+ }
+ return checkFieldTypeSignature(signature, pos);
+ }
+
+ /**
+ * Checks a type variable signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeVariableSignature(
+ final String signature,
+ int pos)
+ {
+ // TypeVariableSignature:
+ // T Identifier ;
+
+ pos = checkChar('T', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks a type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeSignature(final String signature, int pos) {
+ // TypeSignature:
+ // Z | C | B | S | I | F | J | D | FieldTypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return pos + 1;
+ default:
+ return checkFieldTypeSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks an identifier.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkIdentifier(final String signature, int pos) {
+ if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
+ throw new IllegalArgumentException(signature
+ + ": identifier expected at index " + pos);
+ }
+ ++pos;
+ while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
+ ++pos;
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a single character.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkChar(final char c, final String signature, int pos)
+ {
+ if (getChar(signature, pos) == c) {
+ return pos + 1;
+ }
+ throw new IllegalArgumentException(signature + ": '" + c
+ + "' expected at index " + pos);
+ }
+
+ /**
+ * Returns the signature car at the given index.
+ *
+ * @param signature a signature.
+ * @param pos an index in signature.
+ * @return the character at the given index, or 0 if there is no such
+ * character.
+ */
+ private static char getChar(final String signature, int pos) {
+ return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+ }
+
+ /**
+ * Checks that the given label is not null. This method can also check that
+ * the label has been visited.
+ *
+ * @param label the label to be checked.
+ * @param checkVisited <tt>true</tt> to check that the label has been
+ * visited.
+ * @param msg a message to be used in case of error.
+ */
+ void checkLabel(
+ final Label label,
+ final boolean checkVisited,
+ final String msg)
+ {
+ if (label == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null)");
+ }
+ if (checkVisited && labels.get(label) == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be visited first)");
+ }
+ }
+
+ /**
+ * Checks that the given label is not a label used only for debug purposes.
+ *
+ * @param label the label to be checked.
+ */
+ private static void checkNonDebugLabel(final Label label) {
+ Field f = getLabelStatusField();
+ int status = 0;
+ try {
+ status = f == null ? 0 : ((Integer) f.get(label)).intValue();
+ } catch (IllegalAccessException e) {
+ throw new Error("Internal error");
+ }
+ if ((status & 0x01) != 0) {
+ throw new IllegalArgumentException("Labels used for debug info cannot be reused for control flow");
+ }
+ }
+
+ /**
+ * Returns the Field object corresponding to the Label.status field.
+ *
+ * @return the Field object corresponding to the Label.status field.
+ */
+ private static Field getLabelStatusField() {
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("a");
+ if (labelStatusField == null) {
+ labelStatusField = getLabelField("status");
+ }
+ }
+ return labelStatusField;
+ }
+
+ /**
+ * Returns the field of the Label class whose name is given.
+ *
+ * @param name a field name.
+ * @return the field of the Label class whose name is given, or null.
+ */
+ private static Field getLabelField(final String name) {
+ try {
+ Field f = Label.class.getDeclaredField(name);
+ f.setAccessible(true);
+ return f;
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/CheckSignatureAdapter.java b/src/compiler/scala/tools/asm/util/CheckSignatureAdapter.java
new file mode 100644
index 0000000000..3a6c3e780f
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/CheckSignatureAdapter.java
@@ -0,0 +1,329 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckSignatureAdapter extends SignatureVisitor {
+
+ /**
+ * Type to be used to check class signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
+ */
+ public static final int CLASS_SIGNATURE = 0;
+
+ /**
+ * Type to be used to check method signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
+ */
+ public static final int METHOD_SIGNATURE = 1;
+
+ /**
+ * Type to be used to check type signatures.See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
+ */
+ public static final int TYPE_SIGNATURE = 2;
+
+ private static final int EMPTY = 1;
+
+ private static final int FORMAL = 2;
+
+ private static final int BOUND = 4;
+
+ private static final int SUPER = 8;
+
+ private static final int PARAM = 16;
+
+ private static final int RETURN = 32;
+
+ private static final int SIMPLE_TYPE = 64;
+
+ private static final int CLASS_TYPE = 128;
+
+ private static final int END = 256;
+
+ /**
+ * Type of the signature to be checked.
+ */
+ private final int type;
+
+ /**
+ * State of the automaton used to check the order of method calls.
+ */
+ private int state;
+
+ /**
+ * <tt>true</tt> if the checked type signature can be 'V'.
+ */
+ private boolean canBeVoid;
+
+ /**
+ * The visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ private final SignatureVisitor sv;
+
+ /**
+ * Creates a new {@link CheckSignatureAdapter} object. <i>Subclasses must
+ * not use this constructor</i>. Instead, they must use the
+ * {@link #CheckSignatureAdapter(int, int, SignatureVisitor)} version.
+ *
+ * @param type the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv the visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
+ this(Opcodes.ASM4, type, sv);
+ }
+
+ /**
+ * Creates a new {@link CheckSignatureAdapter} object.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ * @param type the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv the visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ protected CheckSignatureAdapter(
+ final int api,
+ final int type,
+ final SignatureVisitor sv)
+ {
+ super(api);
+ this.type = type;
+ this.state = EMPTY;
+ this.sv = sv;
+ }
+
+ // class and method signatures
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ if (type == TYPE_SIGNATURE
+ || (state != EMPTY && state != FORMAL && state != BOUND))
+ {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
+ state = FORMAL;
+ if (sv != null) {
+ sv.visitFormalTypeParameter(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ if (state != FORMAL) {
+ throw new IllegalStateException();
+ }
+ state = BOUND;
+ SignatureVisitor v = sv == null ? null : sv.visitClassBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ if (state != FORMAL && state != BOUND) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // class signatures
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ state = SUPER;
+ SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ if (state != SUPER) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterface();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // method signatures
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ state = PARAM;
+ SignatureVisitor v = sv == null ? null : sv.visitParameterType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ state = RETURN;
+ SignatureVisitor v = sv == null ? null : sv.visitReturnType();
+ CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ cv.canBeVoid = true;
+ return cv;
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (state != RETURN) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // type signatures
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ if (descriptor == 'V') {
+ if (!canBeVoid) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+ throw new IllegalArgumentException();
+ }
+ }
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitBaseType(descriptor);
+ }
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "type variable");
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitTypeVariable(name);
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ state = SIMPLE_TYPE;
+ SignatureVisitor v = sv == null ? null : sv.visitArrayType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ state = CLASS_TYPE;
+ if (sv != null) {
+ sv.visitClassType(name);
+ }
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "inner class name");
+ if (sv != null) {
+ sv.visitInnerClassType(name);
+ }
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if (sv != null) {
+ sv.visitTypeArgument();
+ }
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if ("+-=".indexOf(wildcard) == -1) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ state = END;
+ if (sv != null) {
+ sv.visitEnd();
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/Printer.java b/src/compiler/scala/tools/asm/util/Printer.java
new file mode 100644
index 0000000000..c39fd548ce
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/Printer.java
@@ -0,0 +1,558 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import scala.tools.asm.Attribute;
+import scala.tools.asm.Handle;
+import scala.tools.asm.Label;
+import scala.tools.asm.Opcodes;
+
+/**
+ * An abstract converter from visit events to text.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class Printer {
+
+ /**
+ * The names of the Java Virtual Machine opcodes.
+ */
+ public static final String[] OPCODES;
+
+ /**
+ * The names of the for <code>operand</code> parameter values of the
+ * {@link org.objectweb.asm.MethodVisitor#visitIntInsn} method when
+ * <code>opcode</code> is <code>NEWARRAY</code>.
+ */
+ public static final String[] TYPES;
+
+ /**
+ * The names of the <code>tag</code> field values for
+ * {@link org.objectweb.asm.Handle}.
+ */
+ public static final String[] HANDLE_TAG;
+
+ static {
+ String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2,"
+ + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0,"
+ + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,,"
+ + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD,"
+ + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE,"
+ + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE,"
+ + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP,"
+ + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD,"
+ + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV,"
+ + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL,"
+ + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L,"
+ + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP,"
+ + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE,"
+ + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE,"
+ + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH,"
+ + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC,"
+ + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL,"
+ + "INVOKESTATIC,INVOKEINTERFACE,INVOKEDYNAMIC,NEW,NEWARRAY,"
+ + "ANEWARRAY,ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,"
+ + "MONITORENTER,MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,";
+ OPCODES = new String[200];
+ int i = 0;
+ int j = 0;
+ int l;
+ while ((l = s.indexOf(',', j)) > 0) {
+ OPCODES[i++] = j + 1 == l ? null : s.substring(j, l);
+ j = l + 1;
+ }
+
+ s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,";
+ TYPES = new String[12];
+ j = 0;
+ i = 4;
+ while ((l = s.indexOf(',', j)) > 0) {
+ TYPES[i++] = s.substring(j, l);
+ j = l + 1;
+ }
+
+ s = "H_GETFIELD,H_GETSTATIC,H_PUTFIELD,H_PUTSTATIC,"
+ + "H_INVOKEVIRTUAL,H_INVOKESTATIC,H_INVOKESPECIAL,"
+ + "H_NEWINVOKESPECIAL,H_INVOKEINTERFACE,";
+ HANDLE_TAG = new String[10];
+ j = 0;
+ i = 1;
+ while ((l = s.indexOf(',', j)) > 0) {
+ HANDLE_TAG[i++] = s.substring(j, l);
+ j = l + 1;
+ }
+ }
+
+ /**
+ * The ASM API version implemented by this class. The value of this field
+ * must be one of {@link Opcodes#ASM4}.
+ */
+ protected final int api;
+
+ /**
+ * A buffer that can be used to create strings.
+ */
+ protected final StringBuffer buf;
+
+ /**
+ * The text to be printed. Since the code of methods is not necessarily
+ * visited in sequential order, one method after the other, but can be
+ * interlaced (some instructions from method one, then some instructions
+ * from method two, then some instructions from method one again...), it is
+ * not possible to print the visited instructions directly to a sequential
+ * stream. A class is therefore printed in a two steps process: a string
+ * tree is constructed during the visit, and printed to a sequential stream
+ * at the end of the visit. This string tree is stored in this field, as a
+ * string list that can contain other string lists, which can themselves
+ * contain other string lists, and so on.
+ */
+ public final List<Object> text;
+
+ /**
+ * Constructs a new {@link Printer}.
+ */
+ protected Printer(final int api) {
+ this.api = api;
+ this.buf = new StringBuffer();
+ this.text = new ArrayList<Object>();
+ }
+
+ /**
+ * Class header.
+ * See {@link org.objectweb.asm.ClassVisitor#visit}.
+ */
+ public abstract void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces);
+
+ /**
+ * Class source.
+ * See {@link org.objectweb.asm.ClassVisitor#visitSource}.
+ */
+ public abstract void visitSource(final String file, final String debug);
+
+ /**
+ * Class outer class.
+ * See {@link org.objectweb.asm.ClassVisitor#visitOuterClass}.
+ */
+ public abstract void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc);
+
+ /**
+ * Class annotation.
+ * See {@link org.objectweb.asm.ClassVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitClassAnnotation(
+ final String desc,
+ final boolean visible);
+
+ /**
+ * Class attribute.
+ * See {@link org.objectweb.asm.ClassVisitor#visitAttribute}.
+ */
+ public abstract void visitClassAttribute(final Attribute attr);
+
+ /**
+ * Class inner name.
+ * See {@link org.objectweb.asm.ClassVisitor#visitInnerClass}.
+ */
+ public abstract void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access);
+
+ /**
+ * Class field.
+ * See {@link org.objectweb.asm.ClassVisitor#visitField}.
+ */
+ public abstract Printer visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value);
+
+ /**
+ * Class method.
+ * See {@link org.objectweb.asm.ClassVisitor#visitMethod}.
+ */
+ public abstract Printer visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions);
+
+ /**
+ * Class end.
+ * See {@link org.objectweb.asm.ClassVisitor#visitEnd}.
+ */
+ public abstract void visitClassEnd();
+
+ // ------------------------------------------------------------------------
+ // Annotations
+ // ------------------------------------------------------------------------
+
+ /**
+ * Annotation value.
+ * See {@link org.objectweb.asm.AnnotationVisitor#visit}.
+ */
+ public abstract void visit(final String name, final Object value);
+
+ /**
+ * Annotation enum value.
+ * See {@link org.objectweb.asm.AnnotationVisitor#visitEnum}.
+ */
+ public abstract void visitEnum(
+ final String name,
+ final String desc,
+ final String value);
+
+ /**
+ * Nested annotation value.
+ * See {@link org.objectweb.asm.AnnotationVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitAnnotation(
+ final String name,
+ final String desc);
+
+ /**
+ * Annotation array value.
+ * See {@link org.objectweb.asm.AnnotationVisitor#visitArray}.
+ */
+ public abstract Printer visitArray(final String name);
+
+ /**
+ * Annotation end.
+ * See {@link org.objectweb.asm.AnnotationVisitor#visitEnd}.
+ */
+ public abstract void visitAnnotationEnd();
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * Field annotation.
+ * See {@link org.objectweb.asm.FieldVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitFieldAnnotation(
+ final String desc,
+ final boolean visible);
+
+ /**
+ * Field attribute.
+ * See {@link org.objectweb.asm.FieldVisitor#visitAttribute}.
+ */
+ public abstract void visitFieldAttribute(final Attribute attr);
+
+ /**
+ * Field end.
+ * See {@link org.objectweb.asm.FieldVisitor#visitEnd}.
+ */
+ public abstract void visitFieldEnd();
+
+ // ------------------------------------------------------------------------
+ // Methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Method default annotation.
+ * See {@link org.objectweb.asm.MethodVisitor#visitAnnotationDefault}.
+ */
+ public abstract Printer visitAnnotationDefault();
+
+ /**
+ * Method annotation.
+ * See {@link org.objectweb.asm.MethodVisitor#visitAnnotation}.
+ */
+ public abstract Printer visitMethodAnnotation(
+ final String desc,
+ final boolean visible);
+
+ /**
+ * Method parameter annotation.
+ * See {@link org.objectweb.asm.MethodVisitor#visitParameterAnnotation}.
+ */
+ public abstract Printer visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible);
+
+ /**
+ * Method attribute.
+ * See {@link org.objectweb.asm.MethodVisitor#visitAttribute}.
+ */
+ public abstract void visitMethodAttribute(final Attribute attr);
+
+ /**
+ * Method start.
+ * See {@link org.objectweb.asm.MethodVisitor#visitCode}.
+ */
+ public abstract void visitCode();
+
+ /**
+ * Method stack frame.
+ * See {@link org.objectweb.asm.MethodVisitor#visitFrame}.
+ */
+ public abstract void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitInsn}.
+ */
+ public abstract void visitInsn(final int opcode);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitIntInsn}.
+ */
+ public abstract void visitIntInsn(final int opcode, final int operand);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitVarInsn}.
+ */
+ public abstract void visitVarInsn(final int opcode, final int var);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitTypeInsn}.
+ */
+ public abstract void visitTypeInsn(final int opcode, final String type);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitFieldInsn}.
+ */
+ public abstract void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitMethodInsn}.
+ */
+ public abstract void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitInvokeDynamicInsn}.
+ */
+ public abstract void visitInvokeDynamicInsn(
+ String name,
+ String desc,
+ Handle bsm,
+ Object... bsmArgs);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitJumpInsn}.
+ */
+ public abstract void visitJumpInsn(final int opcode, final Label label);
+
+ /**
+ * Method label.
+ * See {@link org.objectweb.asm.MethodVisitor#visitLabel}.
+ */
+ public abstract void visitLabel(final Label label);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitLdcInsn}.
+ */
+ public abstract void visitLdcInsn(final Object cst);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitIincInsn}.
+ */
+ public abstract void visitIincInsn(final int var, final int increment);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitTableSwitchInsn}.
+ */
+ public abstract void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label... labels);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitLookupSwitchInsn}.
+ */
+ public abstract void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels);
+
+ /**
+ * Method instruction.
+ * See {@link org.objectweb.asm.MethodVisitor#visitMultiANewArrayInsn}.
+ */
+ public abstract void visitMultiANewArrayInsn(
+ final String desc,
+ final int dims);
+
+ /**
+ * Method exception handler.
+ * See {@link org.objectweb.asm.MethodVisitor#visitTryCatchBlock}.
+ */
+ public abstract void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type);
+
+ /**
+ * Method debug info.
+ * See {@link org.objectweb.asm.MethodVisitor#visitLocalVariable}.
+ */
+ public abstract void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index);
+
+ /**
+ * Method debug info.
+ * See {@link org.objectweb.asm.MethodVisitor#visitLineNumber}.
+ */
+ public abstract void visitLineNumber(final int line, final Label start);
+
+ /**
+ * Method max stack and max locals.
+ * See {@link org.objectweb.asm.MethodVisitor#visitMaxs}.
+ */
+ public abstract void visitMaxs(final int maxStack, final int maxLocals);
+
+ /**
+ * Method end.
+ * See {@link org.objectweb.asm.MethodVisitor#visitEnd}.
+ */
+ public abstract void visitMethodEnd();
+
+ /**
+ * Returns the text constructed by this visitor.
+ *
+ * @return the text constructed by this visitor.
+ */
+ public List<Object> getText() {
+ return text;
+ }
+
+ /**
+ * Prints the text constructed by this visitor.
+ *
+ * @param pw the print writer to be used.
+ */
+ public void print(final PrintWriter pw) {
+ printList(pw, text);
+ }
+
+ /**
+ * Appends a quoted string to a given buffer.
+ *
+ * @param buf the buffer where the string must be added.
+ * @param s the string to be added.
+ */
+ public static void appendString(final StringBuffer buf, final String s) {
+ buf.append('\"');
+ for (int i = 0; i < s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c == '\n') {
+ buf.append("\\n");
+ } else if (c == '\r') {
+ buf.append("\\r");
+ } else if (c == '\\') {
+ buf.append("\\\\");
+ } else if (c == '"') {
+ buf.append("\\\"");
+ } else if (c < 0x20 || c > 0x7f) {
+ buf.append("\\u");
+ if (c < 0x10) {
+ buf.append("000");
+ } else if (c < 0x100) {
+ buf.append("00");
+ } else if (c < 0x1000) {
+ buf.append('0');
+ }
+ buf.append(Integer.toString(c, 16));
+ } else {
+ buf.append(c);
+ }
+ }
+ buf.append('\"');
+ }
+
+ /**
+ * Prints the given string tree.
+ *
+ * @param pw the writer to be used to print the tree.
+ * @param l a string tree, i.e., a string list that can contain other string
+ * lists, and so on recursively.
+ */
+ static void printList(final PrintWriter pw, final List<?> l) {
+ for (int i = 0; i < l.size(); ++i) {
+ Object o = l.get(i);
+ if (o instanceof List) {
+ printList(pw, (List<?>) o);
+ } else {
+ pw.print(o.toString());
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/SignatureChecker.java b/src/compiler/scala/tools/asm/util/SignatureChecker.java
new file mode 100644
index 0000000000..7b7eea4383
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/SignatureChecker.java
@@ -0,0 +1,47 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2012 LAMP/EPFL
+ */
+
+package scala.tools.asm.util;
+
+import scala.tools.asm.util.CheckMethodAdapter;
+import scala.tools.asm.MethodVisitor;
+
+/**
+ * A subclass of ASM's CheckMethodAdapter for the sole purpose of accessing some protected methods there.
+ *
+ */
+public class SignatureChecker extends CheckMethodAdapter {
+
+ public SignatureChecker(final MethodVisitor mv) {
+ super(mv);
+ }
+
+ /**
+ * Checks a class signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ public static void checkClassSignature(final String signature) {
+ CheckMethodAdapter.checkClassSignature(signature);
+ }
+
+ /**
+ * Checks a method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ public static void checkMethodSignature(final String signature) {
+ CheckMethodAdapter.checkMethodSignature(signature);
+ }
+
+ /**
+ * Checks a field signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ public static void checkFieldSignature(final String signature) {
+ CheckMethodAdapter.checkFieldSignature(signature);
+ }
+
+}
diff --git a/src/compiler/scala/tools/asm/util/Textifiable.java b/src/compiler/scala/tools/asm/util/Textifiable.java
new file mode 100644
index 0000000000..b80d0139db
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/Textifiable.java
@@ -0,0 +1,54 @@
+/**
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.util.Map;
+
+import scala.tools.asm.Label;
+
+/**
+ * An {@link org.objectweb.asm.Attribute Attribute} that can print a readable
+ * representation of itself.
+ *
+ * Implementations should construct readable output from an attribute data
+ * structure. Such representation could be used in unit test assertions.
+ *
+ * @author Eugene Kuleshov
+ */
+public interface Textifiable {
+
+ /**
+ * Build a human readable representation of this attribute.
+ *
+ * @param buf a buffer used for printing Java code.
+ * @param labelNames map of label instances to their names.
+ */
+ void textify(StringBuffer buf, Map<Label, String> labelNames);
+}
diff --git a/src/compiler/scala/tools/asm/util/Textifier.java b/src/compiler/scala/tools/asm/util/Textifier.java
new file mode 100644
index 0000000000..8d40ebd026
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/Textifier.java
@@ -0,0 +1,1286 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+import scala.tools.asm.Attribute;
+import scala.tools.asm.ClassReader;
+import scala.tools.asm.Handle;
+import scala.tools.asm.Label;
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.Type;
+import scala.tools.asm.signature.SignatureReader;
+
+/**
+ * A {@link Printer} that prints a disassembled view of the classes it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class Textifier extends Printer {
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for internal
+ * type names in bytecode notation.
+ */
+ public static final int INTERNAL_NAME = 0;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int FIELD_DESCRIPTOR = 1;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field
+ * signatures, formatted in bytecode notation
+ */
+ public static final int FIELD_SIGNATURE = 2;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int METHOD_DESCRIPTOR = 3;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * signatures, formatted in bytecode notation
+ */
+ public static final int METHOD_SIGNATURE = 4;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for class
+ * signatures, formatted in bytecode notation
+ */
+ public static final int CLASS_SIGNATURE = 5;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field or
+ * method return value signatures, formatted in default Java notation
+ * (non-bytecode)
+ */
+ public static final int TYPE_DECLARATION = 6;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for class
+ * signatures, formatted in default Java notation (non-bytecode)
+ */
+ public static final int CLASS_DECLARATION = 7;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * parameter signatures, formatted in default Java notation (non-bytecode)
+ */
+ public static final int PARAMETERS_DECLARATION = 8;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for handle
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int HANDLE_DESCRIPTOR = 9;
+
+ /**
+ * Tab for class members.
+ */
+ protected String tab = " ";
+
+ /**
+ * Tab for bytecode instructions.
+ */
+ protected String tab2 = " ";
+
+ /**
+ * Tab for table and lookup switch instructions.
+ */
+ protected String tab3 = " ";
+
+ /**
+ * Tab for labels.
+ */
+ protected String ltab = " ";
+
+ /**
+ * The label names. This map associate String values to Label keys.
+ */
+ protected Map<Label, String> labelNames;
+
+ private int valueNumber = 0;
+
+ /**
+ * Constructs a new {@link Textifier}. <i>Subclasses must not use this
+ * constructor</i>. Instead, they must use the {@link #Textifier(int)}
+ * version.
+ */
+ public Textifier() {
+ this(Opcodes.ASM4);
+ }
+
+ /**
+ * Constructs a new {@link Textifier}.
+ *
+ * @param api the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4}.
+ */
+ protected Textifier(final int api) {
+ super(api);
+ }
+
+ /**
+ * Prints a disassembled view of the given class to the standard output. <p>
+ * Usage: Textifier [-debug] &lt;binary class name or class
+ * file name &gt;
+ *
+ * @param args the command line arguments.
+ *
+ * @throws Exception if the class cannot be found, or if an IO exception
+ * occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err.println("Prints a disassembled view of the given class.");
+ System.err.println("Usage: Textifier [-debug] "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1)
+ {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),
+ flags);
+ }
+
+ // ------------------------------------------------------------------------
+ // Classes
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ int major = version & 0xFFFF;
+ int minor = version >>> 16;
+ buf.setLength(0);
+ buf.append("// class version ")
+ .append(major)
+ .append('.')
+ .append(minor)
+ .append(" (")
+ .append(version)
+ .append(")\n");
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append("// DEPRECATED\n");
+ }
+ buf.append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+
+ appendDescriptor(CLASS_SIGNATURE, signature);
+ if (signature != null) {
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(sv);
+ buf.append("// declaration: ")
+ .append(name)
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+
+ appendAccess(access & ~Opcodes.ACC_SUPER);
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ buf.append("@interface ");
+ } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ buf.append("interface ");
+ } else if ((access & Opcodes.ACC_ENUM) == 0) {
+ buf.append("class ");
+ }
+ appendDescriptor(INTERNAL_NAME, name);
+
+ if (superName != null && !"java/lang/Object".equals(superName)) {
+ buf.append(" extends ");
+ appendDescriptor(INTERNAL_NAME, superName);
+ buf.append(' ');
+ }
+ if (interfaces != null && interfaces.length > 0) {
+ buf.append(" implements ");
+ for (int i = 0; i < interfaces.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, interfaces[i]);
+ buf.append(' ');
+ }
+ }
+ buf.append(" {\n\n");
+
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ buf.setLength(0);
+ if (file != null) {
+ buf.append(tab)
+ .append("// compiled from: ")
+ .append(file)
+ .append('\n');
+ }
+ if (debug != null) {
+ buf.append(tab)
+ .append("// debug info: ")
+ .append(debug)
+ .append('\n');
+ }
+ if (buf.length() > 0) {
+ text.add(buf.toString());
+ }
+ }
+
+ @Override
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(tab).append("OUTERCLASS ");
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append(' ');
+ if (name != null) {
+ buf.append(name).append(' ');
+ }
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public Textifier visitClassAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ text.add("\n");
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitClassAttribute(final Attribute attr) {
+ text.add("\n");
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ buf.setLength(0);
+ buf.append(tab).append("// access flags 0x");
+ buf.append(Integer.toHexString(access & ~Opcodes.ACC_SUPER).toUpperCase()).append('\n');
+ buf.append(tab);
+ appendAccess(access);
+ buf.append("INNERCLASS ");
+ appendDescriptor(INTERNAL_NAME, name);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, outerName);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, innerName);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public Textifier visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+ if (signature != null) {
+ buf.append(tab);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ buf.append(tab)
+ .append("// declaration: ")
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+
+ buf.append(tab);
+ appendAccess(access);
+
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ').append(name);
+ if (value != null) {
+ buf.append(" = ");
+ if (value instanceof String) {
+ buf.append('\"').append(value).append('\"');
+ } else {
+ buf.append(value);
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ return t;
+ }
+
+ @Override
+ public Textifier visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags 0x").append(Integer.toHexString(access).toUpperCase()).append('\n');
+
+ if (signature != null) {
+ buf.append(tab);
+ appendDescriptor(METHOD_SIGNATURE, signature);
+
+ TraceSignatureVisitor v = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(v);
+ String genericDecl = v.getDeclaration();
+ String genericReturn = v.getReturnType();
+ String genericExceptions = v.getExceptions();
+
+ buf.append(tab)
+ .append("// declaration: ")
+ .append(genericReturn)
+ .append(' ')
+ .append(name)
+ .append(genericDecl);
+ if (genericExceptions != null) {
+ buf.append(" throws ").append(genericExceptions);
+ }
+ buf.append('\n');
+ }
+
+ buf.append(tab);
+ appendAccess(access);
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ buf.append("native ");
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0) {
+ buf.append("varargs ");
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0) {
+ buf.append("bridge ");
+ }
+
+ buf.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ if (exceptions != null && exceptions.length > 0) {
+ buf.append(" throws ");
+ for (int i = 0; i < exceptions.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, exceptions[i]);
+ buf.append(' ');
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ return t;
+ }
+
+ @Override
+ public void visitClassEnd() {
+ text.add("}\n");
+ }
+
+ // ------------------------------------------------------------------------
+ // Annotations
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+
+ if (value instanceof String) {
+ visitString((String) value);
+ } else if (value instanceof Type) {
+ visitType((Type) value);
+ } else if (value instanceof Byte) {
+ visitByte(((Byte) value).byteValue());
+ } else if (value instanceof Boolean) {
+ visitBoolean(((Boolean) value).booleanValue());
+ } else if (value instanceof Short) {
+ visitShort(((Short) value).shortValue());
+ } else if (value instanceof Character) {
+ visitChar(((Character) value).charValue());
+ } else if (value instanceof Integer) {
+ visitInt(((Integer) value).intValue());
+ } else if (value instanceof Float) {
+ visitFloat(((Float) value).floatValue());
+ } else if (value instanceof Long) {
+ visitLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ visitDouble(((Double) value).doubleValue());
+ } else if (value.getClass().isArray()) {
+ buf.append('{');
+ if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitByte(v[i]);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitBoolean(v[i]);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitShort(v[i]);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitChar(v[i]);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitInt(v[i]);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitLong(v[i]);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitFloat(v[i]);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitDouble(v[i]);
+ }
+ }
+ buf.append('}');
+ }
+
+ text.add(buf.toString());
+ }
+
+ private void visitInt(final int value) {
+ buf.append(value);
+ }
+
+ private void visitLong(final long value) {
+ buf.append(value).append('L');
+ }
+
+ private void visitFloat(final float value) {
+ buf.append(value).append('F');
+ }
+
+ private void visitDouble(final double value) {
+ buf.append(value).append('D');
+ }
+
+ private void visitChar(final char value) {
+ buf.append("(char)").append((int) value);
+ }
+
+ private void visitShort(final short value) {
+ buf.append("(short)").append(value);
+ }
+
+ private void visitByte(final byte value) {
+ buf.append("(byte)").append(value);
+ }
+
+ private void visitBoolean(final boolean value) {
+ buf.append(value);
+ }
+
+ private void visitString(final String value) {
+ appendString(buf, value);
+ }
+
+ private void visitType(final Type value) {
+ buf.append(value.getClassName()).append(".class");
+ }
+
+ @Override
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('.').append(value);
+ text.add(buf.toString());
+ }
+
+ @Override
+ public Textifier visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ buf.append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add(")");
+ return t;
+ }
+
+ @Override
+ public Textifier visitArray(
+ final String name)
+ {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ buf.append('{');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add("}");
+ return t;
+ }
+
+ @Override
+ public void visitAnnotationEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Textifier visitFieldAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public void visitFieldAttribute(final Attribute attr) {
+ visitAttribute(attr);
+ }
+
+ @Override
+ public void visitFieldEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods
+ // ------------------------------------------------------------------------
+
+ @Override
+ public Textifier visitAnnotationDefault() {
+ text.add(tab2 + "default=");
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add("\n");
+ return t;
+ }
+
+ @Override
+ public Textifier visitMethodAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ return visitAnnotation(desc, visible);
+ }
+
+ @Override
+ public Textifier visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add(visible ? ") // parameter " : ") // invisible, parameter ");
+ text.add(new Integer(parameter));
+ text.add("\n");
+ return t;
+ }
+
+ @Override
+ public void visitMethodAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attr.type);
+
+ if (attr instanceof Textifiable) {
+ ((Textifiable) attr).textify(buf, labelNames);
+ } else {
+ buf.append(" : unknown\n");
+ }
+
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitCode() {
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ buf.setLength(0);
+ buf.append(ltab);
+ buf.append("FRAME ");
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ buf.append("FULL [");
+ appendFrameTypes(nLocal, local);
+ buf.append("] [");
+ appendFrameTypes(nStack, stack);
+ buf.append(']');
+ break;
+ case Opcodes.F_APPEND:
+ buf.append("APPEND [");
+ appendFrameTypes(nLocal, local);
+ buf.append(']');
+ break;
+ case Opcodes.F_CHOP:
+ buf.append("CHOP ").append(nLocal);
+ break;
+ case Opcodes.F_SAME:
+ buf.append("SAME");
+ break;
+ case Opcodes.F_SAME1:
+ buf.append("SAME1 ");
+ appendFrameTypes(1, stack);
+ break;
+ }
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ buf.setLength(0);
+ buf.append(tab2)
+ .append(OPCODES[opcode])
+ .append(' ')
+ .append(opcode == Opcodes.NEWARRAY
+ ? TYPES[operand]
+ : Integer.toString(operand))
+ .append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ buf.setLength(0);
+ buf.append(tab2)
+ .append(OPCODES[opcode])
+ .append(' ')
+ .append(var)
+ .append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append('.').append(name).append(" : ");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append('.').append(name).append(' ');
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ String name,
+ String desc,
+ Handle bsm,
+ Object... bsmArgs)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("INVOKEDYNAMIC").append(' ');
+ buf.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append(" [");
+ appendHandle(bsm);
+ buf.append(tab3).append("// arguments:");
+ if(bsmArgs.length == 0) {
+ buf.append(" none");
+ } else {
+ buf.append('\n').append(tab3);
+ for(int i = 0; i < bsmArgs.length; i++) {
+ Object cst = bsmArgs[i];
+ if (cst instanceof String) {
+ Printer.appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append(((Type) cst).getDescriptor()).append(".class");
+ } else if (cst instanceof Handle) {
+ appendHandle((Handle) cst);
+ } else {
+ buf.append(cst);
+ }
+ buf.append(", ");
+ }
+ buf.setLength(buf.length() - 2);
+ }
+ buf.append('\n');
+ buf.append(tab2).append("]\n");
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendLabel(label);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ buf.setLength(0);
+ buf.append(ltab);
+ appendLabel(label);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ buf.setLength(0);
+ buf.append(tab2).append("LDC ");
+ if (cst instanceof String) {
+ Printer.appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append(((Type) cst).getDescriptor()).append(".class");
+ } else {
+ buf.append(cst);
+ }
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ buf.setLength(0);
+ buf.append(tab2)
+ .append("IINC ")
+ .append(var)
+ .append(' ')
+ .append(increment)
+ .append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label... labels)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("TABLESWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(tab3).append(min + i).append(": ");
+ appendLabel(labels[i]);
+ buf.append('\n');
+ }
+ buf.append(tab3).append("default: ");
+ appendLabel(dflt);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("LOOKUPSWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(tab3).append(keys[i]).append(": ");
+ appendLabel(labels[i]);
+ buf.append('\n');
+ }
+ buf.append(tab3).append("default: ");
+ appendLabel(dflt);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ buf.setLength(0);
+ buf.append(tab2).append("MULTIANEWARRAY ");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ').append(dims).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("TRYCATCHBLOCK ");
+ appendLabel(start);
+ buf.append(' ');
+ appendLabel(end);
+ buf.append(' ');
+ appendLabel(handler);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ');
+ appendLabel(start);
+ buf.append(' ');
+ appendLabel(end);
+ buf.append(' ').append(index).append('\n');
+
+ if (signature != null) {
+ buf.append(tab2);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ buf.append(tab2)
+ .append("// declaration: ")
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ buf.setLength(0);
+ buf.append(tab2).append("LINENUMBER ").append(line).append(' ');
+ appendLabel(start);
+ buf.append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ buf.setLength(0);
+ buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n');
+ text.add(buf.toString());
+
+ buf.setLength(0);
+ buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n');
+ text.add(buf.toString());
+ }
+
+ @Override
+ public void visitMethodEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Common methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Prints a disassembled view of the given annotation.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public Textifier visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append(tab).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ Textifier t = createTextifier();
+ text.add(t.getText());
+ text.add(visible ? ")\n" : ") // invisible\n");
+ return t;
+ }
+
+ /**
+ * Prints a disassembled view of the given attribute.
+ *
+ * @param attr an attribute.
+ */
+ public void visitAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attr.type);
+
+ if (attr instanceof Textifiable) {
+ ((Textifiable) attr).textify(buf, null);
+ } else {
+ buf.append(" : unknown\n");
+ }
+
+ text.add(buf.toString());
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Creates a new TraceVisitor instance.
+ *
+ * @return a new TraceVisitor.
+ */
+ protected Textifier createTextifier() {
+ return new Textifier();
+ }
+
+ /**
+ * Appends an internal name, a type descriptor or a type signature to
+ * {@link #buf buf}.
+ *
+ * @param type indicates if desc is an internal name, a field descriptor, a
+ * method descriptor, a class signature, ...
+ * @param desc an internal name, type descriptor, or type signature. May be
+ * <tt>null</tt>.
+ */
+ protected void appendDescriptor(final int type, final String desc) {
+ if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
+ || type == METHOD_SIGNATURE)
+ {
+ if (desc != null) {
+ buf.append("// signature ").append(desc).append('\n');
+ }
+ } else {
+ buf.append(desc);
+ }
+ }
+
+ /**
+ * Appends the name of the given label to {@link #buf buf}. Creates a new
+ * label name if the given label does not yet have one.
+ *
+ * @param l a label.
+ */
+ protected void appendLabel(final Label l) {
+ if (labelNames == null) {
+ labelNames = new HashMap<Label, String>();
+ }
+ String name = labelNames.get(l);
+ if (name == null) {
+ name = "L" + labelNames.size();
+ labelNames.put(l, name);
+ }
+ buf.append(name);
+ }
+
+ /**
+ * Appends the information about the given handle to {@link #buf buf}.
+ *
+ * @param h a handle, non null.
+ */
+ protected void appendHandle(final Handle h) {
+ buf.append('\n').append(tab3);
+ int tag = h.getTag();
+ buf.append("// handle kind 0x").append(Integer.toHexString(tag)).append(" : ");
+ switch (tag) {
+ case Opcodes.H_GETFIELD:
+ buf.append("GETFIELD");
+ break;
+ case Opcodes.H_GETSTATIC:
+ buf.append("GETSTATIC");
+ break;
+ case Opcodes.H_PUTFIELD:
+ buf.append("PUTFIELD");
+ break;
+ case Opcodes.H_PUTSTATIC:
+ buf.append("PUTSTATIC");
+ break;
+ case Opcodes.H_INVOKEINTERFACE:
+ buf.append("INVOKEINTERFACE");
+ break;
+ case Opcodes.H_INVOKESPECIAL:
+ buf.append("INVOKESPECIAL");
+ break;
+ case Opcodes.H_INVOKESTATIC:
+ buf.append("INVOKESTATIC");
+ break;
+ case Opcodes.H_INVOKEVIRTUAL:
+ buf.append("INVOKEVIRTUAL");
+ break;
+ case Opcodes.H_NEWINVOKESPECIAL:
+ buf.append("NEWINVOKESPECIAL");
+ break;
+ }
+ buf.append('\n');
+ buf.append(tab3);
+ appendDescriptor(INTERNAL_NAME, h.getOwner());
+ buf.append('.');
+ buf.append(h.getName());
+ buf.append('(');
+ appendDescriptor(HANDLE_DESCRIPTOR, h.getDesc());
+ buf.append(')').append('\n');
+ }
+
+ /**
+ * Appends a string representation of the given access modifiers to {@link
+ * #buf buf}.
+ *
+ * @param access some access modifiers.
+ */
+ private void appendAccess(final int access) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ buf.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ buf.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ buf.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ buf.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ buf.append("static ");
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ buf.append("synchronized ");
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ buf.append("volatile ");
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ buf.append("transient ");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ buf.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ buf.append("strictfp ");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ buf.append("enum ");
+ }
+ }
+
+ private void appendComa(final int i) {
+ if (i != 0) {
+ buf.append(", ");
+ }
+ }
+
+ private void appendFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (i > 0) {
+ buf.append(' ');
+ }
+ if (o[i] instanceof String) {
+ String desc = (String) o[i];
+ if (desc.startsWith("[")) {
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ } else {
+ appendDescriptor(INTERNAL_NAME, desc);
+ }
+ } else if (o[i] instanceof Integer) {
+ switch (((Integer) o[i]).intValue()) {
+ case 0:
+ appendDescriptor(FIELD_DESCRIPTOR, "T");
+ break;
+ case 1:
+ appendDescriptor(FIELD_DESCRIPTOR, "I");
+ break;
+ case 2:
+ appendDescriptor(FIELD_DESCRIPTOR, "F");
+ break;
+ case 3:
+ appendDescriptor(FIELD_DESCRIPTOR, "D");
+ break;
+ case 4:
+ appendDescriptor(FIELD_DESCRIPTOR, "J");
+ break;
+ case 5:
+ appendDescriptor(FIELD_DESCRIPTOR, "N");
+ break;
+ case 6:
+ appendDescriptor(FIELD_DESCRIPTOR, "U");
+ break;
+ }
+ } else {
+ appendLabel((Label) o[i]);
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/TraceAnnotationVisitor.java b/src/compiler/scala/tools/asm/util/TraceAnnotationVisitor.java
new file mode 100644
index 0000000000..f112609031
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/TraceAnnotationVisitor.java
@@ -0,0 +1,96 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * An {@link AnnotationVisitor} that prints the annotations it visits with a
+ * {@link Printer}.
+ *
+ * @author Eric Bruneton
+ */
+public final class TraceAnnotationVisitor extends AnnotationVisitor {
+
+ private final Printer p;
+
+ public TraceAnnotationVisitor(final Printer p) {
+ this(null, p);
+ }
+
+ public TraceAnnotationVisitor(final AnnotationVisitor av, final Printer p) {
+ super(Opcodes.ASM4, av);
+ this.p = p;
+ }
+
+ @Override
+ public void visit(final String name, final Object value) {
+ p.visit(name, value);
+ super.visit(name, value);
+ }
+
+ @Override
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ p.visitEnum(name, desc, value);
+ super.visitEnum(name, desc, value);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ Printer p = this.p.visitAnnotation(name, desc);
+ AnnotationVisitor av = this.av == null
+ ? null
+ : this.av.visitAnnotation(name, desc);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ Printer p = this.p.visitArray(name);
+ AnnotationVisitor av = this.av == null
+ ? null
+ : this.av.visitArray(name);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitAnnotationEnd();
+ super.visitEnd();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/TraceClassVisitor.java b/src/compiler/scala/tools/asm/util/TraceClassVisitor.java
new file mode 100644
index 0000000000..bb830b71ce
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/TraceClassVisitor.java
@@ -0,0 +1,232 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import java.io.PrintWriter;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.ClassVisitor;
+import scala.tools.asm.FieldVisitor;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A {@link ClassVisitor} that prints the classes it visits with a
+ * {@link Printer}. This class visitor can be used in the middle of a class
+ * visitor chain to trace the class that is visited at a given point in this
+ * chain. This may be useful for debugging purposes. <p> The trace printed when
+ * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ *
+ * <pre> // class version 49.0 (49) // access flags 0x21 public class Hello {
+ *
+ * // compiled from: Hello.java
+ *
+ * // access flags 0x1 public &lt;init&gt; ()V ALOAD 0 INVOKESPECIAL
+ * java/lang/Object &lt;init&gt; ()V RETURN MAXSTACK = 1 MAXLOCALS = 1
+ *
+ * // access flags 0x9 public static main ([Ljava/lang/String;)V GETSTATIC
+ * java/lang/System out Ljava/io/PrintStream; LDC &quot;hello&quot;
+ * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V RETURN
+ * MAXSTACK = 2 MAXLOCALS = 1 } </pre>
+ *
+ * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ *
+ * <pre> public class Hello {
+ *
+ * public static void main(String[] args) {
+ * System.out.println(&quot;hello&quot;); } } </pre>
+ *
+ * </blockquote>
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public final class TraceClassVisitor extends ClassVisitor {
+
+ /**
+ * The print writer to be used to print the class. May be null.
+ */
+ private final PrintWriter pw;
+
+ /**
+ * The object that actually converts visit events into text.
+ */
+ public final Printer p;
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param pw the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final PrintWriter pw) {
+ this(null, pw);
+ }
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
+ * May be <tt>null</tt>.
+ * @param pw the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
+ this(cv, new Textifier(), pw);
+ }
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
+ * May be <tt>null</tt>.
+ * @param p the object that actually converts visit events into text.
+ * @param pw the print writer to be used to print the class. May be null if
+ * you simply want to use the result via
+ * {@link Printer#getText()}, instead of printing it.
+ */
+ public TraceClassVisitor(
+ final ClassVisitor cv,
+ final Printer p,
+ final PrintWriter pw)
+ {
+ super(Opcodes.ASM4, cv);
+ this.pw = pw;
+ this.p = p;
+ }
+
+ @Override
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ p.visit(version, access, name, signature, superName, interfaces);
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public void visitSource(final String file, final String debug) {
+ p.visitSource(file, debug);
+ super.visitSource(file, debug);
+ }
+
+ @Override
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ p.visitOuterClass(owner, name, desc);
+ super.visitOuterClass(owner, name, desc);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ Printer p = this.p.visitClassAnnotation(desc, visible);
+ AnnotationVisitor av = cv == null ? null : cv.visitAnnotation(desc,
+ visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ p.visitClassAttribute(attr);
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ p.visitInnerClass(name, outerName, innerName, access);
+ super.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ @Override
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ Printer p = this.p.visitField(access,
+ name,
+ desc,
+ signature,
+ value);
+ FieldVisitor fv = cv == null ? null : cv.visitField(access,
+ name,
+ desc,
+ signature,
+ value);
+ return new TraceFieldVisitor(fv, p);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ Printer p = this.p.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+ MethodVisitor mv = cv == null ? null : cv.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+ return new TraceMethodVisitor(mv, p);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitClassEnd();
+ if (pw != null) {
+ p.print(pw);
+ pw.flush();
+ }
+ super.visitEnd();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/TraceFieldVisitor.java b/src/compiler/scala/tools/asm/util/TraceFieldVisitor.java
new file mode 100644
index 0000000000..f537e83be1
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/TraceFieldVisitor.java
@@ -0,0 +1,78 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.FieldVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A {@link FieldVisitor} that prints the fields it visits with a
+ * {@link Printer}.
+ *
+ * @author Eric Bruneton
+ */
+public final class TraceFieldVisitor extends FieldVisitor {
+
+ public final Printer p;
+
+ public TraceFieldVisitor(final Printer p) {
+ this(null, p);
+ }
+
+ public TraceFieldVisitor(final FieldVisitor fv, final Printer p) {
+ super(Opcodes.ASM4, fv);
+ this.p = p;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ Printer p = this.p.visitFieldAnnotation(desc, visible);
+ AnnotationVisitor av = fv == null ? null : fv.visitAnnotation(desc,
+ visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ p.visitFieldAttribute(attr);
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitFieldEnd();
+ super.visitEnd();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/TraceMethodVisitor.java b/src/compiler/scala/tools/asm/util/TraceMethodVisitor.java
new file mode 100644
index 0000000000..9aabf2079e
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/TraceMethodVisitor.java
@@ -0,0 +1,264 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import scala.tools.asm.AnnotationVisitor;
+import scala.tools.asm.Attribute;
+import scala.tools.asm.Handle;
+import scala.tools.asm.Label;
+import scala.tools.asm.MethodVisitor;
+import scala.tools.asm.Opcodes;
+
+/**
+ * A {@link MethodVisitor} that prints the methods it visits with a
+ * {@link Printer}.
+ *
+ * @author Eric Bruneton
+ */
+public final class TraceMethodVisitor extends MethodVisitor {
+
+ public final Printer p;
+
+ public TraceMethodVisitor(final Printer p) {
+ this(null, p);
+ }
+
+ public TraceMethodVisitor(final MethodVisitor mv, final Printer p) {
+ super(Opcodes.ASM4, mv);
+ this.p = p;
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ Printer p = this.p.visitMethodAnnotation(desc, visible);
+ AnnotationVisitor av = mv == null ? null : mv.visitAnnotation(desc,
+ visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ p.visitMethodAttribute(attr);
+ super.visitAttribute(attr);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ Printer p = this.p.visitAnnotationDefault();
+ AnnotationVisitor av = mv == null ? null : mv.visitAnnotationDefault();
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ Printer p = this.p.visitParameterAnnotation(parameter,
+ desc,
+ visible);
+ AnnotationVisitor av = mv == null
+ ? null
+ : mv.visitParameterAnnotation(parameter, desc, visible);
+ return new TraceAnnotationVisitor(av, p);
+ }
+
+ @Override
+ public void visitCode() {
+ p.visitCode();
+ super.visitCode();
+ }
+
+ @Override
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ p.visitFrame(type, nLocal, local, nStack, stack);
+ super.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ p.visitInsn(opcode);
+ super.visitInsn(opcode);
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ p.visitIntInsn(opcode, operand);
+ super.visitIntInsn(opcode, operand);
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ p.visitVarInsn(opcode, var);
+ super.visitVarInsn(opcode, var);
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ p.visitTypeInsn(opcode, type);
+ super.visitTypeInsn(opcode, type);
+ }
+
+ @Override
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ p.visitFieldInsn(opcode, owner, name, desc);
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ p.visitMethodInsn(opcode, owner, name, desc);
+ super.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(
+ String name,
+ String desc,
+ Handle bsm,
+ Object... bsmArgs)
+ {
+ p.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ super.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ p.visitJumpInsn(opcode, label);
+ super.visitJumpInsn(opcode, label);
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ p.visitLabel(label);
+ super.visitLabel(label);
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ p.visitLdcInsn(cst);
+ super.visitLdcInsn(cst);
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ p.visitIincInsn(var, increment);
+ super.visitIincInsn(var, increment);
+ }
+
+ @Override
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label... labels)
+ {
+ p.visitTableSwitchInsn(min, max, dflt, labels);
+ super.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ p.visitLookupSwitchInsn(dflt, keys, labels);
+ super.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ p.visitMultiANewArrayInsn(desc, dims);
+ super.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ @Override
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ p.visitTryCatchBlock(start, end, handler, type);
+ super.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ @Override
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ p.visitLocalVariable(name, desc, signature, start, end, index);
+ super.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ p.visitLineNumber(line, start);
+ super.visitLineNumber(line, start);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ p.visitMaxs(maxStack, maxLocals);
+ super.visitMaxs(maxStack, maxLocals);
+ }
+
+ @Override
+ public void visitEnd() {
+ p.visitMethodEnd();
+ super.visitEnd();
+ }
+}
diff --git a/src/compiler/scala/tools/asm/util/TraceSignatureVisitor.java b/src/compiler/scala/tools/asm/util/TraceSignatureVisitor.java
new file mode 100644
index 0000000000..a37b759811
--- /dev/null
+++ b/src/compiler/scala/tools/asm/util/TraceSignatureVisitor.java
@@ -0,0 +1,318 @@
+/***
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2011 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package scala.tools.asm.util;
+
+import scala.tools.asm.Opcodes;
+import scala.tools.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that prints a disassembled view of the signature
+ * it visits.
+ *
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public final class TraceSignatureVisitor extends SignatureVisitor {
+
+ private final StringBuffer declaration;
+
+ private boolean isInterface;
+
+ private boolean seenFormalParameter;
+
+ private boolean seenInterfaceBound;
+
+ private boolean seenParameter;
+
+ private boolean seenInterface;
+
+ private StringBuffer returnType;
+
+ private StringBuffer exceptions;
+
+ /**
+ * Stack used to keep track of class types that have arguments. Each element
+ * of this stack is a boolean encoded in one bit. The top of the stack is
+ * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+ * /2.
+ */
+ private int argumentStack;
+
+ /**
+ * Stack used to keep track of array class types. Each element of this stack
+ * is a boolean encoded in one bit. The top of the stack is the lowest order
+ * bit. Pushing false = *2, pushing true = *2+1, popping = /2.
+ */
+ private int arrayStack;
+
+ private String separator = "";
+
+ public TraceSignatureVisitor(final int access) {
+ super(Opcodes.ASM4);
+ isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+ this.declaration = new StringBuffer();
+ }
+
+ private TraceSignatureVisitor(final StringBuffer buf) {
+ super(Opcodes.ASM4);
+ this.declaration = buf;
+ }
+
+ @Override
+ public void visitFormalTypeParameter(final String name) {
+ declaration.append(seenFormalParameter ? ", " : "<").append(name);
+ seenFormalParameter = true;
+ seenInterfaceBound = false;
+ }
+
+ @Override
+ public SignatureVisitor visitClassBound() {
+ separator = " extends ";
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterfaceBound() {
+ separator = seenInterfaceBound ? ", " : " extends ";
+ seenInterfaceBound = true;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitSuperclass() {
+ endFormals();
+ separator = " extends ";
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitInterface() {
+ separator = seenInterface ? ", " : isInterface
+ ? " extends "
+ : " implements ";
+ seenInterface = true;
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitParameterType() {
+ endFormals();
+ if (seenParameter) {
+ declaration.append(", ");
+ } else {
+ seenParameter = true;
+ declaration.append('(');
+ }
+ startType();
+ return this;
+ }
+
+ @Override
+ public SignatureVisitor visitReturnType() {
+ endFormals();
+ if (seenParameter) {
+ seenParameter = false;
+ } else {
+ declaration.append('(');
+ }
+ declaration.append(')');
+ returnType = new StringBuffer();
+ return new TraceSignatureVisitor(returnType);
+ }
+
+ @Override
+ public SignatureVisitor visitExceptionType() {
+ if (exceptions == null) {
+ exceptions = new StringBuffer();
+ } else {
+ exceptions.append(", ");
+ }
+ // startType();
+ return new TraceSignatureVisitor(exceptions);
+ }
+
+ @Override
+ public void visitBaseType(final char descriptor) {
+ switch (descriptor) {
+ case 'V':
+ declaration.append("void");
+ break;
+ case 'B':
+ declaration.append("byte");
+ break;
+ case 'J':
+ declaration.append("long");
+ break;
+ case 'Z':
+ declaration.append("boolean");
+ break;
+ case 'I':
+ declaration.append("int");
+ break;
+ case 'S':
+ declaration.append("short");
+ break;
+ case 'C':
+ declaration.append("char");
+ break;
+ case 'F':
+ declaration.append("float");
+ break;
+ // case 'D':
+ default:
+ declaration.append("double");
+ break;
+ }
+ endType();
+ }
+
+ @Override
+ public void visitTypeVariable(final String name) {
+ declaration.append(name);
+ endType();
+ }
+
+ @Override
+ public SignatureVisitor visitArrayType() {
+ startType();
+ arrayStack |= 1;
+ return this;
+ }
+
+ @Override
+ public void visitClassType(final String name) {
+ if ("java/lang/Object".equals(name)) {
+ // Map<java.lang.Object,java.util.List>
+ // or
+ // abstract public V get(Object key); (seen in Dictionary.class)
+ // should have Object
+ // but java.lang.String extends java.lang.Object is unnecessary
+ boolean needObjectClass = argumentStack % 2 != 0 || seenParameter;
+ if (needObjectClass) {
+ declaration.append(separator).append(name.replace('/', '.'));
+ }
+ } else {
+ declaration.append(separator).append(name.replace('/', '.'));
+ }
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitInnerClassType(final String name) {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
+ }
+ argumentStack /= 2;
+ declaration.append('.');
+ declaration.append(separator).append(name.replace('/', '.'));
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ @Override
+ public void visitTypeArgument() {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(", ");
+ }
+ declaration.append('?');
+ }
+
+ @Override
+ public SignatureVisitor visitTypeArgument(final char tag) {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(", ");
+ }
+
+ if (tag == EXTENDS) {
+ declaration.append("? extends ");
+ } else if (tag == SUPER) {
+ declaration.append("? super ");
+ }
+
+ startType();
+ return this;
+ }
+
+ @Override
+ public void visitEnd() {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
+ }
+ argumentStack /= 2;
+ endType();
+ }
+
+ public String getDeclaration() {
+ return declaration.toString();
+ }
+
+ public String getReturnType() {
+ return returnType == null ? null : returnType.toString();
+ }
+
+ public String getExceptions() {
+ return exceptions == null ? null : exceptions.toString();
+ }
+
+ // -----------------------------------------------
+
+ private void endFormals() {
+ if (seenFormalParameter) {
+ declaration.append('>');
+ seenFormalParameter = false;
+ }
+ }
+
+ private void startType() {
+ arrayStack *= 2;
+ }
+
+ private void endType() {
+ if (arrayStack % 2 == 0) {
+ arrayStack /= 2;
+ } else {
+ while (arrayStack % 2 != 0) {
+ arrayStack /= 2;
+ declaration.append("[]");
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/cmd/FromString.scala b/src/compiler/scala/tools/cmd/FromString.scala
index 3792c26c34..91356b3c19 100644
--- a/src/compiler/scala/tools/cmd/FromString.scala
+++ b/src/compiler/scala/tools/cmd/FromString.scala
@@ -7,19 +7,19 @@ package scala.tools
package cmd
import nsc.io.{ Path, File, Directory }
-import scala.reflect.OptManifest
+import scala.reflect.TypeTag
/** A general mechanism for defining how a command line argument
* (always a String) is transformed into an arbitrary type. A few
* example instances are in the companion object, but in general
* either IntFromString will suffice or you'll want custom transformers.
*/
-abstract class FromString[+T](implicit m: OptManifest[T]) extends PartialFunction[String, T] {
+abstract class FromString[+T](implicit t: TypeTag[T]) extends PartialFunction[String, T] {
def apply(s: String): T
def isDefinedAt(s: String): Boolean = true
def zero: T = apply("")
- def targetString: String = m.toString
+ def targetString: String = t.toString
}
object FromString {
diff --git a/src/compiler/scala/tools/cmd/gen/AnyVals.scala b/src/compiler/scala/tools/cmd/gen/AnyVals.scala
index 0869350dd3..83cd9c2578 100644
--- a/src/compiler/scala/tools/cmd/gen/AnyVals.scala
+++ b/src/compiler/scala/tools/cmd/gen/AnyVals.scala
@@ -14,20 +14,43 @@ trait AnyValReps {
sealed abstract class AnyValNum(name: String, repr: Option[String], javaEquiv: String) extends AnyValRep(name,repr,javaEquiv) {
case class Op(val op : String, val doc : String)
+
+ private def companionCoercions(tos: AnyValRep*) = {
+ tos.toList map (to =>
+ """implicit def @javaequiv@2%s(x: @name@): %s = x.to%s""".format(to.javaEquiv, to.name, to.name)
+ )
+ }
+ def coercionCommentExtra = ""
+ def coercionComment = """
+ /** Language mandated coercions from @name@ to "wider" types.%s
+ */""".format(coercionCommentExtra)
+
+ def implicitCoercions: List[String] = {
+ val coercions = this match {
+ case B => companionCoercions(S, I, L, F, D)
+ case S | C => companionCoercions(I, L, F, D)
+ case I => companionCoercions(L, F, D)
+ case L => companionCoercions(F, D)
+ case F => companionCoercions(D)
+ case _ => Nil
+ }
+ if (coercions.isEmpty) Nil
+ else coercionComment :: coercions
+ }
def isCardinal: Boolean = isIntegerType(this)
def unaryOps = {
val ops = List(
Op("+", "/**\n" +
- " * @return this value, unmodified\n" +
+ " * Returns this value, unmodified.\n" +
" */"),
Op("-", "/**\n" +
- " * @return the negation of this value\n" +
+ " * Returns the negation of this value.\n" +
" */"))
if(isCardinal)
Op("~", "/**\n" +
- " * @return the bitwise negation of this value\n" +
+ " * Returns the bitwise negation of this value.\n" +
" * @example {{{\n" +
" * ~5 == -6\n" +
" * // in binary: ~00000101 ==\n" +
@@ -41,7 +64,7 @@ trait AnyValReps {
if (isCardinal)
List(
Op("|", "/**\n" +
- " * @return the bitwise OR of this value and x\n" +
+ " * Returns the bitwise OR of this value and `x`.\n" +
" * @example {{{\n" +
" * (0xf0 | 0xaa) == 0xfa\n" +
" * // in binary: 11110000\n" +
@@ -51,7 +74,7 @@ trait AnyValReps {
" * }}}\n" +
" */"),
Op("&", "/**\n" +
- " * @return the bitwise AND of this value and x\n" +
+ " * Returns the bitwise AND of this value and `x`.\n" +
" * @example {{{\n" +
" * (0xf0 & 0xaa) == 0xa0\n" +
" * // in binary: 11110000\n" +
@@ -61,7 +84,7 @@ trait AnyValReps {
" * }}}\n" +
" */"),
Op("^", "/**\n" +
- " * @return the bitwise XOR of this value and x\n" +
+ " * Returns the bitwise XOR of this value and `x`.\n" +
" * @example {{{\n" +
" * (0xf0 ^ 0xaa) == 0x5a\n" +
" * // in binary: 11110000\n" +
@@ -76,13 +99,13 @@ trait AnyValReps {
if (isCardinal)
List(
Op("<<", "/**\n" +
- " * @return this value bit-shifted left by the specified number of bits,\n" +
+ " * Returns this value bit-shifted left by the specified number of bits,\n" +
" * filling in the new right bits with zeroes.\n" +
" * @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}\n" +
" */"),
Op(">>>", "/**\n" +
- " * @return this value bit-shifted right by the specified number of bits,\n" +
+ " * Returns this value bit-shifted right by the specified number of bits,\n" +
" * filling the new left bits with zeroes.\n" +
" * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}\n" +
" * @example {{{\n" +
@@ -93,7 +116,7 @@ trait AnyValReps {
" */"),
Op(">>", "/**\n" +
- " * @return this value bit-shifted left by the specified number of bits,\n" +
+ " * Returns this value bit-shifted left by the specified number of bits,\n" +
" * filling in the right bits with the same value as the left-most bit of this.\n" +
" * The effect of this is to retain the sign of the value.\n" +
" * @example {{{\n" +
@@ -105,19 +128,19 @@ trait AnyValReps {
else Nil
def comparisonOps = List(
- Op("==", "/**\n * @return `true` if this value is equal x, `false` otherwise\n */"),
- Op("!=", "/**\n * @return `true` if this value is not equal to x, `false` otherwise\n */"),
- Op("<", "/**\n * @return `true` if this value is less than x, `false` otherwise\n */"),
- Op("<=", "/**\n * @return `true` if this value is less than or equal to x, `false` otherwise\n */"),
- Op(">", "/**\n * @return `true` if this value is greater than x, `false` otherwise\n */"),
- Op(">=", "/**\n * @return `true` if this value is greater than or equal to x, `false` otherwise\n */"))
+ Op("==", "/**\n * Returns `true` if this value is equal to x, `false` otherwise.\n */"),
+ Op("!=", "/**\n * Returns `true` if this value is not equal to x, `false` otherwise.\n */"),
+ Op("<", "/**\n * Returns `true` if this value is less than x, `false` otherwise.\n */"),
+ Op("<=", "/**\n * Returns `true` if this value is less than or equal to x, `false` otherwise.\n */"),
+ Op(">", "/**\n * Returns `true` if this value is greater than x, `false` otherwise.\n */"),
+ Op(">=", "/**\n * Returns `true` if this value is greater than or equal to x, `false` otherwise.\n */"))
def otherOps = List(
- Op("+", "/**\n * @return the sum of this value and x\n */"),
- Op("-", "/**\n * @return the difference of this value and x\n */"),
- Op("*", "/**\n * @return the product of this value and x\n */"),
- Op("/", "/**\n * @return the quotient of this value and x\n */"),
- Op("%", "/**\n * @return the remainder of the division of this value by x\n */"))
+ Op("+", "/**\n * Returns the sum of this value and `x`.\n */"),
+ Op("-", "/**\n * Returns the difference of this value and `x`.\n */"),
+ Op("*", "/**\n * Returns the product of this value and `x`.\n */"),
+ Op("/", "/**\n * Returns the quotient of this value and `x`.\n */"),
+ Op("%", "/**\n * Returns the remainder of the division of this value by `x`.\n */"))
// Given two numeric value types S and T , the operation type of S and T is defined as follows:
// If both S and T are subrange types then the operation type of S and T is Int.
@@ -160,7 +183,7 @@ trait AnyValReps {
}
def objectLines = {
val comp = if (isCardinal) cardinalCompanion else floatingCompanion
- (comp + allCompanions).trim.lines map interpolate toList
+ (comp + allCompanions + "\n" + nonUnitCompanions).trim.lines.toList ++ implicitCoercions map interpolate
}
/** Makes a set of binary operations based on the given set of ops, args, and resultFn.
@@ -224,8 +247,9 @@ trait AnyValReps {
def classDoc = interpolate(classDocTemplate)
def objectDoc = ""
def mkImports = ""
- def mkClass = assemble("final class", "AnyVal", classLines) + "\n"
- def mkObject = assemble("object", "AnyValCompanion", objectLines) + "\n"
+
+ def mkClass = assemble("final class " + name + " private extends AnyVal", classLines)
+ def mkObject = assemble("object " + name + " extends AnyValCompanion", objectLines)
def make() = List[String](
headerTemplate,
mkImports,
@@ -235,11 +259,10 @@ trait AnyValReps {
mkObject
) mkString ""
- def assemble(what: String, parent: String, lines: List[String]): String = {
- val decl = "%s %s extends %s ".format(what, name, parent)
- val body = if (lines.isEmpty) "{ }\n\n" else lines map indent mkString ("{\n", "\n", "\n}\n")
+ def assemble(decl: String, lines: List[String]): String = {
+ val body = if (lines.isEmpty) " { }\n\n" else lines map indent mkString (" {\n", "\n", "\n}\n")
- decl + body
+ decl + body + "\n"
}
override def toString = name
}
@@ -296,6 +319,8 @@ def unbox(x: java.lang.Object): @name@ = @unboxImpl@
override def toString = "object scala.@name@"
"""
+ def nonUnitCompanions = "" // todo
+
def cardinalCompanion = """
/** The smallest value representable as a @name@.
*/
@@ -432,7 +457,7 @@ def ^(x: Boolean): Boolean = sys.error("stub")
override def getClass(): Class[Boolean] = sys.error("stub")
""".trim.lines.toList
- def objectLines = interpolate(allCompanions).lines.toList
+ def objectLines = interpolate(allCompanions + "\n" + nonUnitCompanions).lines.toList
}
object U extends AnyValRep("Unit", None, "void") {
override def classDoc = """
diff --git a/src/compiler/scala/tools/cmd/program/DumpClass.scala b/src/compiler/scala/tools/cmd/program/DumpClass.scala
new file mode 100644
index 0000000000..a583f1d3ea
--- /dev/null
+++ b/src/compiler/scala/tools/cmd/program/DumpClass.scala
@@ -0,0 +1,40 @@
+/* NEST (New Scala Test)
+ * Copyright 2007-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools
+package cmd
+package program
+
+import scala.reflect.internal.JvmClassInfo
+import scala.tools.nsc.io.Directory
+
+object DumpClass {
+ private val usage = """
+ |Usage: dump-class [options] <path> <path> ...
+ |
+ |Parses and dumps the bytecode of all classes found at the given paths.
+ |""".stripMargin
+
+ private val unaryOps = List(
+ "signatures" -> "dump signatures"
+ )
+ private val info = Simple.scalaProgramInfo("dump-class", usage)
+ private val spec = Simple(info, unaryOps, Nil, null)
+
+ def deepInfos(dir: String) = {
+ val files = Directory(dir).deepFiles.toList filter (_ hasExtension "class")
+ files.sortBy(_.path) map (f => (f.path, JvmClassInfo fromPath f.path))
+ }
+
+ def main(args: Array[String]): Unit = {
+ val runner = spec instance args
+ import runner._
+
+ if (args.isEmpty)
+ println(usage)
+ else
+ (residualArgs flatMap deepInfos) sortBy (_._1) map (_._2) foreach println
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/ClassLoaders.scala b/src/compiler/scala/tools/nsc/ClassLoaders.scala
new file mode 100644
index 0000000000..4058ee9324
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ClassLoaders.scala
@@ -0,0 +1,64 @@
+package scala.tools.nsc
+
+import util.ScalaClassLoader
+
+trait ClassLoaders { self: Global =>
+
+ def staticClass(fullname: String) = {
+ if (self.forMSIL)
+ throw new UnsupportedOperationException("Scala reflection not available on this platform")
+
+ getClass(newTypeName(fullname))
+ }
+
+ def staticModule(fullname: String) = {
+ if (self.forMSIL)
+ throw new UnsupportedOperationException("Scala reflection not available on this platform")
+
+ getModule(newTermName(fullname))
+ }
+
+ private def getClass(fullname: Name): Symbol = {
+ var result = getModuleOrClass(fullname.toTypeName)
+ while (result.isAliasType) result = result.info.typeSymbol
+ result
+ }
+
+ private def getModule(fullname: Name): Symbol =
+ getModuleOrClass(fullname.toTermName)
+
+ private def getModuleOrClass(path: Name): Symbol =
+ getModuleOrClass(path, path.length)
+
+ private def getModuleOrClass(path: Name, len: Int): Symbol = {
+ val point = path lastPos('.', len - 1)
+ val owner =
+ if (point > 0) getModuleOrClass(path.toTermName, point)
+ else definitions.RootClass
+ val name = path subName (point + 1, len)
+ val sym = owner.info member name
+ val result = if (path.isTermName) sym.suchThat(_ hasFlag symtab.Flags.MODULE) else sym
+ if (result != NoSymbol) result
+ else {
+ if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug
+ if (owner.isRoot && isJavaClass(name.toString))
+ definitions.EmptyPackageClass.info decl name
+ else {
+ def info(msg: => String) = if (settings.verbose.value) println(msg)
+ info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass)
+ MissingRequirementError.notFound((if (path.isTermName) "object " else "class ")+path)
+ }
+ }
+ }
+
+ private def isJavaClass(path: String): Boolean =
+ try {
+ val classpath = platform.classPath.asURLs
+ var classLoader = ScalaClassLoader.fromURLs(classpath)
+ Class.forName(path, true, classLoader)
+ true
+ } catch {
+ case (_: ClassNotFoundException) | (_: NoClassDefFoundError) | (_: IncompatibleClassChangeError) =>
+ false
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala
index d6f57801e7..2f1e15168a 100644
--- a/src/compiler/scala/tools/nsc/CompilationUnits.scala
+++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala
@@ -5,7 +5,7 @@
package scala.tools.nsc
-import util.{ FreshNameCreator, Position, NoPosition, SourceFile, NoSourceFile }
+import util.{ FreshNameCreator, Position, NoPosition, BatchSourceFile, SourceFile, NoSourceFile }
import scala.collection.mutable
import scala.collection.mutable.{ LinkedHashSet, ListBuffer }
@@ -61,6 +61,9 @@ trait CompilationUnits { self: Global =>
/** things to check at end of compilation unit */
val toCheck = new ListBuffer[() => Unit]
+ /** The features that were already checked for this unit */
+ var checkedFeatures = Set[Symbol]()
+
def position(pos: Int) = source.position(pos)
/** The position of a targeted type check
@@ -85,12 +88,13 @@ trait CompilationUnits { self: Global =>
reporter.warning(pos, msg)
def deprecationWarning(pos: Position, msg: String) =
- if (opt.deprecation) warning(pos, msg)
- else currentRun.deprecationWarnings ::= ((pos, msg))
+ currentRun.deprecationWarnings0.warn(pos, msg)
def uncheckedWarning(pos: Position, msg: String) =
- if (opt.unchecked) warning(pos, msg)
- else currentRun.uncheckedWarnings ::= ((pos, msg))
+ currentRun.uncheckedWarnings0.warn(pos, msg)
+
+ def inlinerWarning(pos: Position, msg: String) =
+ currentRun.inlinerWarnings.warn(pos, msg)
def incompleteInputError(pos: Position, msg:String) =
reporter.incompleteInputError(pos, msg)
@@ -104,10 +108,14 @@ trait CompilationUnits { self: Global =>
override def toString() = source.toString()
def clear() {
- fresh = null
- body = null
+ fresh = new FreshNameCreator.Default
+ body = EmptyTree
depends.clear()
defined.clear()
+ synthetics.clear()
+ toCheck.clear()
+ checkedFeatures = Set()
+ icode.clear()
}
}
}
diff --git a/src/compiler/scala/tools/nsc/CompileSocket.scala b/src/compiler/scala/tools/nsc/CompileSocket.scala
index a0c39f71fb..a4a8e1fd11 100644
--- a/src/compiler/scala/tools/nsc/CompileSocket.scala
+++ b/src/compiler/scala/tools/nsc/CompileSocket.scala
@@ -93,7 +93,7 @@ class CompileSocket extends CompileOutputCommon {
/** Start a new server. */
private def startNewServer(vmArgs: String) = {
- val cmd = serverCommand(vmArgs split " " toSeq)
+ val cmd = serverCommand((vmArgs split " ").toSeq)
info("[Executing command: %s]" format cmd.mkString(" "))
// Hiding inadequate daemonized implementation from public API for now
@@ -206,7 +206,7 @@ class CompileSocket extends CompileOutputCommon {
Thread sleep 100
ff.length
}
- if (Iterator continually check take 50 find (_ > 0) isEmpty) {
+ if ((Iterator continually check take 50 find (_ > 0)).isEmpty) {
ff.delete()
fatal("Unable to establish connection to server.")
}
diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala
index 54bc218912..4c8a27083a 100644
--- a/src/compiler/scala/tools/nsc/CompilerCommand.scala
+++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala
@@ -47,7 +47,7 @@ class CompilerCommand(arguments: List[String], val settings: Settings) {
/** Creates a help message for a subset of options based on cond */
def createUsageMsg(cond: Setting => Boolean): String = {
val baseList = (settings.visibleSettings filter cond).toList sortBy (_.name)
- val width = baseList map (_.helpSyntax.length) max
+ val width = (baseList map (_.helpSyntax.length)).max
def format(s: String) = ("%-" + width + "s") format s
def helpStr(s: Setting) = {
val str = format(s.helpSyntax) + " " + s.helpDescription
diff --git a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
index b9e9a14adf..f91cb854c6 100644
--- a/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
+++ b/src/compiler/scala/tools/nsc/GenericRunnerSettings.scala
@@ -8,7 +8,7 @@ package scala.tools.nsc
import scala.tools.util.PathResolver
class GenericRunnerSettings(error: String => Unit) extends Settings(error) {
- def classpathURLs = new PathResolver(this) asURLs
+ def classpathURLs = new PathResolver(this).asURLs
val howtorun =
ChoiceSetting(
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 9ccd0c28db..d3564017f9 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -8,7 +8,6 @@ package scala.tools.nsc
import java.io.{ File, FileOutputStream, PrintWriter, IOException, FileNotFoundException }
import java.nio.charset.{ Charset, CharsetDecoder, IllegalCharsetNameException, UnsupportedCharsetException }
import compat.Platform.currentTime
-
import scala.tools.util.{ Profiling, PathResolver }
import scala.collection.{ mutable, immutable }
import io.{ SourceReader, AbstractFile, Path }
@@ -16,7 +15,6 @@ import reporters.{ Reporter, ConsoleReporter }
import util.{ NoPosition, Exceptional, ClassPath, SourceFile, NoSourceFile, Statistics, StatisticsInfo, BatchSourceFile, ScriptSourceFile, ShowPickled, ScalaClassLoader, returning }
import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat }
import settings.{ AestheticSettings }
-
import symtab.{ Flags, SymbolTable, SymbolLoaders, SymbolTrackers }
import symtab.classfile.Pickler
import dependencies.DependencyAnalysis
@@ -25,26 +23,28 @@ import ast._
import ast.parser._
import typechecker._
import transform._
-
import backend.icode.{ ICodes, GenICode, ICodeCheckers }
import backend.{ ScalaPrimitives, Platform, MSILPlatform, JavaPlatform }
-import backend.jvm.GenJVM
+import backend.jvm.{GenJVM, GenASM}
import backend.opt.{ Inliners, InlineExceptionHandlers, ClosureElimination, DeadCodeElimination }
import backend.icode.analysis._
+import language.postfixOps
+import reflect.internal.StdAttachments
class Global(var currentSettings: Settings, var reporter: Reporter) extends SymbolTable
- with CompilationUnits
- with Plugins
- with PhaseAssembly
- with Trees
- with Reifiers
- with TreePrinters
- with DocComments
- with MacroContext
- with symtab.Positions {
+ with ClassLoaders
+ with ToolBoxes
+ with CompilationUnits
+ with Plugins
+ with PhaseAssembly
+ with Trees
+ with FreeVars
+ with TreePrinters
+ with DocComments
+ with Positions {
override def settings = currentSettings
-
+
import definitions.{ findNamedMember, findMemberFromRoot }
// alternate constructors ------------------------------------------
@@ -61,7 +61,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
type AbstractFileType = scala.tools.nsc.io.AbstractFile
def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree = gen.mkAttributedQualifier(tpe, termSym)
-
+
def picklerPhase: Phase = if (currentRun.isDefined) currentRun.picklerPhase else NoPhase
// platform specific elements
@@ -78,6 +78,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
// sub-components --------------------------------------------------
/** Generate ASTs */
+ type TreeGen = scala.tools.nsc.ast.TreeGen
+
object gen extends {
val global: Global.this.type = Global.this
} with TreeGen {
@@ -127,17 +129,26 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** Print tree in detailed form */
object nodePrinters extends {
val global: Global.this.type = Global.this
- } with NodePrinters with ReifyPrinters {
+ } with NodePrinters {
infolevel = InfoLevel.Verbose
}
+ def withInfoLevel[T](infolevel: nodePrinters.InfoLevel.Value)(op: => T) = {
+ val saved = nodePrinters.infolevel
+ try {
+ nodePrinters.infolevel = infolevel
+ op
+ } finally {
+ nodePrinters.infolevel = saved
+ }
+ }
+
/** Representing ASTs as graphs */
object treeBrowsers extends {
val global: Global.this.type = Global.this
} with TreeBrowsers
val nodeToString = nodePrinters.nodeToString
- val reifiedNodeToString = nodePrinters.reifiedNodeToString
val treeBrowser = treeBrowsers.create()
// ------------ Hooks for interactive mode-------------------------
@@ -215,15 +226,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def logAfterEveryPhase[T](msg: String)(op: => T) {
log("Running operation '%s' after every phase.\n".format(msg) + describeAfterEveryPhase(op))
}
-
+
def shouldLogAtThisPhase = (
(settings.log.isSetByUser)
&& ((settings.log containsPhase globalPhase) || (settings.log containsPhase phase))
)
- def atPhaseStackMessage = atPhaseStack match {
- case Nil => ""
- case ps => ps.reverseMap("->" + _).mkString("(", " ", ")")
- }
// Over 200 closure objects are eliminated by inlining this.
@inline final def log(msg: => AnyRef) {
if (shouldLogAtThisPhase)
@@ -236,7 +243,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
}
def logThrowable(t: Throwable): Unit = globalError(throwableAsString(t))
- def throwableAsString(t: Throwable): String =
+ override def throwableAsString(t: Throwable): String =
if (opt.richExes) Exceptional(t).force().context()
else util.stackTraceString(t)
@@ -323,7 +330,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def showNames = List(showClass, showObject).flatten
def showPhase = isActive(settings.Yshow)
def showSymbols = settings.Yshowsyms.value
- def showTrees = settings.Xshowtrees.value
+ def showTrees = settings.Xshowtrees.value || settings.XshowtreesCompact.value || settings.XshowtreesStringified.value
val showClass = optSetting[String](settings.Xshowcls) map (x => splitClassAndPhase(x, false))
val showObject = optSetting[String](settings.Xshowobj) map (x => splitClassAndPhase(x, true))
@@ -347,9 +354,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
// where I need it, and then an override in Global with the setting.
override protected val etaExpandKeepsStar = settings.etaExpandKeepsStar.value
// Here comes another one...
- override protected val enableTypeVarExperimentals = (
- settings.Xexperimental.value || settings.YvirtPatmat.value
- )
+ override protected val enableTypeVarExperimentals = settings.Xexperimental.value
// True if -Xscript has been set, indicating a script run.
def isScriptRun = opt.script.isDefined
@@ -455,10 +460,19 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val global: Global.this.type = Global.this
} with Analyzer
+ // phaseName = "patmat"
+ object patmat extends {
+ val global: Global.this.type = Global.this
+ val runsAfter = List("typer")
+ // patmat doesn't need to be right after typer, as long as we run before supperaccesors
+ // (sbt does need to run right after typer, so don't conflict)
+ val runsRightAfter = None
+ } with PatternMatching
+
// phaseName = "superaccessors"
object superAccessors extends {
val global: Global.this.type = Global.this
- val runsAfter = List("typer")
+ val runsAfter = List("patmat")
val runsRightAfter = None
} with SuperAccessors
@@ -527,7 +541,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
// phaseName = "lazyvals"
object lazyVals extends {
- final val FLAGS_PER_WORD = 32
val global: Global.this.type = Global.this
val runsAfter = List("erasure")
val runsRightAfter = None
@@ -603,13 +616,20 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
val runsRightAfter = None
} with DeadCodeElimination
- // phaseName = "jvm"
+ // phaseName = "jvm", FJBG-based version
object genJVM extends {
val global: Global.this.type = Global.this
val runsAfter = List("dce")
val runsRightAfter = None
} with GenJVM
+ // phaseName = "jvm", ASM-based version
+ object genASM extends {
+ val global: Global.this.type = Global.this
+ val runsAfter = List("dce")
+ val runsRightAfter = None
+ } with GenASM
+
// This phase is optional: only added if settings.make option is given.
// phaseName = "dependencyAnalysis"
object dependencyAnalysis extends {
@@ -675,6 +695,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
analyzer.namerFactory -> "resolve names, attach symbols to named trees",
analyzer.packageObjects -> "load package objects",
analyzer.typerFactory -> "the meat and potatoes: type the trees",
+ patmat -> "translate match expressions",
superAccessors -> "add super accessors in traits and nested classes",
extensionMethods -> "add extension methods for inline classes",
pickler -> "serialize symbol tables",
@@ -940,6 +961,22 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
inform("[running phase " + ph.name + " on " + currentRun.size + " compilation units]")
}
+ /** Collects for certain classes of warnings during this run. */
+ class ConditionalWarning(what: String, option: Settings#BooleanSetting) {
+ val warnings = new mutable.ListBuffer[(Position, String)]
+ def warn(pos: Position, msg: String) =
+ if (option.value) reporter.warning(pos, msg)
+ else warnings += ((pos, msg))
+ def summarize() =
+ if (option.isDefault && warnings.nonEmpty)
+ reporter.warning(NoPosition, "there were %d %s warnings; re-run with %s for details".format(warnings.size, what, option.name))
+ }
+
+ def newUnitParser(code: String) = new syntaxAnalyzer.UnitParser(newCompilationUnit(code))
+ def newUnitScanner(code: String) = new syntaxAnalyzer.UnitScanner(newCompilationUnit(code))
+ def newCompilationUnit(code: String) = new CompilationUnit(newSourceFile(code))
+ def newSourceFile(code: String) = new BatchSourceFile("<console>", code)
+
/** A Run is a single execution of the compiler on a sets of units
*/
class Run {
@@ -951,9 +988,19 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** The currently compiled unit; set from GlobalPhase */
var currentUnit: CompilationUnit = NoCompilationUnit
- /** Counts for certain classes of warnings during this run. */
- var deprecationWarnings: List[(Position, String)] = Nil
- var uncheckedWarnings: List[(Position, String)] = Nil
+ // This change broke sbt; I gave it the thrilling name of uncheckedWarnings0 so
+ // as to recover uncheckedWarnings for its ever-fragile compiler interface.
+ val deprecationWarnings0 = new ConditionalWarning("deprecation", settings.deprecation)
+ val uncheckedWarnings0 = new ConditionalWarning("unchecked", settings.unchecked)
+ val featureWarnings = new ConditionalWarning("feature", settings.feature)
+ val inlinerWarnings = new ConditionalWarning("inliner", settings.YinlinerWarnings)
+ val allConditionalWarnings = List(deprecationWarnings0, uncheckedWarnings0, featureWarnings, inlinerWarnings)
+
+ // for sbt's benefit
+ def uncheckedWarnings: List[(Position, String)] = uncheckedWarnings0.warnings.toList
+ def deprecationWarnings: List[(Position, String)] = deprecationWarnings0.warnings.toList
+
+ var reportedFeature = Set[Symbol]()
/** A flag whether macro expansions failed */
var macroExpansionFailed = false
@@ -1006,7 +1053,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** Set phase to a newly created syntaxAnalyzer and call definitions.init. */
val parserPhase: Phase = syntaxAnalyzer.newPhase(NoPhase)
phase = parserPhase
- definitions.init
+ definitions.init()
// Flush the cache in the terminal phase: the chain could have been built
// before without being used. (This happens in the interpreter.)
@@ -1112,7 +1159,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
def phaseNamed(name: String): Phase =
findOrElse(firstPhase.iterator)(_.name == name)(NoPhase)
-
+
/** All phases as of 3/2012 here for handiness; the ones in
* active use uncommented.
*/
@@ -1243,12 +1290,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
}
}
else {
- def warn(count: Int, what: String, option: Settings#BooleanSetting) = (
- if (option.isDefault && count > 0)
- warning("there were %d %s warnings; re-run with %s for details".format(count, what, option.name))
- )
- warn(deprecationWarnings.size, "deprecation", settings.deprecation)
- warn(uncheckedWarnings.size, "unchecked", settings.unchecked)
+ allConditionalWarnings foreach (_.summarize)
+
if (macroExpansionFailed)
warning("some macros could not be expanded and code fell back to overridden methods;"+
"\nrecompiling with generated classfiles on the classpath might help.")
@@ -1266,7 +1309,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
// nothing to compile, but we should still report use of deprecated options
if (sources.isEmpty) {
- checkDeprecatedSettings(new CompilationUnit(new BatchSourceFile("<no file>", "")))
+ checkDeprecatedSettings(newCompilationUnit(""))
reportCompileErrors()
return
}
@@ -1356,6 +1399,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
inform(unitTimingsFormatted)
}
+ if (traceSymbolActivity)
+ units map (_.body) foreach (traceSymbols recordSymbolsInTree _)
+
// In case no phase was specified for -Xshow-class/object, show it now for sure.
if (opt.noShow)
showMembers()
@@ -1499,7 +1545,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
/** We resolve the class/object ambiguity by passing a type/term name.
*/
def showDef(fullName: Name, declsOnly: Boolean, ph: Phase) = {
- val boringOwners = Set(definitions.AnyClass, definitions.AnyRefClass, definitions.ObjectClass)
+ val boringOwners = Set[Symbol](definitions.AnyClass, definitions.AnyRefClass, definitions.ObjectClass)
def phased[T](body: => T): T = afterPhase(ph)(body)
def boringMember(sym: Symbol) = boringOwners(sym.owner)
def symString(sym: Symbol) = if (sym.isTerm) sym.defString else sym.toString
diff --git a/src/compiler/scala/tools/nsc/MacroContext.scala b/src/compiler/scala/tools/nsc/MacroContext.scala
deleted file mode 100644
index 9ea1f87125..0000000000
--- a/src/compiler/scala/tools/nsc/MacroContext.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-package scala.tools.nsc
-
-import symtab.Flags._
-
-trait MacroContext extends reflect.macro.Context { self: Global =>
-
- def captureVariable(vble: Symbol): Unit = vble setFlag CAPTURED
-
- def referenceCapturedVariable(id: Ident): Tree = ReferenceToBoxed(id)
-}
diff --git a/src/compiler/scala/tools/nsc/PhaseAssembly.scala b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
index a627b982b6..a9e029e485 100644
--- a/src/compiler/scala/tools/nsc/PhaseAssembly.scala
+++ b/src/compiler/scala/tools/nsc/PhaseAssembly.scala
@@ -8,6 +8,7 @@ package scala.tools.nsc
import java.io.{ BufferedWriter, FileWriter }
import scala.collection.mutable
+import language.postfixOps
/**
* PhaseAssembly
diff --git a/src/compiler/scala/tools/nsc/Phases.scala b/src/compiler/scala/tools/nsc/Phases.scala
index d18495458c..aa0ea1bdd8 100644
--- a/src/compiler/scala/tools/nsc/Phases.scala
+++ b/src/compiler/scala/tools/nsc/Phases.scala
@@ -7,13 +7,14 @@ package scala.tools.nsc
import symtab.Flags
import util.TableDef
+import language.postfixOps
object Phases {
val MaxPhases = 64
/** A class for tracking something about each phase.
*/
- class Model[T: Manifest] {
+ class Model[T] {
case class Cell(ph: Phase, value: T) {
def name = ph.name
def id = ph.id
diff --git a/src/compiler/scala/tools/nsc/ReflectGlobal.scala b/src/compiler/scala/tools/nsc/ReflectGlobal.scala
index 3132a9987d..68a6a4d336 100644
--- a/src/compiler/scala/tools/nsc/ReflectGlobal.scala
+++ b/src/compiler/scala/tools/nsc/ReflectGlobal.scala
@@ -5,7 +5,7 @@ import reporters.Reporter
/** A version of Global that uses reflection to get class
* infos, instead of reading class or source files.
*/
-class ReflectGlobal(currentSettings: Settings, reporter: Reporter)
+class ReflectGlobal(currentSettings: Settings, reporter: Reporter, var classLoader: ClassLoader)
extends Global(currentSettings, reporter) with reflect.runtime.SymbolTable {
override def transformedType(sym: Symbol) =
@@ -13,4 +13,9 @@ class ReflectGlobal(currentSettings: Settings, reporter: Reporter)
uncurry.transformInfo(sym,
refChecks.transformInfo(sym, sym.info)))
+ override def staticClass(fullname: String) =
+ super[SymbolTable].staticClass(fullname)
+
+ override def staticModule(fullname: String) =
+ super[SymbolTable].staticModule(fullname)
}
diff --git a/src/compiler/scala/tools/nsc/ReflectMain.scala b/src/compiler/scala/tools/nsc/ReflectMain.scala
index 7167f5aa27..f9a18abc25 100644
--- a/src/compiler/scala/tools/nsc/ReflectMain.scala
+++ b/src/compiler/scala/tools/nsc/ReflectMain.scala
@@ -1,7 +1,16 @@
package scala.tools.nsc
+import util.ScalaClassLoader
+import tools.util.PathResolver
+import util.ClassPath.DefaultJavaContext
+
object ReflectMain extends Driver {
- override def newCompiler(): Global = new ReflectGlobal(settings, reporter)
+ private def reflectionClassloaderFromSettings(settings: Settings) = {
+ val classpath = new PathResolver(settings).result
+ ScalaClassLoader.fromURLs(classpath.asURLs, getClass.getClassLoader)
+ }
+
+ override def newCompiler(): Global = new ReflectGlobal(settings, reporter, reflectionClassloaderFromSettings(settings))
} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/ToolBoxes.scala b/src/compiler/scala/tools/nsc/ToolBoxes.scala
new file mode 100644
index 0000000000..8bf977090b
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ToolBoxes.scala
@@ -0,0 +1,84 @@
+package scala.tools.nsc
+
+import util.ScalaClassLoader
+
+trait ToolBoxes { self: Global =>
+
+ def mkToolBox(frontEnd: FrontEnd = mkSilentFrontEnd(), options: String = "") = new ToolBox(frontEnd, options)
+
+ class ToolBox(val frontEnd: FrontEnd, val options: String) extends AbsToolBox {
+ def typeCheck(tree0: Tree, pt: Type = WildcardType, freeTypes: Map[FreeType, Type] = Map[FreeType, Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree = {
+ val tree = substituteFreeTypes(tree0, freeTypes)
+ val currentTyper = typer
+ val wrapper1 = if (!withImplicitViewsDisabled) (currentTyper.context.withImplicitsEnabled[Tree] _) else (currentTyper.context.withImplicitsDisabled[Tree] _)
+ val wrapper2 = if (!withMacrosDisabled) (currentTyper.context.withMacrosEnabled[Tree] _) else (currentTyper.context.withMacrosDisabled[Tree] _)
+ def wrapper (tree: => Tree) = wrapper1(wrapper2(tree))
+ wrapper(currentTyper.silent(_.typed(tree, analyzer.EXPRmode, pt)) match {
+ case analyzer.SilentResultValue(result) =>
+ result
+ case error @ analyzer.SilentTypeError(_) =>
+ if (!silent) throw new ToolBoxError(this, "reflective typecheck has failed: %s".format(error.err.errMsg))
+ EmptyTree
+ })
+ }
+
+ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): Tree =
+ // todo. implement this
+ ???
+
+ def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): Tree =
+ // todo. implement this
+ ???
+
+ def resetAllAttrs[T <: Tree](tree: T): T =
+ self.resetAllAttrs(tree)
+
+ def resetLocalAttrs[T <: Tree](tree: T): T =
+ self.resetLocalAttrs(tree)
+
+ def runExpr(tree0: Tree, freeTypes: Map[FreeType, Type] = Map[FreeType, Type]()): Any = {
+ var tree = substituteFreeTypes(tree0, freeTypes)
+ // need to reset the tree, otherwise toolbox will refuse to work with it
+ // upd. this has to be done by the user himself, otherwise we run into troubles. see SI-5713
+// tree = resetAllAttrs(tree0.duplicate)
+ val imported = importer.importTree(tree)
+ val toolBox = libraryClasspathMirror.mkToolBox(frontEnd.asInstanceOf[libraryClasspathMirror.FrontEnd], options)
+ try toolBox.runExpr(imported)
+ catch {
+ case ex: toolBox.ToolBoxError =>
+ throw new ToolBoxError(this, ex.message, ex.cause)
+ }
+ }
+
+ // [Eugene] how do I make this work without casts?
+ // private lazy val importer = libraryClasspathMirror.mkImporter(self)
+ private lazy val importer = libraryClasspathMirror.mkImporter(self).asInstanceOf[libraryClasspathMirror.Importer { val from: self.type }]
+
+ private lazy val libraryClasspathMirror = {
+ if (self.forMSIL)
+ throw new UnsupportedOperationException("Scala reflection not available on this platform")
+
+ val libraryClassLoader = {
+ val classpath = self.classPath.asURLs
+ var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
+
+ // [Eugene] a heuristic to detect REPL
+ if (self.settings.exposeEmptyPackage.value) {
+ import scala.tools.nsc.interpreter._
+ val virtualDirectory = self.settings.outputDirs.getSingleOutput.get
+ loader = new AbstractFileClassLoader(virtualDirectory, loader) {}
+ }
+
+ loader
+ }
+
+ new scala.reflect.runtime.Mirror(libraryClassLoader)
+ }
+
+ class ToolBoxError(val toolBox: ToolBox, val message: String, val cause: Throwable = null) extends Throwable(message, cause)
+
+ object ToolBoxError extends ToolBoxErrorExtractor {
+ def unapply(error: ToolBoxError): Option[(ToolBox, String)] = Some((error.toolBox, error.message))
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index d3f4688d4b..028c5741c9 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -7,7 +7,7 @@ package scala.tools.nsc
package ast
import symtab._
-import reporters.Reporter
+import reporters._
import util.{Position, NoPosition}
import util.DocStrings._
import scala.reflect.internal.Chars._
@@ -21,8 +21,6 @@ trait DocComments { self: Global =>
var cookedDocComments = Map[Symbol, String]()
- def reporter: Reporter
-
/** The raw doc comment map */
val docComments = mutable.HashMap[Symbol, DocComment]()
@@ -252,7 +250,7 @@ trait DocComments { self: Global =>
def replaceInheritdoc(childSection: String, parentSection: => String) =
if (childSection.indexOf("@inheritdoc") == -1)
childSection
- else
+ else
childSection.replaceAllLiterally("@inheritdoc", parentSection)
def getParentSection(section: (Int, Int)): String = {
@@ -275,9 +273,9 @@ trait DocComments { self: Global =>
}
child.substring(section._1, section._1 + 7) match {
- case param@("@param "|"@tparam"|"@throws") =>
+ case param@("@param "|"@tparam"|"@throws") =>
sectionString(extractSectionParam(child, section), parentNamedParams(param.trim))
- case _ =>
+ case _ =>
sectionString(extractSectionTag(child, section), parentTagMap)
}
}
@@ -367,7 +365,7 @@ trait DocComments { self: Global =>
case vname =>
lookupVariable(vname, site) match {
case Some(replacement) => replaceWith(replacement)
- case None => reporter.warning(sym.pos, "Variable " + vname + " undefined in comment for " + sym)
+ case None => reporter.warning(sym.pos, "Variable " + vname + " undefined in comment for " + sym + " in " + site)
}
}
}
@@ -385,7 +383,7 @@ trait DocComments { self: Global =>
}
// !!! todo: inherit from Comment?
- case class DocComment(raw: String, pos: Position = NoPosition) {
+ case class DocComment(raw: String, pos: Position = NoPosition, codePos: Position = NoPosition) {
/** Returns:
* template: the doc comment minus all @define and @usecase sections
@@ -414,7 +412,7 @@ trait DocComments { self: Global =>
val comment = "/** " + raw.substring(commentStart, end) + "*/"
val commentPos = subPos(commentStart, end)
- UseCase(DocComment(comment, commentPos), code, codePos)
+ UseCase(DocComment(comment, commentPos, codePos), code, codePos)
}
private def subPos(start: Int, end: Int) =
@@ -463,7 +461,18 @@ trait DocComments { self: Global =>
findIn(classes ::: List(pkgs.head, definitions.RootClass))
}
- def getType(str: String): Type = {
+ def getType(_str: String, variable: String): Type = {
+ /*
+ * work around the backticks issue suggested by Simon in
+ * https://groups.google.com/forum/?hl=en&fromgroups#!topic/scala-internals/z7s1CCRCz74
+ * ideally, we'd have a removeWikiSyntax method in the CommentFactory to completely eliminate the wiki markup
+ */
+ val str =
+ if (_str.length >= 2 && _str.startsWith("`") && _str.endsWith("`"))
+ _str.substring(1, _str.length - 2)
+ else
+ _str
+
def getParts(start: Int): List[String] = {
val end = skipIdent(str, start)
if (end == start) List()
@@ -473,7 +482,11 @@ trait DocComments { self: Global =>
}
}
val parts = getParts(0)
- assert(parts.nonEmpty, "parts is empty '" + str + "' in site " + site)
+ if (parts.isEmpty) {
+ reporter.error(comment.codePos, "Incorrect variable expansion for " + variable + " in use case. Does the " +
+ "variable expand to wiki syntax when documenting " + site + "?")
+ return ErrorType
+ }
val partnames = (parts.init map newTermName) :+ newTypeName(parts.last)
val (start, rest) = parts match {
case "this" :: _ => (site.thisType, partnames.tail)
@@ -492,11 +505,10 @@ trait DocComments { self: Global =>
for (alias <- aliases) yield
lookupVariable(alias.name.toString.substring(1), site) match {
case Some(repl) =>
- val tpe = getType(repl.trim)
+ val tpe = getType(repl.trim, alias.name.toString)
if (tpe != NoType) tpe
else {
- val alias1 = alias.cloneSymbol(definitions.RootClass)
- alias1.name = newTypeName(repl)
+ val alias1 = alias.cloneSymbol(definitions.RootClass, alias.rawflags, newTypeName(repl))
typeRef(NoPrefix, alias1, Nil)
}
case None =>
@@ -523,10 +535,9 @@ trait DocComments { self: Global =>
}
for (defn <- defined) yield {
- val useCase = defn.cloneSymbol
- useCase.owner = sym.owner
- useCase.flags = sym.flags
- useCase.setFlag(Flags.SYNTHETIC).setInfo(substAliases(defn.info).asSeenFrom(site.thisType, sym.owner))
+ defn.cloneSymbol(sym.owner, sym.flags | Flags.SYNTHETIC) modifyInfo (info =>
+ substAliases(info).asSeenFrom(site.thisType, sym.owner)
+ )
}
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/FreeVars.scala b/src/compiler/scala/tools/nsc/ast/FreeVars.scala
new file mode 100644
index 0000000000..a1983d1834
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ast/FreeVars.scala
@@ -0,0 +1,26 @@
+package scala.tools.nsc
+package ast
+
+trait FreeVars extends reflect.internal.FreeVars { self: Global =>
+
+ import self._
+ import definitions._
+ import treeInfo._
+
+ def logFreeVars(position: Position, reified: Tree): Unit = {
+ if (settings.logFreeTerms.value || settings.logFreeTypes.value) {
+ reified match {
+ case Reified(_, symbolTable, _) =>
+ // logging free vars only when they are untyped prevents avalanches of duplicate messages
+ symbolTable foreach {
+ case FreeTermDef(_, _, binding, _, origin) if settings.logFreeTerms.value && binding.tpe == null =>
+ reporter.echo(position, "free term: %s %s".format(showRaw(binding), origin))
+ case FreeTypeDef(_, _, binding, _, origin) if settings.logFreeTypes.value && binding.tpe == null =>
+ reporter.echo(position, "free type: %s %s".format(showRaw(binding), origin))
+ case _ =>
+ // do nothing
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index acbdcd501f..5d849b9622 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -8,6 +8,7 @@ package ast
import compat.Platform.EOL
import symtab.Flags._
+import language.postfixOps
/** The object `nodePrinter` converts the internal tree
* representation to a string.
@@ -27,24 +28,24 @@ abstract class NodePrinters {
def nodeToString: Tree => String =
if (sys.props contains "scala.colors") nodeToColorizedString
else nodeToRegularString
-
+
object nodeToRegularString extends DefaultPrintAST with (Tree => String) {
def apply(tree: Tree) = stringify(tree)
}
-
+
object nodeToColorizedString extends ColorPrintAST with (Tree => String) {
def apply(tree: Tree) = stringify(tree)
}
trait ColorPrintAST extends DefaultPrintAST {
import scala.tools.util.color._
-
+
def keywordColor = Cyan
def typeColor = Yellow
def termColor = Blue
def flagColor = Red
def literalColor = Green
-
+
override def showFlags(tree: MemberDef) =
super.showFlags(tree) in flagColor.bright
@@ -62,10 +63,14 @@ abstract class NodePrinters {
}
trait DefaultPrintAST extends PrintAST {
+ val printPos = settings.Xprintpos.value || settings.Yposdebug.value
+
+ def showNameAndPos(tree: NameTree) = showPosition(tree) + showName(tree.name)
def showDefTreeName(tree: DefTree) = showName(tree.name)
+ def showPosition(tree: Tree) = if (printPos) tree.pos.show else ""
def showFlags(tree: MemberDef) = flagsToString(tree.symbol.flags | tree.mods.flags)
- def showLiteral(lit: Literal) = lit.value.escapedStringValue
- def showTypeTree(tt: TypeTree) = "<tpt>" + emptyOrComment(showType(tt))
+ def showLiteral(lit: Literal) = showPosition(lit) + lit.value.escapedStringValue
+ def showTypeTree(tt: TypeTree) = showPosition(tt) + "<tpt>" + emptyOrComment(showType(tt))
def showName(name: Name) = name match {
case nme.EMPTY | tpnme.EMPTY => "<empty>"
case name => "\"" + name + "\""
@@ -81,7 +86,7 @@ abstract class NodePrinters {
if (tpe == null || tpe == NoType) ""
else "tree.tpe=" + tpe
}
-
+
def showAttributes(tree: Tree): String = {
if (infolevel == InfoLevel.Quiet) ""
else {
@@ -90,23 +95,27 @@ abstract class NodePrinters {
}
}
}
-
+
trait PrintAST {
private val buf = new StringBuilder
private var level = 0
def showName(name: Name): String
+ def showPosition(tree: Tree): String
+ def showNameAndPos(tree: NameTree): String
def showDefTreeName(defTree: DefTree): String
def showFlags(tree: MemberDef): String
def showLiteral(lit: Literal): String
def showTypeTree(tt: TypeTree): String
def showAttributes(tree: Tree): String // symbol and type
-
- def showRefTreeName(tree: Tree): String = tree match {
- case SelectFromTypeTree(qual, name) => showRefTreeName(qual) + "#" + showName(name)
- case Select(qual, name) => showRefTreeName(qual) + "." + showName(name)
- case Ident(name) => showName(name)
- case _ => "" + tree
+
+ def showRefTreeName(tree: Tree): String = {
+ tree match {
+ case SelectFromTypeTree(qual, name) => showRefTreeName(qual) + "#" + showName(name)
+ case Select(qual, name) => showRefTreeName(qual) + "." + showName(name)
+ case id @ Ident(name) => showNameAndPos(id)
+ case _ => "" + tree
+ }
}
def showRefTree(tree: RefTree): String = {
def prefix0 = showRefTreeName(tree.qualifier)
@@ -115,15 +124,21 @@ abstract class NodePrinters {
case Select(_, _) => prefix0 + "."
case _ => ""
})
- prefix + showName(tree.name) + emptyOrComment(showAttributes(tree))
+ prefix + showNameAndPos(tree) + emptyOrComment(showAttributes(tree))
}
def emptyOrComment(s: String) = if (s == "") "" else " // " + s
def stringify(tree: Tree): String = {
buf.clear()
- level = 0
- traverse(tree)
+ if (settings.XshowtreesStringified.value) buf.append(tree.toString + EOL)
+ if (settings.XshowtreesCompact.value) {
+ // todo. colors for compact representation
+ buf.append(showRaw(tree))
+ } else {
+ level = 0
+ traverse(tree)
+ }
buf.toString
}
def traverseAny(x: Any) {
@@ -134,7 +149,7 @@ abstract class NodePrinters {
}
}
def println(s: String) = printLine(s, "")
-
+
def printLine(value: String, comment: String) {
buf append " " * level
buf append value
@@ -183,9 +198,10 @@ abstract class NodePrinters {
traverseList("Nil", "argument")(args)
}
}
-
+
+ def treePrefix(tree: Tree) = showPosition(tree) + tree.printingPrefix
def printMultiline(tree: Tree)(body: => Unit) {
- printMultiline(tree.printingPrefix, showAttributes(tree))(body)
+ printMultiline(treePrefix(tree), showAttributes(tree))(body)
}
def printMultiline(prefix: String, comment: String)(body: => Unit) {
printLine(prefix + "(", comment)
@@ -211,10 +227,12 @@ abstract class NodePrinters {
}
def printSingle(tree: Tree, name: Name) {
- println(tree.printingPrefix + "(" + showName(name) + ")" + showAttributes(tree))
+ println(treePrefix(tree) + "(" + showName(name) + ")" + showAttributes(tree))
}
def traverse(tree: Tree) {
+ showPosition(tree)
+
tree match {
case AppliedTypeTree(tpt, args) => applyCommon(tree, tpt, args)
case ApplyDynamic(fun, args) => applyCommon(tree, fun, args)
@@ -223,6 +241,19 @@ abstract class NodePrinters {
case Throw(Ident(name)) =>
printSingle(tree, name)
+ case b @ Bind(name, body) =>
+ printMultiline(tree) {
+ println(showDefTreeName(b))
+ traverse(body)
+ }
+
+ case ld @ LabelDef(name, params, rhs) =>
+ printMultiline(tree) {
+ showNameAndPos(ld)
+ traverseList("()", "params")(params)
+ traverse(rhs)
+ }
+
case Function(vparams, body) =>
printMultiline(tree) {
traverseList("()", "parameter")(vparams)
@@ -299,10 +330,10 @@ abstract class NodePrinters {
}
case Template(parents, self, body) =>
printMultiline(tree) {
- val ps0 = parents map { p =>
+ val ps0 = parents map { p =>
if (p.tpe eq null) p match {
case x: RefTree => showRefTree(x)
- case x => "" + x
+ case x => showPosition(x) + x
}
else showName(newTypeName(p.tpe.typeSymbol.fullName))
}
@@ -339,14 +370,14 @@ abstract class NodePrinters {
traverseList("[]", "type parameter")(tparams)
traverse(rhs)
}
-
+
case PackageDef(pid, stats) =>
printMultiline("PackageDef", "")(pid :: stats foreach traverse)
case _ =>
tree match {
case t: RefTree => println(showRefTree(t))
- case t if t.productArity == 0 => println(tree.printingPrefix)
+ case t if t.productArity == 0 => println(treePrefix(t))
case t => printMultiline(tree)(tree.productIterator foreach traverseAny)
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/Positions.scala b/src/compiler/scala/tools/nsc/ast/Positions.scala
new file mode 100644
index 0000000000..83a67cfbe3
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/ast/Positions.scala
@@ -0,0 +1,44 @@
+package scala.tools.nsc
+package ast
+
+import scala.tools.nsc.util.{ SourceFile, Position, OffsetPosition, NoPosition }
+
+trait Positions extends scala.reflect.internal.Positions {
+ self: Global =>
+
+ def rangePos(source: SourceFile, start: Int, point: Int, end: Int) =
+ new OffsetPosition(source, point)
+
+ def validatePositions(tree: Tree) {}
+
+ // [Eugene] disabling this for now. imo it doesn't justify pollution of the public API
+ // override def _checkSetAnnotation(tree: Tree, annot: TreeAnnotation): Unit = {
+ // if (tree.pos != NoPosition && tree.pos != annot.pos) debugwarn("Overwriting annotation "+ tree.annotation +" of tree "+ tree +" with annotation "+ annot)
+ // // if ((tree.annotation.isInstanceOf[scala.tools.nsc.util.Position] || !annot.isInstanceOf[scala.tools.nsc.util.Position]) && tree.isInstanceOf[Block])
+ // // println("Updating block from "+ tree.annotation +" to "+ annot)
+ // }
+
+ class ValidatingPosAssigner extends PosAssigner {
+ var pos: Position = _
+ override def traverse(t: Tree) {
+ if (t eq EmptyTree) ()
+ else if (t.pos == NoPosition) super.traverse(t setPos pos)
+ else if (globalPhase.id <= currentRun.picklerPhase.id) {
+ // When we prune due to encountering a position, traverse the
+ // pruned children so we can warn about those lacking positions.
+ t.children foreach { c =>
+ if ((c eq EmptyTree) || (c eq emptyValDef)) ()
+ else if (c.pos == NoPosition) {
+ reporter.warning(t.pos, " Positioned tree has unpositioned child in phase " + globalPhase)
+ inform("parent: " + treeSymStatus(t))
+ inform(" child: " + treeSymStatus(c) + "\n")
+ }
+ }
+ }
+ }
+ }
+
+ override protected[this] lazy val posAssigner: PosAssigner =
+ if (settings.Yrangepos.value && settings.debug.value || settings.Yposdebug.value) new ValidatingPosAssigner
+ else new DefaultPosAssigner
+}
diff --git a/src/compiler/scala/tools/nsc/ast/Reifiers.scala b/src/compiler/scala/tools/nsc/ast/Reifiers.scala
deleted file mode 100644
index 7ece8bbd31..0000000000
--- a/src/compiler/scala/tools/nsc/ast/Reifiers.scala
+++ /dev/null
@@ -1,761 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Gilles Dubochet
- */
-
-package scala.tools.nsc
-package ast
-
-import symtab._
-import Flags._
-import scala.reflect.api.Modifier._
-import scala.collection.{ mutable, immutable }
-import scala.collection.mutable.ListBuffer
-import scala.tools.nsc.util.FreshNameCreator
-import scala.runtime.ScalaRunTime.{ isAnyVal, isTuple }
-
-/** Given a tree or type, generate a tree that when executed at runtime produces the original tree or type.
- * See more info in the comments to `reify' in scala.reflect.macro.Context.
- *
- * @author Martin Odersky
- * @version 2.10
- */
-trait Reifiers { self: Global =>
-
- def reify(tree: Tree): Tree = {
- class Reifier {
- import definitions._
- import Reifier._
-
- final val scalaPrefix = "scala."
- final val localPrefix = "$local"
- final val memoizerName = "$memo"
-
- val reifyDebug = settings.Yreifydebug.value
-
- private val reifiableSyms = mutable.ArrayBuffer[Symbol]() // the symbols that are reified with the tree
- private val symIndex = mutable.HashMap[Symbol, Int]() // the index of a reifiable symbol in `reifiableSyms`
- private var boundSyms = Set[Symbol]() // set of all symbols that are bound in tree to be reified
-
- private def definedInLiftedCode(tpe: Type) =
- tpe exists (tp => boundSyms contains tp.typeSymbol)
-
- private def definedInLiftedCode(sym: Symbol) =
- boundSyms contains sym
-
- /**
- * Generate tree of the form
- *
- * { val $mr = scala.reflect.runtime.Mirror
- * $local1 = new TypeSymbol(owner1, NoPosition, name1)
- * ...
- * $localN = new TermSymbol(ownerN, NoPositiion, nameN)
- * $local1.setInfo(tpe1)
- * ...
- * $localN.setInfo(tpeN)
- * $localN.setAnnotations(annotsN)
- * rtree
- * }
- *
- * where
- *
- * - `$localI` are free type symbols in the environment, as well as local symbols
- * of refinement types.
- * - `tpeI` are the info's of `symI`
- * - `rtree` is code that generates `data` at runtime, maintaining all attributes.
- * - `data` is typically a tree or a type.
- */
- def reifyTopLevel(data: Any): Tree = {
- val rtree = reify(data)
- Block(mirrorAlias :: reifySymbolTableSetup, rtree)
- }
-
- private def isLocatable(sym: Symbol) =
- sym.isPackageClass || sym.owner.isClass || sym.isTypeParameter && sym.paramPos >= 0
-
- private def registerReifiableSymbol(sym: Symbol): Unit =
- if (!(symIndex contains sym)) {
- sym.owner.ownersIterator find (x => !isLocatable(x)) foreach registerReifiableSymbol
- symIndex(sym) = reifiableSyms.length
- reifiableSyms += sym
- }
-
- // helper methods
-
- private def localName(sym: Symbol): TermName =
- newTermName(localPrefix + symIndex(sym))
-
- private def call(fname: String, args: Tree*): Tree =
- Apply(termPath(fname), args.toList)
-
- private def mirrorSelect(name: String): Tree =
- termPath(nme.MIRROR_PREFIX + name)
-
- private def mirrorCall(name: TermName, args: Tree*): Tree =
- call("" + (nme.MIRROR_PREFIX append name), args: _*)
-
- private def mirrorCall(name: String, args: Tree*): Tree =
- call(nme.MIRROR_PREFIX + name, args: _*)
-
- private def mirrorFactoryCall(value: Product, args: Tree*): Tree =
- mirrorFactoryCall(value.productPrefix, args: _*)
-
- private def mirrorFactoryCall(prefix: String, args: Tree*): Tree =
- mirrorCall(prefix, args: _*)
-
- private def scalaFactoryCall(name: String, args: Tree*): Tree =
- call(scalaPrefix + name + ".apply", args: _*)
-
- private def mkList(args: List[Tree]): Tree =
- scalaFactoryCall("collection.immutable.List", args: _*)
-
- private def reifyModifiers(m: Modifiers) =
- mirrorCall("modifiersFromInternalFlags", reify(m.flags), reify(m.privateWithin), reify(m.annotations))
-
- private def reifyAggregate(name: String, args: Any*) =
- scalaFactoryCall(name, (args map reify).toList: _*)
-
- /**
- * Reify a list
- */
- private def reifyList(xs: List[Any]): Tree =
- mkList(xs map reify)
-
- /**
- * Reify an array
- */
- private def reifyArray(xs: Array[_]): Tree =
- // @xeno.by: doesn't work for Array(LiteralAnnotArg(...))
- // because we cannot generate manifests for path-dependent types
- scalaFactoryCall(nme.Array, xs map reify: _*)
-
- /** Reify a name */
- private def reifyName(name: Name) =
- mirrorCall(if (name.isTypeName) "newTypeName" else "newTermName", Literal(Constant(name.toString)))
-
- private def isFree(sym: Symbol) =
- !(symIndex contains sym)
-
- /**
- * Reify a reference to a symbol
- */
- private def reifySymRef(sym: Symbol): Tree = {
- symIndex get sym match {
- case Some(idx) =>
- Ident(localName(sym))
- case None =>
- if (sym == NoSymbol)
- mirrorSelect("NoSymbol")
- else if (sym == RootPackage)
- mirrorSelect("definitions.RootPackage")
- else if (sym == RootClass)
- mirrorSelect("definitions.RootClass")
- else if (sym == EmptyPackage)
- mirrorSelect("definitions.EmptyPackage")
- else if (sym.isModuleClass)
- Select(reifySymRef(sym.sourceModule), "moduleClass")
- else if (sym.isStatic && sym.isClass)
- mirrorCall("staticClass", reify(sym.fullName))
- else if (sym.isStatic && sym.isModule)
- mirrorCall("staticModule", reify(sym.fullName))
- else if (isLocatable(sym))
- if (sym.isTypeParameter)
- mirrorCall("selectParam", reify(sym.owner), reify(sym.paramPos))
- else {
- if (reifyDebug) println("locatable: " + sym + " " + sym.isPackageClass + " " + sym.owner + " " + sym.isTypeParameter)
- val rowner = reify(sym.owner)
- val rname = reify(sym.name.toString)
- if (sym.isType)
- mirrorCall("selectType", rowner, rname)
- else if (sym.isMethod && sym.owner.isClass && sym.owner.info.decl(sym.name).isOverloaded) {
- val index = sym.owner.info.decl(sym.name).alternatives indexOf sym
- assert(index >= 0, sym)
- mirrorCall("selectOverloadedMethod", rowner, rname, reify(index))
- } else
- mirrorCall("selectTerm", rowner, rname)
- }
- else {
- if (sym.isTerm) {
- if (reifyDebug) println("Free: " + sym)
- val symtpe = lambdaLift.boxIfCaptured(sym, sym.tpe, erasedTypes = false)
- def markIfCaptured(arg: Ident): Tree =
- if (sym.isCapturedVariable) referenceCapturedVariable(arg) else arg
- mirrorCall("newFreeVar", reify(sym.name.toString), reify(symtpe), markIfCaptured(Ident(sym)))
- } else {
- if (reifyDebug) println("Late local: " + sym)
- registerReifiableSymbol(sym)
- reifySymRef(sym)
- }
- }
- }
- }
-
- /**
- * reify the creation of a symbol
- */
- private def reifySymbolDef(sym: Symbol): Tree = {
- if (reifyDebug) println("reify sym def " + sym)
-
- ValDef(NoMods, localName(sym), TypeTree(),
- Apply(
- Select(reify(sym.owner), "newNestedSymbol"),
- List(reify(sym.name), reify(sym.pos), Literal(Constant(sym.flags)))
- )
- )
- }
-
- /**
- * Generate code to add type and annotation info to a reified symbol
- */
- private def fillInSymbol(sym: Symbol): Tree = {
- val rset = Apply(Select(reifySymRef(sym), nme.setTypeSignature), List(reifyType(sym.info)))
- if (sym.annotations.isEmpty) rset
- else Apply(Select(rset, nme.setAnnotations), List(reify(sym.annotations)))
- }
-
- /** Reify a scope */
- private def reifyScope(scope: Scope): Tree = {
- scope foreach registerReifiableSymbol
- mirrorCall(nme.newScopeWith, scope.toList map reifySymRef: _*)
- }
-
- /** Reify a list of symbols that need to be created */
- private def reifySymbols(syms: List[Symbol]): Tree = {
- syms foreach registerReifiableSymbol
- mkList(syms map reifySymRef)
- }
-
- /** Reify a type that defines some symbols */
- private def reifyTypeBinder(value: Product, bound: List[Symbol], underlying: Type): Tree =
- mirrorFactoryCall(value, reifySymbols(bound), reify(underlying))
-
- /** Reify a type */
- private def reifyType(tpe0: Type): Tree = {
- val tpe = tpe0.normalize
-
- if (tpe.isErroneous)
- CannotReifyErroneousType(tpe)
- if (definedInLiftedCode(tpe))
- CannotReifyTypeInvolvingBoundType(tpe)
-
- val tsym = tpe.typeSymbol
- if (tsym.isClass && tpe == tsym.typeConstructor && tsym.isStatic)
- Select(reifySymRef(tpe.typeSymbol), nme.asTypeConstructor)
- else tpe match {
- case t @ NoType =>
- reifyMirrorObject(t)
- case t @ NoPrefix =>
- reifyMirrorObject(t)
- case tpe @ ThisType(clazz) if clazz.isModuleClass && clazz.isStatic =>
- mirrorCall(nme.thisModuleType, reify(clazz.fullName))
- case t @ RefinedType(parents, decls) =>
- registerReifiableSymbol(tpe.typeSymbol)
- mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol))
- case t @ ClassInfoType(parents, decls, clazz) =>
- registerReifiableSymbol(clazz)
- mirrorFactoryCall(t, reify(parents), reify(decls), reify(t.typeSymbol))
- case t @ ExistentialType(tparams, underlying) =>
- reifyTypeBinder(t, tparams, underlying)
- case t @ PolyType(tparams, underlying) =>
- reifyTypeBinder(t, tparams, underlying)
- case t @ MethodType(params, restpe) =>
- reifyTypeBinder(t, params, restpe)
- case t @ AnnotatedType(anns, underlying, selfsym) =>
- val saved1 = reifySymbols
- val saved2 = reifyTypes
-
- try {
- // one more quirk of reifying annotations
- //
- // when reifying AnnotatedTypes we need to reify all the types and symbols of inner ASTs
- // that's because a lot of logic expects post-typer trees to have non-null tpes
- //
- // Q: reified trees are pre-typer, so there's shouldn't be a problem.
- // reflective typechecker will fill in missing symbols and types, right?
- // A: actually, no. annotation ASTs live inside AnnotatedTypes,
- // and insides of the types is the place where typechecker doesn't look.
- reifySymbols = true
- reifyTypes = true
- if (reifyDebug) println("reify AnnotatedType: " + tpe)
- reifyProductUnsafe(tpe)
- } finally {
- reifySymbols = saved1
- reifyTypes = saved2
- }
- case _ =>
- reifyProductUnsafe(tpe)
- }
- }
-
- var reifySymbols = false
- var reifyTypes = false
-
- /** Preprocess a tree before reification */
- private def trimTree(tree: Tree): Tree = {
- def trimSyntheticCaseClassMembers(deff: Tree, stats: List[Tree]) = {
- var stats1 = stats filterNot (stat => stat.isDef && {
- if (stat.symbol.isCaseAccessorMethod && reifyDebug) println("discarding case accessor method: " + stat)
- stat.symbol.isCaseAccessorMethod
- })
- stats1 = stats1 filterNot (memberDef => memberDef.isDef && {
- val isSynthetic = memberDef.symbol.isSynthetic
- // @xeno.by: this doesn't work for local classes, e.g. for ones that are top-level to a quasiquote (see comments to companionClass)
- // that's why I replace the check with an assumption that all synthetic members are, in fact, generated of case classes
-// val isCaseMember = deff.symbol.isCaseClass || deff.symbol.companionClass.isCaseClass
- val isCaseMember = true
- if (isSynthetic && isCaseMember && reifyDebug) println("discarding case class synthetic def: " + memberDef)
- isSynthetic && isCaseMember
- })
- stats1 = stats1 map {
- case valdef @ ValDef(mods, name, tpt, rhs) if valdef.symbol.isCaseAccessor =>
- if (reifyDebug) println("resetting visibility of case accessor field: " + valdef)
- val Modifiers(flags, privateWithin, annotations) = mods
- val flags1 = flags & ~Flags.LOCAL & ~Flags.PRIVATE
- val mods1 = Modifiers(flags1, privateWithin, annotations)
- ValDef(mods1, name, tpt, rhs).copyAttrs(valdef)
- case stat =>
- stat
- }
- stats1
- }
-
- def trimSyntheticCaseClassCompanions(stats: List[Tree]) =
- stats diff (stats collect { case moddef: ModuleDef => moddef } filter (moddef => {
- val isSynthetic = moddef.symbol.isSynthetic
- // @xeno.by: this doesn't work for local classes, e.g. for ones that are top-level to a quasiquote (see comments to companionClass)
- // that's why I replace the check with an assumption that all synthetic modules are, in fact, companions of case classes
-// val isCaseCompanion = moddef.symbol.companionClass.isCaseClass
- val isCaseCompanion = true
- // @xeno.by: we also have to do this ugly hack for the very same reason described above
- // normally this sort of stuff is performed in reifyTree, which binds related symbols, however, local companions will be out of its reach
- if (reifyDebug) println("boundSym: "+ moddef.symbol)
- boundSyms += moddef.symbol
- if (isSynthetic && isCaseCompanion && reifyDebug) println("discarding synthetic case class companion: " + moddef)
- isSynthetic && isCaseCompanion
- }))
-
- tree match {
- case tree if tree.isErroneous =>
- tree
- case ta @ TypeApply(hk, ts) =>
- def isErased(tt: TypeTree) = tt.tpe != null && definedInLiftedCode(tt.tpe) && tt.original == null
- val discard = ts collect { case tt: TypeTree => tt } exists isErased
- if (reifyDebug && discard) println("discarding TypeApply: " + tree)
- if (discard) hk else ta
- case classDef @ ClassDef(mods, name, params, impl) =>
- val Template(parents, self, body) = impl
- val body1 = trimSyntheticCaseClassMembers(classDef, body)
- var impl1 = Template(parents, self, body1).copyAttrs(impl)
- ClassDef(mods, name, params, impl1).copyAttrs(classDef)
- case moduledef @ ModuleDef(mods, name, impl) =>
- val Template(parents, self, body) = impl
- val body1 = trimSyntheticCaseClassMembers(moduledef, body)
- var impl1 = Template(parents, self, body1).copyAttrs(impl)
- ModuleDef(mods, name, impl1).copyAttrs(moduledef)
- case template @ Template(parents, self, body) =>
- val body1 = trimSyntheticCaseClassCompanions(body)
- Template(parents, self, body1).copyAttrs(template)
- case block @ Block(stats, expr) =>
- val stats1 = trimSyntheticCaseClassCompanions(stats)
- Block(stats1, expr).copyAttrs(block)
- case valdef @ ValDef(mods, name, tpt, rhs) if valdef.symbol.isLazy =>
- if (reifyDebug) println("dropping $lzy in lazy val's name: " + tree)
- val name1 = if (name endsWith nme.LAZY_LOCAL) name dropRight nme.LAZY_LOCAL.length else name
- ValDef(mods, name1, tpt, rhs).copyAttrs(valdef)
- case unapply @ UnApply(fun, args) =>
- def extractExtractor(tree: Tree): Tree = {
- val Apply(fun, args) = tree
- args match {
- case List(Ident(special)) if special == nme.SELECTOR_DUMMY =>
- val Select(extractor, flavor) = fun
- assert(flavor == nme.unapply || flavor == nme.unapplySeq)
- extractor
- case _ =>
- extractExtractor(fun)
- }
- }
-
- if (reifyDebug) println("unapplying unapply: " + tree)
- val fun1 = extractExtractor(fun)
- Apply(fun1, args).copyAttrs(unapply)
- case _ =>
- tree
- }
- }
-
- /** Reify a tree */
- private def reifyTree(tree0: Tree): Tree = {
- val tree = trimTree(tree0)
-
- var rtree = tree match {
- case tree if tree.isErroneous =>
- CannotReifyErroneousTree(tree)
- case self.EmptyTree =>
- reifyMirrorObject(EmptyTree)
- case self.emptyValDef =>
- mirrorSelect(nme.emptyValDef)
- case This(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) =>
- reifyFree(tree)
- case Ident(_) if tree.symbol != NoSymbol && !(boundSyms contains tree.symbol) =>
- if (tree.symbol.isVariable && tree.symbol.owner.isTerm) {
- if (reifyDebug) println("captured variable: " + tree.symbol)
- captureVariable(tree.symbol) // Note order dependency: captureVariable needs to come before reifyTree here.
- mirrorCall("Select", reifyFree(tree), reifyName(nme.elem))
- } else reifyFree(tree)
- case tt: TypeTree if (tt.tpe != null) =>
- reifyTypeTree(tt)
- case Literal(constant @ Constant(tpe: Type)) if boundSyms exists (tpe contains _) =>
- CannotReifyClassOfBoundType(tree, tpe)
- case Literal(constant @ Constant(sym: Symbol)) if boundSyms contains sym =>
- CannotReifyClassOfBoundEnum(tree, constant.tpe)
- case tree if tree.isDef =>
- if (reifyDebug) println("boundSym: %s of type %s".format(tree.symbol, (tree.productIterator.toList collect { case tt: TypeTree => tt } headOption).getOrElse(TypeTree(tree.tpe))))
- boundSyms += tree.symbol
-
- bindRelatedSymbol(tree.symbol.sourceModule, "sourceModule")
- bindRelatedSymbol(tree.symbol.moduleClass, "moduleClass")
- bindRelatedSymbol(tree.symbol.companionClass, "companionClass")
- bindRelatedSymbol(tree.symbol.companionModule, "companionModule")
- Some(tree.symbol) collect { case termSymbol: TermSymbol => bindRelatedSymbol(termSymbol.referenced, "referenced") }
- def bindRelatedSymbol(related: Symbol, name: String): Unit =
- if (related != null && related != NoSymbol) {
- if (reifyDebug) println("boundSym (" + name + "): " + related)
- boundSyms += related
- }
-
- val prefix = tree.productPrefix
- val elements = (tree.productIterator map {
- // annotations exist in two flavors:
- // 1) pre-typer ones that populate: a) Modifiers, b) Annotated nodes (irrelevant in this context)
- // 2) post-typer ones that dwell inside: a) sym.annotations, b) AnnotatedTypes (irrelevant in this context)
- //
- // here we process Modifiers that are involved in deftrees
- // AnnotatedTypes get reified elsewhere (currently, in ``reifyTypeTree'')
- case Modifiers(flags, privateWithin, annotations) =>
- assert(annotations.isEmpty) // should've been eliminated by the typer
- val postTyper = tree.symbol.annotations filter (_.original != EmptyTree)
- if (reifyDebug && !postTyper.isEmpty) println("reify symbol annotations for %s: %s".format(tree.symbol, tree.symbol.annotations))
- val preTyper = postTyper map toPreTyperAnnotation
- Modifiers(flags, privateWithin, preTyper)
- case x =>
- x
- }).toList
- reifyProduct(prefix, elements)
- case _ =>
- reifyProduct(tree)
- }
-
- // usually we don't reify symbols/types, because they can be re-inferred during subsequent reflective compilation
- // however, reification of AnnotatedTypes is special. see ``reifyType'' to find out why.
- if (reifySymbols && tree.hasSymbol) {
- if (reifyDebug) println("reifying symbol %s for tree %s".format(tree.symbol, tree))
- rtree = Apply(Select(rtree, nme.setSymbol), List(reifySymRef(tree.symbol)))
- }
- if (reifyTypes && tree.tpe != null) {
- if (reifyDebug) println("reifying type %s for tree %s".format(tree.tpe, tree))
- rtree = Apply(Select(rtree, nme.setType), List(reifyType(tree.tpe)))
- }
-
- rtree
- }
-
- /** Reify pre-typer representation of a type.
- *
- * NB: This is the trickiest part of reification!
- *
- * In most cases, we're perfectly fine to reify a Type itself (see ``reifyType'').
- * However if the type involves a symbol declared inside the quasiquote (i.e. registered in ``boundSyms''),
- * then we cannot reify it, or otherwise subsequent reflective compilation will fail.
- *
- * Why will it fail? Because reified deftrees (e.g. ClassDef(...)) will generate fresh symbols during that compilation,
- * so naively reified symbols will become out of sync, which brings really funny compilation errors and/or crashes, e.g.:
- * https://issues.scala-lang.org/browse/SI-5230
- *
- * To deal with this unpleasant fact, we need to fall back from types to equivalent trees (after all, parser trees don't contain any types, just trees, so it should be possible).
- * Luckily, these original trees get preserved for us in the ``original'' field when Trees get transformed into TypeTrees.
- * And if an original of a type tree is empty, we can safely assume that this type is non-essential (e.g. was inferred/generated by the compiler).
- * In that case the type can be omitted (e.g. reified as an empty TypeTree), since it will be inferred again later on.
- *
- * An important property of the original is that it isn't just a pre-typer tree.
- * It's actually kind of a post-typer tree with symbols assigned to its Idents (e.g. Ident("List") will contain a symbol that points to immutable.this.List).
- * This is very important, since subsequent reflective compilation won't have to resolve these symbols.
- * In general case, such resolution cannot be performed, since reification doesn't preserve lexical context,
- * which means that reflective compilation won't be aware of, say, imports that were provided when the reifee has been compiled.
- *
- * This workaround worked surprisingly well and allowed me to fix several important reification bugs, until the abstraction has leaked.
- * Suddenly I found out that in certain contexts original trees do not contain symbols, but are just parser trees.
- * To the moment I know only one such situation: typedAnnotations does not typecheck the annotation in-place, but rather creates new trees and typechecks them, so the original remains symless.
- * This is laboriously worked around in the code below. I hope this will be the only workaround in this department.
- */
- private def reifyTypeTree(tt: TypeTree): Tree = {
- if (definedInLiftedCode(tt.tpe)) {
- if (reifyDebug) println("reifyTypeTree, defined in lifted code: " + tt.tpe)
- if (tt.original != null) {
- val annotations = tt.tpe filter { _.isInstanceOf[AnnotatedType] } collect { case atp: AnnotatedType => atp.annotations } flatten
- val annmap = annotations map { ann => (ann.original, ann) } toMap
-
- // annotations exist in two flavors:
- // 1) pre-typer ones that populate: a) Modifiers (irrelevant in this context), b) Annotated nodes
- // 2) post-typer ones that dwell inside: a) sym.annotations (irrelevant in this context), b) AnnotatedTypes
- //
- // here we process AnnotatedTypes, since only they can be involved in TypeTrees
- // Modifiers get reified elsewhere (currently, in the "isDef" case of ``reifyTree'')
- //
- // the problem with annotations is that their originals don't preserve any symbols at all
- // read the comment to this method to find out why it's bad
- // that's why we transplant typechecked, i.e. symful, annotations onto original trees
- class AnnotationFixup extends self.Transformer {
- override def transform(tree: Tree) = tree match {
- case Annotated(ann0, args) =>
- assert(annmap contains ann0)
- val ann1 = annmap(ann0)
- val ann = toPreTyperAnnotation(ann1)
- Annotated(ann, transform(args))
- case _ =>
- tree
- }
- }
-
- if (reifyDebug) println("verdict: essential, reify as original")
- val patchedOriginal = new AnnotationFixup().transform(tt.original)
- reifyTree(patchedOriginal)
- } else {
- // type is deemed to be non-essential
- // erase it and hope that subsequent reflective compilation will be able to recreate it again
- if (reifyDebug) println("verdict: non-essential, discard")
- mirrorCall("TypeTree")
- }
- } else {
- var rtt = mirrorCall(nme.TypeTree, reifyType(tt.tpe))
- // @xeno.by: temporarily disabling reification of originals
- // subsequent reflective compilation will try to typecheck them
- // and this means that the reifier has to do additional efforts to ensure that this will succeed
- // additional efforts + no clear benefit = will be implemented later
-// if (tt.original != null) {
-// val setOriginal = Select(rtt, newTermName("setOriginal"))
-// val reifiedOriginal = reify(tt.original)
-// rtt = Apply(setOriginal, List(reifiedOriginal))
-// }
- rtt
- }
- }
-
- /** Reify post-typer representation of an annotation */
- private def reifyAnnotation(ann: AnnotationInfo): Tree =
- // @xeno.by: if you reify originals, you get SO when trying to reify AnnotatedTypes, so screw it - after all, it's not that important
- mirrorFactoryCall("AnnotationInfo", reifyType(ann.atp), reifyList(ann.args), reify(ann.assocs))
-
- /** Reify pre-typer representation of an annotation.
- * The trick here is to retain the symbols that have been populated during typechecking of the annotation.
- * If we do not do that, subsequent reflective compilation will fail.
- */
- private def toPreTyperAnnotation(ann: AnnotationInfo): Tree = {
- if (definedInLiftedCode(ann.atp)) {
- // todo. deconstruct reifiable tree from ann.original and ann.args+ann.assocs
- //
- // keep in mind that we can't simply use ann.original, because its args are symless
- // which means that any imported symbol (e.g. List) will crash subsequent reflective compilation
- // hint: if I had enough time, I'd try to extract reifiable annotation type from ann.original
- // and to apply its constructor to ann.args (that are symful, i.e. suitable for reification)
- //
- // also, if we pursue the route of reifying annotations defined in lifted code
- // we should think about how to provide types for all nodes of the return value
- // this will be necessary for reifying AnnotatedTypes, since ASTs inside ATs must all have non-null tpes
- // an alternative would be downgrading ATs to Annotated nodes, but this needs careful thinking
- // for now I just leave this as an implementation restriction
- CannotReifyAnnotationInvolvingBoundType(ann)
- } else {
- val args = if (ann.assocs.isEmpty) {
- ann.args
- } else {
- def toScalaAnnotation(jann: ClassfileAnnotArg): Tree = jann match {
- case LiteralAnnotArg(const) =>
- Literal(const)
- case ArrayAnnotArg(arr) =>
- Apply(Ident(definitions.ArrayModule), arr.toList map toScalaAnnotation)
- case NestedAnnotArg(ann) =>
- toPreTyperAnnotation(ann)
- }
-
- ann.assocs map { case (nme, arg) => AssignOrNamedArg(Ident(nme), toScalaAnnotation(arg)) }
- }
-
- New(ann.atp, args: _*)
- }
- }
-
- /**
- * Reify a free reference. The result will be either a mirror reference
- * to a global value, or else a mirror Literal.
- */
- private def reifyFree(tree: Tree): Tree = tree match {
- case This(_) if tree.symbol.isClass && !tree.symbol.isModuleClass =>
- val sym = tree.symbol
- if (reifyDebug) println("This for %s, reified as freeVar".format(sym))
- if (reifyDebug) println("Free: " + sym)
- val freeVar = mirrorCall("newFreeVar", reify(sym.name.toString), reify(sym.tpe), This(sym))
- mirrorCall(nme.Ident, freeVar)
- case This(_) =>
- if (reifyDebug) println("This for %s, reified as This".format(tree.symbol))
- mirrorCall(nme.This, reifySymRef(tree.symbol))
- case _ =>
- mirrorCall(nme.Ident, reifySymRef(tree.symbol))
- }
-
- // todo: consider whether we should also reify positions
- private def reifyPosition(pos: Position): Tree =
- reifyMirrorObject(NoPosition)
-
- // !!! we must eliminate these casts.
- private def reifyProductUnsafe(x: Any): Tree =
- if (x.isInstanceOf[Product]) reifyProduct(x.asInstanceOf[Product])
- else throw new Exception("%s of type %s cannot be cast to Product".format(x, x.getClass))
- private def reifyProduct(x: Product): Tree =
- reifyProduct(x.productPrefix, x.productIterator.toList)
- private def reifyProduct(prefix: String, elements: List[Any]): Tree = {
- // @xeno.by: reflection would be more robust, but, hey, this is a hot path
- if (prefix.startsWith("Tuple")) reifyAggregate(prefix, elements: _*)
- else mirrorCall(prefix, (elements map reify): _*)
- }
-
- /**
- * Reify a case object defined in Mirror
- */
- private def reifyMirrorObject(name: String): Tree = mirrorSelect(name)
- private def reifyMirrorObject(x: Product): Tree = reifyMirrorObject(x.productPrefix)
-
- private def isReifiableConstant(value: Any) = value match {
- case null => true // seems pretty reifable to me?
- case _: String => true
- case _ => isAnyVal(value)
- }
-
- /** Reify an arbitary value */
- private def reify(value: Any): Tree = value match {
- case tree: Tree => reifyTree(tree)
- case sym: Symbol => reifySymRef(sym)
- case tpe: Type => reifyType(tpe)
- case xs: List[_] => reifyList(xs)
- case xs: Array[_] => reifyArray(xs)
- case scope: Scope => reifyScope(scope)
- case x: Name => reifyName(x)
- case x: Position => reifyPosition(x)
- case x: Modifiers => reifyModifiers(x)
- case x: AnnotationInfo => reifyAnnotation(x)
- case _ =>
- if (isReifiableConstant(value)) Literal(Constant(value))
- else reifyProductUnsafe(value)
- }
-
- /**
- * An (unreified) path that refers to definition with given fully qualified name
- * @param mkName Creator for last portion of name (either TermName or TypeName)
- */
- private def path(fullname: String, mkName: String => Name): Tree = {
- val parts = fullname split "\\."
- val prefixParts = parts.init
- val lastName = mkName(parts.last)
- if (prefixParts.isEmpty) Ident(lastName)
- else {
- val prefixTree = ((Ident(prefixParts.head): Tree) /: prefixParts.tail)(Select(_, _))
- Select(prefixTree, lastName)
- }
- }
-
- /** An (unreified) path that refers to term definition with given fully qualified name */
- private def termPath(fullname: String): Tree = path(fullname, newTermName)
-
- /** An (unreified) path that refers to type definition with given fully qualified name */
- private def typePath(fullname: String): Tree = path(fullname, newTypeName)
-
- private def mirrorAlias =
- ValDef(NoMods, nme.MIRROR_SHORT, SingletonTypeTree(termPath(fullnme.MirrorPackage)), termPath(fullnme.MirrorPackage))
-
- /**
- * Generate code that generates a symbol table of all symbols registered in `reifiableSyms`
- */
- private def reifySymbolTableSetup: List[Tree] = {
- val symDefs, fillIns = new mutable.ArrayBuffer[Tree]
- var i = 0
- while (i < reifiableSyms.length) {
- // fillInSymbol might create new reifiableSyms, that's why this is done iteratively
- symDefs += reifySymbolDef(reifiableSyms(i))
- fillIns += fillInSymbol(reifiableSyms(i))
- i += 1
- }
-
- symDefs.toList ++ fillIns.toList
- }
- } // end of Reifier
-
- object Reifier {
- def CannotReifyPreTyperTree(tree: Tree) = {
- val msg = "pre-typer trees are not supported, consider typechecking the tree before passing it to the reifier"
- throw new ReifierError(tree.pos, msg)
- }
-
- def CannotReifyErroneousTree(tree: Tree) = {
- val msg = "erroneous trees are not supported, make sure that your tree typechecks successfully before passing it to the reifier"
- throw new ReifierError(tree.pos, msg)
- }
-
- def CannotReifyErroneousType(tpe: Type) = {
- val msg = "erroneous types are not supported, make sure that your tree typechecks successfully before passing it to the reifier"
- throw new ReifierError(NoPosition, msg)
- }
-
- def CannotReifyClassOfBoundType(tree: Tree, tpe: Type) = {
- val msg = "implementation restriction: cannot reify classOf[%s] which refers to a type declared inside the block being reified".format(tpe)
- throw new ReifierError(tree.pos, msg)
- }
-
- def CannotReifyClassOfBoundEnum(tree: Tree, tpe: Type) = {
- val msg = "implementation restriction: cannot reify classOf[%s] which refers to an enum declared inside the block being reified".format(tpe)
- throw new ReifierError(tree.pos, msg)
- }
-
- def CannotReifyTypeInvolvingBoundType(tpe: Type) = {
- val msg = "implementation restriction: cannot reify type %s which involves a symbol declared inside the block being reified".format(tpe)
- throw new ReifierError(NoPosition, msg)
- }
-
- def CannotReifyAnnotationInvolvingBoundType(ann: AnnotationInfo) = {
- val msg = "implementation restriction: cannot reify annotation @%s which involves a symbol declared inside the block being reified".format(ann)
- throw new ReifierError(ann.original.pos, msg)
- }
- } // end of Reifier
-
- // begin reify
- import Reifier._
- if (tree.tpe != null) {
- val saved = printTypings
- try {
- val reifyDebug = settings.Yreifydebug.value
- val debugTrace = util.trace when reifyDebug
- debugTrace("transforming = ")(if (settings.Xshowtrees.value) "\n" + nodePrinters.nodeToString(tree).trim else tree.toString)
- debugTrace("transformed = ") {
- val reifier = new Reifier()
- val untyped = reifier.reifyTopLevel(tree)
-
- val reifyCopypaste = settings.Yreifycopypaste.value
- if (reifyCopypaste) {
- if (reifyDebug) println("=======================")
- println(reifiedNodeToString(untyped))
- if (reifyDebug) println("=======================")
- }
-
- untyped
- }
- } finally {
- printTypings = saved
- }
- } else {
- CannotReifyPreTyperTree(tree)
- }
- }
-
- /** A throwable signalling a reification error */
- class ReifierError(var pos: Position, val msg: String) extends Throwable(msg) {
- def this(msg: String) = this(NoPosition, msg)
- }
-}
diff --git a/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala b/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala
deleted file mode 100644
index fce59bb099..0000000000
--- a/src/compiler/scala/tools/nsc/ast/ReifyPrinters.scala
+++ /dev/null
@@ -1,75 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package ast
-
-import compat.Platform.EOL
-import symtab._
-import Flags._
-
-trait ReifyPrinters { self: NodePrinters =>
-
- val global: Global
- import global._
-
- object reifiedNodeToString extends Function1[Tree, String] {
- def apply(tree: Tree): String = {
- import scala.reflect.api.Modifier
-
- // @PP: I fervently hope this is a test case or something, not anything being
- // depended upon. Of more fragile code I cannot conceive.
- // @eb: This stuff is only needed to debug-print out reifications in human-readable format
- // Rolling a full-fledged, robust TreePrinter would be several times more code.
- (for (line <- (tree.toString.split(EOL) drop 2 dropRight 1)) yield {
- var s = line.trim
- s = s.replace("$mr.", "")
- s = s.replace(".apply", "")
- s = s.replace("scala.collection.immutable.", "")
- s = "List\\[List\\[.*?\\].*?\\]".r.replaceAllIn(s, "List")
- s = "List\\[.*?\\]".r.replaceAllIn(s, "List")
- s = s.replace("immutable.this.Nil", "List()")
- s = s.replace("modifiersFromInternalFlags", "Modifiers")
- s = s.replace("Modifiers(0L, newTypeName(\"\"), List())", "Modifiers()")
- s = """Modifiers\((\d+)[lL], newTypeName\("(.*?)"\), List\((.*?)\)\)""".r.replaceAllIn(s, m => {
- val buf = new collection.mutable.ListBuffer[String]
-
- val annotations = m.group(3)
- if (buf.nonEmpty || annotations.nonEmpty)
- buf.append("List(" + annotations + ")")
-
- val privateWithin = "" + m.group(2)
- if (buf.nonEmpty || privateWithin != "")
- buf.append("newTypeName(\"" + privateWithin + "\")")
-
- val flags = m.group(1).toLong
- val s_flags = Flags.modifiersOfFlags(flags) map (_.sourceString) mkString ", "
- if (buf.nonEmpty || s_flags != "")
- buf.append("Set(" + s_flags + ")")
-
- "Modifiers(" + buf.reverse.mkString(", ") + ")"
- })
- s = """setInternalFlags\((\d+)L\)""".r.replaceAllIn(s, m => {
- val flags = m.group(1).toLong
- val mods = Flags.modifiersOfFlags(flags) map (_.sourceString)
- "setInternalFlags(flagsOfModifiers(List(" + mods.mkString(", ") + ")))"
- })
-
- s
- }) mkString EOL
- }
- }
-
-
- def printReifyCopypaste(tree: Tree) {
- val reifyDebug = settings.Yreifydebug.value
- if (reifyDebug) println("=======================")
- printReifyCopypaste1(tree)
- if (reifyDebug) println("=======================")
- }
-
- def printReifyCopypaste1(tree: Tree) {
- }
-} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
index 3302c11127..b4beb231ab 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeBrowsers.scala
@@ -18,6 +18,7 @@ import scala.concurrent.Lock
import scala.text._
import symtab.Flags._
import symtab.SymbolTable
+import language.implicitConversions
/**
* Tree browsers can show the AST in a graphical and interactive
diff --git a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
index 8703de4e18..91935854f4 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeDSL.scala
@@ -9,6 +9,7 @@ package ast
import PartialFunction._
import symtab.Flags
+import language.implicitConversions
/** A DSL for generating scala code. The goal is that the
* code generating code should look a lot like the code it
@@ -94,6 +95,12 @@ trait TreeDSL {
def INT_>= (other: Tree) = fn(target, getMember(IntClass, nme.GE), other)
def INT_== (other: Tree) = fn(target, getMember(IntClass, nme.EQ), other)
def INT_!= (other: Tree) = fn(target, getMember(IntClass, nme.NE), other)
+
+ // generic operations on ByteClass, IntClass, LongClass
+ def GEN_| (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.OR), other)
+ def GEN_& (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.AND), other)
+ def GEN_== (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.EQ), other)
+ def GEN_!= (other: Tree, kind: ClassSymbol) = fn(target, getMember(kind, nme.NE), other)
def BOOL_&& (other: Tree) = fn(target, Boolean_and, other)
def BOOL_|| (other: Tree) = fn(target, Boolean_or, other)
@@ -292,7 +299,7 @@ trait TreeDSL {
def TRY(tree: Tree) = new TryStart(tree, Nil, EmptyTree)
def BLOCK(xs: Tree*) = Block(xs.init.toList, xs.last)
def NOT(tree: Tree) = Select(tree, Boolean_not)
- def SOME(xs: Tree*) = Apply(SomeModule, makeTupleTerm(xs.toList, true))
+ def SOME(xs: Tree*) = Apply(SomeClass.companionSymbol, makeTupleTerm(xs.toList, true))
/** Typed trees from symbols. */
def THIS(sym: Symbol) = gen.mkAttributedThis(sym)
diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
index ad26ccad5e..a93d9efded 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala
@@ -9,6 +9,7 @@ package ast
import scala.collection.mutable.ListBuffer
import symtab.Flags._
import symtab.SymbolTable
+import language.postfixOps
/** XXX to resolve: TreeGen only assumes global is a SymbolTable, but
* TreeDSL at the moment expects a Global. Can we get by with SymbolTable?
@@ -71,14 +72,6 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
Annotated(Ident(nme.synthSwitch), expr)
}
- // must be kept in synch with the codegen in PatMatVirtualiser
- object VirtualCaseDef {
- def unapply(b: Block): Option[(Assign, Tree, Tree)] = b match {
- case Block(List(assign@Assign(keepGoingLhs, falseLit), matchRes), zero) => Some((assign, matchRes, zero)) // TODO: check tree annotation
- case _ => None
- }
- }
-
def hasSynthCaseSymbol(t: Tree) = (t.symbol ne null) && (t.symbol hasFlag (CASE | SYNTHETIC))
// TODO: would be so much nicer if we would know during match-translation (i.e., type checking)
@@ -86,9 +79,11 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
class MatchMatcher {
def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = unknownTree(orig)
def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = unknownTree(orig)
- def caseVirtualizedMatchOpt(orig: Tree, zero: ValDef, x: ValDef, matchRes: ValDef, keepGoing: ValDef, stats: List[Tree], epilogue: Tree, wrap: Tree => Tree): Tree = unknownTree(orig)
+ def caseVirtualizedMatchOpt(orig: Tree, prologue: List[Tree], cases: List[Tree], matchEndDef: Tree, wrap: Tree => Tree): Tree = unknownTree(orig)
+
+ def genVirtualizedMatch(prologue: List[Tree], cases: List[Tree], matchEndDef: Tree): Tree = Block(prologue ++ cases, matchEndDef)
- def apply(matchExpr: Tree): Tree = (matchExpr: @unchecked) match {
+ def apply(matchExpr: Tree): Tree = matchExpr match {
// old-style match or virtpatmat switch
case Match(selector, cases) => // println("simple match: "+ (selector, cases) + "for:\n"+ matchExpr )
caseMatch(matchExpr, selector, cases, identity)
@@ -99,11 +94,15 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
case Apply(Apply(TypeApply(Select(tgt, nme.runOrElse), targs), List(scrut)), List(matcher)) if opt.virtPatmat => // println("virt match: "+ (tgt, targs, scrut, matcher) + "for:\n"+ matchExpr )
caseVirtualizedMatch(matchExpr, tgt, targs, scrut, matcher)
// optimized version of virtpatmat
- case Block((zero: ValDef) :: (x: ValDef) :: (matchRes: ValDef) :: (keepGoing: ValDef) :: stats, epilogue) if opt.virtPatmat => // TODO: check tree annotation // println("virtopt match: "+ (zero, x, matchRes, keepGoing, stats) + "for:\n"+ matchExpr )
- caseVirtualizedMatchOpt(matchExpr, zero, x, matchRes, keepGoing, stats, epilogue, identity)
+ case Block(stats, matchEndDef) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) =>
+ // the assumption is once we encounter a case, the remainder of the block will consist of cases
+ // the prologue may be empty, usually it is the valdef that stores the scrut
+ val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
+ caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, identity)
// optimized version of virtpatmat
- case Block(outerStats, orig@Block((zero: ValDef) :: (x: ValDef) :: (matchRes: ValDef) :: (keepGoing: ValDef) :: stats, epilogue)) if opt.virtPatmat => // TODO: check tree annotation // println("virt opt block match: "+ (zero, x, matchRes, keepGoing, stats, outerStats) + "for:\n"+ matchExpr )
- caseVirtualizedMatchOpt(matchExpr, zero, x, matchRes, keepGoing, stats, epilogue, m => copyBlock(matchExpr, outerStats, m))
+ case Block(outerStats, orig@Block(stats, matchEndDef)) if opt.virtPatmat && (stats forall hasSynthCaseSymbol) =>
+ val (prologue, cases) = stats span (s => !s.isInstanceOf[LabelDef])
+ caseVirtualizedMatchOpt(matchExpr, prologue, cases, matchEndDef, m => copyBlock(matchExpr, outerStats, m))
case other =>
unknownTree(other)
}
@@ -119,35 +118,6 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
}
}
- def withDefaultCase(matchExpr: Tree, defaultAction: Tree/*scrutinee*/ => Tree): Tree = {
- object withDefaultTransformer extends MatchMatcher {
- override def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = {
- val casesNoSynthCatchAll = dropSyntheticCatchAll(cases)
- if (casesNoSynthCatchAll exists treeInfo.isDefaultCase) orig
- else {
- val defaultCase = CaseDef(Ident(nme.WILDCARD), EmptyTree, defaultAction(selector.duplicate))
- wrap(Match(selector, casesNoSynthCatchAll :+ defaultCase))
- }
- }
- override def caseVirtualizedMatch(orig: Tree, _match: Tree, targs: List[Tree], scrut: Tree, matcher: Tree): Tree = { import CODE._
- ((matcher APPLY (scrut)) DOT nme.getOrElse) APPLY (defaultAction(scrut.duplicate)) // TODO: pass targs
- }
- override def caseVirtualizedMatchOpt(orig: Tree, zero: ValDef, x: ValDef, matchRes: ValDef, keepGoing: ValDef, stats: List[Tree], epilogue: Tree, wrap: Tree => Tree): Tree = { import CODE._
- wrap(Block(
- zero ::
- x ::
- matchRes ::
- keepGoing ::
- stats,
- // replace `if (keepGoing) throw new MatchError(...) else matchRes` by `if (keepGoing) ${defaultAction(`x`)} else matchRes`
- (IF (REF(keepGoing.symbol)) THEN defaultAction(x.rhs.duplicate) ELSE REF(matchRes.symbol))
- ))
- }
- }
- withDefaultTransformer(matchExpr)
- }
-
-
def mkCached(cvar: Symbol, expr: Tree): Tree = {
val cvarRef = mkUnattributedRef(cvar)
Block(
@@ -382,23 +352,19 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL {
else Block(prefix, containing) setPos (prefix.head.pos union containing.pos)
}
- /** Return a double-checked locking idiom around the syncBody tree. It guards with `cond` and
+ /** Return the synchronized part of the double-checked locking idiom around the syncBody tree. It guards with `cond` and
* synchronizez on `clazz.this`. Additional statements can be included after initialization,
* (outside the synchronized block).
*
* The idiom works only if the condition is using a volatile field.
* @see http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
*/
- def mkDoubleCheckedLocking(clazz: Symbol, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree =
- mkDoubleCheckedLocking(mkAttributedThis(clazz), cond, syncBody, stats)
-
- def mkDoubleCheckedLocking(attrThis: Tree, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree = {
- If(cond,
- Block(
- mkSynchronized(
- attrThis,
- If(cond, Block(syncBody: _*), EmptyTree)) ::
- stats: _*),
- EmptyTree)
- }
+ def mkSynchronizedCheck(clazz: Symbol, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree =
+ mkSynchronizedCheck(mkAttributedThis(clazz), cond, syncBody, stats)
+
+ def mkSynchronizedCheck(attrThis: Tree, cond: Tree, syncBody: List[Tree], stats: List[Tree]): Tree =
+ Block(mkSynchronized(
+ attrThis,
+ If(cond, Block(syncBody: _*), EmptyTree)) ::
+ stats: _*)
}
diff --git a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
index 9f361e5bcc..569cb4977b 100644
--- a/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreeInfo.scala
@@ -44,7 +44,7 @@ abstract class TreeInfo extends reflect.internal.TreeInfo {
}
def isInterface(mods: HasFlags, body: List[Tree]) =
- mods.hasTraitFlag && (body forall isInterfaceMember)
+ mods.isTrait && (body forall isInterfaceMember)
def isAllowedInUniversalTrait(stat: Tree): Boolean = stat match {
case _: ValDef => false
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 43c231cf2d..4c509778e9 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -13,6 +13,7 @@ import scala.reflect.internal.Flags.PARAM
import scala.reflect.internal.Flags.PARAMACCESSOR
import scala.reflect.internal.Flags.PRESUPER
import scala.reflect.internal.Flags.TRAIT
+import scala.compat.Platform.EOL
trait Trees extends reflect.internal.Trees { self: Global =>
@@ -33,30 +34,6 @@ trait Trees extends reflect.internal.Trees { self: Global =>
)
}
- class ValidatingPosAssigner extends PosAssigner {
- var pos: Position = _
- override def traverse(t: Tree) {
- if (t eq EmptyTree) ()
- else if (t.pos == NoPosition) super.traverse(t setPos pos)
- else if (globalPhase.id <= currentRun.picklerPhase.id) {
- // When we prune due to encountering a position, traverse the
- // pruned children so we can warn about those lacking positions.
- t.children foreach { c =>
- if ((c eq EmptyTree) || (c eq emptyValDef)) ()
- else if (c.pos == NoPosition) {
- reporter.warning(t.pos, " Positioned tree has unpositioned child in phase " + globalPhase)
- inform("parent: " + treeSymStatus(t))
- inform(" child: " + treeSymStatus(c) + "\n")
- }
- }
- }
- }
- }
-
- override protected[this] lazy val posAssigner: PosAssigner =
- if (settings.Yrangepos.value && settings.debug.value || settings.Yposdebug.value) new ValidatingPosAssigner
- else new DefaultPosAssigner
-
// --- additional cases --------------------------------------------------------
/** Only used during parsing */
case class Parens(args: List[Tree]) extends Tree
@@ -81,18 +58,11 @@ trait Trees extends reflect.internal.Trees { self: Global =>
case class InjectDerivedValue(arg: Tree)
extends SymTree
+ class PostfixSelect(qual: Tree, name: Name) extends Select(qual, name)
+
/** emitted by typer, eliminated by refchecks */
case class TypeTreeWithDeferredRefCheck()(val check: () => TypeTree) extends TypTree
- /** Marks underlying reference to id as boxed.
- * @pre: id must refer to a captured variable
- * A reference such marked will refer to the boxed entity, no dereferencing
- * with `.elem` is done on it.
- * This tree node can be emitted by macros such as reify that call markBoxedReference.
- * It is eliminated in LambdaLift, where the boxing conversion takes place.
- */
- case class ReferenceToBoxed(idt: Ident) extends TermTree
-
// --- factory methods ----------------------------------------------------------
/** Generates a template with constructor corresponding to
@@ -116,13 +86,12 @@ trait Trees extends reflect.internal.Trees { self: Global =>
/* Add constructor to template */
// create parameters for <init> as synthetic trees.
- var vparamss1 =
- vparamss map (vps => vps.map { vd =>
- atPos(focusPos(vd.pos)) {
- ValDef(
- Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM | BYNAMEPARAM) | PARAM | PARAMACCESSOR) withAnnotations vd.mods.annotations,
- vd.name, vd.tpt.duplicate, vd.rhs.duplicate)
- }})
+ var vparamss1 = mmap(vparamss) { vd =>
+ atPos(vd.pos.focus) {
+ val mods = Modifiers(vd.mods.flags & (IMPLICIT | DEFAULTPARAM | BYNAMEPARAM) | PARAM | PARAMACCESSOR)
+ ValDef(mods withAnnotations vd.mods.annotations, vd.name, vd.tpt.duplicate, vd.rhs.duplicate)
+ }
+ }
val (edefs, rest) = body span treeInfo.isEarlyDef
val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef
val gvdefs = evdefs map {
@@ -130,7 +99,7 @@ trait Trees extends reflect.internal.Trees { self: Global =>
// !!! I know "atPos in case" wasn't intentionally planted to
// add an air of mystery to this file, but it is the sort of
// comment which only its author could love.
- tpt = atPos(focusPos(vdef.pos))(TypeTree() setOriginal tpt setPos focusPos(tpt.pos)), // atPos in case
+ tpt = atPos(vdef.pos.focus)(TypeTree() setOriginal tpt setPos tpt.pos.focus), // atPos in case
rhs = EmptyTree
)
}
@@ -173,11 +142,18 @@ trait Trees extends reflect.internal.Trees { self: Global =>
* @param body the template statements without primary constructor
* and value parameter fields.
*/
- def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef =
+ def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], argss: List[List[Tree]], body: List[Tree], superPos: Position): ClassDef = {
+ // "if they have symbols they should be owned by `sym`"
+ assert(
+ mforall(vparamss)(p => (p.symbol eq NoSymbol) || (p.symbol.owner == sym)),
+ ((mmap(vparamss)(_.symbol), sym))
+ )
+
ClassDef(sym,
Template(sym.info.parents map TypeTree,
if (sym.thisSym == sym || phase.erasedTypes) emptyValDef else ValDef(sym.thisSym),
constrMods, vparamss, argss, body, superPos))
+ }
// --- subcomponents --------------------------------------------------
@@ -198,8 +174,6 @@ trait Trees extends reflect.internal.Trees { self: Global =>
traverser.traverse(qualifier)
case InjectDerivedValue(arg) =>
traverser.traverse(arg)
- case ReferenceToBoxed(idt) =>
- traverser.traverse(idt)
case TypeTreeWithDeferredRefCheck() =>
// (and rewrap the result? how to update the deferred check? would need to store wrapped tree instead of returning it from check)
case _ => super.xtraverse(traverser, tree)
@@ -209,7 +183,6 @@ trait Trees extends reflect.internal.Trees { self: Global =>
def DocDef(tree: Tree, comment: DocComment, definition: Tree): DocDef
def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type): SelectFromArray
def InjectDerivedValue(tree: Tree, arg: Tree): InjectDerivedValue
- def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed
def TypeTreeWithDeferredRefCheck(tree: Tree): TypeTreeWithDeferredRefCheck
}
@@ -222,9 +195,7 @@ trait Trees extends reflect.internal.Trees { self: Global =>
def SelectFromArray(tree: Tree, qualifier: Tree, selector: Name, erasure: Type) =
new SelectFromArray(qualifier, selector, erasure).copyAttrs(tree)
def InjectDerivedValue(tree: Tree, arg: Tree) =
- new InjectDerivedValue(arg)
- def ReferenceToBoxed(tree: Tree, idt: Ident) =
- new ReferenceToBoxed(idt).copyAttrs(tree)
+ new InjectDerivedValue(arg).copyAttrs(tree)
def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match {
case dc@TypeTreeWithDeferredRefCheck() => new TypeTreeWithDeferredRefCheck()(dc.check).copyAttrs(tree)
}
@@ -246,11 +217,6 @@ trait Trees extends reflect.internal.Trees { self: Global =>
if (arg0 == arg) => t
case _ => this.treeCopy.InjectDerivedValue(tree, arg)
}
- def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match {
- case t @ ReferenceToBoxed(idt0)
- if (idt0 == idt) => t
- case _ => this.treeCopy.ReferenceToBoxed(tree, idt)
- }
def TypeTreeWithDeferredRefCheck(tree: Tree) = tree match {
case t @ TypeTreeWithDeferredRefCheck() => t
case _ => this.treeCopy.TypeTreeWithDeferredRefCheck(tree)
@@ -268,6 +234,11 @@ trait Trees extends reflect.internal.Trees { self: Global =>
}
}
+ // used when a phase is disabled
+ object noopTransformer extends Transformer {
+ override def transformUnit(unit: CompilationUnit): Unit = {}
+ }
+
override protected def xtransform(transformer: super.Transformer, tree: Tree): Tree = tree match {
case DocDef(comment, definition) =>
transformer.treeCopy.DocDef(tree, comment, transformer.transform(definition))
@@ -277,9 +248,6 @@ trait Trees extends reflect.internal.Trees { self: Global =>
case InjectDerivedValue(arg) =>
transformer.treeCopy.InjectDerivedValue(
tree, transformer.transform(arg))
- case ReferenceToBoxed(idt) =>
- transformer.treeCopy.ReferenceToBoxed(
- tree, transformer.transform(idt) match { case idt1: Ident => idt1 })
case TypeTreeWithDeferredRefCheck() =>
transformer.treeCopy.TypeTreeWithDeferredRefCheck(tree)
}
@@ -296,8 +264,9 @@ trait Trees extends reflect.internal.Trees { self: Global =>
// def resetAllAttrs[A<:Tree](x:A): A = { new ResetAttrsTraverser().traverse(x); x }
// def resetLocalAttrs[A<:Tree](x:A): A = { new ResetLocalAttrsTraverser().traverse(x); x }
- def resetAllAttrs[A<:Tree](x:A): A = new ResetAttrs(false).transform(x)
- def resetLocalAttrs[A<:Tree](x:A): A = new ResetAttrs(true).transform(x)
+ def resetAllAttrs[A <: Tree](x: A, leaveAlone: Tree => Boolean = null): A = new ResetAttrs(false, leaveAlone).transform(x)
+ def resetLocalAttrs[A <: Tree](x: A, leaveAlone: Tree => Boolean = null): A = new ResetAttrs(true, leaveAlone).transform(x)
+ def resetLocalAttrsKeepLabels[A<:Tree](x: A, leaveAlone: Tree => Boolean = null): A = new ResetAttrs(true, leaveAlone, true).transform(x)
/** A transformer which resets symbol and tpe fields of all nodes in a given tree,
* with special treatment of:
@@ -308,7 +277,7 @@ trait Trees extends reflect.internal.Trees { self: Global =>
*
* (bq:) This transformer has mutable state and should be discarded after use
*/
- private class ResetAttrs(localOnly: Boolean) {
+ private class ResetAttrs(localOnly: Boolean, leaveAlone: Tree => Boolean = null, keepLabels: Boolean = false) {
val debug = settings.debug.value
val trace = scala.tools.nsc.util.trace when debug
@@ -328,6 +297,12 @@ trait Trees extends reflect.internal.Trees { self: Global =>
registerLocal(sym)
registerLocal(sym.sourceModule)
registerLocal(sym.moduleClass)
+ registerLocal(sym.companionClass)
+ registerLocal(sym.companionModule)
+ sym match {
+ case sym: TermSymbol => registerLocal(sym.referenced)
+ case _ => ;
+ }
}
}
@@ -335,10 +310,8 @@ trait Trees extends reflect.internal.Trees { self: Global =>
tree match {
case _: DefTree | Function(_, _) | Template(_, _, _) =>
markLocal(tree)
- case _ if tree.symbol.isInstanceOf[FreeVar] =>
- markLocal(tree)
case _ =>
- ;
+ tree
}
super.traverse(tree)
@@ -346,43 +319,50 @@ trait Trees extends reflect.internal.Trees { self: Global =>
}
class Transformer extends self.Transformer {
- override def transform(tree: Tree): Tree = super.transform {
- tree match {
- case tpt: TypeTree =>
- if (tpt.original != null) {
- transform(tpt.original)
- } else {
- if (tpt.tpe != null && (tpt.wasEmpty || (tpt.tpe exists (tp => locals contains tp.typeSymbol))))
- tpt.tpe = null
- tree
+ override def transform(tree: Tree): Tree = {
+ if (leaveAlone != null && leaveAlone(tree))
+ tree
+ else
+ super.transform {
+ tree match {
+ case tpt: TypeTree =>
+ if (tpt.original != null)
+ transform(tpt.original)
+ else if (tpt.tpe != null && (tpt.wasEmpty || (tpt.tpe exists (tp => locals contains tp.typeSymbol)))) {
+ val dupl = tpt.duplicate
+ dupl.tpe = null
+ dupl
+ }
+ else tree
+ case TypeApply(fn, args) if args map transform exists (_.isEmpty) =>
+ transform(fn)
+ case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
+ tree
+ case EmptyTree =>
+ tree
+ case _ =>
+ val dupl = tree.duplicate
+ if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)) && !(keepLabels && tree.symbol.isLabel))
+ dupl.symbol = NoSymbol
+ dupl.tpe = null
+ dupl
}
- case TypeApply(fn, args) if args map transform exists (_.isEmpty) =>
- transform(fn)
- case This(_) if tree.symbol != null && tree.symbol.isPackageClass =>
- tree
- case EmptyTree =>
- tree
- case _ =>
- if (tree.hasSymbol && (!localOnly || (locals contains tree.symbol)))
- tree.symbol = NoSymbol
- tree.tpe = null
- tree
- }
+ }
}
}
def transform[T <: Tree](x: T): T = {
+ if (localOnly)
new MarkLocals().traverse(x)
- if (debug) {
+ if (localOnly && debug) {
assert(locals.size == orderedLocals.size)
- val eoln = System.getProperty("line.separator")
- val msg = orderedLocals.toList filter {_ != NoSymbol} map {" " + _} mkString eoln
+ val msg = orderedLocals.toList filter {_ != NoSymbol} map {" " + _} mkString EOL
trace("locals (%d total): %n".format(orderedLocals.size))(msg)
}
val x1 = new Transformer().transform(x)
- assert(x.getClass isInstance x1)
+ assert(x.getClass isInstance x1, x1.getClass)
x1.asInstanceOf[T]
}
}
@@ -397,4 +377,4 @@ trait Trees extends reflect.internal.Trees { self: Global =>
*/
- } \ No newline at end of file
+ }
diff --git a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
index 93fa9a60f6..f702f44338 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/MarkupParsers.scala
@@ -397,7 +397,7 @@ trait MarkupParsers {
/** xScalaPatterns ::= patterns
*/
- def xScalaPatterns: List[Tree] = escapeToScala(parser.seqPatterns(), "pattern")
+ def xScalaPatterns: List[Tree] = escapeToScala(parser.xmlSeqPatterns(), "pattern")
def reportSyntaxError(pos: Int, str: String) = parser.syntaxError(pos, str)
def reportSyntaxError(str: String) {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 45325b4694..c02a7e493e 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -70,6 +70,9 @@ trait ParsersCommon extends ScannersCommon {
@inline final def inBracesOrNil[T](body: => List[T]): List[T] = inBracesOrError(body, Nil)
@inline final def inBracesOrUnit[T](body: => Tree): Tree = inBracesOrError(body, Literal(Constant()))
+ @inline final def dropAnyBraces[T](body: => T): T =
+ if (in.token == LBRACE) inBraces(body)
+ else body
@inline final def inBrackets[T](body: => T): T = {
accept(LBRACKET)
@@ -249,7 +252,7 @@ self =>
final val InBlock = 1
final val InTemplate = 2
- lazy val ScalaValueClassNames: Set[Name] = definitions.scalaValueClassesSet map (_.name)
+ lazy val ScalaValueClassNames = tpnme.AnyVal :: definitions.ScalaValueClasses.map(_.name)
import nme.raw
@@ -314,7 +317,7 @@ self =>
* by compilationUnit().
*/
def scriptBody(): Tree = {
- val stmts = templateStatSeq(false)._2
+ val stmts = templateStats()
accept(EOF)
def mainModuleName = newTermName(settings.script.value)
@@ -1024,7 +1027,7 @@ self =>
val tok = in.token
val name = ident()
t = atPos(start) {
- if (tok == BACKQUOTED_IDENT) new BackQuotedIdent(name)
+ if (tok == BACKQUOTED_IDENT) Ident(name) withAttachment BackquotedIdentifier
else Ident(name)
}
if (in.token == DOT) {
@@ -1106,7 +1109,7 @@ self =>
* }}}
* @note The returned tree does not yet have a position
*/
- def literal(isNegated: Boolean = false): Tree = {
+ def literal(isNegated: Boolean = false, inPattern: Boolean = false): Tree = {
def finish(value: Any): Tree = {
val t = Literal(Constant(value))
in.nextToken()
@@ -1115,7 +1118,7 @@ self =>
if (in.token == SYMBOLLIT)
Apply(scalaDot(nme.Symbol), List(finish(in.strVal)))
else if (in.token == INTERPOLATIONID)
- interpolatedString()
+ interpolatedString(inPattern)
else finish(in.token match {
case CHARLIT => in.charVal
case INTLIT => in.intVal(isNegated).toInt
@@ -1141,7 +1144,7 @@ self =>
}
}
- private def interpolatedString(): Tree = atPos(in.offset) {
+ private def interpolatedString(inPattern: Boolean = false): Tree = atPos(in.offset) {
val start = in.offset
val interpolator = in.name
@@ -1151,8 +1154,11 @@ self =>
while (in.token == STRINGPART) {
partsBuf += literal()
exprBuf += {
- if (in.token == IDENTIFIER) atPos(in.offset)(Ident(ident()))
- else expr()
+ if (inPattern) dropAnyBraces(pattern())
+ else {
+ if (in.token == IDENTIFIER) atPos(in.offset)(Ident(ident()))
+ else expr()
+ }
}
}
if (in.token == STRINGLIT) partsBuf += literal()
@@ -1456,11 +1462,12 @@ self =>
return reduceStack(true, base, top, 0, true)
top = next
} else {
+ // postfix expression
val topinfo = opstack.head
opstack = opstack.tail
val od = stripParens(reduceStack(true, base, topinfo.operand, 0, true))
return atPos(od.pos.startOrPoint, topinfo.offset) {
- Select(od, topinfo.operator.encode)
+ new PostfixSelect(od, topinfo.operator.encode)
}
}
}
@@ -1698,11 +1705,11 @@ self =>
* was threaded through methods as boolean seqOK.
*/
trait SeqContextSensitive extends PatternContextSensitive {
- /** Returns Some(tree) if it finds a star and prematurely ends parsing.
- * This is an artifact of old implementation which has proven difficult
- * to cleanly extract.
- */
- def interceptStarPattern(top: Tree): Option[Tree]
+ // is a sequence pattern _* allowed?
+ def isSequenceOK: Boolean
+
+ // are we in an XML pattern?
+ def isXML: Boolean = false
def functionArgType(): Tree = argType()
def argType(): Tree = {
@@ -1771,7 +1778,9 @@ self =>
* }}}
*/
def pattern2(): Tree = {
+ val nameOffset = in.offset
val p = pattern3()
+
if (in.token != AT) p
else p match {
case Ident(nme.WILDCARD) =>
@@ -1787,45 +1796,98 @@ self =>
/** {{{
* Pattern3 ::= SimplePattern
* | SimplePattern {Id [nl] SimplePattern}
- * SeqPattern3 ::= SeqSimplePattern [ `*' | `?' | `+' ]
- * | SeqSimplePattern {Id [nl] SeqSimplePattern}
* }}}
*/
def pattern3(): Tree = {
+ var top = simplePattern(badPattern3)
+ // after peekahead
+ def acceptWildStar() = atPos(top.pos.startOrPoint, in.prev.offset)(Star(stripParens(top)))
+ def peekahead() = {
+ in.prev copyFrom in
+ in.nextToken()
+ }
+ def pushback() = {
+ in.next copyFrom in
+ in copyFrom in.prev
+ }
+ // See SI-3189, SI-4832 for motivation. Cf SI-3480 for counter-motivation.
+ // TODO: dredge out the remnants of regexp patterns.
+ // /{/ peek for _*) or _*} (for xml escape)
+ if (isSequenceOK) {
+ top match {
+ case Ident(nme.WILDCARD) if (isRawStar) =>
+ peekahead()
+ in.token match {
+ case RBRACE if (isXML) => return acceptWildStar()
+ case RPAREN if (!isXML) => return acceptWildStar()
+ case _ => pushback()
+ }
+ case _ =>
+ }
+ }
val base = opstack
- var top = simplePattern()
- interceptStarPattern(top) foreach { x => return x }
-
while (isIdent && in.name != raw.BAR) {
- top = reduceStack(
- false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
+ top = reduceStack(false, base, top, precedence(in.name), treeInfo.isLeftAssoc(in.name))
val op = in.name
opstack = OpInfo(top, op, in.offset) :: opstack
ident()
- top = simplePattern()
+ top = simplePattern(badPattern3)
}
stripParens(reduceStack(false, base, top, 0, true))
}
+ def badPattern3(): Tree = {
+ def isComma = in.token == COMMA
+ def isAnyBrace = in.token == RPAREN || in.token == RBRACE
+ val badStart = "illegal start of simple pattern"
+ // better recovery if don't skip delims of patterns
+ var skip = !(isComma || isAnyBrace)
+ val msg = if (!opstack.isEmpty && opstack.head.operator == nme.STAR) {
+ opstack.head.operand match {
+ case Ident(nme.WILDCARD) =>
+ if (isSequenceOK && isComma)
+ "bad use of _* (a sequence pattern must be the last pattern)"
+ else if (isSequenceOK && isAnyBrace) {
+ skip = true // do skip bad paren; scanner may skip bad brace already
+ "bad brace or paren after _*"
+ } else if (!isSequenceOK && isAnyBrace)
+ "bad use of _* (sequence pattern not allowed)"
+ else badStart
+ case _ =>
+ if (isSequenceOK && isAnyBrace)
+ "use _* to match a sequence"
+ else if (isComma || isAnyBrace)
+ "trailing * is not a valid pattern"
+ else badStart
+ }
+ } else {
+ badStart
+ }
+ syntaxErrorOrIncomplete(msg, skip)
+ errorPatternTree
+ }
/** {{{
* SimplePattern ::= varid
* | `_'
* | literal
* | XmlPattern
- * | StableId [TypeArgs] [`(' [SeqPatterns] `)']
+ * | StableId /[TypeArgs]/ [`(' [Patterns] `)']
+ * | StableId [`(' [Patterns] `)']
+ * | StableId [`(' [Patterns] `,' [varid `@'] `_' `*' `)']
* | `(' [Patterns] `)'
- * SimpleSeqPattern ::= varid
- * | `_'
- * | literal
- * | XmlPattern
- * | `<' xLiteralPattern
- * | StableId [TypeArgs] [`(' [SeqPatterns] `)']
- * | `(' [SeqPatterns] `)'
* }}}
*
* XXX: Hook for IDE
*/
def simplePattern(): Tree = {
+ // simple diagnostics for this entry point
+ def badStart(): Tree = {
+ syntaxErrorOrIncomplete("illegal start of simple pattern", true)
+ errorPatternTree
+ }
+ simplePattern(badStart)
+ }
+ def simplePattern(onError: () => Tree): Tree = {
val start = in.offset
in.token match {
case IDENTIFIER | BACKQUOTED_IDENT | THIS =>
@@ -1834,7 +1896,7 @@ self =>
case INTLIT | LONGLIT | FLOATLIT | DOUBLELIT =>
t match {
case Ident(nme.MINUS) =>
- return atPos(start) { literal(isNegated = true) }
+ return atPos(start) { literal(isNegated = true, inPattern = true) }
case _ =>
}
case _ =>
@@ -1852,14 +1914,13 @@ self =>
atPos(start, start) { Ident(nme.WILDCARD) }
case CHARLIT | INTLIT | LONGLIT | FLOATLIT | DOUBLELIT |
STRINGLIT | INTERPOLATIONID | SYMBOLLIT | TRUE | FALSE | NULL =>
- atPos(start) { literal() }
+ atPos(start) { literal(inPattern = true) }
case LPAREN =>
atPos(start)(makeParens(noSeq.patterns()))
case XMLSTART =>
xmlLiteralPattern()
case _ =>
- syntaxErrorOrIncomplete("illegal start of simple pattern", true)
- errorPatternTree
+ onError()
}
}
}
@@ -1870,16 +1931,16 @@ self =>
}
/** The implementation for parsing inside of patterns at points where sequences are allowed. */
object seqOK extends SeqContextSensitive {
- // See ticket #3189 for the motivation for the null check.
- // TODO: dredge out the remnants of regexp patterns.
- // ... and now this is back the way it was because it caused #3480.
- def interceptStarPattern(top: Tree): Option[Tree] =
- if (isRawStar) Some(atPos(top.pos.startOrPoint, in.skipToken())(Star(stripParens(top))))
- else None
+ val isSequenceOK = true
}
/** The implementation for parsing inside of patterns at points where sequences are disallowed. */
object noSeq extends SeqContextSensitive {
- def interceptStarPattern(top: Tree) = None
+ val isSequenceOK = false
+ }
+ /** For use from xml pattern, where sequence is allowed and encouraged. */
+ object xmlSeqOK extends SeqContextSensitive {
+ val isSequenceOK = true
+ override val isXML = true
}
/** These are default entry points into the pattern context sensitive methods:
* they are all initiated from non-pattern context.
@@ -1893,7 +1954,8 @@ self =>
/** Default entry points into some pattern contexts. */
def pattern(): Tree = noSeq.pattern()
def patterns(): List[Tree] = noSeq.patterns()
- def seqPatterns(): List[Tree] = seqOK.patterns() // Also called from xml parser
+ def seqPatterns(): List[Tree] = seqOK.patterns()
+ def xmlSeqPatterns(): List[Tree] = xmlSeqOK.patterns() // Called from xml parser
def argumentPatterns(): List[Tree] = inParens {
if (in.token == RPAREN) Nil
else seqPatterns()
@@ -2421,10 +2483,10 @@ self =>
*/
/** {{{
- * FunDef ::= FunSig `:' Type `=' Expr
- * | FunSig [nl] `{' Block `}'
- * | this ParamClause ParamClauses (`=' ConstrExpr | [nl] ConstrBlock)
- * | `macro' FunSig [`:' Type] `=' Expr
+ * FunDef ::= FunSig [`:' Type] `=' [`macro'] Expr
+ * | FunSig [nl] `{' Block `}'
+ * | `this' ParamClause ParamClauses
+ * (`=' ConstrExpr | [nl] ConstrBlock)
* FunDcl ::= FunSig [`:' Type]
* FunSig ::= id [FunTypeParamClause] ParamClauses
* }}}
@@ -2445,17 +2507,12 @@ self =>
else {
val nameOffset = in.offset
val name = ident()
- if (name == nme.macro_ && isIdent && settings.Xmacros.value)
- funDefRest(start, in.offset, mods | Flags.MACRO, ident())
- else
- funDefRest(start, nameOffset, mods, name)
+ funDefRest(start, nameOffset, mods, name)
}
}
def funDefRest(start: Int, nameOffset: Int, mods: Modifiers, name: Name): Tree = {
val result = atPos(start, if (name.toTermName == nme.ERROR) start else nameOffset) {
- val isMacro = mods hasFlag Flags.MACRO
- val isTypeMacro = isMacro && name.isTypeName
var newmods = mods
// contextBoundBuf is for context bounded type parameters of the form
// [T : B] or [T : => B]; it contains the equivalent implicit parameter type,
@@ -2463,12 +2520,10 @@ self =>
val contextBoundBuf = new ListBuffer[Tree]
val tparams = typeParamClauseOpt(name, contextBoundBuf)
val vparamss = paramClauses(name, contextBoundBuf.toList, false)
- if (!isMacro) newLineOptWhenFollowedBy(LBRACE)
- var restype = if (isTypeMacro) TypeTree() else fromWithinReturnType(typedOpt())
+ newLineOptWhenFollowedBy(LBRACE)
+ var restype = fromWithinReturnType(typedOpt())
val rhs =
- if (isMacro)
- equalsExpr()
- else if (isStatSep || in.token == RBRACE) {
+ if (isStatSep || in.token == RBRACE) {
if (restype.isEmpty) restype = scalaUnitConstr
newmods |= Flags.DEFERRED
EmptyTree
@@ -2476,10 +2531,17 @@ self =>
restype = scalaUnitConstr
blockExpr()
} else {
- if (name == nme.macro_ && isIdent && in.token != EQUALS) {
- warning("this syntactically invalid code resembles a macro definition. have you forgotten to enable -Xmacros?")
+ if (in.token == EQUALS) {
+ in.nextTokenAllow(nme.MACROkw)
+ if (settings.Xmacros.value && in.token == MACRO || // [Martin] Xmacros can be retired now
+ in.token == IDENTIFIER && in.name == nme.MACROkw) {
+ in.nextToken()
+ newmods |= Flags.MACRO
+ }
+ } else {
+ accept(EQUALS)
}
- equalsExpr()
+ expr()
}
DefDef(newmods, name, tparams, vparamss, restype, rhs)
}
@@ -2529,7 +2591,7 @@ self =>
/** {{{
* TypeDef ::= type Id [TypeParamClause] `=' Type
- * | `macro' FunSig `=' Expr
+ * | FunSig `=' Expr
* TypeDcl ::= type Id [TypeParamClause] TypeBounds
* }}}
*/
@@ -2537,22 +2599,19 @@ self =>
in.nextToken()
newLinesOpt()
atPos(start, in.offset) {
+ val nameOffset = in.offset
val name = identForType()
- if (name == nme.macro_.toTypeName && isIdent && settings.Xmacros.value) {
- funDefRest(start, in.offset, mods | Flags.MACRO, identForType())
- } else {
- // @M! a type alias as well as an abstract type may declare type parameters
- val tparams = typeParamClauseOpt(name, null)
- in.token match {
- case EQUALS =>
- in.nextToken()
- TypeDef(mods, name, tparams, typ())
- case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE =>
- TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
- case _ =>
- syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true)
- EmptyTree
- }
+ // @M! a type alias as well as an abstract type may declare type parameters
+ val tparams = typeParamClauseOpt(name, null)
+ in.token match {
+ case EQUALS =>
+ in.nextToken()
+ TypeDef(mods, name, tparams, typ())
+ case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE =>
+ TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
+ case _ =>
+ syntaxErrorOrIncomplete("`=', `>:', or `<:' expected", true)
+ EmptyTree
}
}
}
@@ -2600,24 +2659,22 @@ self =>
in.nextToken
val nameOffset = in.offset
val name = identForType()
- def isTrait = mods.hasTraitFlag
-
atPos(start, if (name == tpnme.ERROR) start else nameOffset) {
savingClassContextBounds {
val contextBoundBuf = new ListBuffer[Tree]
val tparams = typeParamClauseOpt(name, contextBoundBuf)
classContextBounds = contextBoundBuf.toList
- val tstart = in.offset :: classContextBounds.map(_.pos.startOrPoint) min;
- if (!classContextBounds.isEmpty && isTrait) {
+ val tstart = (in.offset :: classContextBounds.map(_.pos.startOrPoint)).min
+ if (!classContextBounds.isEmpty && mods.isTrait) {
syntaxError("traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'", false)
classContextBounds = List()
}
val constrAnnots = constructorAnnotations()
val (constrMods, vparamss) =
- if (isTrait) (Modifiers(Flags.TRAIT), List())
+ if (mods.isTrait) (Modifiers(Flags.TRAIT), List())
else (accessModifierOpt(), paramClauses(name, classContextBounds, mods.isCase))
var mods1 = mods
- if (isTrait) {
+ if (mods.isTrait) {
if (settings.YvirtClasses && in.token == SUBTYPE) mods1 |= Flags.DEFERRED
} else if (in.token == SUBTYPE) {
syntaxError("classes are not allowed to be virtual", false)
@@ -2709,7 +2766,7 @@ self =>
}
def isInterface(mods: Modifiers, body: List[Tree]): Boolean =
- mods.hasTraitFlag && (body forall treeInfo.isInterfaceMember)
+ mods.isTrait && (body forall treeInfo.isInterfaceMember)
/** {{{
* ClassTemplateOpt ::= `extends' ClassTemplate | [[`extends'] TemplateBody]
@@ -2719,9 +2776,9 @@ self =>
*/
def templateOpt(mods: Modifiers, name: Name, constrMods: Modifiers, vparamss: List[List[ValDef]], tstart: Int): Template = {
val (parents0, argss, self, body) = (
- if (in.token == EXTENDS || in.token == SUBTYPE && mods.hasTraitFlag) {
+ if (in.token == EXTENDS || in.token == SUBTYPE && mods.isTrait) {
in.nextToken()
- template(mods.hasTraitFlag)
+ template(mods.isTrait)
}
else {
newLineOptWhenFollowedBy(LBRACE)
@@ -2744,9 +2801,8 @@ self =>
val tstart0 = if (body.isEmpty && in.lastOffset < tstart) in.lastOffset else tstart
atPos(tstart0) {
- // [Martin to Paul: This needs to be refined. We should only include the 9 primitive classes,
- // not any other value classes that happen to be defined in the Scala package.
- if (inScalaRootPackage && (name == tpnme.AnyVal || (ScalaValueClassNames contains name)))
+ // Exclude only the 9 primitives plus AnyVal.
+ if (inScalaRootPackage && ScalaValueClassNames.contains(name))
Template(parents0, self, anyvalConstructor :: body)
else
Template(anyrefParents, self, constrMods, vparamss, argss, body, o2p(tstart))
@@ -2820,6 +2876,7 @@ self =>
* }}}
*/
def packaging(start: Int): Tree = {
+ val nameOffset = in.offset
val pkg = pkgQualId()
val stats = inBracesOrNil(topStatSeq())
makePackaging(start, pkg, stats)
@@ -2861,6 +2918,13 @@ self =>
stats.toList
}
+ /** Informal - for the repl and other direct parser accessors.
+ */
+ def templateStats(): List[Tree] = templateStatSeq(false)._2 match {
+ case Nil => List(EmptyTree)
+ case stats => stats
+ }
+
/** {{{
* TemplateStatSeq ::= [id [`:' Type] `=>'] TemplateStat {semi TemplateStat}
* TemplateStat ::= Import
@@ -3022,8 +3086,10 @@ self =>
ts ++= topStatSeq()
}
} else {
+ val nameOffset = in.offset
in.flushDoc
val pkg = pkgQualId()
+
if (in.token == EOF) {
ts += makePackaging(start, pkg, List())
} else if (isStatSep) {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 2895d02dfe..87072f3172 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -113,10 +113,18 @@ trait Scanners extends ScannersCommon {
}
/** Clear buffer and set name and token */
- private def finishNamed() {
+ private def finishNamed(idtoken: Int = IDENTIFIER) {
name = newTermName(cbuf.toString)
- token = name2token(name)
cbuf.clear()
+ token = idtoken
+ if (idtoken == IDENTIFIER) {
+ val idx = name.start - kwOffset
+ if (idx >= 0 && idx < kwArray.length) {
+ token = kwArray(idx)
+ if (token == IDENTIFIER && allowIdent != name)
+ deprecationWarning(name+" is now a reserved word; usage as an identifier is deprecated")
+ }
+ }
}
/** Clear buffer and set string */
@@ -190,6 +198,20 @@ trait Scanners extends ScannersCommon {
off
}
+ /** Allow an otherwise deprecated ident here */
+ private var allowIdent: Name = nme.EMPTY
+
+ /** Get next token, and allow the otherwise deprecated ident `name` */
+ def nextTokenAllow(name: Name) = {
+ val prev = allowIdent
+ allowIdent = name
+ try {
+ nextToken()
+ } finally {
+ allowIdent = prev
+ }
+ }
+
/** Produce next token, filling TokenData fields of Scanner.
*/
def nextToken() {
@@ -231,6 +253,12 @@ trait Scanners extends ScannersCommon {
lastOffset -= 1
}
if (inStringInterpolation) fetchStringPart() else fetchToken()
+ if(token == ERROR) {
+ if (inMultiLineInterpolation)
+ sepRegions = sepRegions.tail.tail
+ else if (inStringInterpolation)
+ sepRegions = sepRegions.tail
+ }
} else {
this copyFrom next
next.token = EMPTY
@@ -328,7 +356,7 @@ trait Scanners extends ScannersCommon {
putChar(ch)
nextChar()
getIdentRest()
- if (ch == '"' && token == IDENTIFIER && settings.Xexperimental.value)
+ if (ch == '"' && token == IDENTIFIER)
token = INTERPOLATIONID
case '<' => // is XMLSTART?
val last = if (charOffset >= 2) buf(charOffset - 2) else ' '
@@ -562,9 +590,8 @@ trait Scanners extends ScannersCommon {
getLitChars('`')
if (ch == '`') {
nextChar()
- finishNamed()
+ finishNamed(BACKQUOTED_IDENT)
if (name.length == 0) syntaxError("empty quoted identifier")
- token = BACKQUOTED_IDENT
}
else syntaxError("unclosed quoted identifier")
}
@@ -697,7 +724,7 @@ trait Scanners extends ScannersCommon {
do {
putChar(ch)
nextRawChar()
- } while (Character.isUnicodeIdentifierPart(ch))
+ } while (ch != SU && Character.isUnicodeIdentifierPart(ch))
next.token = IDENTIFIER
next.name = newTermName(cbuf.toString)
cbuf.clear()
@@ -1124,8 +1151,9 @@ trait Scanners extends ScannersCommon {
nme.VIEWBOUNDkw -> VIEWBOUND,
nme.SUPERTYPEkw -> SUPERTYPE,
nme.HASHkw -> HASH,
- nme.ATkw -> AT
- )
+ nme.ATkw -> AT,
+ nme.MACROkw -> IDENTIFIER,
+ nme.THENkw -> IDENTIFIER)
private var kwOffset: Int = -1
private val kwArray: Array[Int] = {
@@ -1134,14 +1162,7 @@ trait Scanners extends ScannersCommon {
arr
}
- final val token2name = allKeywords map (_.swap) toMap
-
- /** Convert name to token */
- final def name2token(name: Name) = {
- val idx = name.start - kwOffset
- if (idx >= 0 && idx < kwArray.length) kwArray(idx)
- else IDENTIFIER
- }
+ final val token2name = (allKeywords map (_.swap)).toMap
// Token representation ----------------------------------------------------
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
index 849437e4ff..b0204c5971 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SymbolicXMLBuilder.scala
@@ -11,6 +11,7 @@ import xml.{ EntityRef, Text }
import xml.XML.{ xmlns }
import symtab.Flags.MUTABLE
import scala.tools.util.StringOps.splitWhere
+import language.implicitConversions
/** This class builds instance of `Tree` that represent XML.
*
@@ -29,7 +30,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
private[parser] var isPattern: Boolean = _
- private trait XMLTypeNames extends TypeNames {
+ private object xmltypes extends TypeNames {
val _Comment: NameType = "Comment"
val _Elem: NameType = "Elem"
val _EntityRef: NameType = "EntityRef"
@@ -44,7 +45,7 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
val _UnprefixedAttribute: NameType = "UnprefixedAttribute"
}
- private trait XMLTermNames extends TermNames {
+ private object xmlterms extends TermNames {
val _Null: NameType = "Null"
val __Elem: NameType = "Elem"
val __Text: NameType = "Text"
@@ -56,15 +57,6 @@ abstract class SymbolicXMLBuilder(p: Parsers#Parser, preserveWS: Boolean) {
val _xml: NameType = "xml"
}
- private object xmltypes extends XMLTypeNames {
- type NameType = TypeName
- implicit def createNameType(name: String): TypeName = newTypeNameCached(name)
- }
- private object xmlterms extends XMLTermNames {
- type NameType = TermName
- implicit def createNameType(name: String): TermName = newTermNameCached(name)
- }
-
import xmltypes.{_Comment, _Elem, _EntityRef, _Group, _MetaData, _NamespaceBinding, _NodeBuffer,
_PrefixedAttribute, _ProcInstr, _Text, _Unparsed, _UnprefixedAttribute}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
index fb4daefd57..a4a062609b 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Tokens.scala
@@ -110,6 +110,8 @@ object Tokens extends Tokens {
final val MATCH = 58
final val FORSOME = 59
final val LAZY = 61
+ final val MACRO = 62 // not yet used in 2.10
+ final val THEN = 63 // not yet used in 2.10
def isKeyword(code: Int) =
code >= IF && code <= LAZY
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 3a6e26d3b5..de7e6f9c7a 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -521,11 +521,29 @@ abstract class TreeBuilder {
// val/var x_1 = t$._1
// ...
// val/var x_N = t$._N
- val pat1 = patvarTransformer.transform(pat)
+
+ val rhsUnchecked = gen.mkUnchecked(rhs)
+
+ // TODO: clean this up -- there is too much information packked into makePatDef's `pat` argument
+ // when it's a simple identifier (case Some((name, tpt)) -- above),
+ // pat should have the type ascription that was specified by the user
+ // however, in `case None` (here), we must be careful not to generate illegal pattern trees (such as `(a, b): Tuple2[Int, String]`)
+ // i.e., this must hold: pat1 match { case Typed(expr, tp) => assert(expr.isInstanceOf[Ident]) case _ => }
+ // if we encounter such an erroneous pattern, we strip off the type ascription from pat and propagate the type information to rhs
+ val (pat1, rhs1) = patvarTransformer.transform(pat) match {
+ // move the Typed ascription to the rhs
+ case Typed(expr, tpt) if !expr.isInstanceOf[Ident] =>
+ val rhsTypedUnchecked =
+ if (tpt.isEmpty) rhsUnchecked
+ else Typed(rhsUnchecked, tpt) setPos (rhs.pos union tpt.pos)
+ (expr, rhsTypedUnchecked)
+ case ok =>
+ (ok, rhsUnchecked)
+ }
val vars = getVariables(pat1)
val matchExpr = atPos((pat1.pos union rhs.pos).makeTransparent) {
Match(
- gen.mkUnchecked(rhs),
+ rhs1,
List(
atPos(pat1.pos) {
CaseDef(pat1, EmptyTree, makeTupleTerm(vars map (_._1) map Ident, true))
diff --git a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
index 27df45b563..7da7611ce2 100644
--- a/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
+++ b/src/compiler/scala/tools/nsc/backend/JavaPlatform.scala
@@ -33,15 +33,19 @@ trait JavaPlatform extends Platform {
if (settings.make.isDefault) Nil
else List(dependencyAnalysis)
+ private def classEmitPhase =
+ if (settings.target.value == "jvm-1.5") genJVM
+ else genASM
+
def platformPhases = List(
- flatten, // get rid of inner classes
- genJVM // generate .class files
+ flatten, // get rid of inner classes
+ classEmitPhase // generate .class files
) ++ depAnalysisPhase
- lazy val externalEquals = getMember(BoxesRunTimeClass, nme.equals_)
- lazy val externalEqualsNumNum = getMember(BoxesRunTimeClass, nme.equalsNumNum)
- lazy val externalEqualsNumChar = getMember(BoxesRunTimeClass, nme.equalsNumChar)
- lazy val externalEqualsNumObject = getMember(BoxesRunTimeClass, nme.equalsNumObject)
+ lazy val externalEquals = getDecl(BoxesRunTimeClass, nme.equals_)
+ lazy val externalEqualsNumNum = getDecl(BoxesRunTimeClass, nme.equalsNumNum)
+ lazy val externalEqualsNumChar = getDecl(BoxesRunTimeClass, nme.equalsNumChar)
+ lazy val externalEqualsNumObject = getDecl(BoxesRunTimeClass, nme.equalsNumObject)
/** We could get away with excluding BoxedBooleanClass for the
* purpose of equality testing since it need not compare equal
diff --git a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
index 4f3b0bf951..b8ecaf1b43 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/BasicBlocks.scala
@@ -11,6 +11,7 @@ import scala.collection.{ mutable, immutable }
import mutable.{ ListBuffer, ArrayBuffer }
import util.{ Position, NoPosition }
import backend.icode.analysis.ProgramPoint
+import language.postfixOps
trait BasicBlocks {
self: ICodes =>
@@ -218,8 +219,8 @@ trait BasicBlocks {
///////////////////// Substitutions ///////////////////////
/**
- * Replace the instruction at the given position. Used by labels when
- * they are anchored. It retains the position of the previous instruction.
+ * Replace the instruction at the given position. Used by labels when they are anchored.
+ * The replacing instruction is given the nsc.util.Position of the instruction it replaces.
*/
def replaceInstruction(pos: Int, instr: Instruction): Boolean = {
assert(closed, "Instructions can be replaced only after the basic block is closed")
@@ -232,7 +233,7 @@ trait BasicBlocks {
/**
* Replace the given instruction with the new one.
* Returns `true` if it actually changed something.
- * It retains the position of the previous instruction.
+ * The replacing instruction is given the nsc.util.Position of the instruction it replaces.
*/
def replaceInstruction(oldInstr: Instruction, newInstr: Instruction): Boolean = {
assert(closed, "Instructions can be replaced only after the basic block is closed")
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 8e568eca79..4aeb537f9b 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -13,6 +13,7 @@ import scala.collection.mutable.{ ListBuffer, Buffer }
import scala.tools.nsc.symtab._
import scala.annotation.switch
import PartialFunction._
+import language.postfixOps
/** This class ...
*
@@ -820,7 +821,7 @@ abstract class GenICode extends SubComponent {
ctx2
case _ =>
- abort("Cannot instantiate " + tpt + "of kind: " + generatedType)
+ abort("Cannot instantiate " + tpt + " of kind: " + generatedType)
}
case Apply(fun @ _, List(expr)) if (definitions.isBox(fun.symbol)) =>
@@ -1533,7 +1534,7 @@ abstract class GenICode extends SubComponent {
*/
def genEqEqPrimitive(l: Tree, r: Tree, ctx: Context)(thenCtx: Context, elseCtx: Context): Unit = {
def getTempLocal = ctx.method.lookupLocal(nme.EQEQ_LOCAL_VAR) getOrElse {
- ctx.makeLocal(l.pos, AnyRefClass.typeConstructor, nme.EQEQ_LOCAL_VAR)
+ ctx.makeLocal(l.pos, AnyRefClass.tpe, nme.EQEQ_LOCAL_VAR)
}
/** True if the equality comparison is between values that require the use of the rich equality
@@ -2224,7 +2225,7 @@ abstract class GenICode extends SubComponent {
* jumps to the given basic block.
*/
def patch(code: Code) {
- val map = toPatch map (i => (i -> patch(i))) toMap;
+ val map = mapFrom(toPatch)(patch)
code.blocks foreach (_ subst map)
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
index 36651541b2..71795a02aa 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala
@@ -44,7 +44,7 @@ trait Members {
def blocksList: List[BasicBlock] = blocks.toList
def instructions = blocksList flatMap (_.iterator)
def blockCount = blocks.size
- def instructionCount = blocks map (_.length) sum
+ def instructionCount = (blocks map (_.length)).sum
def touched = _touched
def touched_=(b: Boolean): Unit = {
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
index ec6c631bd1..576cc72f82 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Opcodes.scala
@@ -435,6 +435,8 @@ trait Opcodes { self: ICodes =>
override def consumed = 1
override def produced = 0
+
+ def flatTagsCount: Int = { var acc = 0; var rest = tags; while(rest.nonEmpty) { acc += rest.head.length; rest = rest.tail }; acc } // a one-liner
}
/** This class represents a JUMP instruction
@@ -593,48 +595,49 @@ trait Opcodes { self: ICodes =>
/** This class represents a method invocation style. */
sealed abstract class InvokeStyle {
/** Is this a dynamic method call? */
- def isDynamic: Boolean = this match {
- case Dynamic => true
- case _ => false
- }
+ def isDynamic: Boolean = false
/** Is this a static method call? */
- def isStatic: Boolean = this match {
- case Static(_) => true
- case _ => false
- }
+ def isStatic: Boolean = false
- def isSuper: Boolean = this match {
- case SuperCall(_) => true
- case _ => false
- }
+ def isSuper: Boolean = false
/** Is this an instance method call? */
- def hasInstance: Boolean = this match {
- case Static(false) => false
- case _ => true
- }
+ def hasInstance: Boolean = true
/** Returns a string representation of this style. */
- override def toString(): String = this match {
- case Dynamic => "dynamic"
- case Static(false) => "static-class"
- case Static(true) => "static-instance"
- case SuperCall(mix) => "super(" + mix + ")"
- }
+ override def toString(): String
}
- /** Virtual calls */
- case object Dynamic extends InvokeStyle
+ /** Virtual calls.
+ * On JVM, translated to either `invokeinterface` or `invokevirtual`.
+ */
+ case object Dynamic extends InvokeStyle {
+ override def isDynamic = true
+ override def toString(): String = "dynamic"
+ }
/**
- * Special invoke. Static(true) is used for calls to private
- * members.
+ * Special invoke:
+ * Static(true) is used for calls to private members, ie `invokespecial` on JVM.
+ * Static(false) is used for calls to class-level instance-less static methods, ie `invokestatic` on JVM.
*/
- case class Static(onInstance: Boolean) extends InvokeStyle
+ case class Static(onInstance: Boolean) extends InvokeStyle {
+ override def isStatic = true
+ override def hasInstance = onInstance
+ override def toString(): String = {
+ if(onInstance) "static-instance"
+ else "static-class"
+ }
+ }
- /** Call through super[mix]. */
- case class SuperCall(mix: Name) extends InvokeStyle
+ /** Call through super[mix].
+ * On JVM, translated to `invokespecial`.
+ */
+ case class SuperCall(mix: Name) extends InvokeStyle {
+ override def isSuper = true
+ override def toString(): String = { "super(" + mix + ")" }
+ }
// CLR backend
diff --git a/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala b/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala
index f99ac28e9d..72220184d2 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/Primitives.scala
@@ -127,42 +127,61 @@ trait Primitives { self: ICodes =>
/** Returns a string representation of this operation. */
override def toString(): String
+
+ /** used only from GenASM */
+ def opcodeIF(): Int
+
+ /** used only from GenASM */
+ def opcodeIFICMP(): Int
+
}
/** An equality test */
case object EQ extends TestOp {
def negate() = NE
override def toString() = "EQ"
+ override def opcodeIF() = scala.tools.asm.Opcodes.IFEQ
+ override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPEQ
}
/** A non-equality test */
case object NE extends TestOp {
def negate() = EQ
override def toString() = "NE"
+ override def opcodeIF() = scala.tools.asm.Opcodes.IFNE
+ override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPNE
}
/** A less-than test */
case object LT extends TestOp {
def negate() = GE
override def toString() = "LT"
+ override def opcodeIF() = scala.tools.asm.Opcodes.IFLT
+ override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPLT
}
/** A greater-than-or-equal test */
case object GE extends TestOp {
def negate() = LT
override def toString() = "GE"
+ override def opcodeIF() = scala.tools.asm.Opcodes.IFGE
+ override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPGE
}
/** A less-than-or-equal test */
case object LE extends TestOp {
def negate() = GT
override def toString() = "LE"
+ override def opcodeIF() = scala.tools.asm.Opcodes.IFLE
+ override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPLE
}
/** A greater-than test */
case object GT extends TestOp {
def negate() = LE
override def toString() = "GT"
+ override def opcodeIF() = scala.tools.asm.Opcodes.IFGT
+ override def opcodeIFICMP() = scala.tools.asm.Opcodes.IF_ICMPGT
}
/** This class represents an arithmetic operation. */
diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
index 2ff0c1926c..1ec2cf017a 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala
@@ -44,7 +44,7 @@ trait TypeKinds { self: ICodes =>
}
/** Reverse map for toType */
private lazy val reversePrimitiveMap: Map[TypeKind, Symbol] =
- primitiveTypeMap map (_.swap) toMap
+ (primitiveTypeMap map (_.swap)).toMap
/** This class represents a type kind. Type kinds
* represent the types that the VM know (or the ICode
@@ -142,7 +142,7 @@ trait TypeKinds { self: ICodes =>
def lub0(tk1: TypeKind, tk2: TypeKind): Type = beforeUncurry {
import definitions._
val tp = global.lub(List(tk1.toType, tk2.toType))
- val (front, rest) = tp.parents span (_.typeSymbol.hasTraitFlag)
+ val (front, rest) = tp.parents span (_.typeSymbol.isTrait)
if (front.isEmpty || rest.isEmpty || rest.head.typeSymbol == ObjectClass) tp
else rest.head
@@ -420,7 +420,7 @@ trait TypeKinds { self: ICodes =>
// between "object PackratParsers$class" and "trait PackratParsers"
if (sym.isImplClass) {
// pos/spec-List.scala is the sole failure if we don't check for NoSymbol
- val traitSym = sym.owner.info.decl(nme.interfaceName(sym.name))
+ val traitSym = sym.owner.info.decl(tpnme.interfaceName(sym.name))
if (traitSym != NoSymbol)
return REFERENCE(traitSym)
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
index f5be82a776..4427da92c8 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala
@@ -566,8 +566,8 @@ abstract class CopyPropagation {
method.blocks map { b =>
"\nIN(%s):\t Bindings: %s".format(b.label, in(b).bindings) +
"\nIN(%s):\t Stack: %s".format(b.label, in(b).stack)
- } mkString
- )
+ }
+ ).mkString
} /* class CopyAnalysis */
}
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
index 49f5b51d51..5f261ba05e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/Liveness.scala
@@ -97,6 +97,6 @@ abstract class Liveness {
}
}
override def toString() =
- method.blocks map (b => "\nlive-in(%s)=%s\nlive-out(%s)=%s".format(b, in(b), b, out(b))) mkString
+ (method.blocks map (b => "\nlive-in(%s)=%s\nlive-out(%s)=%s".format(b, in(b), b, out(b)))).mkString
} /* Liveness analysis */
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
index c217869a48..ff68aba845 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala
@@ -6,13 +6,13 @@
package scala.tools.nsc
package backend.jvm
-import ch.epfl.lamp.fjbg._
import java.io.{ DataOutputStream, FileOutputStream, OutputStream, File => JFile }
import scala.tools.nsc.io._
import scala.tools.nsc.util.ScalaClassLoader
import scala.tools.util.JavapClass
import java.util.jar.{ JarEntry, JarOutputStream, Attributes }
import Attributes.Name
+import language.postfixOps
/** For the last mile: turning generated bytecode in memory into
* something you can use. Has implementations for writing to class
@@ -25,19 +25,19 @@ trait BytecodeWriters {
private def outputDirectory(sym: Symbol): AbstractFile = (
settings.outputDirs.outputDirFor(beforeFlatten(sym.sourceFile))
)
- private def getFile(base: AbstractFile, cls: JClass, suffix: String): AbstractFile = {
+ private def getFile(base: AbstractFile, /*cls.getName()*/ clsName: String, suffix: String): AbstractFile = {
var dir = base
- val pathParts = cls.getName().split("[./]").toList
+ val pathParts = clsName.split("[./]").toList
for (part <- pathParts.init) {
dir = dir.subdirectoryNamed(part)
}
dir.fileNamed(pathParts.last + suffix)
}
- private def getFile(sym: Symbol, cls: JClass, suffix: String): AbstractFile =
- getFile(outputDirectory(sym), cls, suffix)
+ private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
+ getFile(outputDirectory(sym), clsName, suffix)
trait BytecodeWriter {
- def writeClass(label: String, jclass: JClass, sym: Symbol): Unit
+ def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol): Unit
def close(): Unit = ()
}
@@ -48,11 +48,11 @@ trait BytecodeWriters {
)
val writer = new Jar(jfile).jarWriter(jarMainAttrs: _*)
- def writeClass(label: String, jclass: JClass, sym: Symbol) {
- val path = jclass.getName + ".class"
+ def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
+ val path = jclassName + ".class"
val out = writer.newOutputStream(path)
- try jclass writeTo out
+ try out.write(jclassBytes, 0, jclassBytes.length)
finally out.flush()
informProgress("added " + label + path + " to jar")
@@ -72,11 +72,11 @@ trait BytecodeWriters {
try javap(Seq("-verbose", "dummy")) foreach (_.show())
finally pw.close()
}
- abstract override def writeClass(label: String, jclass: JClass, sym: Symbol) {
- super.writeClass(label, jclass, sym)
+ abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
+ super.writeClass(label, jclassName, jclassBytes, sym)
- val bytes = getFile(sym, jclass, ".class").toByteArray
- val segments = jclass.getName().split("[./]")
+ val bytes = getFile(sym, jclassName, ".class").toByteArray
+ val segments = jclassName.split("[./]")
val javapFile = segments.foldLeft(baseDir: Path)(_ / _) changeExtension "javap" toFile;
javapFile.parent.createDirectory()
@@ -85,11 +85,11 @@ trait BytecodeWriters {
}
trait ClassBytecodeWriter extends BytecodeWriter {
- def writeClass(label: String, jclass: JClass, sym: Symbol) {
- val outfile = getFile(sym, jclass, ".class")
+ def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
+ val outfile = getFile(sym, jclassName, ".class")
val outstream = new DataOutputStream(outfile.bufferedOutput)
- try jclass writeTo outstream
+ try outstream.write(jclassBytes, 0, jclassBytes.length)
finally outstream.close()
informProgress("wrote '" + label + "' to " + outfile)
}
@@ -98,15 +98,15 @@ trait BytecodeWriters {
trait DumpBytecodeWriter extends BytecodeWriter {
val baseDir = Directory(settings.Ydumpclasses.value).createDirectory()
- abstract override def writeClass(label: String, jclass: JClass, sym: Symbol) {
- super.writeClass(label, jclass, sym)
+ abstract override def writeClass(label: String, jclassName: String, jclassBytes: Array[Byte], sym: Symbol) {
+ super.writeClass(label, jclassName, jclassBytes, sym)
- val pathName = jclass.getName()
+ val pathName = jclassName
var dumpFile = pathName.split("[./]").foldLeft(baseDir: Path) (_ / _) changeExtension "class" toFile;
dumpFile.parent.createDirectory()
val outstream = new DataOutputStream(new FileOutputStream(dumpFile.path))
- try jclass writeTo outstream
+ try outstream.write(jclassBytes, 0, jclassBytes.length)
finally outstream.close()
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
new file mode 100644
index 0000000000..aa8f469513
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala
@@ -0,0 +1,3288 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.tools.nsc
+package backend.jvm
+
+import java.nio.ByteBuffer
+import scala.collection.{ mutable, immutable }
+import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer }
+import scala.tools.nsc.symtab._
+import scala.tools.nsc.io.AbstractFile
+
+import scala.tools.asm
+import asm.Label
+
+/**
+ * @author Iulian Dragos (version 1.0, FJBG-based implementation)
+ * @author Miguel Garcia (version 2.0, ASM-based implementation)
+ *
+ * Documentation at http://lamp.epfl.ch/~magarcia/ScalaCompilerCornerReloaded/2012Q2/GenASM.pdf
+ */
+abstract class GenASM extends SubComponent with BytecodeWriters {
+ import global._
+ import icodes._
+ import icodes.opcodes._
+ import definitions._
+
+ val phaseName = "jvm"
+
+ /** Create a new phase */
+ override def newPhase(p: Phase): Phase = new AsmPhase(p)
+
+ private def outputDirectory(sym: Symbol): AbstractFile =
+ settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile)
+
+ private def getFile(base: AbstractFile, clsName: String, suffix: String): AbstractFile = {
+ var dir = base
+ val pathParts = clsName.split("[./]").toList
+ for (part <- pathParts.init) {
+ dir = dir.subdirectoryNamed(part)
+ }
+ dir.fileNamed(pathParts.last + suffix)
+ }
+ private def getFile(sym: Symbol, clsName: String, suffix: String): AbstractFile =
+ getFile(outputDirectory(sym), clsName, suffix)
+
+ /** JVM code generation phase
+ */
+ class AsmPhase(prev: Phase) extends ICodePhase(prev) {
+ def name = phaseName
+ override def erasedTypes = true
+ def apply(cls: IClass) = sys.error("no implementation")
+
+ val BeanInfoAttr = definitions.getRequiredClass("scala.beans.BeanInfo")
+
+ def isJavaEntryPoint(icls: IClass) = {
+ val sym = icls.symbol
+ def fail(msg: String, pos: Position = sym.pos) = {
+ icls.cunit.warning(sym.pos,
+ sym.name + " has a main method with parameter type Array[String], but " + sym.fullName('.') + " will not be a runnable program.\n" +
+ " Reason: " + msg
+ // TODO: make this next claim true, if possible
+ // by generating valid main methods as static in module classes
+ // not sure what the jvm allows here
+ // + " You can still run the program by calling it as " + sym.javaSimpleName + " instead."
+ )
+ false
+ }
+ def failNoForwarder(msg: String) = {
+ fail(msg + ", which means no static forwarder can be generated.\n")
+ }
+ val possibles = if (sym.hasModuleFlag) (sym.tpe nonPrivateMember nme.main).alternatives else Nil
+ val hasApproximate = possibles exists { m =>
+ m.info match {
+ case MethodType(p :: Nil, _) => p.tpe.typeSymbol == ArrayClass
+ case _ => false
+ }
+ }
+ // At this point it's a module with a main-looking method, so either succeed or warn that it isn't.
+ hasApproximate && {
+ // Before erasure so we can identify generic mains.
+ beforeErasure {
+ val companion = sym.linkedClassOfClass
+ val companionMain = companion.tpe.member(nme.main)
+
+ if (hasJavaMainMethod(companion))
+ failNoForwarder("companion contains its own main method")
+ else if (companion.tpe.member(nme.main) != NoSymbol)
+ // this is only because forwarders aren't smart enough yet
+ failNoForwarder("companion contains its own main method (implementation restriction: no main is allowed, regardless of signature)")
+ else if (companion.isTrait)
+ failNoForwarder("companion is a trait")
+ // Now either succeeed, or issue some additional warnings for things which look like
+ // attempts to be java main methods.
+ else possibles exists { m =>
+ m.info match {
+ case PolyType(_, _) =>
+ fail("main methods cannot be generic.")
+ case MethodType(params, res) =>
+ if (res.typeSymbol :: params exists (_.isAbstractType))
+ fail("main methods cannot refer to type parameters or abstract types.", m.pos)
+ else
+ isJavaMainMethod(m) || fail("main method must have exact signature (Array[String])Unit", m.pos)
+ case tp =>
+ fail("don't know what this is: " + tp, m.pos)
+ }
+ }
+ }
+ }
+ }
+
+ private def initBytecodeWriter(entryPoints: List[IClass]): BytecodeWriter = {
+ settings.outputDirs.getSingleOutput match {
+ case Some(f) if f hasExtension "jar" =>
+ // If no main class was specified, see if there's only one
+ // entry point among the classes going into the jar.
+ if (settings.mainClass.isDefault) {
+ entryPoints map (_.symbol fullName '.') match {
+ case Nil =>
+ log("No Main-Class designated or discovered.")
+ case name :: Nil =>
+ log("Unique entry point: setting Main-Class to " + name)
+ settings.mainClass.value = name
+ case names =>
+ log("No Main-Class due to multiple entry points:\n " + names.mkString("\n "))
+ }
+ }
+ else log("Main-Class was specified: " + settings.mainClass.value)
+
+ new DirectToJarfileWriter(f.file)
+
+ case _ =>
+ if (settings.Ygenjavap.isDefault) {
+ if(settings.Ydumpclasses.isDefault)
+ new ClassBytecodeWriter { }
+ else
+ new ClassBytecodeWriter with DumpBytecodeWriter { }
+ }
+ else new ClassBytecodeWriter with JavapBytecodeWriter { }
+
+ // TODO A ScalapBytecodeWriter could take asm.util.Textifier as starting point.
+ // Three areas where javap ouput is less than ideal (e.g. when comparing versions of the same classfile) are:
+ // (a) unreadable pickle;
+ // (b) two constant pools, while having identical contents, are displayed differently due to physical layout.
+ // (c) stack maps (classfile version 50 and up) are displayed in encoded form by javap, their expansion makes more sense instead.
+ }
+ }
+
+ override def run() {
+
+ if (settings.debug.value)
+ inform("[running phase " + name + " on icode]")
+
+ if (settings.Xdce.value)
+ for ((sym, cls) <- icodes.classes if inliner.isClosureClass(sym) && !deadCode.liveClosures(sym))
+ icodes.classes -= sym
+
+ // For predictably ordered error messages.
+ var sortedClasses = classes.values.toList sortBy ("" + _.symbol.fullName)
+
+ debuglog("Created new bytecode generator for " + classes.size + " classes.")
+ val bytecodeWriter = initBytecodeWriter(sortedClasses filter isJavaEntryPoint)
+ val plainCodeGen = new JPlainBuilder(bytecodeWriter)
+ val mirrorCodeGen = new JMirrorBuilder(bytecodeWriter)
+ val beanInfoCodeGen = new JBeanInfoBuilder(bytecodeWriter)
+
+ while(!sortedClasses.isEmpty) {
+ val c = sortedClasses.head
+
+ if (isStaticModule(c.symbol) && isTopLevelModule(c.symbol)) {
+ if (c.symbol.companionClass == NoSymbol) {
+ mirrorCodeGen.genMirrorClass(c.symbol, c.cunit)
+ } else {
+ log("No mirror class for module with linked class: " + c.symbol.fullName)
+ }
+ }
+
+ plainCodeGen.genClass(c)
+
+ if (c.symbol hasAnnotation BeanInfoAttr) {
+ beanInfoCodeGen.genBeanInfoClass(c)
+ }
+
+ sortedClasses = sortedClasses.tail
+ classes -= c.symbol // GC opportunity
+ }
+
+ bytecodeWriter.close()
+ classes.clear()
+ reverseJavaName.clear()
+
+ /* don't javaNameCache.clear() because that causes the following tests to fail:
+ * test/files/run/macro-repl-dontexpand.scala
+ * test/files/jvm/interpreter.scala
+ * TODO but why? what use could javaNameCache possibly see once GenJVM is over?
+ */
+
+ /* TODO After emitting all class files (e.g., in a separate compiler phase) ASM can perform bytecode verification:
+ *
+ * (1) call the asm.util.CheckAdapter.verify() overload:
+ * public static void verify(ClassReader cr, ClassLoader loader, boolean dump, PrintWriter pw)
+ *
+ * (2) passing a custom ClassLoader to verify inter-dependent classes.
+ *
+ * Alternatively, an offline-bytecode verifier could be used (e.g. Maxine brings one as separate tool).
+ */
+
+ } // end of AsmPhase.run()
+
+ } // end of class AsmPhase
+
+ var pickledBytes = 0 // statistics
+
+ // Don't put this in per run caches. Contains entries for classes as well as members.
+ val javaNameCache = new mutable.WeakHashMap[Symbol, Name]() ++= List(
+ NothingClass -> binarynme.RuntimeNothing,
+ RuntimeNothingClass -> binarynme.RuntimeNothing,
+ NullClass -> binarynme.RuntimeNull,
+ RuntimeNullClass -> binarynme.RuntimeNull
+ )
+
+ // unlike javaNameCache, reverseJavaName contains entries only for class symbols and their internal names.
+ val reverseJavaName = mutable.Map.empty[String, Symbol] ++= List(
+ binarynme.RuntimeNothing.toString() -> NothingClass, // neither RuntimeNothingClass nor RuntimeNullClass belong to the co-domain of this map.
+ binarynme.RuntimeNull.toString() -> NullClass
+ )
+
+ private def mkFlags(args: Int*) = args.foldLeft(0)(_ | _)
+
+ @inline final private def hasPublicBitSet(flags: Int) = ((flags & asm.Opcodes.ACC_PUBLIC) != 0)
+
+ @inline final private def isRemote(s: Symbol) = (s hasAnnotation RemoteAttr)
+
+ /**
+ * Return the Java modifiers for the given symbol.
+ * Java modifiers for classes:
+ * - public, abstract, final, strictfp (not used)
+ * for interfaces:
+ * - the same as for classes, without 'final'
+ * for fields:
+ * - public, private (*)
+ * - static, final
+ * for methods:
+ * - the same as for fields, plus:
+ * - abstract, synchronized (not used), strictfp (not used), native (not used)
+ *
+ * (*) protected cannot be used, since inner classes 'see' protected members,
+ * and they would fail verification after lifted.
+ */
+ def javaFlags(sym: Symbol): Int = {
+ // constructors of module classes should be private
+ // PP: why are they only being marked private at this stage and not earlier?
+ val privateFlag =
+ sym.isPrivate || (sym.isPrimaryConstructor && isTopLevelModule(sym.owner))
+
+ // Final: the only fields which can receive ACC_FINAL are eager vals.
+ // Neither vars nor lazy vals can, because:
+ //
+ // Source: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.3
+ // "Another problem is that the specification allows aggressive
+ // optimization of final fields. Within a thread, it is permissible to
+ // reorder reads of a final field with those modifications of a final
+ // field that do not take place in the constructor."
+ //
+ // A var or lazy val which is marked final still has meaning to the
+ // scala compiler. The word final is heavily overloaded unfortunately;
+ // for us it means "not overridable". At present you can't override
+ // vars regardless; this may change.
+ //
+ // The logic does not check .isFinal (which checks flags for the FINAL flag,
+ // and includes symbols marked lateFINAL) instead inspecting rawflags so
+ // we can exclude lateFINAL. Such symbols are eligible for inlining, but to
+ // avoid breaking proxy software which depends on subclassing, we do not
+ // emit ACC_FINAL.
+ val finalFlag = (
+ ((sym.rawflags & (Flags.FINAL | Flags.MODULE)) != 0)
+ && !sym.enclClass.isInterface
+ && !sym.isClassConstructor
+ && !sym.isMutable // lazy vals and vars both
+ )
+
+ import asm.Opcodes._
+ mkFlags(
+ if (privateFlag) ACC_PRIVATE else ACC_PUBLIC,
+ if (sym.isDeferred || sym.hasAbstractFlag) ACC_ABSTRACT else 0,
+ if (sym.isInterface) ACC_INTERFACE else 0,
+ if (finalFlag) ACC_FINAL else 0,
+ if (sym.isStaticMember) ACC_STATIC else 0,
+ if (sym.isBridge) ACC_BRIDGE | ACC_SYNTHETIC else 0,
+ if (sym.isClass && !sym.isInterface) ACC_SUPER else 0,
+ if (sym.isVarargsMethod) ACC_VARARGS else 0,
+ if (sym.hasFlag(Flags.SYNCHRONIZED)) ACC_SYNCHRONIZED else 0
+ )
+ }
+
+ def javaFieldFlags(sym: Symbol) = {
+ javaFlags(sym) | mkFlags(
+ if (sym hasAnnotation TransientAttr) asm.Opcodes.ACC_TRANSIENT else 0,
+ if (sym hasAnnotation VolatileAttr) asm.Opcodes.ACC_VOLATILE else 0,
+ if (sym.isMutable) 0 else asm.Opcodes.ACC_FINAL
+ )
+ }
+
+ def isTopLevelModule(sym: Symbol): Boolean =
+ afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass }
+
+ def isStaticModule(sym: Symbol): Boolean = {
+ sym.isModuleClass && !sym.isImplClass && !sym.isLifted
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // finding the least upper bound in agreement with the bytecode verifier (given two internal names handed by ASM)
+ // Background:
+ // http://gallium.inria.fr/~xleroy/publi/bytecode-verification-JAR.pdf
+ // http://comments.gmane.org/gmane.comp.java.vm.languages/2293
+ // https://issues.scala-lang.org/browse/SI-3872
+ // -----------------------------------------------------------------------------------------
+
+ /**
+ * Given an internal name (eg "java/lang/Integer") returns the class symbol for it.
+ *
+ * Better not to need this method (an example where control flow arrives here is welcome).
+ * This method is invoked only upon both (1) and (2) below happening:
+ * (1) providing an asm.ClassWriter with an internal name by other means than javaName()
+ * (2) forgetting to track the corresponding class-symbol in reverseJavaName.
+ *
+ * (The first item is already unlikely because we rely on javaName()
+ * to do the bookkeeping for entries that should go in innerClassBuffer.)
+ *
+ * (We could do completely without this method at the expense of computing stack-map-frames ourselves and
+ * invoking visitFrame(), but that would require another pass over all instructions.)
+ *
+ * Right now I can't think of any invocation of visitSomething() on MethodVisitor
+ * where we hand an internal name not backed by a reverseJavaName.
+ * However, I'm leaving this note just in case any such oversight is discovered.
+ */
+ def inameToSymbol(iname: String): Symbol = {
+ val name = global.newTypeName(iname)
+ val res0 =
+ if (nme.isModuleName(name)) definitions.getModule(nme.stripModuleSuffix(name))
+ else definitions.getClassByName(name.replace('/', '.')) // TODO fails for inner classes (but this hasn't been tested).
+ assert(res0 != NoSymbol)
+ val res = jsymbol(res0)
+ res
+ }
+
+ def jsymbol(sym: Symbol): Symbol = {
+ if(sym.isJavaDefined && sym.isModuleClass) sym.linkedClassOfClass
+ else if(sym.isModule) sym.moduleClass
+ else sym // we track only module-classes and plain-classes
+ }
+
+ private def superClasses(s: Symbol): List[Symbol] = {
+ assert(!s.isInterface)
+ s.superClass match {
+ case NoSymbol => List(s)
+ case sc => s :: superClasses(sc)
+ }
+ }
+
+ private def firstCommonSuffix(as: List[Symbol], bs: List[Symbol]): Symbol = {
+ assert(!(as contains NoSymbol))
+ assert(!(bs contains NoSymbol))
+ var chainA = as
+ var chainB = bs
+ var fcs: Symbol = NoSymbol
+ do {
+ if (chainB contains chainA.head) fcs = chainA.head
+ else if (chainA contains chainB.head) fcs = chainB.head
+ else {
+ chainA = chainA.tail
+ chainB = chainB.tail
+ }
+ } while(fcs == NoSymbol)
+ fcs
+ }
+
+ @inline final private def jvmWiseLUB(a: Symbol, b: Symbol): Symbol = {
+
+ assert(a.isClass)
+ assert(b.isClass)
+
+ val res = Pair(a.isInterface, b.isInterface) match {
+ case (true, true) =>
+ global.lub(List(a.tpe, b.tpe)).typeSymbol // TODO assert == firstCommonSuffix of resp. parents
+ case (true, false) =>
+ if(b isSubClass a) a else ObjectClass
+ case (false, true) =>
+ if(a isSubClass b) b else ObjectClass
+ case _ =>
+ firstCommonSuffix(superClasses(a), superClasses(b))
+ }
+ assert(res != NoSymbol)
+ res
+ }
+
+ /* The internal name of the least common ancestor of the types given by inameA and inameB.
+ It's what ASM needs to know in order to compute stack map frames, http://asm.ow2.org/doc/developer-guide.html#controlflow */
+ def getCommonSuperClass(inameA: String, inameB: String): String = {
+ val a = reverseJavaName.getOrElseUpdate(inameA, inameToSymbol(inameA))
+ val b = reverseJavaName.getOrElseUpdate(inameB, inameToSymbol(inameB))
+
+ // global.lub(List(a.tpe, b.tpe)).typeSymbol.javaBinaryName.toString()
+ // icodes.lub(icodes.toTypeKind(a.tpe), icodes.toTypeKind(b.tpe)).toType
+ val lcaSym = jvmWiseLUB(a, b)
+ val lcaName = lcaSym.javaBinaryName.toString // don't call javaName because that side-effects innerClassBuffer.
+ val oldsym = reverseJavaName.put(lcaName, lcaSym)
+ assert(oldsym.isEmpty || (oldsym.get == lcaSym), "somehow we're not managing to compute common-super-class for ASM consumption")
+ assert(lcaName != "scala/Any")
+
+ lcaName // TODO ASM caches the answer during the lifetime of a ClassWriter. We outlive that. Do some caching.
+ }
+
+ class CClassWriter(flags: Int) extends asm.ClassWriter(flags) {
+ override def getCommonSuperClass(iname1: String, iname2: String): String = {
+ GenASM.this.getCommonSuperClass(iname1, iname2)
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // constants
+ // -----------------------------------------------------------------------------------------
+
+ private val classfileVersion: Int = settings.target.value match {
+ case "jvm-1.5" => asm.Opcodes.V1_5
+ case "jvm-1.5-asm" => asm.Opcodes.V1_5
+ case "jvm-1.6" => asm.Opcodes.V1_6
+ case "jvm-1.7" => asm.Opcodes.V1_7
+ }
+
+ private val majorVersion: Int = (classfileVersion & 0xFF)
+
+ private val extraProc: Int = mkFlags(
+ asm.ClassWriter.COMPUTE_MAXS,
+ if(majorVersion >= 50) asm.ClassWriter.COMPUTE_FRAMES else 0
+ )
+
+ val JAVA_LANG_OBJECT = asm.Type.getObjectType("java/lang/Object")
+ val JAVA_LANG_STRING = asm.Type.getObjectType("java/lang/String")
+
+ /** basic functionality for class file building */
+ abstract class JBuilder(bytecodeWriter: BytecodeWriter) {
+
+ val EMPTY_JTYPE_ARRAY = Array.empty[asm.Type]
+ val EMPTY_STRING_ARRAY = Array.empty[String]
+
+ val mdesc_arglessvoid = "()V"
+
+ val CLASS_CONSTRUCTOR_NAME = "<clinit>"
+ val INSTANCE_CONSTRUCTOR_NAME = "<init>"
+
+ // -----------------------------------------------------------------------------------------
+ // factory methods
+ // -----------------------------------------------------------------------------------------
+
+ /**
+ * Returns a new ClassWriter for the class given by arguments.
+ *
+ * @param access the class's access flags. This parameter also indicates if the class is deprecated.
+ *
+ * @param name the internal name of the class.
+ *
+ * @param signature the signature of this class. May be <tt>null</tt> if
+ * the class is not a generic one, and does not extend or implement
+ * generic classes or interfaces.
+ *
+ * @param superName the internal of name of the super class. For interfaces,
+ * the super class is {@link Object}. May be <tt>null</tt>, but
+ * only for the {@link Object} class.
+ *
+ * @param interfaces the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ */
+ def createJClass(access: Int, name: String, signature: String, superName: String, interfaces: Array[String]): asm.ClassWriter = {
+ val cw = new CClassWriter(extraProc)
+ cw.visit(classfileVersion,
+ access, name, signature,
+ superName, interfaces)
+
+ cw
+ }
+
+ def createJAttribute(name: String, b: Array[Byte], offset: Int, len: Int): asm.Attribute = {
+ val dest = new Array[Byte](len);
+ System.arraycopy(b, offset, dest, 0, len);
+ new asm.CustomAttr(name, dest)
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // utitilies useful when emitting plain, mirror, and beaninfo classes.
+ // -----------------------------------------------------------------------------------------
+
+ def writeIfNotTooBig(label: String, jclassName: String, jclass: asm.ClassWriter, sym: Symbol) {
+ try {
+ val arr = jclass.toByteArray()
+ bytecodeWriter.writeClass(label, jclassName, arr, sym)
+ } catch {
+ case e: java.lang.RuntimeException if(e.getMessage() == "Class file too large!") =>
+ // TODO check where ASM throws the equivalent of CodeSizeTooBigException
+ log("Skipped class "+jclassName+" because it exceeds JVM limits (it's too big or has methods that are too long).")
+ }
+ }
+
+ /** Specialized array conversion to prevent calling
+ * java.lang.reflect.Array.newInstance via TraversableOnce.toArray
+ */
+ def mkArray(xs: Traversable[asm.Type]): Array[asm.Type] = { val a = new Array[asm.Type](xs.size); xs.copyToArray(a); a }
+ def mkArray(xs: Traversable[String]): Array[String] = { val a = new Array[String](xs.size); xs.copyToArray(a); a }
+
+ // -----------------------------------------------------------------------------------------
+ // Getters for (JVMS 4.2) internal and unqualified names (represented as JType instances).
+ // These getters track behind the scenes the inner classes referred to in the class being emitted,
+ // so as to build the InnerClasses attribute (JVMS 4.7.6) via `addInnerClasses()`
+ // (which also adds as member classes those inner classes that have been declared,
+ // thus also covering the case of inner classes declared but otherwise not referred).
+ // -----------------------------------------------------------------------------------------
+
+ val innerClassBuffer = mutable.LinkedHashSet[Symbol]()
+
+ /** For given symbol return a symbol corresponding to a class that should be declared as inner class.
+ *
+ * For example:
+ * class A {
+ * class B
+ * object C
+ * }
+ *
+ * then method will return:
+ * NoSymbol for A,
+ * the same symbol for A.B (corresponding to A$B class), and
+ * A$C$ symbol for A.C.
+ */
+ def innerClassSymbolFor(s: Symbol): Symbol =
+ if (s.isClass) s else if (s.isModule) s.moduleClass else NoSymbol
+
+ /** Return the a name of this symbol that can be used on the Java platform. It removes spaces from names.
+ *
+ * Special handling:
+ * scala.Nothing erases to scala.runtime.Nothing$
+ * scala.Null erases to scala.runtime.Null$
+ *
+ * This is needed because they are not real classes, and they mean
+ * 'abrupt termination upon evaluation of that expression' or null respectively.
+ * This handling is done already in GenICode, but here we need to remove
+ * references from method signatures to these types, because such classes
+ * cannot exist in the classpath: the type checker will be very confused.
+ */
+ def javaName(sym: Symbol): String = {
+
+ /**
+ * Checks if given symbol corresponds to inner class/object and add it to innerClassBuffer
+ *
+ * Note: This method is called recursively thus making sure that we add complete chain
+ * of inner class all until root class.
+ */
+ def collectInnerClass(s: Symbol): Unit = {
+ // TODO: some beforeFlatten { ... } which accounts for
+ // being nested in parameterized classes (if we're going to selectively flatten.)
+ val x = innerClassSymbolFor(s)
+ if(x ne NoSymbol) {
+ assert(x.isClass, "not an inner-class symbol")
+ val isInner = !x.rawowner.isPackageClass
+ if (isInner) {
+ innerClassBuffer += x
+ collectInnerClass(x.rawowner)
+ }
+ }
+ }
+
+ collectInnerClass(sym)
+
+ var hasInternalName = (sym.isClass || (sym.isModule && !sym.isMethod))
+ val cachedJN = javaNameCache.getOrElseUpdate(sym, {
+ if (hasInternalName) { sym.javaBinaryName }
+ else { sym.javaSimpleName }
+ })
+
+ if(hasInternalName) {
+ val internalName = cachedJN.toString()
+ val trackedSym = jsymbol(sym)
+ reverseJavaName.get(internalName) match {
+ case None =>
+ reverseJavaName.put(internalName, trackedSym)
+ case Some(oldsym) =>
+ assert(List(NothingClass, NullClass).contains(oldsym) || oldsym == trackedSym,
+ "how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name.")
+ }
+ }
+
+ cachedJN.toString
+ }
+
+ def descriptor(t: Type): String = { javaType(t).getDescriptor }
+ def descriptor(k: TypeKind): String = { javaType(k).getDescriptor }
+ def descriptor(s: Symbol): String = { javaType(s).getDescriptor }
+
+ def javaType(tk: TypeKind): asm.Type = {
+ if(tk.isValueType) {
+ if(tk.isIntSizedType) {
+ (tk: @unchecked) match {
+ case BOOL => asm.Type.BOOLEAN_TYPE
+ case BYTE => asm.Type.BYTE_TYPE
+ case SHORT => asm.Type.SHORT_TYPE
+ case CHAR => asm.Type.CHAR_TYPE
+ case INT => asm.Type.INT_TYPE
+ }
+ } else {
+ (tk: @unchecked) match {
+ case UNIT => asm.Type.VOID_TYPE
+ case LONG => asm.Type.LONG_TYPE
+ case FLOAT => asm.Type.FLOAT_TYPE
+ case DOUBLE => asm.Type.DOUBLE_TYPE
+ }
+ }
+ } else {
+ assert(!tk.isBoxedType, tk) // documentation (BOXED matches none below anyway)
+ (tk: @unchecked) match {
+ case REFERENCE(cls) => asm.Type.getObjectType(javaName(cls))
+ case ARRAY(elem) => javaArrayType(javaType(elem))
+ }
+ }
+ }
+
+ def javaType(t: Type): asm.Type = javaType(toTypeKind(t))
+
+ def javaType(s: Symbol): asm.Type = {
+ if (s.isMethod) {
+ val resT: asm.Type = if (s.isClassConstructor) asm.Type.VOID_TYPE else javaType(s.tpe.resultType);
+ asm.Type.getMethodType( resT, (s.tpe.paramTypes map javaType): _* )
+ } else { javaType(s.tpe) }
+ }
+
+ def javaArrayType(elem: asm.Type): asm.Type = { asm.Type.getObjectType("[" + elem.getDescriptor) }
+
+ def isDeprecated(sym: Symbol): Boolean = { sym.annotations exists (_ matches definitions.DeprecatedAttr) }
+
+ } // end of class JBuilder
+
+
+ /** functionality for building plain and mirror classes */
+ abstract class JCommonBuilder(bytecodeWriter: BytecodeWriter) extends JBuilder(bytecodeWriter) {
+
+ // -----------------------------------------------------------------------------------------
+ // more constants
+ // -----------------------------------------------------------------------------------------
+
+ val INNER_CLASSES_FLAGS =
+ (asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED |
+ asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_FINAL |
+ asm.Opcodes.ACC_INTERFACE | asm.Opcodes.ACC_ABSTRACT)
+
+ val PublicStatic = asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_STATIC
+ val PublicStaticFinal = asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_FINAL
+
+ val strMODULE_INSTANCE_FIELD = nme.MODULE_INSTANCE_FIELD.toString
+
+ // -----------------------------------------------------------------------------------------
+ // Custom attribute (JVMS 4.7.1) "ScalaSig" used as marker only
+ // i.e., the pickle is contained in a custom annotation, see:
+ // (1) `addAnnotations()`,
+ // (2) SID # 10 (draft) - Storage of pickled Scala signatures in class files, http://www.scala-lang.org/sid/10
+ // (3) SID # 5 - Internals of Scala Annotations, http://www.scala-lang.org/sid/5
+ // That annotation in turn is not related to the "java-generic-signature" (JVMS 4.7.9)
+ // other than both ending up encoded as attributes (JVMS 4.7)
+ // (with the caveat that the "ScalaSig" attribute is associated to some classes,
+ // while the "Signature" attribute can be associated to classes, methods, and fields.)
+ // -----------------------------------------------------------------------------------------
+
+ val versionPickle = {
+ val vp = new PickleBuffer(new Array[Byte](16), -1, 0)
+ assert(vp.writeIndex == 0, vp)
+ vp writeNat PickleFormat.MajorVersion
+ vp writeNat PickleFormat.MinorVersion
+ vp writeNat 0
+ vp
+ }
+
+ def pickleMarkerLocal = {
+ createJAttribute(tpnme.ScalaSignatureATTR.toString, versionPickle.bytes, 0, versionPickle.writeIndex)
+ }
+
+ def pickleMarkerForeign = {
+ createJAttribute(tpnme.ScalaATTR.toString, new Array[Byte](0), 0, 0)
+ }
+
+ /** Returns a ScalaSignature annotation if it must be added to this class, none otherwise.
+ * This annotation must be added to the class' annotations list when generating them.
+ *
+ * Depending on whether the returned option is defined, it adds to `jclass` one of:
+ * (a) the ScalaSig marker attribute
+ * (indicating that a scala-signature-annotation aka pickle is present in this class); or
+ * (b) the Scala marker attribute
+ * (indicating that a scala-signature-annotation aka pickle is to be found in another file).
+ *
+ *
+ * @param jclassName The class file that is being readied.
+ * @param sym The symbol for which the signature has been entered in the symData map.
+ * This is different than the symbol
+ * that is being generated in the case of a mirror class.
+ * @return An option that is:
+ * - defined and contains an AnnotationInfo of the ScalaSignature type,
+ * instantiated with the pickle signature for sym.
+ * - empty if the jclass/sym pair must not contain a pickle.
+ *
+ */
+ def getAnnotPickle(jclassName: String, sym: Symbol): Option[AnnotationInfo] = {
+ currentRun.symData get sym match {
+ case Some(pickle) if !nme.isModuleName(newTermName(jclassName)) =>
+ val scalaAnnot = {
+ val sigBytes = ScalaSigBytes(pickle.bytes.take(pickle.writeIndex))
+ AnnotationInfo(sigBytes.sigAnnot, Nil, List((nme.bytes, sigBytes)))
+ }
+ pickledBytes += pickle.writeIndex
+ currentRun.symData -= sym
+ currentRun.symData -= sym.companionSymbol
+ Some(scalaAnnot)
+ case _ =>
+ None
+ }
+ }
+
+ /**
+ * Quoting from JVMS 4.7.5 The Exceptions Attribute
+ * "The Exceptions attribute indicates which checked exceptions a method may throw.
+ * There may be at most one Exceptions attribute in each method_info structure."
+ *
+ * The contents of that attribute are determined by the `String[] exceptions` argument to ASM's ClassVisitor.visitMethod()
+ * This method returns such list of internal names.
+ *
+ */
+ def getExceptions(excs: List[AnnotationInfo]): List[String] = {
+ for (AnnotationInfo(tp, List(exc), _) <- excs.distinct if tp.typeSymbol == ThrowsClass)
+ yield {
+ val Literal(const) = exc
+ javaName(const.typeValue.typeSymbol)
+ }
+ }
+
+ /** Whether an annotation should be emitted as a Java annotation
+ * .initialize: if 'annot' is read from pickle, atp might be un-initialized
+ */
+ private def shouldEmitAnnotation(annot: AnnotationInfo) =
+ annot.symbol.initialize.isJavaDefined &&
+ annot.matches(ClassfileAnnotationClass) &&
+ annot.args.isEmpty &&
+ !annot.matches(DeprecatedAttr)
+
+ // @M don't generate java generics sigs for (members of) implementation
+ // classes, as they are monomorphic (TODO: ok?)
+ private def needsGenericSignature(sym: Symbol) = !(
+ // PP: This condition used to include sym.hasExpandedName, but this leads
+ // to the total loss of generic information if a private member is
+ // accessed from a closure: both the field and the accessor were generated
+ // without it. This is particularly bad because the availability of
+ // generic information could disappear as a consequence of a seemingly
+ // unrelated change.
+ sym.isSynthetic
+ || sym.isLiftedMethod
+ || sym.isBridge
+ || (sym.ownerChain exists (_.isImplClass))
+ )
+
+ def getCurrentCUnit(): CompilationUnit
+
+ /** @return
+ * - `null` if no Java signature is to be added (`null` is what ASM expects in these cases).
+ * - otherwise the signature in question
+ */
+ def getGenericSignature(sym: Symbol, owner: Symbol): String = {
+
+ if (!needsGenericSignature(sym)) { return null }
+
+ val memberTpe = beforeErasure(owner.thisType.memberInfo(sym))
+
+ val jsOpt: Option[String] = erasure.javaSig(sym, memberTpe)
+ if (jsOpt.isEmpty) { return null }
+
+ val sig = jsOpt.get
+ log(sig) // This seems useful enough in the general case.
+
+ def wrap(op: => Unit) = {
+ try { op; true }
+ catch { case _ => false }
+ }
+
+ if (settings.Xverify.value) {
+ // Run the signature parser to catch bogus signatures.
+ val isValidSignature = wrap {
+ // Alternative: scala.tools.reflect.SigParser (frontend to sun.reflect.generics.parser.SignatureParser)
+ import scala.tools.asm.util.SignatureChecker
+ if (sym.isMethod) { SignatureChecker checkMethodSignature sig } // requires asm-util.jar
+ else if (sym.isTerm) { SignatureChecker checkFieldSignature sig }
+ else { SignatureChecker checkClassSignature sig }
+ }
+
+ if(!isValidSignature) {
+ getCurrentCUnit().warning(sym.pos,
+ """|compiler bug: created invalid generic signature for %s in %s
+ |signature: %s
+ |if this is reproducible, please report bug at https://issues.scala-lang.org/
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig))
+ return null
+ }
+ }
+
+ if ((settings.check containsName phaseName)) {
+ val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe))
+ val bytecodeTpe = owner.thisType.memberInfo(sym)
+ if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym)(normalizedTpe) =:= bytecodeTpe)) {
+ getCurrentCUnit().warning(sym.pos,
+ """|compiler bug: created generic signature for %s in %s that does not conform to its erasure
+ |signature: %s
+ |original type: %s
+ |normalized type: %s
+ |erasure type: %s
+ |if this is reproducible, please report bug at http://issues.scala-lang.org/
+ """.trim.stripMargin.format(sym, sym.owner.skipPackageObject.fullName, sig, memberTpe, normalizedTpe, bytecodeTpe))
+ return null
+ }
+ }
+
+ sig
+ }
+
+ def ubytesToCharArray(bytes: Array[Byte]): Array[Char] = {
+ val ca = new Array[Char](bytes.size)
+ var idx = 0
+ while(idx < bytes.size) {
+ val b: Byte = bytes(idx)
+ assert((b & ~0x7f) == 0)
+ ca(idx) = b.asInstanceOf[Char]
+ idx += 1
+ }
+
+ ca
+ }
+
+ // TODO this method isn't exercised during bootstrapping. Open question: is it bug free?
+ private def arrEncode(sb: ScalaSigBytes): Array[String] = {
+ var strs: List[String] = Nil
+ val bSeven: Array[Byte] = sb.sevenBitsMayBeZero
+ // chop into slices of at most 65535 bytes, counting 0x00 as taking two bytes (as per JVMS 4.4.7 The CONSTANT_Utf8_info Structure)
+ var prevOffset = 0
+ var offset = 0
+ var encLength = 0
+ while(offset < bSeven.size) {
+ val newEncLength = encLength.toLong + (if(bSeven(offset) == 0) 2 else 1)
+ if(newEncLength > 65535) {
+ val ba = bSeven.slice(prevOffset, offset)
+ strs ::= new java.lang.String(ubytesToCharArray(ba))
+ encLength = 0
+ prevOffset = offset
+ } else {
+ encLength += 1
+ offset += 1
+ }
+ }
+ if(prevOffset < offset) {
+ assert(offset == bSeven.length)
+ val ba = bSeven.slice(prevOffset, offset)
+ strs ::= new java.lang.String(ubytesToCharArray(ba))
+ }
+ assert(strs.size > 1, "encode instead as one String via strEncode()") // TODO too strict?
+ strs.reverse.toArray
+ }
+
+ private def strEncode(sb: ScalaSigBytes): String = {
+ val ca = ubytesToCharArray(sb.sevenBitsMayBeZero)
+ new java.lang.String(ca)
+ // debug val bvA = new asm.ByteVector; bvA.putUTF8(s)
+ // debug val enc: Array[Byte] = scala.reflect.internal.pickling.ByteCodecs.encode(bytes)
+ // debug assert(enc(idx) == bvA.getByte(idx + 2))
+ // debug assert(bvA.getLength == enc.size + 2)
+ }
+
+ def emitArgument(av: asm.AnnotationVisitor,
+ name: String,
+ arg: ClassfileAnnotArg) {
+ arg match {
+
+ case LiteralAnnotArg(const) =>
+ if(const.isNonUnitAnyVal) { av.visit(name, const.value) }
+ else {
+ const.tag match {
+ case StringTag =>
+ assert(const.value != null, const) // TODO this invariant isn't documented in `case class Constant`
+ av.visit(name, const.stringValue) // `stringValue` special-cases null, but that execution path isn't exercised for a const with StringTag
+ case ClazzTag => av.visit(name, javaType(const.typeValue))
+ case EnumTag =>
+ val edesc = descriptor(const.tpe) // the class descriptor of the enumeration class.
+ val evalue = const.symbolValue.name.toString // value the actual enumeration value.
+ av.visitEnum(name, edesc, evalue)
+ }
+ }
+
+ case sb@ScalaSigBytes(bytes) =>
+ // see http://www.scala-lang.org/sid/10 (Storage of pickled Scala signatures in class files)
+ // also JVMS Sec. 4.7.16.1 The element_value structure and JVMS Sec. 4.4.7 The CONSTANT_Utf8_info Structure.
+ val assocValue = (if(sb.fitsInOneString) strEncode(sb) else arrEncode(sb))
+ av.visit(name, assocValue)
+ // for the lazy val in ScalaSigBytes to be GC'ed, the invoker of emitAnnotations() should hold the ScalaSigBytes in a method-local var that doesn't escape.
+
+ case ArrayAnnotArg(args) =>
+ val arrAnnotV: asm.AnnotationVisitor = av.visitArray(name)
+ for(arg <- args) { emitArgument(arrAnnotV, null, arg) }
+ arrAnnotV.visitEnd()
+
+ case NestedAnnotArg(annInfo) =>
+ val AnnotationInfo(typ, args, assocs) = annInfo
+ assert(args.isEmpty, args)
+ val desc = descriptor(typ) // the class descriptor of the nested annotation class
+ val nestedVisitor = av.visitAnnotation(name, desc)
+ emitAssocs(nestedVisitor, assocs)
+ }
+ }
+
+ def emitAssocs(av: asm.AnnotationVisitor, assocs: List[(Name, ClassfileAnnotArg)]) {
+ for ((name, value) <- assocs) {
+ emitArgument(av, name.toString(), value)
+ }
+ av.visitEnd()
+ }
+
+ def emitAnnotations(cw: asm.ClassVisitor, annotations: List[AnnotationInfo]) {
+ for(annot <- annotations; if shouldEmitAnnotation(annot)) {
+ val AnnotationInfo(typ, args, assocs) = annot
+ assert(args.isEmpty, args)
+ val av = cw.visitAnnotation(descriptor(typ), true)
+ emitAssocs(av, assocs)
+ }
+ }
+
+ def emitAnnotations(mw: asm.MethodVisitor, annotations: List[AnnotationInfo]) {
+ for(annot <- annotations; if shouldEmitAnnotation(annot)) {
+ val AnnotationInfo(typ, args, assocs) = annot
+ assert(args.isEmpty, args)
+ val av = mw.visitAnnotation(descriptor(typ), true)
+ emitAssocs(av, assocs)
+ }
+ }
+
+ def emitAnnotations(fw: asm.FieldVisitor, annotations: List[AnnotationInfo]) {
+ for(annot <- annotations; if shouldEmitAnnotation(annot)) {
+ val AnnotationInfo(typ, args, assocs) = annot
+ assert(args.isEmpty, args)
+ val av = fw.visitAnnotation(descriptor(typ), true)
+ emitAssocs(av, assocs)
+ }
+ }
+
+ def emitParamAnnotations(jmethod: asm.MethodVisitor, pannotss: List[List[AnnotationInfo]]) {
+ val annotationss = pannotss map (_ filter shouldEmitAnnotation)
+ if (annotationss forall (_.isEmpty)) return
+ for (Pair(annots, idx) <- annotationss.zipWithIndex;
+ annot <- annots) {
+ val AnnotationInfo(typ, args, assocs) = annot
+ assert(args.isEmpty, args)
+ val pannVisitor: asm.AnnotationVisitor = jmethod.visitParameterAnnotation(idx, descriptor(typ), true)
+ emitAssocs(pannVisitor, assocs)
+ }
+ }
+
+ def addInnerClasses(csym: Symbol, jclass: asm.ClassVisitor) {
+ /** The outer name for this inner class. Note that it returns null
+ * when the inner class should not get an index in the constant pool.
+ * That means non-member classes (anonymous). See Section 4.7.5 in the JVMS.
+ */
+ def outerName(innerSym: Symbol): String = {
+ if (innerSym.originalEnclosingMethod != NoSymbol)
+ null
+ else {
+ val outerName = javaName(innerSym.rawowner)
+ if (isTopLevelModule(innerSym.rawowner)) "" + nme.stripModuleSuffix(newTermName(outerName))
+ else outerName
+ }
+ }
+
+ def innerName(innerSym: Symbol): String =
+ if (innerSym.isAnonymousClass || innerSym.isAnonymousFunction)
+ null
+ else
+ innerSym.rawname + innerSym.moduleSuffix
+
+ // add inner classes which might not have been referenced yet
+ afterErasure {
+ for (sym <- List(csym, csym.linkedClassOfClass); m <- sym.info.decls.map(innerClassSymbolFor) if m.isClass)
+ innerClassBuffer += m
+ }
+
+ val allInners: List[Symbol] = innerClassBuffer.toList
+ if (allInners.nonEmpty) {
+ debuglog(csym.fullName('.') + " contains " + allInners.size + " inner classes.")
+
+ // entries ready to be serialized into the classfile, used to detect duplicates.
+ val entries = mutable.Map.empty[String, String]
+
+ // sort them so inner classes succeed their enclosing class to satisfy the Eclipse Java compiler
+ for (innerSym <- allInners sortBy (_.name.length)) { // TODO why not sortBy (_.name.toString()) ??
+ val flags = mkFlags(
+ if (innerSym.rawowner.hasModuleFlag) asm.Opcodes.ACC_STATIC else 0,
+ javaFlags(innerSym),
+ if(isDeprecated(innerSym)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo-access flag
+ ) & (INNER_CLASSES_FLAGS | asm.Opcodes.ACC_DEPRECATED)
+ val jname = javaName(innerSym) // never null
+ val oname = outerName(innerSym) // null when method-enclosed
+ val iname = innerName(innerSym) // null for anonymous inner class
+
+ // Mimicking javap inner class output
+ debuglog(
+ if (oname == null || iname == null) "//class " + jname
+ else "//%s=class %s of class %s".format(iname, jname, oname)
+ )
+
+ assert(jname != null, "javaName is broken.") // documentation
+ val doAdd = entries.get(jname) match {
+ // TODO is it ok for prevOName to be null? (Someone should really document the invariants of the InnerClasses bytecode attribute)
+ case Some(prevOName) =>
+ // this occurs e.g. when innerClassBuffer contains both class Thread$State, object Thread$State,
+ // i.e. for them it must be the case that oname == java/lang/Thread
+ assert(prevOName == oname, "duplicate")
+ false
+ case None => true
+ }
+
+ if(doAdd) {
+ entries += (jname -> oname)
+ jclass.visitInnerClass(jname, oname, iname, flags)
+ }
+
+ /*
+ * TODO assert (JVMS 4.7.6 The InnerClasses attribute)
+ * If a class file has a version number that is greater than or equal to 51.0, and
+ * has an InnerClasses attribute in its attributes table, then for all entries in the
+ * classes array of the InnerClasses attribute, the value of the
+ * outer_class_info_index item must be zero if the value of the
+ * inner_name_index item is zero.
+ */
+
+ }
+ }
+ }
+
+ /** Adds a @remote annotation, actual use unknown.
+ *
+ * Invoked from genMethod() and addForwarder().
+ */
+ def addRemoteExceptionAnnot(isRemoteClass: Boolean, isJMethodPublic: Boolean, meth: Symbol) {
+ val needsAnnotation = (
+ ( isRemoteClass ||
+ isRemote(meth) && isJMethodPublic
+ ) && !(meth.throwsAnnotations contains RemoteExceptionClass)
+ )
+ if (needsAnnotation) {
+ val c = Constant(RemoteExceptionClass.tpe)
+ val arg = Literal(c) setType c.tpe
+ meth.addAnnotation(ThrowsClass, arg)
+ }
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // Static forwarders (related to mirror classes but also present in
+ // a plain class lacking companion module, for details see `isCandidateForForwarders`).
+ // -----------------------------------------------------------------------------------------
+
+ val ExcludedForwarderFlags = {
+ import Flags._
+ // Should include DEFERRED but this breaks findMember.
+ ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags )
+ }
+
+ /** Add a forwarder for method m. Used only from addForwarders(). */
+ private def addForwarder(isRemoteClass: Boolean, jclass: asm.ClassVisitor, module: Symbol, m: Symbol) {
+ val moduleName = javaName(module)
+ val methodInfo = module.thisType.memberInfo(m)
+ val paramJavaTypes: List[asm.Type] = methodInfo.paramTypes map javaType
+ // val paramNames = 0 until paramJavaTypes.length map ("x_" + _)
+
+ /** Forwarders must not be marked final,
+ * as the JVM will not allow redefinition of a final static method,
+ * and we don't know what classes might be subclassing the companion class. See SI-4827.
+ */
+ // TODO: evaluate the other flags we might be dropping on the floor here.
+ // TODO: ACC_SYNTHETIC ?
+ val flags = PublicStatic | (
+ if (m.isVarargsMethod) asm.Opcodes.ACC_VARARGS else 0
+ )
+
+ // TODO needed? for(ann <- m.annotations) { ann.symbol.initialize }
+ val jgensig = if (m.isDeferred) null else getGenericSignature(m, module); // only add generic signature if method concrete; bug #1745
+ addRemoteExceptionAnnot(isRemoteClass, hasPublicBitSet(flags), m)
+ val (throws, others) = m.annotations partition (_.symbol == ThrowsClass)
+ val thrownExceptions: List[String] = getExceptions(throws)
+
+ val jReturnType = javaType(methodInfo.resultType)
+ val mdesc = asm.Type.getMethodDescriptor(jReturnType, paramJavaTypes: _*)
+ val mirrorMethodName = javaName(m)
+ val mirrorMethod: asm.MethodVisitor = jclass.visitMethod(
+ flags,
+ mirrorMethodName,
+ mdesc,
+ jgensig,
+ mkArray(thrownExceptions)
+ )
+
+ // typestate: entering mode with valid call sequences:
+ // [ visitAnnotationDefault ] ( visitAnnotation | visitParameterAnnotation | visitAttribute )*
+
+ emitAnnotations(mirrorMethod, others)
+ emitParamAnnotations(mirrorMethod, m.info.params.map(_.annotations))
+
+ // typestate: entering mode with valid call sequences:
+ // visitCode ( visitFrame | visitXInsn | visitLabel | visitTryCatchBlock | visitLocalVariable | visitLineNumber )* visitMaxs ] visitEnd
+
+ mirrorMethod.visitCode()
+
+ mirrorMethod.visitFieldInsn(asm.Opcodes.GETSTATIC, moduleName, strMODULE_INSTANCE_FIELD, descriptor(module))
+
+ var index = 0
+ for(jparamType <- paramJavaTypes) {
+ mirrorMethod.visitVarInsn(jparamType.getOpcode(asm.Opcodes.ILOAD), index)
+ assert(jparamType.getSort() != asm.Type.METHOD, jparamType)
+ index += jparamType.getSize()
+ }
+
+ mirrorMethod.visitMethodInsn(asm.Opcodes.INVOKEVIRTUAL, moduleName, mirrorMethodName, javaType(m).getDescriptor)
+ mirrorMethod.visitInsn(jReturnType.getOpcode(asm.Opcodes.IRETURN))
+
+ mirrorMethod.visitMaxs(0, 0) // just to follow protocol, dummy arguments
+ mirrorMethod.visitEnd()
+
+ }
+
+ /** Add forwarders for all methods defined in `module` that don't conflict
+ * with methods in the companion class of `module`. A conflict arises when
+ * a method with the same name is defined both in a class and its companion object:
+ * method signature is not taken into account.
+ */
+ def addForwarders(isRemoteClass: Boolean, jclass: asm.ClassVisitor, jclassName: String, moduleClass: Symbol) {
+ assert(moduleClass.isModuleClass, moduleClass)
+ debuglog("Dumping mirror class for object: " + moduleClass)
+
+ val linkedClass = moduleClass.companionClass
+ val linkedModule = linkedClass.companionSymbol
+ lazy val conflictingNames: Set[Name] = {
+ linkedClass.info.members collect { case sym if sym.name.isTermName => sym.name } toSet
+ }
+ debuglog("Potentially conflicting names for forwarders: " + conflictingNames)
+
+ for (m <- moduleClass.info.membersBasedOnFlags(ExcludedForwarderFlags, Flags.METHOD)) {
+ if (m.isType || m.isDeferred || (m.owner eq ObjectClass) || m.isConstructor)
+ debuglog("No forwarder for '%s' from %s to '%s'".format(m, jclassName, moduleClass))
+ else if (conflictingNames(m.name))
+ log("No forwarder for " + m + " due to conflict with " + linkedClass.info.member(m.name))
+ else {
+ log("Adding static forwarder for '%s' from %s to '%s'".format(m, jclassName, moduleClass))
+ addForwarder(isRemoteClass, jclass, moduleClass, m)
+ }
+ }
+ }
+
+ } // end of class JCommonBuilder
+
+
+ trait JAndroidBuilder {
+ self: JPlainBuilder =>
+
+ /** From the reference documentation of the Android SDK:
+ * The `Parcelable` interface identifies classes whose instances can be written to and restored from a `Parcel`.
+ * Classes implementing the `Parcelable` interface must also have a static field called `CREATOR`,
+ * which is an object implementing the `Parcelable.Creator` interface.
+ */
+ private val androidFieldName = newTermName("CREATOR")
+
+ private lazy val AndroidParcelableInterface = definitions.getClassIfDefined("android.os.Parcelable")
+ private lazy val AndroidCreatorClass = definitions.getClassIfDefined("android.os.Parcelable$Creator")
+
+ def isAndroidParcelableClass(sym: Symbol) =
+ (AndroidParcelableInterface != NoSymbol) &&
+ (sym.parentSymbols contains AndroidParcelableInterface)
+
+ /* Typestate: should be called before emitting fields (because it adds an IField to the current IClass). */
+ def addCreatorCode(block: BasicBlock) {
+ val fieldSymbol = (
+ clasz.symbol.newValue(newTermName(androidFieldName), NoPosition, Flags.STATIC | Flags.FINAL)
+ setInfo AndroidCreatorClass.tpe
+ )
+ val methodSymbol = definitions.getMember(clasz.symbol.companionModule, androidFieldName)
+ clasz addField new IField(fieldSymbol)
+ block emit CALL_METHOD(methodSymbol, Static(false))
+ block emit STORE_FIELD(fieldSymbol, true)
+ }
+
+ def legacyAddCreatorCode(clinit: asm.MethodVisitor) {
+ val creatorType: asm.Type = javaType(AndroidCreatorClass)
+ val tdesc_creator = creatorType.getDescriptor
+
+ jclass.visitField(
+ PublicStaticFinal,
+ androidFieldName,
+ tdesc_creator,
+ null, // no java-generic-signature
+ null // no initial value
+ ).visitEnd()
+
+ val moduleName = javaName(clasz.symbol)+"$"
+
+ // GETSTATIC `moduleName`.MODULE$ : `moduleName`;
+ clinit.visitFieldInsn(
+ asm.Opcodes.GETSTATIC,
+ moduleName,
+ strMODULE_INSTANCE_FIELD,
+ asm.Type.getObjectType(moduleName).getDescriptor
+ )
+
+ // INVOKEVIRTUAL `moduleName`.CREATOR() : android.os.Parcelable$Creator;
+ clinit.visitMethodInsn(
+ asm.Opcodes.INVOKEVIRTUAL,
+ moduleName,
+ androidFieldName,
+ asm.Type.getMethodDescriptor(creatorType, Array.empty[asm.Type]: _*)
+ )
+
+ // PUTSTATIC `thisName`.CREATOR;
+ clinit.visitFieldInsn(
+ asm.Opcodes.PUTSTATIC,
+ thisName,
+ androidFieldName,
+ tdesc_creator
+ )
+ }
+
+ } // end of trait JAndroidBuilder
+
+ /** Map from type kinds to the Java reference types.
+ * It is used to push class literals onto the operand stack.
+ * @see Predef.classOf
+ * @see genConstant()
+ */
+ private val classLiteral = immutable.Map[TypeKind, asm.Type](
+ UNIT -> asm.Type.getObjectType("java/lang/Void"),
+ BOOL -> asm.Type.getObjectType("java/lang/Boolean"),
+ BYTE -> asm.Type.getObjectType("java/lang/Byte"),
+ SHORT -> asm.Type.getObjectType("java/lang/Short"),
+ CHAR -> asm.Type.getObjectType("java/lang/Character"),
+ INT -> asm.Type.getObjectType("java/lang/Integer"),
+ LONG -> asm.Type.getObjectType("java/lang/Long"),
+ FLOAT -> asm.Type.getObjectType("java/lang/Float"),
+ DOUBLE -> asm.Type.getObjectType("java/lang/Double")
+ )
+
+ def isNonUnitValueTK(tk: TypeKind): Boolean = { tk.isValueType && tk != UNIT }
+
+ case class MethodNameAndType(mname: String, mdesc: String)
+
+ private val jBoxTo: Map[TypeKind, MethodNameAndType] = {
+ Map(
+ BOOL -> MethodNameAndType("boxToBoolean", "(Z)Ljava/lang/Boolean;" ) ,
+ BYTE -> MethodNameAndType("boxToByte", "(B)Ljava/lang/Byte;" ) ,
+ CHAR -> MethodNameAndType("boxToCharacter", "(C)Ljava/lang/Character;") ,
+ SHORT -> MethodNameAndType("boxToShort", "(S)Ljava/lang/Short;" ) ,
+ INT -> MethodNameAndType("boxToInteger", "(I)Ljava/lang/Integer;" ) ,
+ LONG -> MethodNameAndType("boxToLong", "(J)Ljava/lang/Long;" ) ,
+ FLOAT -> MethodNameAndType("boxToFloat", "(F)Ljava/lang/Float;" ) ,
+ DOUBLE -> MethodNameAndType("boxToDouble", "(D)Ljava/lang/Double;" )
+ )
+ }
+
+ private val jUnboxTo: Map[TypeKind, MethodNameAndType] = {
+ Map(
+ BOOL -> MethodNameAndType("unboxToBoolean", "(Ljava/lang/Object;)Z") ,
+ BYTE -> MethodNameAndType("unboxToByte", "(Ljava/lang/Object;)B") ,
+ CHAR -> MethodNameAndType("unboxToChar", "(Ljava/lang/Object;)C") ,
+ SHORT -> MethodNameAndType("unboxToShort", "(Ljava/lang/Object;)S") ,
+ INT -> MethodNameAndType("unboxToInt", "(Ljava/lang/Object;)I") ,
+ LONG -> MethodNameAndType("unboxToLong", "(Ljava/lang/Object;)J") ,
+ FLOAT -> MethodNameAndType("unboxToFloat", "(Ljava/lang/Object;)F") ,
+ DOUBLE -> MethodNameAndType("unboxToDouble", "(Ljava/lang/Object;)D")
+ )
+ }
+
+ case class BlockInteval(start: BasicBlock, end: BasicBlock)
+
+ /** builder of plain classes */
+ class JPlainBuilder(bytecodeWriter: BytecodeWriter)
+ extends JCommonBuilder(bytecodeWriter)
+ with JAndroidBuilder {
+
+ val MIN_SWITCH_DENSITY = 0.7
+
+ val StringBuilderClassName = javaName(definitions.StringBuilderClass)
+ val BoxesRunTime = "scala/runtime/BoxesRunTime"
+
+ val StringBuilderType = asm.Type.getObjectType(StringBuilderClassName)
+ val mdesc_toString = "()Ljava/lang/String;"
+ val mdesc_arrayClone = "()Ljava/lang/Object;"
+
+ val tdesc_long = asm.Type.LONG_TYPE.getDescriptor // ie. "J"
+
+ def isParcelableClass = isAndroidParcelableClass(clasz.symbol)
+
+ def serialVUID: Option[Long] = clasz.symbol getAnnotation SerialVersionUIDAttr collect {
+ case AnnotationInfo(_, Literal(const) :: _, _) => const.longValue
+ }
+
+ private def getSuperInterfaces(c: IClass): Array[String] = {
+
+ // Additional interface parents based on annotations and other cues
+ def newParentForAttr(attr: Symbol): Option[Symbol] = attr match {
+ case SerializableAttr => Some(SerializableClass)
+ case CloneableAttr => Some(JavaCloneableClass)
+ case RemoteAttr => Some(RemoteInterfaceClass)
+ case _ => None
+ }
+
+ /** Drop redundant interfaces (ones which are implemented by some other parent) from the immediate parents.
+ * This is important on Android because there is otherwise an interface explosion.
+ */
+ def minimizeInterfaces(lstIfaces: List[Symbol]): List[Symbol] = {
+ var rest = lstIfaces
+ var leaves = List.empty[Symbol]
+ while(!rest.isEmpty) {
+ val candidate = rest.head
+ val nonLeaf = leaves exists { lsym => lsym isSubClass candidate }
+ if(!nonLeaf) {
+ leaves = candidate :: (leaves filterNot { lsym => candidate isSubClass lsym })
+ }
+ rest = rest.tail
+ }
+
+ leaves
+ }
+
+ val ps = c.symbol.info.parents
+ val superInterfaces0: List[Symbol] = if(ps.isEmpty) Nil else c.symbol.mixinClasses;
+ val superInterfaces = superInterfaces0 ++ c.symbol.annotations.flatMap(ann => newParentForAttr(ann.symbol)) distinct
+
+ if(superInterfaces.isEmpty) EMPTY_STRING_ARRAY
+ else mkArray(minimizeInterfaces(superInterfaces) map javaName)
+ }
+
+ var clasz: IClass = _ // this var must be assigned only by genClass()
+ var jclass: asm.ClassWriter = _ // the classfile being emitted
+ var thisName: String = _ // the internal name of jclass
+
+ def thisDescr: String = {
+ assert(thisName != null, "thisDescr invoked too soon.")
+ asm.Type.getObjectType(thisName).getDescriptor
+ }
+
+ def getCurrentCUnit(): CompilationUnit = { clasz.cunit }
+
+ def genClass(c: IClass) {
+ clasz = c
+ innerClassBuffer.clear()
+
+ thisName = javaName(c.symbol) // the internal name of the class being emitted
+
+ val ps = c.symbol.info.parents
+ val superClass: String = if(ps.isEmpty) JAVA_LANG_OBJECT.getInternalName else javaName(ps.head.typeSymbol);
+
+ val ifaces = getSuperInterfaces(c)
+
+ val thisSignature = getGenericSignature(c.symbol, c.symbol.owner)
+ val flags = mkFlags(
+ javaFlags(c.symbol),
+ if(isDeprecated(c.symbol)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo access flag
+ )
+ jclass = createJClass(flags,
+ thisName, thisSignature,
+ superClass, ifaces)
+
+ // typestate: entering mode with valid call sequences:
+ // [ visitSource ] [ visitOuterClass ] ( visitAnnotation | visitAttribute )*
+
+ jclass.visitSource(c.cunit.source.toString,
+ null /* SourceDebugExtension */)
+
+ val enclM = getEnclosingMethodAttribute()
+ if(enclM != null) {
+ val EnclMethodEntry(className, methodName, methodType) = enclM
+ jclass.visitOuterClass(className, methodName, methodType.getDescriptor)
+ }
+
+ // typestate: entering mode with valid call sequences:
+ // ( visitAnnotation | visitAttribute )*
+
+ val ssa = getAnnotPickle(thisName, c.symbol)
+ jclass.visitAttribute(if(ssa.isDefined) pickleMarkerLocal else pickleMarkerForeign)
+ emitAnnotations(jclass, c.symbol.annotations ++ ssa)
+
+ // typestate: entering mode with valid call sequences:
+ // ( visitInnerClass | visitField | visitMethod )* visitEnd
+
+ if (isStaticModule(c.symbol) || serialVUID != None || isParcelableClass) {
+
+ if (isStaticModule(c.symbol)) { addModuleInstanceField() }
+ addStaticInit(c.lookupStaticCtor)
+
+ } else {
+
+ for (constructor <- c.lookupStaticCtor) {
+ addStaticInit(Some(constructor))
+ }
+ val skipStaticForwarders = (c.symbol.isInterface || settings.noForwarders.value)
+ if (!skipStaticForwarders) {
+ val lmoc = c.symbol.companionModule
+ // add static forwarders if there are no name conflicts; see bugs #363 and #1735
+ if (lmoc != NoSymbol) {
+ // it must be a top level class (name contains no $s)
+ val isCandidateForForwarders = {
+ afterPickler { !(lmoc.name.toString contains '$') && lmoc.hasModuleFlag && !lmoc.isImplClass && !lmoc.isNestedClass }
+ }
+ if (isCandidateForForwarders) {
+ log("Adding static forwarders from '%s' to implementations in '%s'".format(c.symbol, lmoc))
+ addForwarders(isRemote(clasz.symbol), jclass, thisName, lmoc.moduleClass)
+ }
+ }
+ }
+
+ }
+
+ clasz.fields foreach genField
+ clasz.methods foreach { im => genMethod(im, c.symbol.isInterface) }
+
+ addInnerClasses(clasz.symbol, jclass)
+ jclass.visitEnd()
+ writeIfNotTooBig("" + c.symbol.name, thisName, jclass, c.symbol)
+
+ }
+
+ /**
+ * @param owner internal name of the enclosing class of the class.
+ *
+ * @param name the name of the method that contains the class.
+
+ * @param methodType the method that contains the class.
+ */
+ case class EnclMethodEntry(owner: String, name: String, methodType: asm.Type)
+
+ /**
+ * @return null if the current class is not internal to a method
+ *
+ * Quoting from JVMS 4.7.7 The EnclosingMethod Attribute
+ * A class must have an EnclosingMethod attribute if and only if it is a local class or an anonymous class.
+ * A class may have no more than one EnclosingMethod attribute.
+ *
+ */
+ private def getEnclosingMethodAttribute(): EnclMethodEntry = { // JVMS 4.7.7
+ var res: EnclMethodEntry = null
+ val clazz = clasz.symbol
+ val sym = clazz.originalEnclosingMethod
+ if (sym.isMethod) {
+ debuglog("enclosing method for %s is %s (in %s)".format(clazz, sym, sym.enclClass))
+ res = EnclMethodEntry(javaName(sym.enclClass), javaName(sym), javaType(sym))
+ } else if (clazz.isAnonymousClass) {
+ val enclClass = clazz.rawowner
+ assert(enclClass.isClass, enclClass)
+ val sym = enclClass.primaryConstructor
+ if (sym == NoSymbol) {
+ log("Ran out of room looking for an enclosing method for %s: no constructor here.".format(enclClass, clazz))
+ } else {
+ debuglog("enclosing method for %s is %s (in %s)".format(clazz, sym, enclClass))
+ res = EnclMethodEntry(javaName(enclClass), javaName(sym), javaType(sym))
+ }
+ }
+
+ res
+ }
+
+ def genField(f: IField) {
+ debuglog("Adding field: " + f.symbol.fullName)
+
+ val javagensig = getGenericSignature(f.symbol, clasz.symbol)
+
+ val flags = mkFlags(
+ javaFieldFlags(f.symbol),
+ if(isDeprecated(f.symbol)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo access flag
+ )
+
+ val jfield: asm.FieldVisitor = jclass.visitField(
+ flags,
+ javaName(f.symbol),
+ javaType(f.symbol.tpe).getDescriptor(),
+ javagensig,
+ null // no initial value
+ )
+
+ emitAnnotations(jfield, f.symbol.annotations)
+ jfield.visitEnd()
+ }
+
+ def debugLevel = settings.debuginfo.indexOfChoice
+
+ // val emitSource = debugLevel >= 1
+ val emitLines = debugLevel >= 2
+ val emitVars = debugLevel >= 3
+
+ var method: IMethod = _
+ var jmethod: asm.MethodVisitor = _
+ var jMethodName: String = _
+
+ @inline final def emit(opc: Int) { jmethod.visitInsn(opc) }
+
+ def genMethod(m: IMethod, isJInterface: Boolean) {
+
+ def isClosureApply(sym: Symbol): Boolean = {
+ (sym.name == nme.apply) &&
+ sym.owner.isSynthetic &&
+ sym.owner.tpe.parents.exists { t =>
+ val TypeRef(_, sym, _) = t
+ FunctionClass contains sym
+ }
+ }
+
+ if (m.symbol.isStaticConstructor || definitions.isGetClass(m.symbol)) return
+
+ debuglog("Generating method " + m.symbol.fullName)
+ method = m
+ computeLocalVarsIndex(m)
+
+ var resTpe: asm.Type = javaType(m.symbol.tpe.resultType)
+ if (m.symbol.isClassConstructor)
+ resTpe = asm.Type.VOID_TYPE
+
+ val flags = mkFlags(
+ javaFlags(m.symbol),
+ if (isJInterface) asm.Opcodes.ACC_ABSTRACT else 0,
+ if (m.symbol.isStrictFP) asm.Opcodes.ACC_STRICT else 0,
+ if (method.native) asm.Opcodes.ACC_NATIVE else 0, // native methods of objects are generated in mirror classes
+ if(isDeprecated(m.symbol)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo access flag
+ )
+
+ // TODO needed? for(ann <- m.symbol.annotations) { ann.symbol.initialize }
+ val jgensig = getGenericSignature(m.symbol, clasz.symbol)
+ addRemoteExceptionAnnot(isRemote(clasz.symbol), hasPublicBitSet(flags), m.symbol)
+ val (excs, others) = m.symbol.annotations partition (_.symbol == ThrowsClass)
+ val thrownExceptions: List[String] = getExceptions(excs)
+
+ jMethodName = javaName(m.symbol)
+ val mdesc = asm.Type.getMethodDescriptor(resTpe, (m.params map (p => javaType(p.kind))): _*)
+ jmethod = jclass.visitMethod(
+ flags,
+ jMethodName,
+ mdesc,
+ jgensig,
+ mkArray(thrownExceptions)
+ )
+
+ // TODO param names: (m.params map (p => javaName(p.sym)))
+
+ // typestate: entering mode with valid call sequences:
+ // [ visitAnnotationDefault ] ( visitAnnotation | visitParameterAnnotation | visitAttribute )*
+
+ emitAnnotations(jmethod, others)
+ emitParamAnnotations(jmethod, m.params.map(_.sym.annotations))
+
+ // typestate: entering mode with valid call sequences:
+ // [ visitCode ( visitFrame | visitXInsn | visitLabel | visitTryCatchBlock | visitLocalVariable | visitLineNumber )* visitMaxs ] visitEnd
+ // In addition, the visitXInsn and visitLabel methods must be called in the sequential order of the bytecode instructions of the visited code,
+ // visitTryCatchBlock must be called before the labels passed as arguments have been visited, and
+ // the visitLocalVariable and visitLineNumber methods must be called after the labels passed as arguments have been visited.
+
+ val hasAbstractBitSet = ((flags & asm.Opcodes.ACC_ABSTRACT) != 0)
+ val hasCodeAttribute = (!hasAbstractBitSet && !method.native)
+ if (hasCodeAttribute) {
+
+ jmethod.visitCode()
+
+ if (emitVars && isClosureApply(method.symbol)) {
+ // add a fake local for debugging purposes
+ val outerField = clasz.symbol.info.decl(nme.OUTER_LOCAL)
+ if (outerField != NoSymbol) {
+ log("Adding fake local to represent outer 'this' for closure " + clasz)
+ val _this =
+ new Local(method.symbol.newVariable(nme.FAKE_LOCAL_THIS),
+ toTypeKind(outerField.tpe),
+ false)
+ m.locals = m.locals ::: List(_this)
+ computeLocalVarsIndex(m) // since we added a new local, we need to recompute indexes
+ jmethod.visitVarInsn(asm.Opcodes.ALOAD, 0)
+ jmethod.visitFieldInsn(asm.Opcodes.GETFIELD,
+ javaName(clasz.symbol), // field owner
+ javaName(outerField), // field name
+ descriptor(outerField) // field descriptor
+ )
+ assert(_this.kind.isReferenceType, _this.kind)
+ jmethod.visitVarInsn(asm.Opcodes.ASTORE, indexOf(_this))
+ }
+ }
+
+ assert( m.locals forall { local => (m.params contains local) == local.arg }, m.locals )
+
+ val hasStaticBitSet = ((flags & asm.Opcodes.ACC_STATIC) != 0)
+ genCode(m, emitVars, hasStaticBitSet)
+
+ jmethod.visitMaxs(0, 0) // just to follow protocol, dummy arguments
+ }
+
+ jmethod.visitEnd()
+
+ }
+
+ def addModuleInstanceField() {
+ val fv =
+ jclass.visitField(PublicStaticFinal, // TODO confirm whether we really don't want ACC_SYNTHETIC nor ACC_DEPRECATED
+ strMODULE_INSTANCE_FIELD,
+ thisDescr,
+ null, // no java-generic-signature
+ null // no initial value
+ )
+
+ // typestate: entering mode with valid call sequences:
+ // ( visitAnnotation | visitAttribute )* visitEnd.
+
+ fv.visitEnd()
+ }
+
+
+ /* Typestate: should be called before being done with emitting fields (because it invokes addCreatorCode() which adds an IField to the current IClass). */
+ def addStaticInit(mopt: Option[IMethod]) {
+
+ val clinitMethod: asm.MethodVisitor = jclass.visitMethod(
+ PublicStatic, // TODO confirm whether we really don't want ACC_SYNTHETIC nor ACC_DEPRECATED
+ CLASS_CONSTRUCTOR_NAME,
+ mdesc_arglessvoid,
+ null, // no java-generic-signature
+ null // no throwable exceptions
+ )
+
+ mopt match {
+
+ case Some(m) =>
+
+ val oldLastBlock = m.lastBlock
+ val lastBlock = m.newBlock()
+ oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock))
+
+ if (isStaticModule(clasz.symbol)) {
+ // call object's private ctor from static ctor
+ lastBlock emit NEW(REFERENCE(m.symbol.enclClass))
+ lastBlock emit CALL_METHOD(m.symbol.enclClass.primaryConstructor, Static(true))
+ }
+
+ // add serialVUID code
+ serialVUID foreach { value =>
+ val fieldName = "serialVersionUID"
+ val fieldSymbol = clasz.symbol.newValue(newTermName(fieldName), NoPosition, Flags.STATIC | Flags.FINAL) setInfo LongClass.tpe
+ clasz addField new IField(fieldSymbol)
+ lastBlock emit CONSTANT(Constant(value))
+ lastBlock emit STORE_FIELD(fieldSymbol, true)
+ }
+
+ if (isParcelableClass) { addCreatorCode(lastBlock) }
+
+ lastBlock emit RETURN(UNIT)
+ lastBlock.close
+
+ method = m
+ jmethod = clinitMethod
+ jMethodName = CLASS_CONSTRUCTOR_NAME
+ jmethod.visitCode()
+ genCode(m, false, true)
+ jmethod.visitMaxs(0, 0) // just to follow protocol, dummy arguments
+ jmethod.visitEnd()
+
+ case None =>
+ clinitMethod.visitCode()
+ legacyStaticInitializer(clinitMethod)
+ clinitMethod.visitMaxs(0, 0) // just to follow protocol, dummy arguments
+ clinitMethod.visitEnd()
+
+ }
+ }
+
+ /* used only from addStaticInit() */
+ private def legacyStaticInitializer(clinit: asm.MethodVisitor) {
+ if (isStaticModule(clasz.symbol)) {
+ clinit.visitTypeInsn(asm.Opcodes.NEW, thisName)
+ clinit.visitMethodInsn(asm.Opcodes.INVOKESPECIAL,
+ thisName, INSTANCE_CONSTRUCTOR_NAME, mdesc_arglessvoid)
+ }
+
+ serialVUID foreach { value =>
+ val fieldName = "serialVersionUID"
+ jclass.visitField(
+ PublicStaticFinal,
+ fieldName,
+ tdesc_long,
+ null, // no java-generic-signature
+ value // TODO confirm whether initial value here is behaviorally equiv to fjbg's emitPUSH emitPUTSTATIC
+ ).visitEnd()
+ }
+
+ if (isParcelableClass) { legacyAddCreatorCode(clinit) }
+
+ clinit.visitInsn(asm.Opcodes.RETURN)
+ }
+
+ // -----------------------------------------------------------------------------------------
+ // Emitting bytecode instructions.
+ // -----------------------------------------------------------------------------------------
+
+ private def genConstant(mv: asm.MethodVisitor, const: Constant) {
+ const.tag match {
+
+ case BooleanTag => jcode.boolconst(const.booleanValue)
+
+ case ByteTag => jcode.iconst(const.byteValue)
+ case ShortTag => jcode.iconst(const.shortValue)
+ case CharTag => jcode.iconst(const.charValue)
+ case IntTag => jcode.iconst(const.intValue)
+
+ case LongTag => jcode.lconst(const.longValue)
+ case FloatTag => jcode.fconst(const.floatValue)
+ case DoubleTag => jcode.dconst(const.doubleValue)
+
+ case UnitTag => ()
+
+ case StringTag =>
+ assert(const.value != null, const) // TODO this invariant isn't documented in `case class Constant`
+ mv.visitLdcInsn(const.stringValue) // `stringValue` special-cases null, but not for a const with StringTag
+
+ case NullTag => mv.visitInsn(asm.Opcodes.ACONST_NULL)
+
+ case ClazzTag =>
+ val kind = toTypeKind(const.typeValue)
+ val toPush: asm.Type =
+ if (kind.isValueType) classLiteral(kind)
+ else javaType(kind);
+ mv.visitLdcInsn(toPush)
+
+ case EnumTag =>
+ val sym = const.symbolValue
+ mv.visitFieldInsn(
+ asm.Opcodes.GETSTATIC,
+ javaName(sym.owner),
+ javaName(sym),
+ javaType(sym.tpe.underlying).getDescriptor()
+ )
+
+ case _ => abort("Unknown constant value: " + const)
+ }
+ }
+
+ /** Just a namespace for utilities that encapsulate MethodVisitor idioms.
+ * In the ASM world, org.objectweb.asm.commons.InstructionAdapter plays a similar role,
+ * but the methods here allow choosing when to transition from ICode to ASM types
+ * (including not at all, e.g. for performance).
+ */
+ object jcode {
+
+ import asm.Opcodes;
+
+ def aconst(cst: AnyRef) {
+ if (cst == null) { jmethod.visitInsn(Opcodes.ACONST_NULL) }
+ else { jmethod.visitLdcInsn(cst) }
+ }
+
+ @inline final def boolconst(b: Boolean) { iconst(if(b) 1 else 0) }
+
+ def iconst(cst: Int) {
+ if (cst >= -1 && cst <= 5) {
+ jmethod.visitInsn(Opcodes.ICONST_0 + cst)
+ } else if (cst >= java.lang.Byte.MIN_VALUE && cst <= java.lang.Byte.MAX_VALUE) {
+ jmethod.visitIntInsn(Opcodes.BIPUSH, cst)
+ } else if (cst >= java.lang.Short.MIN_VALUE && cst <= java.lang.Short.MAX_VALUE) {
+ jmethod.visitIntInsn(Opcodes.SIPUSH, cst)
+ } else {
+ jmethod.visitLdcInsn(new Integer(cst))
+ }
+ }
+
+ def lconst(cst: Long) {
+ if (cst == 0L || cst == 1L) {
+ jmethod.visitInsn(Opcodes.LCONST_0 + cst.asInstanceOf[Int])
+ } else {
+ jmethod.visitLdcInsn(new java.lang.Long(cst))
+ }
+ }
+
+ def fconst(cst: Float) {
+ val bits: Int = java.lang.Float.floatToIntBits(cst)
+ if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+ jmethod.visitInsn(Opcodes.FCONST_0 + cst.asInstanceOf[Int])
+ } else {
+ jmethod.visitLdcInsn(new java.lang.Float(cst))
+ }
+ }
+
+ def dconst(cst: Double) {
+ val bits: Long = java.lang.Double.doubleToLongBits(cst)
+ if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+ jmethod.visitInsn(Opcodes.DCONST_0 + cst.asInstanceOf[Int])
+ } else {
+ jmethod.visitLdcInsn(new java.lang.Double(cst))
+ }
+ }
+
+ def newarray(elem: TypeKind) {
+ if(elem.isRefOrArrayType) {
+ jmethod.visitTypeInsn(Opcodes.ANEWARRAY, javaType(elem).getInternalName)
+ } else {
+ val rand = {
+ if(elem.isIntSizedType) {
+ (elem: @unchecked) match {
+ case BOOL => Opcodes.T_BOOLEAN
+ case BYTE => Opcodes.T_BYTE
+ case SHORT => Opcodes.T_SHORT
+ case CHAR => Opcodes.T_CHAR
+ case INT => Opcodes.T_INT
+ }
+ } else {
+ (elem: @unchecked) match {
+ case LONG => Opcodes.T_LONG
+ case FLOAT => Opcodes.T_FLOAT
+ case DOUBLE => Opcodes.T_DOUBLE
+ }
+ }
+ }
+ jmethod.visitIntInsn(Opcodes.NEWARRAY, rand)
+ }
+ }
+
+
+ @inline def load( idx: Int, tk: TypeKind) { emitVarInsn(Opcodes.ILOAD, idx, tk) }
+ @inline def store(idx: Int, tk: TypeKind) { emitVarInsn(Opcodes.ISTORE, idx, tk) }
+
+ @inline def aload( tk: TypeKind) { emitTypeBased(aloadOpcodes, tk) }
+ @inline def astore(tk: TypeKind) { emitTypeBased(astoreOpcodes, tk) }
+
+ @inline def neg(tk: TypeKind) { emitPrimitive(negOpcodes, tk) }
+ @inline def add(tk: TypeKind) { emitPrimitive(addOpcodes, tk) }
+ @inline def sub(tk: TypeKind) { emitPrimitive(subOpcodes, tk) }
+ @inline def mul(tk: TypeKind) { emitPrimitive(mulOpcodes, tk) }
+ @inline def div(tk: TypeKind) { emitPrimitive(divOpcodes, tk) }
+ @inline def rem(tk: TypeKind) { emitPrimitive(remOpcodes, tk) }
+
+ @inline def invokespecial(owner: String, name: String, desc: String) {
+ jmethod.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc)
+ }
+ @inline def invokestatic(owner: String, name: String, desc: String) {
+ jmethod.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc)
+ }
+ @inline def invokeinterface(owner: String, name: String, desc: String) {
+ jmethod.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc)
+ }
+ @inline def invokevirtual(owner: String, name: String, desc: String) {
+ jmethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc)
+ }
+
+ @inline def goTo(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.GOTO, label) }
+ @inline def emitIF(cond: TestOp, label: asm.Label) { jmethod.visitJumpInsn(cond.opcodeIF, label) }
+ @inline def emitIF_ICMP(cond: TestOp, label: asm.Label) { jmethod.visitJumpInsn(cond.opcodeIFICMP, label) }
+ @inline def emitIF_ACMP(cond: TestOp, label: asm.Label) {
+ assert((cond == EQ) || (cond == NE), cond)
+ val opc = (if(cond == EQ) Opcodes.IF_ACMPEQ else Opcodes.IF_ACMPNE)
+ jmethod.visitJumpInsn(opc, label)
+ }
+ @inline def emitIFNONNULL(label: asm.Label) { jmethod.visitJumpInsn(Opcodes.IFNONNULL, label) }
+ @inline def emitIFNULL (label: asm.Label) { jmethod.visitJumpInsn(Opcodes.IFNULL, label) }
+
+ @inline def emitRETURN(tk: TypeKind) {
+ if(tk == UNIT) { jmethod.visitInsn(Opcodes.RETURN) }
+ else { emitTypeBased(returnOpcodes, tk) }
+ }
+
+ /** Emits one of tableswitch or lookoupswitch. */
+ def emitSWITCH(keys: Array[Int], branches: Array[asm.Label], defaultBranch: asm.Label, minDensity: Double) {
+ assert(keys.length == branches.length)
+
+ // For empty keys, it makes sense emitting LOOKUPSWITCH with defaultBranch only.
+ // Similar to what javac emits for a switch statement consisting only of a default case.
+ if (keys.length == 0) {
+ jmethod.visitLookupSwitchInsn(defaultBranch, keys, branches)
+ return
+ }
+
+ // sort `keys` by increasing key, keeping `branches` in sync. TODO FIXME use quicksort
+ var i = 1
+ while (i < keys.length) {
+ var j = 1
+ while (j <= keys.length - i) {
+ if (keys(j) < keys(j - 1)) {
+ val tmp = keys(j)
+ keys(j) = keys(j - 1)
+ keys(j - 1) = tmp
+ val tmpL = branches(j)
+ branches(j) = branches(j - 1)
+ branches(j - 1) = tmpL
+ }
+ j += 1
+ }
+ i += 1
+ }
+
+ val keyMin = keys(0)
+ val keyMax = keys(keys.length - 1)
+
+ val isDenseEnough: Boolean = {
+ /** Calculate in long to guard against overflow. TODO what overflow??? */
+ val keyRangeD: Double = (keyMax.asInstanceOf[Long] - keyMin + 1).asInstanceOf[Double]
+ val klenD: Double = keys.length
+ val kdensity: Double = (klenD / keyRangeD)
+
+ kdensity >= minDensity
+ }
+
+ if (isDenseEnough) {
+ // use a table in which holes are filled with defaultBranch.
+ val keyRange = (keyMax - keyMin + 1)
+ val newBranches = new Array[asm.Label](keyRange)
+ var oldPos = 0;
+ var i = 0
+ while(i < keyRange) {
+ val key = keyMin + i;
+ if (keys(oldPos) == key) {
+ newBranches(i) = branches(oldPos)
+ oldPos += 1
+ } else {
+ newBranches(i) = defaultBranch
+ }
+ i += 1
+ }
+ assert(oldPos == keys.length, "emitSWITCH")
+ jmethod.visitTableSwitchInsn(keyMin, keyMax, defaultBranch, newBranches: _*)
+ } else {
+ jmethod.visitLookupSwitchInsn(defaultBranch, keys, branches)
+ }
+ }
+
+ // internal helpers -- not part of the public API of `jcode`
+ // don't make private otherwise inlining will suffer
+
+ def emitVarInsn(opc: Int, idx: Int, tk: TypeKind) {
+ assert((opc == Opcodes.ILOAD) || (opc == Opcodes.ISTORE), opc)
+ jmethod.visitVarInsn(javaType(tk).getOpcode(opc), idx)
+ }
+
+ // ---------------- array load and store ----------------
+
+ val aloadOpcodes = { import Opcodes._; Array(AALOAD, BALOAD, SALOAD, CALOAD, IALOAD, LALOAD, FALOAD, DALOAD) }
+ val astoreOpcodes = { import Opcodes._; Array(AASTORE, BASTORE, SASTORE, CASTORE, IASTORE, LASTORE, FASTORE, DASTORE) }
+
+ val returnOpcodes = { import Opcodes._; Array(ARETURN, IRETURN, IRETURN, IRETURN, IRETURN, LRETURN, FRETURN, DRETURN) }
+
+ def emitTypeBased(opcs: Array[Int], tk: TypeKind) {
+ assert(tk != UNIT, tk)
+ val opc = {
+ if(tk.isRefOrArrayType) { opcs(0) }
+ else if(tk.isIntSizedType) {
+ (tk: @unchecked) match {
+ case BOOL | BYTE => opcs(1)
+ case SHORT => opcs(2)
+ case CHAR => opcs(3)
+ case INT => opcs(4)
+ }
+ } else {
+ (tk: @unchecked) match {
+ case LONG => opcs(5)
+ case FLOAT => opcs(6)
+ case DOUBLE => opcs(7)
+ }
+ }
+ }
+ jmethod.visitInsn(opc)
+ }
+
+ // ---------------- primitive operations ----------------
+
+ val negOpcodes: Array[Int] = { import Opcodes._; Array(INEG, LNEG, FNEG, DNEG) }
+ val addOpcodes: Array[Int] = { import Opcodes._; Array(IADD, LADD, FADD, DADD) }
+ val subOpcodes: Array[Int] = { import Opcodes._; Array(ISUB, LSUB, FSUB, DSUB) }
+ val mulOpcodes: Array[Int] = { import Opcodes._; Array(IMUL, LMUL, FMUL, DMUL) }
+ val divOpcodes: Array[Int] = { import Opcodes._; Array(IDIV, LDIV, FDIV, DDIV) }
+ val remOpcodes: Array[Int] = { import Opcodes._; Array(IREM, LREM, FREM, DREM) }
+
+ def emitPrimitive(opcs: Array[Int], tk: TypeKind) {
+ val opc = {
+ if(tk.isIntSizedType) { opcs(0) }
+ else {
+ (tk: @unchecked) match {
+ case LONG => opcs(1)
+ case FLOAT => opcs(2)
+ case DOUBLE => opcs(3)
+ }
+ }
+ }
+ jmethod.visitInsn(opc)
+ }
+
+ }
+
+ /** Invoked from genMethod() and addStaticInit() */
+ def genCode(m: IMethod,
+ emitVars: Boolean, // this param name hides the instance-level var
+ isStatic: Boolean) {
+
+
+ newNormal.normalize(m)
+
+ // ------------------------------------------------------------------------------------------------------------
+ // Part 1 of genCode(): setting up one-to-one correspondence between ASM Labels and BasicBlocks `linearization`
+ // ------------------------------------------------------------------------------------------------------------
+
+ val linearization: List[BasicBlock] = linearizer.linearize(m)
+ if(linearization.isEmpty) { return }
+
+ var isModuleInitialized = false
+
+ val labels: collection.Map[BasicBlock, asm.Label] = mutable.HashMap(linearization map (_ -> new asm.Label()) : _*)
+
+ val onePastLast = new asm.Label // token for the mythical instruction past the last instruction in the method being emitted
+
+ // maps a BasicBlock b to the Label that corresponds to b's successor in the linearization. The last BasicBlock is mapped to the onePastLast label.
+ val linNext: collection.Map[BasicBlock, asm.Label] = {
+ val result = mutable.HashMap.empty[BasicBlock, asm.Label]
+ var rest = linearization
+ var prev = rest.head
+ rest = rest.tail
+ while(!rest.isEmpty) {
+ result += (prev -> labels(rest.head))
+ prev = rest.head
+ rest = rest.tail
+ }
+ assert(!result.contains(prev))
+ result += (prev -> onePastLast)
+
+ result
+ }
+
+ // ------------------------------------------------------------------------------------------------------------
+ // Part 2 of genCode(): demarcating exception handler boundaries (visitTryCatchBlock() must be invoked before visitLabel() in genBlock())
+ // ------------------------------------------------------------------------------------------------------------
+
+ /**Generate exception handlers for the current method.
+ *
+ * Quoting from the JVMS 4.7.3 The Code Attribute
+ * The items of the Code_attribute structure are as follows:
+ * . . .
+ * exception_table[]
+ * Each entry in the exception_table array describes one
+ * exception handler in the code array. The order of the handlers in
+ * the exception_table array is significant.
+ * Each exception_table entry contains the following four items:
+ * start_pc, end_pc:
+ * ... The value of end_pc either must be a valid index into
+ * the code array of the opcode of an instruction or must be equal to code_length,
+ * the length of the code array.
+ * handler_pc:
+ * The value of the handler_pc item indicates the start of the exception handler
+ * catch_type:
+ * ... If the value of the catch_type item is zero,
+ * this exception handler is called for all exceptions.
+ * This is used to implement finally
+ */
+ def genExceptionHandlers() {
+
+ /** Return a list of pairs of intervals where the handler is active.
+ * Each interval is closed on both ends, ie. inclusive both in the left and right endpoints: [start, end].
+ * Preconditions:
+ * - e.covered non-empty
+ * Postconditions for the result:
+ * - always non-empty
+ * - intervals are sorted as per `linearization`
+ * - the argument's `covered` blocks have been grouped into maximally contiguous intervals,
+ * ie. between any two intervals in the result there is a non-empty gap.
+ * - each of the `covered` blocks in the argument is contained in some interval in the result
+ */
+ def intervals(e: ExceptionHandler): List[BlockInteval] = {
+ assert(e.covered.nonEmpty, e)
+ var result: List[BlockInteval] = Nil
+ var rest = linearization
+
+ // find intervals
+ while(!rest.isEmpty) {
+ // find interval start
+ var start: BasicBlock = null
+ while(!rest.isEmpty && (start eq null)) {
+ if(e.covered(rest.head)) { start = rest.head }
+ rest = rest.tail
+ }
+ if(start ne null) {
+ // find interval end
+ var end = start // for the time being
+ while(!rest.isEmpty && (e.covered(rest.head))) {
+ end = rest.head
+ rest = rest.tail
+ }
+ result = BlockInteval(start, end) :: result
+ }
+ }
+
+ assert(result.nonEmpty, e)
+
+ result
+ }
+
+ /* TODO test/files/run/exceptions-2.scala displays an ExceptionHandler.covered that contains
+ * blocks not in the linearization (dead-code?). Is that well-formed or not?
+ * For now, we ignore those blocks (after all, that's what `genBlocks(linearization)` in effect does).
+ */
+ for (e <- this.method.exh) {
+ val ignore: Set[BasicBlock] = (e.covered filterNot { b => linearization contains b } )
+ // TODO someday assert(ignore.isEmpty, "an ExceptionHandler.covered contains blocks not in the linearization (dead-code?)")
+ if(ignore.nonEmpty) {
+ e.covered = e.covered filterNot ignore
+ }
+ }
+
+ // an ExceptionHandler lacking covered blocks doesn't get an entry in the Exceptions table.
+ // TODO in that case, ExceptionHandler.cls doesn't go through javaName(). What if cls is an inner class?
+ for (e <- this.method.exh ; if e.covered.nonEmpty ; p <- intervals(e)) {
+ debuglog("Adding exception handler " + e + "at block: " + e.startBlock + " for " + method +
+ " from: " + p.start + " to: " + p.end + " catching: " + e.cls);
+ val cls: String = if (e.cls == NoSymbol || e.cls == ThrowableClass) null
+ else javaName(e.cls)
+ jmethod.visitTryCatchBlock(labels(p.start), linNext(p.end), labels(e.startBlock), cls)
+ }
+ } // end of genCode()'s genExceptionHandlers()
+
+ if (m.exh.nonEmpty) { genExceptionHandlers() }
+
+ // ------------------------------------------------------------------------------------------------------------
+ // Part 3 of genCode(): "Infrastructure" to later emit debug info for local variables and method params (LocalVariablesTable bytecode attribute).
+ // ------------------------------------------------------------------------------------------------------------
+
+ case class LocVarEntry(local: Local, start: asm.Label, end: asm.Label) // start is inclusive while end exclusive.
+
+ case class Interval(lstart: asm.Label, lend: asm.Label) {
+ @inline final def start = lstart.getOffset
+ @inline final def end = lend.getOffset
+
+ def precedes(that: Interval): Boolean = { this.end < that.start }
+
+ def overlaps(that: Interval): Boolean = { !(this.precedes(that) || that.precedes(this)) }
+
+ def mergeWith(that: Interval): Interval = {
+ val newStart = if(this.start <= that.start) this.lstart else that.lstart;
+ val newEnd = if(this.end <= that.end) that.lend else this.lend;
+ Interval(newStart, newEnd)
+ }
+
+ def repOK: Boolean = { start <= end }
+
+ }
+
+ /** Track those instruction ranges where certain locals are in scope. Used to later emit the LocalVariableTable attribute (JVMS 4.7.13) */
+ object scoping {
+
+ private val pending = mutable.Map.empty[Local, mutable.Stack[Label]]
+ private var seen: List[LocVarEntry] = Nil
+
+ private def fuse(ranges: List[Interval], added: Interval): List[Interval] = {
+ assert(added.repOK, added)
+ if(ranges.isEmpty) { return List(added) }
+ // precond: ranges is sorted by increasing start
+ var fused: List[Interval] = Nil
+ var done = false
+ var rest = ranges
+ while(!done && rest.nonEmpty) {
+ val current = rest.head
+ assert(current.repOK, current)
+ rest = rest.tail
+ if(added precedes current) {
+ fused = fused ::: ( added :: current :: rest )
+ done = true
+ } else if(current overlaps added) {
+ fused = fused ::: ( added.mergeWith(current) :: rest )
+ done = true
+ }
+ }
+ if(!done) { fused = fused ::: List(added) }
+ assert(repOK(fused), fused)
+
+ fused
+ }
+
+ def pushScope(lv: Local, start: Label) {
+ val st = pending.getOrElseUpdate(lv, mutable.Stack.empty[Label])
+ st.push(start)
+ }
+ def popScope(lv: Local, end: Label) {
+ val start = pending(lv).pop()
+ seen ::= LocVarEntry(lv, start, end)
+ }
+
+ def getMerged(): collection.Map[Local, List[Interval]] = {
+ // TODO should but isn't: unbalanced start(s) of scope(s)
+ val shouldBeEmpty = pending filter { p => val Pair(k, st) = p; st.nonEmpty };
+
+ val merged = mutable.Map.empty[Local, List[Interval]]
+
+ def addToMerged(lv: Local, start: Label, end: Label) {
+ val ranges = merged.getOrElseUpdate(lv, Nil)
+ val coalesced = fuse(ranges, Interval(start, end))
+ merged.update(lv, coalesced)
+ }
+
+ for(LocVarEntry(lv, start, end) <- seen) { addToMerged(lv, start, end) }
+
+ /* for each var with unbalanced start(s) of scope(s):
+ (a) take the earliest start (among unbalanced and balanced starts)
+ (b) take the latest end (onePastLast if none available)
+ (c) merge the thus made-up interval
+ */
+ for(Pair(k, st) <- shouldBeEmpty) {
+ var start = st.toList.sortBy(_.getOffset).head
+ if(merged.isDefinedAt(k)) {
+ val balancedStart = merged(k).head.lstart
+ if(balancedStart.getOffset < start.getOffset) {
+ start = balancedStart;
+ }
+ }
+ val endOpt: Option[Label] = for(ranges <- merged.get(k)) yield ranges.last.lend;
+ val end = endOpt.getOrElse(onePastLast)
+ addToMerged(k, start, end)
+ }
+
+ merged
+ }
+
+ private def repOK(fused: List[Interval]): Boolean = {
+ fused match {
+ case Nil => true
+ case h :: Nil => h.repOK
+ case h :: n :: rest =>
+ h.repOK && h.precedes(n) && !h.overlaps(n) && repOK(n :: rest)
+ }
+ }
+
+ }
+
+ def genLocalVariableTable() {
+ // adding `this` and method params.
+ if (!isStatic) {
+ jmethod.visitLocalVariable("this", thisDescr, null, labels(m.startBlock), onePastLast, 0)
+ }
+ for(lv <- m.params) {
+ jmethod.visitLocalVariable(javaName(lv.sym), descriptor(lv.kind), null, labels(m.startBlock), onePastLast, indexOf(lv))
+ }
+ // adding non-param locals
+ var anonCounter = 0
+ var fltnd: List[Triple[String, Local, Interval]] = Nil
+ for(Pair(local, ranges) <- scoping.getMerged()) {
+ var name = javaName(local.sym)
+ if (name == null) {
+ anonCounter += 1;
+ name = "<anon" + anonCounter + ">"
+ }
+ for(intrvl <- ranges) {
+ fltnd ::= Triple(name, local, intrvl)
+ }
+ }
+ // quest for deterministic output that Map.toList doesn't provide (so that ant test.stability doesn't complain).
+ val srtd = fltnd.sortBy { kr =>
+ val Triple(name: String, local: Local, intrvl: Interval) = kr
+
+ Triple(intrvl.start, intrvl.end - intrvl.start, name) // ie sort by (start, length, name)
+ }
+
+ for(Triple(name, local, Interval(start, end)) <- srtd) {
+ jmethod.visitLocalVariable(name, descriptor(local.kind), null, start, end, indexOf(local))
+ }
+ // "There may be no more than one LocalVariableTable attribute per local variable in the Code attribute"
+ }
+
+ // ------------------------------------------------------------------------------------------------------------
+ // Part 4 of genCode(): Bookkeeping (to later emit debug info) of association between line-number and instruction position.
+ // ------------------------------------------------------------------------------------------------------------
+
+ case class LineNumberEntry(line: Int, start: asm.Label)
+ var lastLineNr: Int = -1
+ var lnEntries: List[LineNumberEntry] = Nil
+
+ // ------------------------------------------------------------------------------------------------------------
+ // Part 5 of genCode(): "Utilities" to emit code proper (most prominently: genBlock()).
+ // ------------------------------------------------------------------------------------------------------------
+
+ var nextBlock: BasicBlock = linearization.head
+
+ def genBlocks(l: List[BasicBlock]): Unit = l match {
+ case Nil => ()
+ case x :: Nil => nextBlock = null; genBlock(x)
+ case x :: y :: ys => nextBlock = y; genBlock(x); genBlocks(y :: ys)
+ }
+
+ def isAccessibleFrom(target: Symbol, site: Symbol): Boolean = {
+ target.isPublic || target.isProtected && {
+ (site.enclClass isSubClass target.enclClass) ||
+ (site.enclosingPackage == target.privateWithin)
+ }
+ } // end of genCode()'s isAccessibleFrom()
+
+ def genCallMethod(call: CALL_METHOD) {
+ val CALL_METHOD(method, style) = call
+ val siteSymbol = clasz.symbol
+ val hostSymbol = call.hostClass
+ val methodOwner = method.owner
+ // info calls so that types are up to date; erasure may add lateINTERFACE to traits
+ hostSymbol.info ; methodOwner.info
+
+ def isInterfaceCall(sym: Symbol) = (
+ sym.isInterface && methodOwner != ObjectClass
+ || sym.isJavaDefined && sym.isNonBottomSubClass(ClassfileAnnotationClass)
+ )
+ // whether to reference the type of the receiver or
+ // the type of the method owner (if not an interface!)
+ val useMethodOwner = (
+ style != Dynamic
+ || !isInterfaceCall(hostSymbol) && isAccessibleFrom(methodOwner, siteSymbol)
+ || hostSymbol.isBottomClass
+ )
+ val receiver = if (useMethodOwner) methodOwner else hostSymbol
+ val jowner = javaName(receiver)
+ val jname = javaName(method)
+ val jtype = javaType(method).getDescriptor()
+
+ def dbg(invoke: String) {
+ debuglog("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype))
+ }
+
+ def initModule() {
+ // we initialize the MODULE$ field immediately after the super ctor
+ if (isStaticModule(siteSymbol) && !isModuleInitialized &&
+ jMethodName == INSTANCE_CONSTRUCTOR_NAME &&
+ jname == INSTANCE_CONSTRUCTOR_NAME) {
+ isModuleInitialized = true
+ jmethod.visitVarInsn(asm.Opcodes.ALOAD, 0)
+ jmethod.visitFieldInsn(asm.Opcodes.PUTSTATIC, thisName, strMODULE_INSTANCE_FIELD, thisDescr)
+ }
+ }
+
+ style match {
+ case Static(true) => dbg("invokespecial"); jcode.invokespecial (jowner, jname, jtype)
+ case Static(false) => dbg("invokestatic"); jcode.invokestatic (jowner, jname, jtype)
+ case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.invokeinterface(jowner, jname, jtype)
+ case Dynamic => dbg("invokevirtual"); jcode.invokevirtual (jowner, jname, jtype)
+ case SuperCall(_) =>
+ dbg("invokespecial")
+ jcode.invokespecial(jowner, jname, jtype)
+ initModule()
+ }
+ } // end of genCode()'s genCallMethod()
+
+ def genBlock(b: BasicBlock) {
+ jmethod.visitLabel(labels(b))
+
+ import asm.Opcodes;
+
+ debuglog("Generating code for block: " + b)
+
+ // val lastInstr = b.lastInstruction
+
+ for (instr <- b) {
+
+ if(instr.pos.isDefined) {
+ val iPos = instr.pos
+ val currentLineNr = iPos.line
+ val skip = (currentLineNr == lastLineNr) // if(iPos.isRange) iPos.sameRange(lastPos) else
+ if(!skip) {
+ lastLineNr = currentLineNr
+ val lineLab = new asm.Label
+ jmethod.visitLabel(lineLab)
+ lnEntries ::= LineNumberEntry(currentLineNr, lineLab)
+ }
+ }
+
+ instr match {
+ case THIS(_) => jmethod.visitVarInsn(Opcodes.ALOAD, 0)
+
+ case CONSTANT(const) => genConstant(jmethod, const)
+
+ case LOAD_ARRAY_ITEM(kind) => jcode.aload(kind)
+
+ case LOAD_LOCAL(local) => jcode.load(indexOf(local), local.kind)
+
+ case lf @ LOAD_FIELD(field, isStatic) =>
+ var owner = javaName(lf.hostClass)
+ debuglog("LOAD_FIELD with owner: " + owner + " flags: " + Flags.flagsToString(field.owner.flags))
+ val fieldJName = javaName(field)
+ val fieldDescr = descriptor(field)
+ val opc = if (isStatic) Opcodes.GETSTATIC else Opcodes.GETFIELD
+ jmethod.visitFieldInsn(opc, owner, fieldJName, fieldDescr)
+
+ case LOAD_MODULE(module) =>
+ // assert(module.isModule, "Expected module: " + module)
+ debuglog("generating LOAD_MODULE for: " + module + " flags: " + Flags.flagsToString(module.flags));
+ if (clasz.symbol == module.moduleClass && jMethodName != nme.readResolve.toString) {
+ jmethod.visitVarInsn(Opcodes.ALOAD, 0)
+ } else {
+ jmethod.visitFieldInsn(
+ Opcodes.GETSTATIC,
+ javaName(module) /* + "$" */ ,
+ strMODULE_INSTANCE_FIELD,
+ descriptor(module)
+ )
+ }
+
+ case STORE_ARRAY_ITEM(kind) => jcode.astore(kind)
+
+ case STORE_LOCAL(local) => jcode.store(indexOf(local), local.kind)
+
+ case STORE_THIS(_) =>
+ // this only works for impl classes because the self parameter comes first
+ // in the method signature. If that changes, this code has to be revisited.
+ jmethod.visitVarInsn(Opcodes.ASTORE, 0)
+
+ case STORE_FIELD(field, isStatic) =>
+ val owner = javaName(field.owner)
+ val fieldJName = javaName(field)
+ val fieldDescr = descriptor(field)
+ val opc = if (isStatic) Opcodes.PUTSTATIC else Opcodes.PUTFIELD
+ jmethod.visitFieldInsn(opc, owner, fieldJName, fieldDescr)
+
+ case CALL_PRIMITIVE(primitive) => genPrimitive(primitive, instr.pos)
+
+ /** Special handling to access native Array.clone() */
+ case call @ CALL_METHOD(definitions.Array_clone, Dynamic) =>
+ val target: String = javaType(call.targetTypeKind).getInternalName
+ jcode.invokevirtual(target, "clone", mdesc_arrayClone)
+
+ case call @ CALL_METHOD(method, style) => genCallMethod(call)
+
+ case BOX(kind) =>
+ val MethodNameAndType(mname, mdesc) = jBoxTo(kind)
+ jcode.invokestatic(BoxesRunTime, mname, mdesc)
+
+ case UNBOX(kind) =>
+ val MethodNameAndType(mname, mdesc) = jUnboxTo(kind)
+ jcode.invokestatic(BoxesRunTime, mname, mdesc)
+
+ case NEW(REFERENCE(cls)) =>
+ val className = javaName(cls)
+ jmethod.visitTypeInsn(Opcodes.NEW, className)
+
+ case CREATE_ARRAY(elem, 1) => jcode newarray elem
+
+ case CREATE_ARRAY(elem, dims) =>
+ jmethod.visitMultiANewArrayInsn(descriptor(ArrayN(elem, dims)), dims)
+
+ case IS_INSTANCE(tpe) =>
+ val jtyp: asm.Type =
+ tpe match {
+ case REFERENCE(cls) => asm.Type.getObjectType(javaName(cls))
+ case ARRAY(elem) => javaArrayType(javaType(elem))
+ case _ => abort("Unknown reference type in IS_INSTANCE: " + tpe)
+ }
+ jmethod.visitTypeInsn(Opcodes.INSTANCEOF, jtyp.getInternalName)
+
+ case CHECK_CAST(tpe) =>
+ tpe match {
+
+ case REFERENCE(cls) =>
+ if (cls != ObjectClass) { // No need to checkcast for Objects
+ jmethod.visitTypeInsn(Opcodes.CHECKCAST, javaName(cls))
+ }
+
+ case ARRAY(elem) =>
+ val iname = javaArrayType(javaType(elem)).getInternalName
+ jmethod.visitTypeInsn(Opcodes.CHECKCAST, iname)
+
+ case _ => abort("Unknown reference type in IS_INSTANCE: " + tpe)
+ }
+
+ case sw @ SWITCH(tagss, branches) =>
+ assert(branches.length == tagss.length + 1, sw)
+ val flatSize = sw.flatTagsCount
+ val flatKeys = new Array[Int](flatSize)
+ val flatBranches = new Array[asm.Label](flatSize)
+
+ var restTagss = tagss
+ var restBranches = branches
+ var k = 0 // ranges over flatKeys and flatBranches
+ while(restTagss.nonEmpty) {
+ val currLabel = labels(restBranches.head)
+ for(cTag <- restTagss.head) {
+ flatKeys(k) = cTag;
+ flatBranches(k) = currLabel
+ k += 1
+ }
+ restTagss = restTagss.tail
+ restBranches = restBranches.tail
+ }
+ val defaultLabel = labels(restBranches.head)
+ assert(restBranches.tail.isEmpty)
+ debuglog("Emitting SWITCH:\ntags: " + tagss + "\nbranches: " + branches)
+ jcode.emitSWITCH(flatKeys, flatBranches, defaultLabel, MIN_SWITCH_DENSITY)
+
+ case JUMP(whereto) =>
+ if (nextBlock != whereto) {
+ jcode goTo labels(whereto)
+ }
+
+ case CJUMP(success, failure, cond, kind) =>
+ if(kind.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
+ if (nextBlock == success) {
+ jcode.emitIF_ICMP(cond.negate, labels(failure))
+ // .. and fall through to success label
+ } else {
+ jcode.emitIF_ICMP(cond, labels(success))
+ if (nextBlock != failure) { jcode goTo labels(failure) }
+ }
+ } else if(kind.isRefOrArrayType) { // REFERENCE(_) | ARRAY(_)
+ if (nextBlock == success) {
+ jcode.emitIF_ACMP(cond.negate, labels(failure))
+ // .. and fall through to success label
+ } else {
+ jcode.emitIF_ACMP(cond, labels(success))
+ if (nextBlock != failure) { jcode goTo labels(failure) }
+ }
+ } else {
+ (kind: @unchecked) match {
+ case LONG => emit(Opcodes.LCMP)
+ case FLOAT =>
+ if (cond == LT || cond == LE) emit(Opcodes.FCMPG)
+ else emit(Opcodes.FCMPL)
+ case DOUBLE =>
+ if (cond == LT || cond == LE) emit(Opcodes.DCMPG)
+ else emit(Opcodes.DCMPL)
+ }
+ if (nextBlock == success) {
+ jcode.emitIF(cond.negate, labels(failure))
+ // .. and fall through to success label
+ } else {
+ jcode.emitIF(cond, labels(success))
+ if (nextBlock != failure) { jcode goTo labels(failure) }
+ }
+ }
+
+ case CZJUMP(success, failure, cond, kind) =>
+ if(kind.isIntSizedType) { // BOOL, BYTE, CHAR, SHORT, or INT
+ if (nextBlock == success) {
+ jcode.emitIF(cond.negate, labels(failure))
+ } else {
+ jcode.emitIF(cond, labels(success))
+ if (nextBlock != failure) { jcode goTo labels(failure) }
+ }
+ } else if(kind.isRefOrArrayType) { // REFERENCE(_) | ARRAY(_)
+ val Success = success
+ val Failure = failure
+ (cond, nextBlock) match {
+ case (EQ, Success) => jcode emitIFNONNULL labels(failure)
+ case (NE, Failure) => jcode emitIFNONNULL labels(success)
+ case (EQ, Failure) => jcode emitIFNULL labels(success)
+ case (NE, Success) => jcode emitIFNULL labels(failure)
+ case (EQ, _) =>
+ jcode emitIFNULL labels(success)
+ jcode goTo labels(failure)
+ case (NE, _) =>
+ jcode emitIFNONNULL labels(success)
+ jcode goTo labels(failure)
+ }
+ } else {
+ (kind: @unchecked) match {
+ case LONG =>
+ emit(Opcodes.LCONST_0)
+ emit(Opcodes.LCMP)
+ case FLOAT =>
+ emit(Opcodes.FCONST_0)
+ if (cond == LT || cond == LE) emit(Opcodes.FCMPG)
+ else emit(Opcodes.FCMPL)
+ case DOUBLE =>
+ emit(Opcodes.DCONST_0)
+ if (cond == LT || cond == LE) emit(Opcodes.DCMPG)
+ else emit(Opcodes.DCMPL)
+ }
+ if (nextBlock == success) {
+ jcode.emitIF(cond.negate, labels(failure))
+ } else {
+ jcode.emitIF(cond, labels(success))
+ if (nextBlock != failure) { jcode goTo labels(failure) }
+ }
+ }
+
+ case RETURN(kind) => jcode emitRETURN kind
+
+ case THROW(_) => emit(Opcodes.ATHROW)
+
+ case DROP(kind) =>
+ emit(if(kind.isWideType) Opcodes.POP2 else Opcodes.POP)
+
+ case DUP(kind) =>
+ emit(if(kind.isWideType) Opcodes.DUP2 else Opcodes.DUP)
+
+ case MONITOR_ENTER() => emit(Opcodes.MONITORENTER)
+
+ case MONITOR_EXIT() => emit(Opcodes.MONITOREXIT)
+
+ case SCOPE_ENTER(lv) =>
+ // locals removed by closelim (via CopyPropagation) may have left behind SCOPE_ENTER, SCOPE_EXIT that are to be ignored
+ val relevant = (!lv.sym.isSynthetic && m.locals.contains(lv))
+ if(relevant) { // TODO check: does GenICode emit SCOPE_ENTER, SCOPE_EXIT for synthetic vars?
+ // this label will have DEBUG bit set in its flags (ie ASM ignores it for dataflow purposes)
+ // similarly, these labels aren't tracked in the `labels` map.
+ val start = new asm.Label
+ jmethod.visitLabel(start)
+ scoping.pushScope(lv, start)
+ }
+
+ case SCOPE_EXIT(lv) =>
+ val relevant = (!lv.sym.isSynthetic && m.locals.contains(lv))
+ if(relevant) {
+ // this label will have DEBUG bit set in its flags (ie ASM ignores it for dataflow purposes)
+ // similarly, these labels aren't tracked in the `labels` map.
+ val end = new asm.Label
+ jmethod.visitLabel(end)
+ scoping.popScope(lv, end)
+ }
+
+ case LOAD_EXCEPTION(_) =>
+ ()
+ }
+
+ }
+
+ } // end of genCode()'s genBlock()
+
+ /**
+ * Emits one or more conversion instructions based on the types given as arguments.
+ *
+ * @param from The type of the value to be converted into another type.
+ * @param to The type the value will be converted into.
+ */
+ def emitT2T(from: TypeKind, to: TypeKind) {
+ assert(isNonUnitValueTK(from), from)
+ assert(isNonUnitValueTK(to), to)
+
+ def pickOne(opcs: Array[Int]) {
+ val chosen = (to: @unchecked) match {
+ case BYTE => opcs(0)
+ case SHORT => opcs(1)
+ case CHAR => opcs(2)
+ case INT => opcs(3)
+ case LONG => opcs(4)
+ case FLOAT => opcs(5)
+ case DOUBLE => opcs(6)
+ }
+ if(chosen != -1) { emit(chosen) }
+ }
+
+ if(from == to) { return }
+ if((from == BOOL) || (to == BOOL)) {
+ // the only conversion involving BOOL that is allowed is (BOOL -> BOOL)
+ throw new Error("inconvertible types : " + from.toString() + " -> " + to.toString())
+ }
+
+ if(from.isIntSizedType) { // BYTE, CHAR, SHORT, and INT. (we're done with BOOL already)
+
+ val fromByte = { import asm.Opcodes._; Array( -1, -1, I2C, -1, I2L, I2F, I2D) } // do nothing for (BYTE -> SHORT) and for (BYTE -> INT)
+ val fromChar = { import asm.Opcodes._; Array(I2B, I2S, -1, -1, I2L, I2F, I2D) } // for (CHAR -> INT) do nothing
+ val fromShort = { import asm.Opcodes._; Array(I2B, -1, I2C, -1, I2L, I2F, I2D) } // for (SHORT -> INT) do nothing
+ val fromInt = { import asm.Opcodes._; Array(I2B, I2S, I2C, -1, I2L, I2F, I2D) }
+
+ (from: @unchecked) match {
+ case BYTE => pickOne(fromByte)
+ case SHORT => pickOne(fromShort)
+ case CHAR => pickOne(fromChar)
+ case INT => pickOne(fromInt)
+ }
+
+ } else { // FLOAT, LONG, DOUBLE
+
+ (from: @unchecked) match {
+ case FLOAT =>
+ import asm.Opcodes.{ F2L, F2D, F2I }
+ (to: @unchecked) match {
+ case LONG => emit(F2L)
+ case DOUBLE => emit(F2D)
+ case _ => emit(F2I); emitT2T(INT, to)
+ }
+
+ case LONG =>
+ import asm.Opcodes.{ L2F, L2D, L2I }
+ (to: @unchecked) match {
+ case FLOAT => emit(L2F)
+ case DOUBLE => emit(L2D)
+ case _ => emit(L2I); emitT2T(INT, to)
+ }
+
+ case DOUBLE =>
+ import asm.Opcodes.{ D2L, D2F, D2I }
+ (to: @unchecked) match {
+ case FLOAT => emit(D2F)
+ case LONG => emit(D2L)
+ case _ => emit(D2I); emitT2T(INT, to)
+ }
+ }
+ }
+ } // end of genCode()'s emitT2T()
+
+ def genPrimitive(primitive: Primitive, pos: Position) {
+
+ import asm.Opcodes;
+
+ primitive match {
+
+ case Negation(kind) => jcode.neg(kind)
+
+ case Arithmetic(op, kind) =>
+ op match {
+
+ case ADD => jcode.add(kind)
+ case SUB => jcode.sub(kind)
+ case MUL => jcode.mul(kind)
+ case DIV => jcode.div(kind)
+ case REM => jcode.rem(kind)
+
+ case NOT =>
+ if(kind.isIntSizedType) {
+ emit(Opcodes.ICONST_M1)
+ emit(Opcodes.IXOR)
+ } else if(kind == LONG) {
+ jmethod.visitLdcInsn(new java.lang.Long(-1))
+ jmethod.visitInsn(Opcodes.LXOR)
+ } else {
+ abort("Impossible to negate an " + kind)
+ }
+
+ case _ =>
+ abort("Unknown arithmetic primitive " + primitive)
+ }
+
+ // TODO Logical's 2nd elem should be declared ValueTypeKind, to better approximate its allowed values (isIntSized, its comments appears to convey)
+ // TODO GenICode uses `toTypeKind` to define that elem, `toValueTypeKind` would be needed instead.
+ // TODO How about adding some asserts to Logical and similar ones to capture the remaining constraint (UNIT not allowed).
+ case Logical(op, kind) => (op, kind) match {
+ case (AND, LONG) => emit(Opcodes.LAND)
+ case (AND, INT) => emit(Opcodes.IAND)
+ case (AND, _) =>
+ emit(Opcodes.IAND)
+ if (kind != BOOL) { emitT2T(INT, kind) }
+
+ case (OR, LONG) => emit(Opcodes.LOR)
+ case (OR, INT) => emit(Opcodes.IOR)
+ case (OR, _) =>
+ emit(Opcodes.IOR)
+ if (kind != BOOL) { emitT2T(INT, kind) }
+
+ case (XOR, LONG) => emit(Opcodes.LXOR)
+ case (XOR, INT) => emit(Opcodes.IXOR)
+ case (XOR, _) =>
+ emit(Opcodes.IXOR)
+ if (kind != BOOL) { emitT2T(INT, kind) }
+ }
+
+ case Shift(op, kind) => (op, kind) match {
+ case (LSL, LONG) => emit(Opcodes.LSHL)
+ case (LSL, INT) => emit(Opcodes.ISHL)
+ case (LSL, _) =>
+ emit(Opcodes.ISHL)
+ emitT2T(INT, kind)
+
+ case (ASR, LONG) => emit(Opcodes.LSHR)
+ case (ASR, INT) => emit(Opcodes.ISHR)
+ case (ASR, _) =>
+ emit(Opcodes.ISHR)
+ emitT2T(INT, kind)
+
+ case (LSR, LONG) => emit(Opcodes.LUSHR)
+ case (LSR, INT) => emit(Opcodes.IUSHR)
+ case (LSR, _) =>
+ emit(Opcodes.IUSHR)
+ emitT2T(INT, kind)
+ }
+
+ case Comparison(op, kind) => ((op, kind): @unchecked) match {
+ case (CMP, LONG) => emit(Opcodes.LCMP)
+ case (CMPL, FLOAT) => emit(Opcodes.FCMPL)
+ case (CMPG, FLOAT) => emit(Opcodes.FCMPG)
+ case (CMPL, DOUBLE) => emit(Opcodes.DCMPL)
+ case (CMPG, DOUBLE) => emit(Opcodes.DCMPL) // TODO bug? why not DCMPG? http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc3.html
+ }
+
+ case Conversion(src, dst) =>
+ debuglog("Converting from: " + src + " to: " + dst)
+ if (dst == BOOL) { println("Illegal conversion at: " + clasz + " at: " + pos.source + ":" + pos.line) }
+ else { emitT2T(src, dst) }
+
+ case ArrayLength(_) => emit(Opcodes.ARRAYLENGTH)
+
+ case StartConcat =>
+ jmethod.visitTypeInsn(Opcodes.NEW, StringBuilderClassName)
+ jmethod.visitInsn(Opcodes.DUP)
+ jcode.invokespecial(
+ StringBuilderClassName,
+ INSTANCE_CONSTRUCTOR_NAME,
+ mdesc_arglessvoid
+ )
+
+ case StringConcat(el) =>
+ val jtype = el match {
+ case REFERENCE(_) | ARRAY(_) => JAVA_LANG_OBJECT
+ case _ => javaType(el)
+ }
+ jcode.invokevirtual(
+ StringBuilderClassName,
+ "append",
+ asm.Type.getMethodDescriptor(StringBuilderType, Array(jtype): _*)
+ )
+
+ case EndConcat =>
+ jcode.invokevirtual(StringBuilderClassName, "toString", mdesc_toString)
+
+ case _ => abort("Unimplemented primitive " + primitive)
+ }
+ } // end of genCode()'s genPrimitive()
+
+ // ------------------------------------------------------------------------------------------------------------
+ // Part 6 of genCode(): the executable part of genCode() starts here.
+ // ------------------------------------------------------------------------------------------------------------
+
+ genBlocks(linearization)
+
+ jmethod.visitLabel(onePastLast)
+
+ if(emitLines) {
+ for(LineNumberEntry(line, start) <- lnEntries.sortBy(_.start.getOffset)) { jmethod.visitLineNumber(line, start) }
+ }
+ if(emitVars) { genLocalVariableTable() }
+
+ } // end of BytecodeGenerator.genCode()
+
+
+ ////////////////////// local vars ///////////////////////
+
+ // def sizeOf(sym: Symbol): Int = sizeOf(toTypeKind(sym.tpe))
+
+ def sizeOf(k: TypeKind): Int = if(k.isWideType) 2 else 1
+
+ // def indexOf(m: IMethod, sym: Symbol): Int = {
+ // val Some(local) = m lookupLocal sym
+ // indexOf(local)
+ // }
+
+ @inline final def indexOf(local: Local): Int = {
+ assert(local.index >= 0, "Invalid index for: " + local + "{" + local.## + "}: ")
+ local.index
+ }
+
+ /**
+ * Compute the indexes of each local variable of the given method.
+ * *Does not assume the parameters come first!*
+ */
+ def computeLocalVarsIndex(m: IMethod) {
+ var idx = if (m.symbol.isStaticMember) 0 else 1;
+
+ for (l <- m.params) {
+ debuglog("Index value for " + l + "{" + l.## + "}: " + idx)
+ l.index = idx
+ idx += sizeOf(l.kind)
+ }
+
+ for (l <- m.locals if !l.arg) {
+ debuglog("Index value for " + l + "{" + l.## + "}: " + idx)
+ l.index = idx
+ idx += sizeOf(l.kind)
+ }
+ }
+
+ } // end of class JPlainBuilder
+
+
+ /** builder of mirror classes */
+ class JMirrorBuilder(bytecodeWriter: BytecodeWriter) extends JCommonBuilder(bytecodeWriter) {
+
+ private var cunit: CompilationUnit = _
+ def getCurrentCUnit(): CompilationUnit = cunit;
+
+ /** Generate a mirror class for a top-level module. A mirror class is a class
+ * containing only static methods that forward to the corresponding method
+ * on the MODULE instance of the given Scala object. It will only be
+ * generated if there is no companion class: if there is, an attempt will
+ * instead be made to add the forwarder methods to the companion class.
+ */
+ def genMirrorClass(modsym: Symbol, cunit: CompilationUnit) {
+ assert(modsym.companionClass == NoSymbol, modsym)
+ innerClassBuffer.clear()
+ this.cunit = cunit
+ val moduleName = javaName(modsym) // + "$"
+ val mirrorName = moduleName.substring(0, moduleName.length() - 1)
+
+ val flags = (asm.Opcodes.ACC_SUPER | asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_FINAL)
+ val mirrorClass = createJClass(flags,
+ mirrorName,
+ null /* no java-generic-signature */,
+ JAVA_LANG_OBJECT.getInternalName,
+ EMPTY_STRING_ARRAY)
+
+ log("Dumping mirror class for '%s'".format(mirrorName))
+
+ // typestate: entering mode with valid call sequences:
+ // [ visitSource ] [ visitOuterClass ] ( visitAnnotation | visitAttribute )*
+
+ mirrorClass.visitSource("" + cunit.source,
+ null /* SourceDebugExtension */)
+
+ val ssa = getAnnotPickle(mirrorName, modsym.companionSymbol)
+ mirrorClass.visitAttribute(if(ssa.isDefined) pickleMarkerLocal else pickleMarkerForeign)
+ emitAnnotations(mirrorClass, modsym.annotations ++ ssa)
+
+ // typestate: entering mode with valid call sequences:
+ // ( visitInnerClass | visitField | visitMethod )* visitEnd
+
+ addForwarders(isRemote(modsym), mirrorClass, mirrorName, modsym)
+
+ addInnerClasses(modsym, mirrorClass)
+ mirrorClass.visitEnd()
+ writeIfNotTooBig("" + modsym.name, mirrorName, mirrorClass, modsym)
+ }
+
+
+ } // end of class JMirrorBuilder
+
+
+ /** builder of bean info classes */
+ class JBeanInfoBuilder(bytecodeWriter: BytecodeWriter) extends JBuilder(bytecodeWriter) {
+
+ /**
+ * Generate a bean info class that describes the given class.
+ *
+ * @author Ross Judson (ross.judson@soletta.com)
+ */
+ def genBeanInfoClass(clasz: IClass) {
+
+ // val BeanInfoSkipAttr = definitions.getRequiredClass("scala.beans.BeanInfoSkip")
+ // val BeanDisplayNameAttr = definitions.getRequiredClass("scala.beans.BeanDisplayName")
+ // val BeanDescriptionAttr = definitions.getRequiredClass("scala.beans.BeanDescription")
+ // val description = c.symbol getAnnotation BeanDescriptionAttr
+ // informProgress(description.toString)
+ innerClassBuffer.clear()
+
+ val flags = mkFlags(
+ javaFlags(clasz.symbol),
+ if(isDeprecated(clasz.symbol)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo access flag
+ )
+
+ val beanInfoName = (javaName(clasz.symbol) + "BeanInfo")
+ val beanInfoClass = createJClass(
+ flags,
+ beanInfoName,
+ null, // no java-generic-signature
+ "scala/beans/ScalaBeanInfo",
+ EMPTY_STRING_ARRAY
+ )
+
+ // beanInfoClass typestate: entering mode with valid call sequences:
+ // [ visitSource ] [ visitOuterClass ] ( visitAnnotation | visitAttribute )*
+
+ beanInfoClass.visitSource(
+ clasz.cunit.source.toString,
+ null /* SourceDebugExtension */
+ )
+
+ var fieldList = List[String]()
+
+ for (f <- clasz.fields if f.symbol.hasGetter;
+ g = f.symbol.getter(clasz.symbol);
+ s = f.symbol.setter(clasz.symbol);
+ if g.isPublic && !(f.symbol.name startsWith "$")
+ ) {
+ // inserting $outer breaks the bean
+ fieldList = javaName(f.symbol) :: javaName(g) :: (if (s != NoSymbol) javaName(s) else null) :: fieldList
+ }
+
+ val methodList: List[String] =
+ for (m <- clasz.methods
+ if !m.symbol.isConstructor &&
+ m.symbol.isPublic &&
+ !(m.symbol.name startsWith "$") &&
+ !m.symbol.isGetter &&
+ !m.symbol.isSetter)
+ yield javaName(m.symbol)
+
+ // beanInfoClass typestate: entering mode with valid call sequences:
+ // ( visitInnerClass | visitField | visitMethod )* visitEnd
+
+ val constructor = beanInfoClass.visitMethod(
+ asm.Opcodes.ACC_PUBLIC,
+ INSTANCE_CONSTRUCTOR_NAME,
+ mdesc_arglessvoid,
+ null, // no java-generic-signature
+ EMPTY_STRING_ARRAY // no throwable exceptions
+ )
+
+ // constructor typestate: entering mode with valid call sequences:
+ // [ visitAnnotationDefault ] ( visitAnnotation | visitParameterAnnotation | visitAttribute )*
+
+ val stringArrayJType: asm.Type = javaArrayType(JAVA_LANG_STRING)
+ val conJType: asm.Type =
+ asm.Type.getMethodType(
+ asm.Type.VOID_TYPE,
+ Array(javaType(ClassClass), stringArrayJType, stringArrayJType): _*
+ )
+
+ def push(lst: List[String]) {
+ var fi = 0
+ for (f <- lst) {
+ constructor.visitInsn(asm.Opcodes.DUP)
+ constructor.visitLdcInsn(new java.lang.Integer(fi))
+ if (f == null) { constructor.visitInsn(asm.Opcodes.ACONST_NULL) }
+ else { constructor.visitLdcInsn(f) }
+ constructor.visitInsn(JAVA_LANG_STRING.getOpcode(asm.Opcodes.IASTORE))
+ fi += 1
+ }
+ }
+
+ // constructor typestate: entering mode with valid call sequences:
+ // [ visitCode ( visitFrame | visitXInsn | visitLabel | visitTryCatchBlock | visitLocalVariable | visitLineNumber )* visitMaxs ] visitEnd
+
+ constructor.visitCode()
+
+ constructor.visitVarInsn(asm.Opcodes.ALOAD, 0)
+ // push the class
+ constructor.visitLdcInsn(javaType(clasz.symbol))
+
+ // push the string array of field information
+ constructor.visitLdcInsn(new java.lang.Integer(fieldList.length))
+ constructor.visitTypeInsn(asm.Opcodes.ANEWARRAY, JAVA_LANG_STRING.getInternalName)
+ push(fieldList)
+
+ // push the string array of method information
+ constructor.visitLdcInsn(new java.lang.Integer(methodList.length))
+ constructor.visitTypeInsn(asm.Opcodes.ANEWARRAY, JAVA_LANG_STRING.getInternalName)
+ push(methodList)
+
+ // invoke the superclass constructor, which will do the
+ // necessary java reflection and create Method objects.
+ constructor.visitMethodInsn(asm.Opcodes.INVOKESPECIAL, "scala/beans/ScalaBeanInfo", INSTANCE_CONSTRUCTOR_NAME, conJType.getDescriptor)
+ constructor.visitInsn(asm.Opcodes.RETURN)
+
+ constructor.visitMaxs(0, 0) // just to follow protocol, dummy arguments
+ constructor.visitEnd()
+
+ // TODO no inner classes attribute is written. Confirm intent.
+ assert(innerClassBuffer.isEmpty, innerClassBuffer)
+
+ beanInfoClass.visitEnd()
+
+ writeIfNotTooBig("BeanInfo ", beanInfoName, beanInfoClass, clasz.symbol)
+ }
+
+ } // end of class JBeanInfoBuilder
+
+ /** A namespace for utilities to normalize the code of an IMethod, over and beyond what IMethod.normalize() strives for.
+ * In particualr, IMethod.normalize() doesn't collapseJumpChains().
+ *
+ * TODO Eventually, these utilities should be moved to IMethod and reused from normalize() (there's nothing JVM-specific about them).
+ */
+ object newNormal {
+
+ def startsWithJump(b: BasicBlock): Boolean = { assert(b.nonEmpty, "empty block"); b.firstInstruction.isInstanceOf[JUMP] }
+
+ /** Prune from an exception handler those covered blocks which are jump-only. */
+ private def coverWhatCountsOnly(m: IMethod): Boolean = {
+ assert(m.hasCode, "code-less method")
+
+ var wasReduced = false
+ for(h <- m.exh) {
+ val shouldntCover = (h.covered filter startsWithJump)
+ if(shouldntCover.nonEmpty) {
+ wasReduced = true
+ h.covered --= shouldntCover // not removing any block on purpose.
+ }
+ }
+
+ wasReduced
+ }
+
+ /** An exception handler is pruned provided any of the following holds:
+ * (1) it covers nothing (for example, this may result after removing unreachable blocks)
+ * (2) each block it covers is of the form: JUMP(_)
+ * Return true iff one or more ExceptionHandlers were removed.
+ *
+ * A caveat: removing an exception handler, for whatever reason, means that its handler code (even if unreachable)
+ * won't be able to cause a class-loading-exception. As a result, behavior can be different.
+ */
+ private def elimNonCoveringExh(m: IMethod): Boolean = {
+ assert(m.hasCode, "code-less method")
+
+ def isRedundant(eh: ExceptionHandler): Boolean = {
+ (eh.cls != NoSymbol) && ( // TODO `eh.isFinallyBlock` more readable than `eh.cls != NoSymbol`
+ eh.covered.isEmpty
+ || (eh.covered forall startsWithJump)
+ )
+ }
+
+ var wasReduced = false
+ val toPrune = (m.exh.toSet filter isRedundant)
+ if(toPrune.nonEmpty) {
+ wasReduced = true
+ for(h <- toPrune; r <- h.blocks) { m.code.removeBlock(r) } // TODO m.code.removeExh(h)
+ m.exh = (m.exh filterNot toPrune)
+ }
+
+ wasReduced
+ }
+
+ private def isJumpOnly(b: BasicBlock): Option[BasicBlock] = {
+ b.toList match {
+ case JUMP(whereto) :: rest =>
+ assert(rest.isEmpty, "A block contains instructions after JUMP (looks like enterIgnoreMode() was itself ignored.)")
+ Some(whereto)
+ case _ => None
+ }
+ }
+
+ private def directSuccStar(b: BasicBlock): List[BasicBlock] = { directSuccStar(List(b)) }
+
+ /** Transitive closure of successors potentially reachable due to normal (non-exceptional) control flow.
+ Those BBs in the argument are also included in the result */
+ private def directSuccStar(starters: Traversable[BasicBlock]): List[BasicBlock] = {
+ val result = new mutable.ListBuffer[BasicBlock]
+ var toVisit: List[BasicBlock] = starters.toList.distinct
+ while(toVisit.nonEmpty) {
+ val h = toVisit.head
+ toVisit = toVisit.tail
+ result += h
+ for(p <- h.directSuccessors; if !result.contains(p) && !toVisit.contains(p)) { toVisit = p :: toVisit }
+ }
+ result.toList
+ }
+
+ /** Returns:
+ * for single-block self-loops, the pair (start, Nil)
+ * for other cycles, the pair (backedge-target, basic-blocks-in-the-cycle-except-backedge-target)
+ * otherwise a pair consisting of:
+ * (a) the endpoint of a (single or multi-hop) chain of JUMPs
+ * (such endpoint does not start with a JUMP and therefore is not part of the chain); and
+ * (b) the chain (ie blocks to be removed when collapsing the chain of jumps).
+ * Precondition: the BasicBlock given as argument starts with an unconditional JUMP.
+ */
+ private def finalDestination(start: BasicBlock): (BasicBlock, List[BasicBlock]) = {
+ assert(startsWithJump(start), "not the start of a (single or multi-hop) chain of JUMPs.")
+ var hops: List[BasicBlock] = Nil
+ var prev = start
+ var done = false
+ do {
+ done = isJumpOnly(prev) match {
+ case Some(dest) =>
+ if (dest == start) { return (start, hops) } // leave infinite-loops in place
+ hops ::= prev
+ if (hops.contains(dest)) {
+ // leave infinite-loops in place
+ return (dest, hops filterNot (dest eq))
+ }
+ prev = dest;
+ false
+ case None => true
+ }
+ } while(!done)
+
+ (prev, hops)
+ }
+
+ /**
+ * Collapse a chain of "jump-only" blocks such as:
+ *
+ * JUMP b1;
+ * b1: JUMP b2;
+ * b2: JUMP ... etc.
+ *
+ * by re-wiring predecessors to target directly the "final destination".
+ * Even if covered by an exception handler, a "non-self-loop jump-only block" can always be removed.
+
+ * Returns true if any replacement was made, false otherwise.
+ *
+ * In more detail:
+ * Starting at each of the entry points (m.startBlock, the start block of each exception handler)
+ * rephrase those control-flow instructions targeting a jump-only block (which jumps to a final destination D) to target D.
+ * The blocks thus skipped are also removed from IMethod.blocks.
+ *
+ * Rationale for this normalization:
+ * test/files/run/private-inline.scala after -optimize is chock full of
+ * BasicBlocks containing just JUMP(whereTo), where no exception handler straddles them.
+ * They should be collapsed by IMethod.normalize() but aren't.
+ * That was fine in FJBG times when by the time the exception table was emitted,
+ * it already contained "anchored" labels (ie instruction offsets were known)
+ * and thus ranges with identical (start, end) (i.e, identical after GenJVM omitted the JUMPs in question)
+ * could be weeded out to avoid "java.lang.ClassFormatError: Illegal exception table range"
+ * Now that visitTryCatchBlock() must be called before Labels are resolved,
+ * this method gets rid of the BasicBlocks described above (to recap, consisting of just a JUMP).
+ */
+ private def collapseJumpOnlyBlocks(m: IMethod): Boolean = {
+ assert(m.hasCode, "code-less method")
+
+ /* "start" is relative in a cycle, but we call this helper with the "first" entry-point we found. */
+ def realTarget(jumpStart: BasicBlock): Map[BasicBlock, BasicBlock] = {
+ assert(startsWithJump(jumpStart), "not part of a jump-chain")
+ val Pair(dest, redundants) = finalDestination(jumpStart)
+ (for(skipOver <- redundants) yield Pair(skipOver, dest)).toMap
+ }
+
+ def rephraseGotos(detour: Map[BasicBlock, BasicBlock]) {
+ for(Pair(oldTarget, newTarget) <- detour.iterator) {
+ if(m.startBlock == oldTarget) {
+ m.code.startBlock = newTarget
+ }
+ for(eh <- m.exh; if eh.startBlock == oldTarget) {
+ eh.setStartBlock(newTarget)
+ }
+ for(b <- m.blocks; if !detour.isDefinedAt(b)) {
+ val idxLast = (b.size - 1)
+ b.lastInstruction match {
+ case JUMP(whereto) =>
+ if (whereto == oldTarget) {
+ b.replaceInstruction(idxLast, JUMP(newTarget))
+ }
+ case CJUMP(succ, fail, cond, kind) =>
+ if ((succ == oldTarget) || (fail == oldTarget)) {
+ b.replaceInstruction(idxLast, CJUMP(detour.getOrElse(succ, succ),
+ detour.getOrElse(fail, fail),
+ cond, kind))
+ }
+ case CZJUMP(succ, fail, cond, kind) =>
+ if ((succ == oldTarget) || (fail == oldTarget)) {
+ b.replaceInstruction(idxLast, CZJUMP(detour.getOrElse(succ, succ),
+ detour.getOrElse(fail, fail),
+ cond, kind))
+ }
+ case SWITCH(tags, labels) =>
+ if(labels exists (detour.isDefinedAt(_))) {
+ val newLabels = (labels map { lab => detour.getOrElse(lab, lab) })
+ b.replaceInstruction(idxLast, SWITCH(tags, newLabels))
+ }
+ case _ => ()
+ }
+ }
+ }
+ }
+
+ /* remove from all containers that may contain a reference to */
+ def elide(redu: BasicBlock) {
+ assert(m.startBlock != redu, "startBlock should have been re-wired by now")
+ m.code.removeBlock(redu);
+ }
+
+ var wasReduced = false
+ val entryPoints: List[BasicBlock] = m.startBlock :: (m.exh map (_.startBlock));
+
+ var elided = mutable.Set.empty[BasicBlock] // debug
+ var newTargets = mutable.Set.empty[BasicBlock] // debug
+
+ for (ep <- entryPoints) {
+ var reachable = directSuccStar(ep) // this list may contain blocks belonging to jump-chains that we'll skip over
+ while(reachable.nonEmpty) {
+ val h = reachable.head
+ reachable = reachable.tail
+ if(startsWithJump(h)) {
+ val detour = realTarget(h)
+ if(detour.nonEmpty) {
+ wasReduced = true
+ reachable = (reachable filterNot (detour.keySet.contains(_)))
+ rephraseGotos(detour)
+ detour.keySet foreach elide
+ elided ++= detour.keySet
+ newTargets ++= detour.values
+ }
+ }
+ }
+ }
+ assert(newTargets.intersect(elided).isEmpty, "contradiction: we just elided the final destionation of a jump-chain")
+
+ wasReduced
+ }
+
+ def normalize(m: IMethod) {
+ if(!m.hasCode) { return }
+ collapseJumpOnlyBlocks(m)
+ var wasReduced = false;
+ do {
+ wasReduced = false
+ // Prune from an exception handler those covered blocks which are jump-only.
+ wasReduced |= coverWhatCountsOnly(m); icodes.checkValid(m) // TODO should be unnecessary now that collapseJumpOnlyBlocks(m) is in place
+ // Prune exception handlers covering nothing.
+ wasReduced |= elimNonCoveringExh(m); icodes.checkValid(m)
+
+ // TODO see note in genExceptionHandlers about an ExceptionHandler.covered containing dead blocks (newNormal should remove them, but, where do those blocks come from?)
+ } while (wasReduced)
+
+ // TODO this would be a good time to remove synthetic local vars seeing no use, don't forget to call computeLocalVarsIndex() afterwards.
+ }
+
+ }
+
+}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index 7b7135d180..042e739abe 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc
package backend.jvm
-import java.io.{ DataOutputStream, OutputStream }
+import java.io.{ByteArrayOutputStream, DataOutputStream, OutputStream }
import java.nio.ByteBuffer
import scala.collection.{ mutable, immutable }
import scala.reflect.internal.pickling.{ PickleFormat, PickleBuffer }
@@ -19,6 +19,7 @@ import JAccessFlags._
import JObjectType.{ JAVA_LANG_STRING, JAVA_LANG_OBJECT }
import java.util.jar.{ JarEntry, JarOutputStream }
import scala.tools.nsc.io.AbstractFile
+import language.postfixOps
/** This class ...
*
@@ -344,7 +345,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
*/
def emitClass(jclass: JClass, sym: Symbol) {
addInnerClasses(jclass)
- writeClass("" + sym.name, jclass, sym)
+ writeClass("" + sym.name, jclass.getName(), toByteArray(jclass), sym)
}
/** Returns the ScalaSignature annotation if it must be added to this class,
@@ -516,6 +517,14 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
}
+ private def toByteArray(jc: JClass): Array[Byte] = {
+ val bos = new java.io.ByteArrayOutputStream()
+ val dos = new java.io.DataOutputStream(bos)
+ jc.writeTo(dos)
+ dos.close()
+ bos.toByteArray
+ }
+
/**
* Generate a bean info class that describes the given class.
*
@@ -585,7 +594,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
jcode.emitRETURN()
// write the bean information class file.
- writeClass("BeanInfo ", beanInfoClass, c.symbol)
+ writeClass("BeanInfo ", beanInfoClass.getName(), toByteArray(beanInfoClass), c.symbol)
}
/** Add the given 'throws' attributes to jmethod */
@@ -651,7 +660,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
case StringTag =>
buf put 's'.toByte
buf putShort cpool.addUtf8(const.stringValue).toShort
- case ClassTag =>
+ case ClazzTag =>
buf put 'c'.toByte
buf putShort cpool.addUtf8(javaType(const.typeValue).getSignature()).toShort
case EnumTag =>
@@ -1022,7 +1031,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
serialVUID foreach { value =>
import Flags._, definitions._
val fieldName = "serialVersionUID"
- val fieldSymbol = clasz.symbol.newValue(newTermName(fieldName), NoPosition, STATIC | FINAL) setInfo longType
+ val fieldSymbol = clasz.symbol.newValue(newTermName(fieldName), NoPosition, STATIC | FINAL) setInfo LongClass.tpe
clasz addField new IField(fieldSymbol)
lastBlock emit CONSTANT(Constant(value))
lastBlock emit STORE_FIELD(fieldSymbol, true)
@@ -1281,7 +1290,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val jname = javaName(method)
val jtype = javaType(method).asInstanceOf[JMethodType]
- def debugMsg(invoke: String) {
+ def dbg(invoke: String) {
debuglog("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype))
}
@@ -1299,14 +1308,14 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
style match {
- case Static(true) => jcode.emitINVOKESPECIAL (jowner, jname, jtype) ; debugMsg("invokespecial")
- case Static(false) => jcode.emitINVOKESTATIC (jowner, jname, jtype) ; debugMsg("invokestatic")
- case Dynamic if isInterfaceCall(receiver) => jcode.emitINVOKEINTERFACE(jowner, jname, jtype) ; debugMsg("invokinterface")
- case Dynamic => jcode.emitINVOKEVIRTUAL (jowner, jname, jtype) ; debugMsg("invokevirtual")
+ case Static(true) => dbg("invokespecial"); jcode.emitINVOKESPECIAL(jowner, jname, jtype)
+ case Static(false) => dbg("invokestatic"); jcode.emitINVOKESTATIC(jowner, jname, jtype)
+ case Dynamic if isInterfaceCall(receiver) => dbg("invokinterface"); jcode.emitINVOKEINTERFACE(jowner, jname, jtype)
+ case Dynamic => dbg("invokevirtual"); jcode.emitINVOKEVIRTUAL(jowner, jname, jtype)
case SuperCall(_) =>
+ dbg("invokespecial")
jcode.emitINVOKESPECIAL(jowner, jname, jtype)
initModule()
- debugMsg("invokespecial")
}
}
@@ -1323,7 +1332,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val lastInstr = b.lastInstruction
for (instr <- b) {
-
instr match {
case THIS(clasz) => jcode.emitALOAD_0()
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
index b74981b999..807a3dd0bb 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
@@ -121,7 +121,7 @@ trait GenJVMUtil {
case DoubleTag => jcode emitPUSH const.doubleValue
case StringTag => jcode emitPUSH const.stringValue
case NullTag => jcode.emitACONST_NULL()
- case ClassTag =>
+ case ClazzTag =>
val kind = toTypeKind(const.typeValue)
val toPush =
if (kind.isValueType) classLiteral(kind)
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 2fb615f893..66e7becb12 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -15,6 +15,7 @@ import scala.tools.nsc.symtab._
import ch.epfl.lamp.compiler.msil.{Type => MsilType, _}
import ch.epfl.lamp.compiler.msil.emit._
import ch.epfl.lamp.compiler.msil.util.PECustomMod
+import language.postfixOps
abstract class GenMSIL extends SubComponent {
import global._
@@ -365,7 +366,7 @@ abstract class GenMSIL extends SubComponent {
arr.foreach(emitConst)
}
- // TODO: other Tags: NoTag, UnitTag, ClassTag, EnumTag, ArrayTag ???
+ // TODO: other Tags: NoTag, UnitTag, ClazzTag, EnumTag, ArrayTag ???
case _ => abort("could not handle attribute argument: " + const)
}
@@ -388,7 +389,7 @@ abstract class GenMSIL extends SubComponent {
case DoubleTag => buf.put(0x0d.toByte)
case StringTag => buf.put(0x0e.toByte)
- // TODO: other Tags: NoTag, UnitTag, ClassTag, EnumTag ???
+ // TODO: other Tags: NoTag, UnitTag, ClazzTag, EnumTag ???
// ArrayTag falls in here
case _ => abort("could not handle attribute argument: " + c)
@@ -968,7 +969,7 @@ abstract class GenMSIL extends SubComponent {
case DoubleTag => mcode.Emit(OpCodes.Ldc_R8, const.doubleValue)
case StringTag => mcode.Emit(OpCodes.Ldstr, const.stringValue)
case NullTag => mcode.Emit(OpCodes.Ldnull)
- case ClassTag =>
+ case ClazzTag =>
mcode.Emit(OpCodes.Ldtoken, msilType(const.typeValue))
mcode.Emit(OpCodes.Call, TYPE_FROM_HANDLE)
case _ => abort("Unknown constant value: " + const)
diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
index 95c371fa8b..d4ee9b6b48 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala
@@ -82,7 +82,7 @@ abstract class DeadCodeElimination extends SubComponent {
mark
sweep(m)
accessedLocals = accessedLocals.distinct
- if (m.locals diff accessedLocals nonEmpty) {
+ if ((m.locals diff accessedLocals).nonEmpty) {
log("Removed dead locals: " + (m.locals diff accessedLocals))
m.locals = accessedLocals.reverse
}
diff --git a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
index ec137203bf..0d47352215 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/InlineExceptionHandlers.scala
@@ -360,7 +360,7 @@ abstract class InlineExceptionHandlers extends SubComponent {
val caughtException = toTypeKind(caughtClass.tpe)
// copy the exception handler code once again, dropping the LOAD_EXCEPTION
val copy = handler.code.newBlock
- copy.emitOnly(handler.iterator drop dropCount toSeq: _*)
+ copy.emitOnly((handler.iterator drop dropCount).toSeq: _*)
// extend the handlers of the handler to the copy
for (parentHandler <- handler.method.exh ; if parentHandler covers handler) {
diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
index dfe9081ee5..08e059419a 100644
--- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
+++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala
@@ -9,7 +9,7 @@ package backend.opt
import scala.collection.mutable
import scala.tools.nsc.symtab._
-import scala.tools.nsc.util.{ NoSourceFile }
+import scala.tools.nsc.util.NoSourceFile
/**
* @author Iulian Dragos
@@ -135,7 +135,7 @@ abstract class Inliners extends SubComponent {
/** The current iclass */
private var currentIClazz: IClass = _
- private def warn(pos: Position, msg: String) = currentIClazz.cunit.warning(pos, msg)
+ private def warn(pos: Position, msg: String) = currentIClazz.cunit.inlinerWarning(pos, msg)
val recentTFAs = mutable.Map.empty[Symbol, Tuple2[Boolean, analysis.MethodTFA]]
private def getRecentTFA(incm: IMethod): (Boolean, analysis.MethodTFA) = {
@@ -196,33 +196,35 @@ abstract class Inliners extends SubComponent {
val staleIn = mutable.Set.empty[BasicBlock]
/**
- * A transformation local to the body of the argument.
+ * A transformation local to the body of the IMethod received as argument.
* An linining decision consists in replacing a callsite with the body of the callee.
* Please notice that, because `analyzeMethod()` itself may modify a method body,
* the particular callee bodies that end up being inlined depend on the particular order in which methods are visited
- * (no topological ordering over the call-graph is attempted).
+ * (no topological sorting over the call-graph is attempted).
*
* Making an inlining decision requires type-flow information for both caller and callee.
* Regarding the caller, such information is needed only for basic blocks containing inlining candidates
* (and their transitive predecessors). This observation leads to using a custom type-flow analysis (MTFAGrowable)
- * that can be re-inited, i.e. that reuses lattice elements (type-flow information) computed in a previous iteration
+ * that can be re-inited, i.e. that reuses lattice elements (type-flow information computed in a previous iteration)
* as starting point for faster convergence in a new iteration.
*
* The mechanics of inlining are iterative for a given invocation of `analyzeMethod(m)`,
- * thus considering the basic blocks that successful inlining added in a previous iteration:
+ * and are affected by inlinings from previous iterations
+ * (ie, "heuristic" rules are based on statistics tracked for that purpose):
*
* (1) before the iterations proper start, so-called preinlining is performed.
* Those callsites whose (receiver, concreteMethod) are both known statically
* can be analyzed for inlining before computing a type-flow. Details in `preInline()`
*
* (2) the first iteration computes type-flow information for basic blocks containing inlining candidates
- * (and their transitive predecessors), so called `relevantBBs`.
+ * (and their transitive predecessors), so called `relevantBBs` basic blocks.
* The ensuing analysis of each candidate (performed by `analyzeInc()`)
- * may result in a CFG isomorphic to that of the callee being inserted where the callsite was
- * (i.e. a CALL_METHOD instruction is replaced with a single-entry single-exit CFG, which we call "successful inlining").
+ * may result in a CFG isomorphic to that of the callee being inserted in place of the callsite
+ * (i.e. a CALL_METHOD instruction is replaced with a single-entry single-exit CFG,
+ * a situation we call "successful inlining").
*
- * (3) following iterations have their relevant basic blocks updated to focus
- * on the inlined basic blocks and their successors only. Details in `MTFAGrowable.reinit()`
+ * (3) following iterations have `relevantBBs` updated to focus on the inlined basic blocks and their successors only.
+ * Details in `MTFAGrowable.reinit()`
* */
def analyzeMethod(m: IMethod): Unit = {
// m.normalize
@@ -372,7 +374,7 @@ abstract class Inliners extends SubComponent {
* That's why preInline() is invoked twice: any inlinings downplayed by the heuristics during the first round get an opportunity to rank higher during the second.
*
* As a whole, both `preInline()` invocations amount to priming the inlining process,
- * so that the first TFA run afterwards is able to gain more information as compared to a cold-start.
+ * so that the first TFA that is run afterwards is able to gain more information as compared to a cold-start.
*/
val totalPreInlines = {
val firstRound = preInline(true)
@@ -388,9 +390,10 @@ abstract class Inliners extends SubComponent {
/* it's important not to inline in unreachable basic blocks. linearizedBlocks() returns only reachable ones. */
tfa.callerLin = caller.m.linearizedBlocks()
- /* TODO Do we want to perform inlining in non-finally exception handlers?
+ /* TODO Do we really want to inline inside exception handlers?
* Seems counterproductive (the larger the method the less likely it will be JITed).
- * The alternative above would be `linearizer.linearizeAt(caller.m, caller.m.startBlock)`.
+ * The alternative would be `linearizer.linearizeAt(caller.m, caller.m.startBlock)`.
+ * And, we would cut down on TFA iterations, too.
* See also comment on the same topic in TypeFlowAnalysis. */
tfa.reinit(m, staleOut.toList, splicedBlocks, staleIn)
@@ -759,12 +762,16 @@ abstract class Inliners extends SubComponent {
private def helperIsSafeToInline(stackLength: Int): Boolean = {
def makePublic(f: Symbol): Boolean =
- (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && {
- debuglog("Making not-private symbol out of synthetic: " + f)
+ /*
+ * Completely disabling member publifying. This shouldn't have been done in the first place. :|
+ */
+ false
+ // (inc.m.sourceFile ne NoSourceFile) && (f.isSynthetic || f.isParamAccessor) && {
+ // debuglog("Making not-private symbol out of synthetic: " + f)
- f setNotFlag Flags.PRIVATE
- true
- }
+ // f setNotFlag Flags.PRIVATE
+ // true
+ // }
if (!inc.m.hasCode || inc.isRecursive) { return false }
if (inc.m.symbol.hasFlag(Flags.SYNCHRONIZED)) { return false }
@@ -854,7 +861,7 @@ abstract class Inliners extends SubComponent {
def lookupIMethod(meth: Symbol, receiver: Symbol): Option[IMethod] = {
def tryParent(sym: Symbol) = icodes icode sym flatMap (_ lookupMethod meth)
- receiver.info.baseClasses.iterator map tryParent find (_.isDefined) flatten
+ (receiver.info.baseClasses.iterator map tryParent find (_.isDefined)).flatten
}
} /* class Inliner */
} /* class Inliners */
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index f32564f097..76a8b87ba7 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -58,7 +58,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
case Right(sourceCode) =>
new compiler.Run() compileSources List(new BatchSourceFile("newSource", sourceCode))
}
-
+
if (reporter.hasErrors)
return None
@@ -80,6 +80,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
val modelFactory = (
new { override val global: compiler.type = compiler }
with model.ModelFactory(compiler, settings)
+ with model.ModelFactoryImplicitSupport
with model.comment.CommentFactory
with model.TreeFactory {
override def templateShouldDocument(sym: compiler.Symbol) =
@@ -89,7 +90,8 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
modelFactory.makeModel match {
case Some(madeModel) =>
- println("model contains " + modelFactory.templatesCount + " documentable templates")
+ if (settings.reportModel)
+ println("model contains " + modelFactory.templatesCount + " documentable templates")
Some(madeModel)
case None =>
println("no documentable class found in compilation units")
diff --git a/src/compiler/scala/tools/nsc/doc/Settings.scala b/src/compiler/scala/tools/nsc/doc/Settings.scala
index 45a2ad78b4..d3a1d47de8 100644
--- a/src/compiler/scala/tools/nsc/doc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/doc/Settings.scala
@@ -8,6 +8,7 @@ package doc
import java.io.File
import java.lang.System
+import language.postfixOps
/** An extended version of compiler settings, with additional Scaladoc-specific options.
* @param error A function that prints a string to the appropriate error stream. */
@@ -87,6 +88,38 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
""
)
+ val docImplicits = BooleanSetting (
+ "-implicits",
+ "Document members inherited by implicit conversions."
+ )
+
+ val docImplicitsDebug = BooleanSetting (
+ "-implicits-debug",
+ "Show debugging information for members inherited by implicit conversions."
+ )
+
+ val docImplicitsShowAll = BooleanSetting (
+ "-implicits-show-all",
+ "Show members inherited by implicit conversions that are impossible in the default scope. " +
+ "(for example conversions that require Numeric[String] to be in scope)"
+ )
+
+ val docDiagrams = BooleanSetting (
+ "-diagrams",
+ "Create inheritance diagrams for classes, traits and packages."
+ )
+
+ val docDiagramsDebug = BooleanSetting (
+ "-diagrams-debug",
+ "Show debugging information for the diagram creation process."
+ )
+
+ val docDiagramsDotPath = PathSetting (
+ "-diagrams-dot-path",
+ "The path to the dot executable used to generate the inheritance diagrams. Ex: /usr/bin/dot",
+ "dot" // by default, just pick up the system-wide dot
+ )
+
// Somewhere slightly before r18708 scaladoc stopped building unless the
// self-type check was suppressed. I hijacked the slotted-for-removal-anyway
// suppress-vt-warnings option and renamed it for this purpose.
@@ -94,9 +127,105 @@ class Settings(error: String => Unit) extends scala.tools.nsc.Settings(error) {
// For improved help output.
def scaladocSpecific = Set[Settings#Setting](
- docformat, doctitle, docfooter, docversion, docUncompilable, docsourceurl, docgenerator
+ docformat, doctitle, docfooter, docversion, docUncompilable, docsourceurl, docgenerator, docRootContent, useStupidTypes,
+ docDiagrams, docDiagramsDebug, docDiagramsDotPath,
+ docImplicits, docImplicitsDebug, docImplicitsShowAll
)
val isScaladocSpecific: String => Boolean = scaladocSpecific map (_.name)
override def isScaladoc = true
+
+ // unset by the testsuite, we don't need to count the entities in the model
+ var reportModel = true
+
+ /**
+ * This is the hardcoded area of Scaladoc. This is where "undesirable" stuff gets eliminated. I know it's not pretty,
+ * but ultimately scaladoc has to be useful. :)
+ */
+ object hardcoded {
+
+ /** The common context bounds and some humanly explanations. Feel free to add more explanations
+ * `<root>.scala.package.Numeric` is the type class
+ * `tparam` is the name of the type parameter it gets (this only describes type classes with 1 type param)
+ * the function result should be a humanly-understandable description of the type class
+ */
+ val knownTypeClasses: Map[String, String => String] = Map() +
+ ("<root>.scala.package.Numeric" -> ((tparam: String) => tparam + " is a numeric class, such as Int, Long, Float or Double")) +
+ ("<root>.scala.package.Integral" -> ((tparam: String) => tparam + " is an integral numeric class, such as Int or Long")) +
+ ("<root>.scala.package.Fractional" -> ((tparam: String) => tparam + " is a fractional numeric class, such as Float or Double")) +
+ ("<root>.scala.reflect.Manifest" -> ((tparam: String) => tparam + " is accompanied by a Manifest, which is a runtime representation of its type that survives erasure")) +
+ ("<root>.scala.reflect.ClassManifest" -> ((tparam: String) => tparam + " is accompanied by a ClassManifest, which is a runtime representation of its type that survives erasure")) +
+ ("<root>.scala.reflect.OptManifest" -> ((tparam: String) => tparam + " is accompanied by an OptManifest, which can be either a runtime representation of its type or the NoManifest, which means the runtime type is not available")) +
+ ("<root>.scala.reflect.ClassTag" -> ((tparam: String) => tparam + " is accompanied by a ClassTag, which is a runtime representation of its type that survives erasure")) +
+ ("<root>.scala.reflect.TypeTag" -> ((tparam: String) => tparam + " is accompanied by a TypeTag, which is a runtime representation of its type that survives erasure")) +
+ ("<root>.scala.reflect.ConcreteTypeTag" -> ((tparam: String) => tparam + " is accompanied by an ConcreteTypeTag, which is a runtime representation of a concrete type that survives erasure"))
+
+ /**
+ * Set of classes to exclude from index and diagrams
+ * TODO: Should be configurable
+ */
+ def isExcluded(qname: String) = {
+ ( ( qname.startsWith("scala.Tuple") || qname.startsWith("scala.Product") ||
+ qname.startsWith("scala.Function") || qname.startsWith("scala.runtime.AbstractFunction")
+ ) && !(
+ qname == "scala.Tuple1" || qname == "scala.Tuple2" ||
+ qname == "scala.Product" || qname == "scala.Product1" || qname == "scala.Product2" ||
+ qname == "scala.Function" || qname == "scala.Function1" || qname == "scala.Function2" ||
+ qname == "scala.runtime.AbstractFunction0" || qname == "scala.runtime.AbstractFunction1" ||
+ qname == "scala.runtime.AbstractFunction2"
+ )
+ )
+ }
+
+ /** Common conversion targets that affect any class in Scala */
+ val commonConversionTargets = List(
+ "scala.Predef.any2stringfmt",
+ "scala.Predef.any2stringadd",
+ "scala.Predef.any2ArrowAssoc",
+ "scala.Predef.any2Ensuring")
+
+ /** There's a reason all these are specialized by hand but documenting each of them is beyond the point */
+ val arraySkipConversions = List(
+ "scala.Predef.refArrayOps",
+ "scala.Predef.intArrayOps",
+ "scala.Predef.doubleArrayOps",
+ "scala.Predef.longArrayOps",
+ "scala.Predef.floatArrayOps",
+ "scala.Predef.charArrayOps",
+ "scala.Predef.byteArrayOps",
+ "scala.Predef.shortArrayOps",
+ "scala.Predef.booleanArrayOps",
+ "scala.Predef.unitArrayOps",
+ "scala.LowPriorityImplicits.wrapRefArray",
+ "scala.LowPriorityImplicits.wrapIntArray",
+ "scala.LowPriorityImplicits.wrapDoubleArray",
+ "scala.LowPriorityImplicits.wrapLongArray",
+ "scala.LowPriorityImplicits.wrapFloatArray",
+ "scala.LowPriorityImplicits.wrapCharArray",
+ "scala.LowPriorityImplicits.wrapByteArray",
+ "scala.LowPriorityImplicits.wrapShortArray",
+ "scala.LowPriorityImplicits.wrapBooleanArray",
+ "scala.LowPriorityImplicits.wrapUnitArray",
+ "scala.LowPriorityImplicits.genericWrapArray")
+
+ // included as names as here we don't have access to a Global with Definitions :(
+ def valueClassList = List("unit", "boolean", "byte", "short", "char", "int", "long", "float", "double")
+ def valueClassFilterPrefixes = List("scala.LowPriorityImplicits", "scala.Predef")
+
+ /** Dirty, dirty, dirty hack: the value params conversions can all kick in -- and they are disambiguated by priority
+ * but showing priority in scaladoc would make no sense -- so we have to manually remove the conversions that we
+ * know will never get a chance to kick in. Anyway, DIRTY DIRTY DIRTY! */
+ def valueClassFilter(value: String, conversionName: String): Boolean = {
+ val valueName = value.toLowerCase
+ val otherValues = valueClassList.filterNot(_ == valueName)
+
+ for (prefix <- valueClassFilterPrefixes)
+ if (conversionName.startsWith(prefix))
+ for (otherValue <- otherValues)
+ if (conversionName.startsWith(prefix + "." + otherValue))
+ return false
+
+ true
+ }
+ }
}
diff --git a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala
index 9b29ebd745..8f426a443d 100644
--- a/src/compiler/scala/tools/nsc/doc/Uncompilable.scala
+++ b/src/compiler/scala/tools/nsc/doc/Uncompilable.scala
@@ -5,6 +5,8 @@
package scala.tools.nsc
package doc
+import language.implicitConversions
+import language.postfixOps
/** Some glue between DocParser (which reads source files which can't be compiled)
* and the scaladoc model.
@@ -14,7 +16,7 @@ trait Uncompilable {
val settings: Settings
import global.{ reporter, inform, warning, newTypeName, newTermName, Symbol, Name, DocComment, NoSymbol }
- import global.definitions.RootClass
+ import global.definitions.{ RootClass, AnyRefClass }
private implicit def translateName(name: Global#Name) =
if (name.isTypeName) newTypeName("" + name) else newTermName("" + name)
@@ -32,7 +34,7 @@ trait Uncompilable {
}
def files = settings.uncompilableFiles
def symbols = pairs map (_._1)
- def templates = symbols filter (x => x.isClass || x.isTrait) toSet
+ def templates = symbols filter (x => x.isClass || x.isTrait || x == AnyRefClass/* which is now a type alias */) toSet
def comments = {
if (settings.debug.value || settings.verbose.value)
inform("Found %d uncompilable files: %s".format(files.size, files mkString ", "))
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
index 0116e02e0e..914824d523 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlFactory.scala
@@ -71,6 +71,7 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
"signaturebg.gif",
"signaturebg2.gif",
"typebg.gif",
+ "conversionbg.gif",
"valuemembersbg.gif",
"navigation-li-a.png",
@@ -80,6 +81,8 @@ class HtmlFactory(val universe: doc.Universe, index: doc.Index) {
"selected.png",
"selected2-right.png",
"selected2.png",
+ "selected-right-implicits.png",
+ "selected-implicits.png",
"unselected.png"
)
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
index 1544dafc69..e3da8bddea 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -23,7 +23,7 @@ abstract class HtmlPage extends Page { thisPage =>
protected def title: String
/** The page description */
- protected def description: String =
+ protected def description: String =
// unless overwritten, will display the title in a spaced format, keeping - and .
title.replaceAll("[^a-zA-Z0-9\\.\\-]+", " ").replaceAll("\\-+", " - ").replaceAll(" +", " ")
@@ -164,15 +164,15 @@ abstract class HtmlPage extends Page { thisPage =>
}
/** Returns the HTML code that represents the template in `tpl` as a hyperlinked name. */
- def templateToHtml(tpl: TemplateEntity) = tpl match {
+ def templateToHtml(tpl: TemplateEntity, name: String = null) = tpl match {
case dTpl: DocTemplateEntity =>
if (hasPage(dTpl)) {
- <a href={ relativeLinkTo(dTpl) } class="extype" name={ dTpl.qualifiedName }>{ dTpl.name }</a>
+ <a href={ relativeLinkTo(dTpl) } class="extype" name={ dTpl.qualifiedName }>{ if (name eq null) dTpl.name else name }</a>
} else {
- xml.Text(dTpl.name)
+ xml.Text(if (name eq null) dTpl.name else name)
}
case ndTpl: NoDocTemplate =>
- xml.Text(ndTpl.name)
+ xml.Text(if (name eq null) ndTpl.name else name)
}
/** Returns the HTML code that represents the templates in `tpls` as a list of hyperlinked names. */
@@ -192,6 +192,6 @@ abstract class HtmlPage extends Page { thisPage =>
else if (ety.isObject && !ety.companion.isEmpty && ety.companion.get.visibility.isPublic && ety.companion.get.inSource != None && ety.companion.get.isTrait) "object_to_trait_big.png"
else if (ety.isObject) "object_big.png"
else if (ety.isPackage) "package_big.png"
- else "class_big.png" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
+ else "class_big.png" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala
index f67abc58da..3ff973ec66 100644
--- a/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/SyntaxHigh.scala
@@ -41,13 +41,13 @@ private[html] object SyntaxHigh {
/** Standard library classes/objects, sorted alphabetically */
val standards = Array (
"Any", "AnyRef", "AnyVal", "App", "Application", "Array",
- "Boolean", "Byte", "Char", "Class", "Console", "Double",
- "Enumeration", "Float", "Function", "Int",
+ "Boolean", "Byte", "Char", "Class", "ClassTag", "ClassManifest", "ConcreteTypeTag",
+ "Console", "Double", "Enumeration", "Float", "Function", "Int",
"List", "Long", "Manifest", "Map",
- "None", "Nothing", "Null", "Object", "Option",
+ "NoManifest", "None", "Nothing", "Null", "Object", "Option", "OptManifest",
"Pair", "Predef",
"Seq", "Set", "Short", "Some", "String", "Symbol",
- "Triple", "Unit")
+ "Triple", "TypeTag", "Unit")
def apply(data: String): NodeSeq = {
val buf = data.getBytes
diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
index f059b5c0cb..4463857aa5 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -10,6 +10,7 @@ package page
import model._
import scala.xml.{ NodeSeq, Text, UnprefixedAttribute }
+import language.postfixOps
class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage {
@@ -69,8 +70,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
<p id="owner">{ templatesToHtml(tpl.inTemplate.toRoot.reverse.tail, xml.Text(".")) }</p>
}
- <body class={ if (tpl.isTrait || tpl.isClass || tpl.qualifiedName == "scala.AnyRef") "type" else "value" }
- onload={ "sh_highlightDocument('../lib/', '.min.js');" }>
+ <body class={ if (tpl.isTrait || tpl.isClass || tpl.qualifiedName == "scala.AnyRef") "type" else "value" }>
<div id="definition">
{
tpl.companion match {
@@ -88,21 +88,42 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
<div id="mbrsel">
<div id='textfilter'><span class='pre'/><span class='input'><input type='text' accesskey='/'/></span><span class='post'/></div>
- { if (tpl.linearizationTemplates.isEmpty) NodeSeq.Empty else
+ { if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty) NodeSeq.Empty else
<div id="order">
<span class="filtertype">Ordering</span>
<ol><li class="alpha in"><span>Alphabetic</span></li><li class="inherit out"><span>By inheritance</span></li></ol>
</div>
}
- { if (tpl.linearizationTemplates.isEmpty) NodeSeq.Empty else
- <div id="ancestors">
- <span class="filtertype">Inherited</span>
- <ol><li class="hideall out"><span>Hide All</span></li>
- <li class="showall in"><span>Show all</span></li></ol>
- <ol id="linearization">{
- (tpl :: tpl.linearizationTemplates) map { wte => <li class="in" name={ wte.qualifiedName }><span>{ wte.name }</span></li> }
- }</ol>
- </div>
+ { if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty) NodeSeq.Empty else
+ {
+ if (!tpl.linearization.isEmpty)
+ <div id="ancestors">
+ <span class="filtertype">Inherited<br/>
+ </span>
+ <ol id="linearization">
+ { (tpl :: tpl.linearizationTemplates).map(wte => <li class="in" name={ wte.qualifiedName }><span>{ wte.name }</span></li>) }
+ </ol>
+ </div>
+ else NodeSeq.Empty
+ } ++ {
+ if (!tpl.conversions.isEmpty)
+ <div id="ancestors">
+ <span class="filtertype">Implicitly<br/>
+ </span>
+ <ol id="implicits">
+ { tpl.conversions.map(conv => <li class="in" name={ conv.conversionQualifiedName }><span>{ "by " + conv.conversionShortName }</span></li>) }
+ </ol>
+ </div>
+ else NodeSeq.Empty
+ } ++
+ <div id="ancestors">
+ <span class="filtertype"></span>
+ <ol>
+ <li class="hideall out"><span>Hide All</span></li>
+ <li class="showall in"><span>Show all</span></li>
+ </ol>
+ <a href="docs.scala-lang.org/overviews/scaladoc/usage.html#members" target="_blank">Learn more about member selection</a>
+ </div>
}
{
<div id="visbl">
@@ -152,23 +173,25 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
<div id="inheritedMembers">
{
+ // linearization
NodeSeq fromSeq (for ((superTpl, superType) <- (tpl.linearizationTemplates zip tpl.linearizationTypes)) yield
<div class="parent" name={ superTpl.qualifiedName }>
<h3>Inherited from {
- if (tpl.universe.settings.useStupidTypes.value)
- superTpl match {
- case dtpl: DocTemplateEntity =>
- val sig = signature(dtpl, false, true) \ "_"
- sig
- case tpl: TemplateEntity =>
- tpl.name
- }
- else
- typeToHtml(superType, true)
+ typeToHtmlWithStupidTypes(tpl, superTpl, superType)
}</h3>
</div>
)
}
+ {
+ // implicitly inherited
+ NodeSeq fromSeq (for (conversion <- (tpl.conversions)) yield
+ <div class="conversion" name={ conversion.conversionQualifiedName }>
+ <h3>Inherited by implicit conversion { conversion.conversionShortName } from
+ { typeToHtml(tpl.resultType, true) } to { typeToHtml(conversion.targetType, true) }
+ </h3>
+ </div>
+ )
+ }
</div>
</div>
@@ -219,11 +242,12 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
case d:MemberEntity with Def => defParamsToString(d)
case _ => ""
}
+ val memberComment = memberToCommentHtml(mbr, false)
<li name={ mbr.definitionName } visbl={ if (mbr.visibility.isProtected) "prt" else "pub" }
- data-isabs={ mbr.isAbstract.toString }>
+ data-isabs={ mbr.isAbstract.toString } fullComment={ if(memberComment.isEmpty) "no" else "yes" }>
<a id={ mbr.name +defParamsString +":"+ mbr.resultType.name}/>
{ signature(mbr, false) }
- { memberToCommentHtml(mbr, false) }
+ { memberComment }
</li>
}
@@ -275,6 +299,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
<p class="comment cmt">{ inlineToHtml(mbr.comment.get.short) }</p>
def memberToCommentBodyHtml(mbr: MemberEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = {
+
val memberComment =
if (mbr.comment.isEmpty) NodeSeq.Empty
else <div class="comment cmt">{ commentToHtml(mbr.comment) }</div>
@@ -326,6 +351,45 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
}
}
+ val implicitInformation = mbr.byConversion match {
+ case Some(conv) =>
+ <dt class="implicit">Implicit information</dt> ++
+ {
+ val targetType = typeToHtml(conv.targetType, true)
+ val conversionMethod = conv.convertorMethod match {
+ case Left(member) => Text(member.name)
+ case Right(name) => Text(name)
+ }
+
+ // strip off the package object endings, they make things harder to follow
+ val conversionOwnerQualifiedNane = conv.convertorOwner.qualifiedName.stripSuffix(".package")
+ val conversionOwner = templateToHtml(conv.convertorOwner, conversionOwnerQualifiedNane)
+
+ val constraintText = conv.constraints match {
+ case Nil =>
+ NodeSeq.Empty
+ case List(constraint) =>
+ xml.Text("This conversion will take place only if ") ++ constraintToHtml(constraint) ++ xml.Text(".")
+ case List(constraint1, constraint2) =>
+ xml.Text("This conversion will take place only if ") ++ constraintToHtml(constraint1) ++
+ xml.Text(" and at the same time ") ++ constraintToHtml(constraint2) ++ xml.Text(".")
+ case constraints =>
+ <br/> ++ "This conversion will take place only if all of the following constraints are met:" ++ <br/> ++ {
+ var index = 0
+ constraints map { constraint => xml.Text({ index += 1; index } + ". ") ++ constraintToHtml(constraint) ++ <br/> }
+ }
+ }
+
+ <dd>
+ This member is added by an implicit conversion from { typeToHtml(mbr.inTemplate.resultType, true) } to
+ { targetType } performed by method { conversionMethod } in { conversionOwner }.
+ { constraintText }
+ </dd>
+ }
+ case _ =>
+ NodeSeq.Empty
+ }
+
// --- start attributes block vals
val attributes: Seq[scala.xml.Node] = {
val fvs: List[comment.Paragraph] = visibility(mbr).toList
@@ -354,7 +418,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
</div>
case _ => NodeSeq.Empty
}
- }
+ }
val selfType: Seq[scala.xml.Node] = mbr match {
case dtpl: DocTemplateEntity if (isSelf && !dtpl.selfType.isEmpty && !isReduced) =>
@@ -477,7 +541,7 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
}
// end attributes block vals ---
- val attributesInfo = attributes ++ definitionClasses ++ fullSignature ++ selfType ++ annotations ++ deprecation ++ migration ++ sourceLink ++ mainComment
+ val attributesInfo = implicitInformation ++ attributes ++ definitionClasses ++ fullSignature ++ selfType ++ annotations ++ deprecation ++ migration ++ sourceLink ++ mainComment
val attributesBlock =
if (attributesInfo.isEmpty)
NodeSeq.Empty
@@ -561,12 +625,13 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
</span>
<span class="symbol">
{
+ val nameClass = if (mbr.byConversion.isDefined) "implicit" else "name"
val nameHtml = {
val value = if (mbr.isConstructor) tpl.name else mbr.name
val span = if (mbr.deprecation.isDefined)
- <span class={"name deprecated"} title={"Deprecated: "+bodyToStr(mbr.deprecation.get)}>{ value }</span>
+ <span class={ nameClass + " deprecated"} title={"Deprecated: "+bodyToStr(mbr.deprecation.get)}>{ value }</span>
else
- <span class={"name"}>{ value }</span>
+ <span class={ nameClass }>{ value }</span>
val encoded = scala.reflect.NameTransformer.encode(value)
if (encoded != value) {
span % new UnprefixedAttribute("title",
@@ -765,4 +830,43 @@ class Template(universe: doc.Universe, tpl: DocTemplateEntity) extends HtmlPage
case _ => inl.toString
}
+ private def typeToHtmlWithStupidTypes(tpl: TemplateEntity, superTpl: TemplateEntity, superType: TypeEntity): NodeSeq =
+ if (tpl.universe.settings.useStupidTypes.value)
+ superTpl match {
+ case dtpl: DocTemplateEntity =>
+ val sig = signature(dtpl, false, true) \ "_"
+ sig
+ case tpl: TemplateEntity =>
+ Text(tpl.name)
+ }
+ else
+ typeToHtml(superType, true)
+
+ private def constraintToHtml(constraint: Constraint): NodeSeq = constraint match {
+ case ktcc: KnownTypeClassConstraint =>
+ xml.Text(ktcc.typeExplanation(ktcc.typeParamName) + " (" + ktcc.typeParamName + ": ") ++
+ templateToHtml(ktcc.typeClassEntity) ++ xml.Text(")")
+ case tcc: TypeClassConstraint =>
+ xml.Text(tcc.typeParamName + " is ") ++
+ <a href="http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala" target="_blank">
+ context-bounded</a> ++ xml.Text(" by " + tcc.typeClassEntity.qualifiedName + " (" + tcc.typeParamName + ": ") ++
+ templateToHtml(tcc.typeClassEntity) ++ xml.Text(")")
+ case impl: ImplicitInScopeConstraint =>
+ xml.Text("an implicit value of type ") ++ typeToHtml(impl.implicitType, true) ++ xml.Text(" is in scope")
+ case eq: EqualTypeParamConstraint =>
+ xml.Text(eq.typeParamName + " is " + eq.rhs.name + " (" + eq.typeParamName + " =:= ") ++
+ typeToHtml(eq.rhs, true) ++ xml.Text(")")
+ case bt: BoundedTypeParamConstraint =>
+ xml.Text(bt.typeParamName + " is a superclass of " + bt.lowerBound.name + " and a subclass of " +
+ bt.upperBound.name + " (" + bt.typeParamName + " >: ") ++
+ typeToHtml(bt.lowerBound, true) ++ xml.Text(" <: ") ++
+ typeToHtml(bt.upperBound, true) ++ xml.Text(")")
+ case lb: LowerBoundedTypeParamConstraint =>
+ xml.Text(lb.typeParamName + " is a superclass of " + lb.lowerBound.name + " (" + lb.typeParamName + " >: ") ++
+ typeToHtml(lb.lowerBound, true) ++ xml.Text(")")
+ case ub: UpperBoundedTypeParamConstraint =>
+ xml.Text(ub.typeParamName + " is a subclass of " + ub.upperBound.name + " (" + ub.typeParamName + " <: ") ++
+ typeToHtml(ub.upperBound, true) ++ xml.Text(")")
+ }
+
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/conversionbg.gif b/src/compiler/scala/tools/nsc/doc/html/resource/lib/conversionbg.gif
new file mode 100644
index 0000000000..4be145d0af
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/conversionbg.gif
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
index e9ed7181e4..b767722b8c 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
@@ -454,7 +454,7 @@ function resizeFilterBlock() {
function printAlphabet() {
var html = '<a target="template" href="index/index-_.html">#</a>';
var c;
- for (c = 'a'; c < 'z'; c = String.fromCharCode(c.charCodeAt(0) + 1)) {
+ for (c = 'a'; c <= 'z'; c = String.fromCharCode(c.charCodeAt(0) + 1)) {
html += [
'<a target="template" href="index/index-',
c,
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.js
index 7c24308023..16ad06c5ac 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.js
@@ -1,154 +1,4 @@
-/*!
- * jQuery JavaScript Library v1.4.2
- * http://jquery.com/
- *
- * Copyright 2010, John Resig
- * Dual licensed under the MIT or GPL Version 2 licenses.
- * http://jquery.org/license
- *
- * Includes Sizzle.js
- * http://sizzlejs.com/
- * Copyright 2010, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- *
- * Date: Sat Feb 13 22:33:48 2010 -0500
- */
-(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
-e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
-j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
-"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
-true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
-Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
-(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
-a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
-"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
-function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
-c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
-L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
-"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
-a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
-d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
-a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
-!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
-true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
-var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
-parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
-false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
-s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
-applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
-else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
-a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
-w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
-cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
-i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
-" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
-this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
-e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
-c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
-a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
-function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
-k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
-C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
-null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
-e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
-f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
-if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
-fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
-d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
-"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
-a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
-isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
-{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
-if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
-e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
-"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
-d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
-!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
-toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
-u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
-function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
-if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
-e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
-t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
-g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
-for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
-1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
-CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
-relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
-l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
-h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
-CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
-g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
-text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
-setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
-h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
-m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
-"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
-h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
-!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
-h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
-q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
-if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
-(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
-function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
-gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
-c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
-{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
-"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
-d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
-a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
-1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
-a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
-c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
-wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
-prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
-this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
-return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
-""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
-this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
-u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
-1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
-return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
-""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
-c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
-c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
-function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
-Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
-"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
-a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
-a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
-"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
-serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
-function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
-global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
-e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
-"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
-false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
-false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
-c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
-d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
-g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
-1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
-"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
-if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
-this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
-"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
-animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
-j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
-this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
-"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
-c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
-this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
-this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
-e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
-c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
-function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
-this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
-k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
-f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
-a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
-c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
-d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
-f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
-"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
-e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
+/*! jQuery v1.7.2 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
+a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
+.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js
index 4ab99764ce..4e0c9d75c7 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/jquery.layout.js
@@ -1,18 +1,5448 @@
-/*
- * jquery.layout 1.3.0 - Release Candidate 29.3
+/**
+ * @preserve jquery.layout 1.3.0 - Release Candidate 30.5
+ * $Date: 2012-04-14 08:00:00 (Sat, 14 Apr 2012) $
+ * $Rev: 303005 $
*
- * Copyright (c) 2010
+ * Copyright (c) 2012
* Fabrizio Balliano (http://www.fabrizioballiano.net)
* Kevin Dalman (http://allpro.net)
*
* Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
* and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
*
+ * Changelog: http://layout.jquery-dev.net/changelog.cfm#1.3.0.rc30.5
+ *
* Docs: http://layout.jquery-dev.net/documentation.html
* Tips: http://layout.jquery-dev.net/tips.html
* Help: http://groups.google.com/group/jquery-ui-layout
+ */
+
+/* JavaDoc Info: http://code.google.com/closure/compiler/docs/js-for-compiler.html
+ * {!Object} non-nullable type (never NULL)
+ * {?string} nullable type (sometimes NULL) - default for {Object}
+ * {number=} optional parameter
+ * {*} ALL types
+ */
+
+// NOTE: For best readability, view with a fixed-width font and tabs equal to 4-chars
+
+;(function ($) {
+
+// alias Math methods - used a lot!
+var min = Math.min
+, max = Math.max
+, round = Math.floor
+;
+function isStr (v) { return $.type(v) === "string"; }
+
+function runPluginCallbacks (Instance, a_fn) {
+ if ($.isArray(a_fn))
+ for (var i=0, c=a_fn.length; i<c; i++) {
+ var fn = a_fn[i];
+ try {
+ if (isStr(fn)) // 'name' of a function
+ fn = eval(fn);
+ if ($.isFunction(fn))
+ fn( Instance );
+ } catch (ex) {}
+ }
+};
+
+
+
+/*
+ * GENERIC $.layout METHODS - used by all layouts
+ */
+$.layout = {
+
+ version: "1.3.rc30.5"
+, revision: 0.033005 // 1.3.0 final = 1.0300 - major(n+).minor(nn)+patch(nn+)
+
+ // LANGUAGE CUSTOMIZATION
+, language: {
+ // Tips and messages for resizers, togglers, custom buttons, etc.
+ Open: "Open" // eg: "Open Pane"
+ , Close: "Close"
+ , Resize: "Resize"
+ , Slide: "Slide Open"
+ , Pin: "Pin"
+ , Unpin: "Un-Pin"
+ , noRoomToOpenTip: "Not enough room to show this pane."
+ , minSizeWarning: "Panel has reached its minimum size"
+ , maxSizeWarning: "Panel has reached its maximum size"
+ // Developer error messages
+ , pane: "pane" // description of "layout pane element"
+ , selector: "selector" // description of "jQuery-selector"
+ , errButton: "Error Adding Button \n\nInvalid "
+ , errContainerMissing: "UI Layout Initialization Error\n\nThe specified layout-container does not exist."
+ , errCenterPaneMissing: "UI Layout Initialization Error\n\nThe center-pane element does not exist.\n\nThe center-pane is a required element."
+ , errContainerHeight: "UI Layout Initialization Warning\n\nThe layout-container \"CONTAINER\" has no height.\n\nTherefore the layout is 0-height and hence 'invisible'!"
+ }
+
+ // can update code here if $.browser is phased out
+, browser: {
+ mozilla: !!$.browser.mozilla
+ , webkit: !!$.browser.webkit || !!$.browser.safari // webkit = jQ 1.4
+ , msie: !!$.browser.msie
+ , isIE6: !!$.browser.msie && $.browser.version == 6
+ , version: $.browser.version // not used in Layout core, but may be used by plugins
+ }
+
+ // *PREDEFINED* EFFECTS & DEFAULTS
+ // MUST list effect here - OR MUST set an fxSettings option (can be an empty hash: {})
+, effects: {
+
+ // Pane Open/Close Animations
+ slide: {
+ all: { duration: "fast" } // eg: duration: 1000, easing: "easeOutBounce"
+ , north: { direction: "up" }
+ , south: { direction: "down" }
+ , east: { direction: "right"}
+ , west: { direction: "left" }
+ }
+ , drop: {
+ all: { duration: "slow" }
+ , north: { direction: "up" }
+ , south: { direction: "down" }
+ , east: { direction: "right"}
+ , west: { direction: "left" }
+ }
+ , scale: {
+ all: { duration: "fast" }
+ }
+ // these are not recommended, but can be used
+ , blind: {}
+ , clip: {}
+ , explode: {}
+ , fade: {}
+ , fold: {}
+ , puff: {}
+
+ // Pane Resize Animations
+ , size: {
+ all: { easing: "swing" }
+ }
+ }
+
+ // INTERNAL CONFIG DATA - DO NOT CHANGE THIS!
+, config: {
+ optionRootKeys: "effects,panes,north,south,west,east,center".split(",")
+ , allPanes: "north,south,west,east,center".split(",")
+ , borderPanes: "north,south,west,east".split(",")
+ , oppositeEdge: {
+ north: "south"
+ , south: "north"
+ , east: "west"
+ , west: "east"
+ }
+ // offscreen data
+ , offscreenCSS: { left: "-99999px", right: "auto" } // used by hide/close if useOffscreenClose=true
+ , offscreenReset: "offscreenReset" // key used for data
+ // CSS used in multiple places
+ , hidden: { visibility: "hidden" }
+ , visible: { visibility: "visible" }
+ // layout element settings
+ , resizers: {
+ cssReq: {
+ position: "absolute"
+ , padding: 0
+ , margin: 0
+ , fontSize: "1px"
+ , textAlign: "left" // to counter-act "center" alignment!
+ , overflow: "hidden" // prevent toggler-button from overflowing
+ // SEE $.layout.defaults.zIndexes.resizer_normal
+ }
+ , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
+ background: "#DDD"
+ , border: "none"
+ }
+ }
+ , togglers: {
+ cssReq: {
+ position: "absolute"
+ , display: "block"
+ , padding: 0
+ , margin: 0
+ , overflow: "hidden"
+ , textAlign: "center"
+ , fontSize: "1px"
+ , cursor: "pointer"
+ , zIndex: 1
+ }
+ , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
+ background: "#AAA"
+ }
+ }
+ , content: {
+ cssReq: {
+ position: "relative" /* contain floated or positioned elements */
+ }
+ , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
+ overflow: "auto"
+ , padding: "10px"
+ }
+ , cssDemoPane: { // DEMO CSS - REMOVE scrolling from 'pane' when it has a content-div
+ overflow: "hidden"
+ , padding: 0
+ }
+ }
+ , panes: { // defaults for ALL panes - overridden by 'per-pane settings' below
+ cssReq: {
+ position: "absolute"
+ , margin: 0
+ // $.layout.defaults.zIndexes.pane_normal
+ }
+ , cssDemo: { // DEMO CSS - applied if: options.PANE.applyDemoStyles=true
+ padding: "10px"
+ , background: "#FFF"
+ , border: "1px solid #BBB"
+ , overflow: "auto"
+ }
+ }
+ , north: {
+ side: "Top"
+ , sizeType: "Height"
+ , dir: "horz"
+ , cssReq: {
+ top: 0
+ , bottom: "auto"
+ , left: 0
+ , right: 0
+ , width: "auto"
+ // height: DYNAMIC
+ }
+ }
+ , south: {
+ side: "Bottom"
+ , sizeType: "Height"
+ , dir: "horz"
+ , cssReq: {
+ top: "auto"
+ , bottom: 0
+ , left: 0
+ , right: 0
+ , width: "auto"
+ // height: DYNAMIC
+ }
+ }
+ , east: {
+ side: "Right"
+ , sizeType: "Width"
+ , dir: "vert"
+ , cssReq: {
+ left: "auto"
+ , right: 0
+ , top: "auto" // DYNAMIC
+ , bottom: "auto" // DYNAMIC
+ , height: "auto"
+ // width: DYNAMIC
+ }
+ }
+ , west: {
+ side: "Left"
+ , sizeType: "Width"
+ , dir: "vert"
+ , cssReq: {
+ left: 0
+ , right: "auto"
+ , top: "auto" // DYNAMIC
+ , bottom: "auto" // DYNAMIC
+ , height: "auto"
+ // width: DYNAMIC
+ }
+ }
+ , center: {
+ dir: "center"
+ , cssReq: {
+ left: "auto" // DYNAMIC
+ , right: "auto" // DYNAMIC
+ , top: "auto" // DYNAMIC
+ , bottom: "auto" // DYNAMIC
+ , height: "auto"
+ , width: "auto"
+ }
+ }
+ }
+
+ // CALLBACK FUNCTION NAMESPACE - used to store reusable callback functions
+, callbacks: {}
+
+, getParentPaneElem: function (el) {
+ // must pass either a container or pane element
+ var $el = $(el)
+ , layout = $el.data("layout") || $el.data("parentLayout");
+ if (layout) {
+ var $cont = layout.container;
+ // see if this container is directly-nested inside an outer-pane
+ if ($cont.data("layoutPane")) return $cont;
+ var $pane = $cont.closest("."+ $.layout.defaults.panes.paneClass);
+ // if a pane was found, return it
+ if ($pane.data("layoutPane")) return $pane;
+ }
+ return null;
+ }
+
+, getParentPaneInstance: function (el) {
+ // must pass either a container or pane element
+ var $pane = $.layout.getParentPaneElem(el);
+ return $pane ? $pane.data("layoutPane") : null;
+ }
+
+, getParentLayoutInstance: function (el) {
+ // must pass either a container or pane element
+ var $pane = $.layout.getParentPaneElem(el);
+ return $pane ? $pane.data("parentLayout") : null;
+ }
+
+, getEventObject: function (evt) {
+ return typeof evt === "object" && evt.stopPropagation ? evt : null;
+ }
+, parsePaneName: function (evt_or_pane) {
+ // getEventObject() automatically calls .stopPropagation(), WHICH MUST BE DONE!
+ var evt = $.layout.getEventObject( evt_or_pane );
+ if (evt) {
+ // ALWAYS stop propagation of events triggered in Layout!
+ evt.stopPropagation();
+ return $(this).data("layoutEdge");
+ }
+ else
+ return evt_or_pane;
+ }
+
+
+ // LAYOUT-PLUGIN REGISTRATION
+ // more plugins can added beyond this default list
+, plugins: {
+ draggable: !!$.fn.draggable // resizing
+ , effects: {
+ core: !!$.effects // animimations (specific effects tested by initOptions)
+ , slide: $.effects && $.effects.slide // default effect
+ }
+ }
+
+// arrays of plugin or other methods to be triggered for events in *each layout* - will be passed 'Instance'
+, onCreate: [] // runs when layout is just starting to be created - right after options are set
+, onLoad: [] // runs after layout container and global events init, but before initPanes is called
+, onReady: [] // runs after initialization *completes* - ie, after initPanes completes successfully
+, onDestroy: [] // runs after layout is destroyed
+, onUnload: [] // runs after layout is destroyed OR when page unloads
+, afterOpen: [] // runs after setAsOpen() completes
+, afterClose: [] // runs after setAsClosed() completes
+
+ /*
+ * GENERIC UTILITY METHODS
+ */
+
+ // calculate and return the scrollbar width, as an integer
+, scrollbarWidth: function () { return window.scrollbarWidth || $.layout.getScrollbarSize('width'); }
+, scrollbarHeight: function () { return window.scrollbarHeight || $.layout.getScrollbarSize('height'); }
+, getScrollbarSize: function (dim) {
+ var $c = $('<div style="position: absolute; top: -10000px; left: -10000px; width: 100px; height: 100px; overflow: scroll;"></div>').appendTo("body");
+ var d = { width: $c.width() - $c[0].clientWidth, height: $c.height() - $c[0].clientHeight };
+ $c.remove();
+ window.scrollbarWidth = d.width;
+ window.scrollbarHeight = d.height;
+ return dim.match(/^(width|height)$/) ? d[dim] : d;
+ }
+
+
+ /**
+ * Returns hash container 'display' and 'visibility'
+ *
+ * @see $.swap() - swaps CSS, runs callback, resets CSS
+ */
+, showInvisibly: function ($E, force) {
+ if (!$E) return {};
+ if (!$E.jquery) $E = $($E);
+ var CSS = {
+ display: $E.css('display')
+ , visibility: $E.css('visibility')
+ };
+ if (force || CSS.display === "none") { // only if not *already hidden*
+ $E.css({ display: "block", visibility: "hidden" }); // show element 'invisibly' so can be measured
+ return CSS;
+ }
+ else return {};
+ }
+
+ /**
+ * Returns data for setting size of an element (container or a pane).
+ *
+ * @see _create(), onWindowResize() for container, plus others for pane
+ * @return JSON Returns a hash of all dimensions: top, bottom, left, right, outerWidth, innerHeight, etc
+ */
+, getElementDimensions: function ($E) {
+ var
+ d = {} // dimensions hash
+ , x = d.css = {} // CSS hash
+ , i = {} // TEMP insets
+ , b, p // TEMP border, padding
+ , N = $.layout.cssNum
+ , off = $E.offset()
+ ;
+ d.offsetLeft = off.left;
+ d.offsetTop = off.top;
+
+ $.each("Left,Right,Top,Bottom".split(","), function (idx, e) { // e = edge
+ b = x["border" + e] = $.layout.borderWidth($E, e);
+ p = x["padding"+ e] = $.layout.cssNum($E, "padding"+e);
+ i[e] = b + p; // total offset of content from outer side
+ d["inset"+ e] = p;
+ });
+
+ d.offsetWidth = $E.innerWidth(); // offsetWidth is used in calc when doing manual resize
+ d.offsetHeight = $E.innerHeight(); // ditto
+ d.outerWidth = $E.outerWidth();
+ d.outerHeight = $E.outerHeight();
+ d.innerWidth = max(0, d.outerWidth - i.Left - i.Right);
+ d.innerHeight = max(0, d.outerHeight - i.Top - i.Bottom);
+
+ x.width = $E.width();
+ x.height = $E.height();
+ x.top = N($E,"top",true);
+ x.bottom = N($E,"bottom",true);
+ x.left = N($E,"left",true);
+ x.right = N($E,"right",true);
+
+ //d.visible = $E.is(":visible");// && x.width > 0 && x.height > 0;
+
+ return d;
+ }
+
+, getElementCSS: function ($E, list) {
+ var
+ CSS = {}
+ , style = $E[0].style
+ , props = list.split(",")
+ , sides = "Top,Bottom,Left,Right".split(",")
+ , attrs = "Color,Style,Width".split(",")
+ , p, s, a, i, j, k
+ ;
+ for (i=0; i < props.length; i++) {
+ p = props[i];
+ if (p.match(/(border|padding|margin)$/))
+ for (j=0; j < 4; j++) {
+ s = sides[j];
+ if (p === "border")
+ for (k=0; k < 3; k++) {
+ a = attrs[k];
+ CSS[p+s+a] = style[p+s+a];
+ }
+ else
+ CSS[p+s] = style[p+s];
+ }
+ else
+ CSS[p] = style[p];
+ };
+ return CSS
+ }
+
+ /**
+ * Return the innerWidth for the current browser/doctype
+ *
+ * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
+ * @param {Array.<Object>} $E Must pass a jQuery object - first element is processed
+ * @param {number=} outerWidth (optional) Can pass a width, allowing calculations BEFORE element is resized
+ * @return {number} Returns the innerWidth of the elem by subtracting padding and borders
+ */
+, cssWidth: function ($E, outerWidth) {
+ var
+ b = $.layout.borderWidth
+ , n = $.layout.cssNum
+ ;
+ // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
+ if (outerWidth <= 0) return 0;
+
+ if (!$.support.boxModel) return outerWidth;
+
+ // strip border and padding from outerWidth to get CSS Width
+ var W = outerWidth
+ - b($E, "Left")
+ - b($E, "Right")
+ - n($E, "paddingLeft")
+ - n($E, "paddingRight")
+ ;
+
+ return max(0,W);
+ }
+
+ /**
+ * Return the innerHeight for the current browser/doctype
+ *
+ * @see initPanes(), sizeMidPanes(), initHandles(), sizeHandles()
+ * @param {Array.<Object>} $E Must pass a jQuery object - first element is processed
+ * @param {number=} outerHeight (optional) Can pass a width, allowing calculations BEFORE element is resized
+ * @return {number} Returns the innerHeight of the elem by subtracting padding and borders
+ */
+, cssHeight: function ($E, outerHeight) {
+ var
+ b = $.layout.borderWidth
+ , n = $.layout.cssNum
+ ;
+ // a 'calculated' outerHeight can be passed so borders and/or padding are removed if needed
+ if (outerHeight <= 0) return 0;
+
+ if (!$.support.boxModel) return outerHeight;
+
+ // strip border and padding from outerHeight to get CSS Height
+ var H = outerHeight
+ - b($E, "Top")
+ - b($E, "Bottom")
+ - n($E, "paddingTop")
+ - n($E, "paddingBottom")
+ ;
+
+ return max(0,H);
+ }
+
+ /**
+ * Returns the 'current CSS numeric value' for a CSS property - 0 if property does not exist
+ *
+ * @see Called by many methods
+ * @param {Array.<Object>} $E Must pass a jQuery object - first element is processed
+ * @param {string} prop The name of the CSS property, eg: top, width, etc.
+ * @param {boolean=} [allowAuto=false] true = return 'auto' if that is value; false = return 0
+ * @return {(string|number)} Usually used to get an integer value for position (top, left) or size (height, width)
+ */
+, cssNum: function ($E, prop, allowAuto) {
+ if (!$E.jquery) $E = $($E);
+ var CSS = $.layout.showInvisibly($E)
+ , p = $.curCSS($E[0], prop, true)
+ , v = allowAuto && p=="auto" ? p : (parseInt(p, 10) || 0);
+ $E.css( CSS ); // RESET
+ return v;
+ }
+
+, borderWidth: function (el, side) {
+ if (el.jquery) el = el[0];
+ var b = "border"+ side.substr(0,1).toUpperCase() + side.substr(1); // left => Left
+ return $.curCSS(el, b+"Style", true) === "none" ? 0 : (parseInt($.curCSS(el, b+"Width", true), 10) || 0);
+ }
+
+ /**
+ * Mouse-tracking utility - FUTURE REFERENCE
+ *
+ * init: if (!window.mouse) {
+ * window.mouse = { x: 0, y: 0 };
+ * $(document).mousemove( $.layout.trackMouse );
+ * }
+ *
+ * @param {Object} evt
+ *
+, trackMouse: function (evt) {
+ window.mouse = { x: evt.clientX, y: evt.clientY };
+ }
+ */
+
+ /**
+ * SUBROUTINE for preventPrematureSlideClose option
+ *
+ * @param {Object} evt
+ * @param {Object=} el
+ */
+, isMouseOverElem: function (evt, el) {
+ var
+ $E = $(el || this)
+ , d = $E.offset()
+ , T = d.top
+ , L = d.left
+ , R = L + $E.outerWidth()
+ , B = T + $E.outerHeight()
+ , x = evt.pageX // evt.clientX ?
+ , y = evt.pageY // evt.clientY ?
+ ;
+ // if X & Y are < 0, probably means is over an open SELECT
+ return ($.layout.browser.msie && x < 0 && y < 0) || ((x >= L && x <= R) && (y >= T && y <= B));
+ }
+
+ /**
+ * Message/Logging Utility
+ *
+ * @example $.layout.msg("My message"); // log text
+ * @example $.layout.msg("My message", true); // alert text
+ * @example $.layout.msg({ foo: "bar" }, "Title"); // log hash-data, with custom title
+ * @example $.layout.msg({ foo: "bar" }, true, "Title", { sort: false }); -OR-
+ * @example $.layout.msg({ foo: "bar" }, "Title", { sort: false, display: true }); // alert hash-data
+ *
+ * @param {(Object|string)} info String message OR Hash/Array
+ * @param {(Boolean|string|Object)=} [popup=false] True means alert-box - can be skipped
+ * @param {(Object|string)=} [debugTitle=""] Title for Hash data - can be skipped
+ * @param {Object=} [debutOpts={}] Extra options for debug output
+ */
+, msg: function (info, popup, debugTitle, debugOpts) {
+ if ($.isPlainObject(info) && window.debugData) {
+ if (typeof popup === "string") {
+ debugOpts = debugTitle;
+ debugTitle = popup;
+ }
+ else if (typeof debugTitle === "object") {
+ debugOpts = debugTitle;
+ debugTitle = null;
+ }
+ var t = debugTitle || "log( <object> )"
+ , o = $.extend({ sort: false, returnHTML: false, display: false }, debugOpts);
+ if (popup === true || o.display)
+ debugData( info, t, o );
+ else if (window.console)
+ console.log(debugData( info, t, o ));
+ }
+ else if (popup)
+ alert(info);
+ else if (window.console)
+ console.log(info);
+ else {
+ var id = "#layoutLogger"
+ , $l = $(id);
+ if (!$l.length)
+ $l = createLog();
+ $l.children("ul").append('<li style="padding: 4px 10px; margin: 0; border-top: 1px solid #CCC;">'+ info.replace(/\</g,"&lt;").replace(/\>/g,"&gt;") +'</li>');
+ }
+
+ function createLog () {
+ var pos = $.support.fixedPosition ? 'fixed' : 'absolute'
+ , $e = $('<div id="layoutLogger" style="position: '+ pos +'; top: 5px; z-index: 999999; max-width: 25%; overflow: hidden; border: 1px solid #000; border-radius: 5px; background: #FBFBFB; box-shadow: 0 2px 10px rgba(0,0,0,0.3);">'
+ + '<div style="font-size: 13px; font-weight: bold; padding: 5px 10px; background: #F6F6F6; border-radius: 5px 5px 0 0; cursor: move;">'
+ + '<span style="float: right; padding-left: 7px; cursor: pointer;" title="Remove Console" onclick="$(this).closest(\'#layoutLogger\').remove()">X</span>Layout console.log</div>'
+ + '<ul style="font-size: 13px; font-weight: none; list-style: none; margin: 0; padding: 0 0 2px;"></ul>'
+ + '</div>'
+ ).appendTo("body");
+ $e.css('left', $(window).width() - $e.outerWidth() - 5)
+ if ($.ui.draggable) $e.draggable({ handle: ':first-child' });
+ return $e;
+ };
+ }
+
+};
+
+var lang = $.layout.language; // alias used in defaults...
+
+// DEFAULT OPTIONS - CHANGE IF DESIRED
+$.layout.defaults = {
+/*
+ * LAYOUT & LAYOUT-CONTAINER OPTIONS
+ * - none of these options are applicable to individual panes
+ */
+ name: "" // Not required, but useful for buttons and used for the state-cookie
+, containerSelector: "" // ONLY used when specifying a childOptions - to find container-element that is NOT directly-nested
+, containerClass: "ui-layout-container" // layout-container element
+, scrollToBookmarkOnLoad: true // after creating a layout, scroll to bookmark in URL (.../page.htm#myBookmark)
+, resizeWithWindow: true // bind thisLayout.resizeAll() to the window.resize event
+, resizeWithWindowDelay: 200 // delay calling resizeAll because makes window resizing very jerky
+, resizeWithWindowMaxDelay: 0 // 0 = none - force resize every XX ms while window is being resized
+, onresizeall_start: null // CALLBACK when resizeAll() STARTS - NOT pane-specific
+, onresizeall_end: null // CALLBACK when resizeAll() ENDS - NOT pane-specific
+, onload_start: null // CALLBACK when Layout inits - after options initialized, but before elements
+, onload_end: null // CALLBACK when Layout inits - after EVERYTHING has been initialized
+, onunload_start: null // CALLBACK when Layout is destroyed OR onWindowUnload
+, onunload_end: null // CALLBACK when Layout is destroyed OR onWindowUnload
+, autoBindCustomButtons: false // search for buttons with ui-layout-button class and auto-bind them
+, initPanes: true // false = DO NOT initialize the panes onLoad - will init later
+, showErrorMessages: true // enables fatal error messages to warn developers of common errors
+, showDebugMessages: false // display console-and-alert debug msgs - IF this Layout version _has_ debugging code!
+// Changing this zIndex value will cause other zIndex values to automatically change
+, zIndex: null // the PANE zIndex - resizers and masks will be +1
+// DO NOT CHANGE the zIndex values below unless you clearly understand their relationships
+, zIndexes: { // set _default_ z-index values here...
+ pane_normal: 0 // normal z-index for panes
+ , content_mask: 1 // applied to overlays used to mask content INSIDE panes during resizing
+ , resizer_normal: 2 // normal z-index for resizer-bars
+ , pane_sliding: 100 // applied to *BOTH* the pane and its resizer when a pane is 'slid open'
+ , pane_animate: 1000 // applied to the pane when being animated - not applied to the resizer
+ , resizer_drag: 10000 // applied to the CLONED resizer-bar when being 'dragged'
+ }
+/*
+ * PANE DEFAULT SETTINGS
+ * - settings under the 'panes' key become the default settings for *all panes*
+ * - ALL pane-options can also be set specifically for each panes, which will override these 'default values'
+ */
+, panes: { // default options for 'all panes' - will be overridden by 'per-pane settings'
+ applyDemoStyles: false // NOTE: renamed from applyDefaultStyles for clarity
+ , closable: true // pane can open & close
+ , resizable: true // when open, pane can be resized
+ , slidable: true // when closed, pane can 'slide open' over other panes - closes on mouse-out
+ , initClosed: false // true = init pane as 'closed'
+ , initHidden: false // true = init pane as 'hidden' - no resizer-bar/spacing
+ // SELECTORS
+ //, paneSelector: "" // MUST be pane-specific - jQuery selector for pane
+ , contentSelector: ".ui-layout-content" // INNER div/element to auto-size so only it scrolls, not the entire pane!
+ , contentIgnoreSelector: ".ui-layout-ignore" // element(s) to 'ignore' when measuring 'content'
+ , findNestedContent: false // true = $P.find(contentSelector), false = $P.children(contentSelector)
+ // GENERIC ROOT-CLASSES - for auto-generated classNames
+ , paneClass: "ui-layout-pane" // Layout Pane
+ , resizerClass: "ui-layout-resizer" // Resizer Bar
+ , togglerClass: "ui-layout-toggler" // Toggler Button
+ , buttonClass: "ui-layout-button" // CUSTOM Buttons - eg: '[ui-layout-button]-toggle/-open/-close/-pin'
+ // ELEMENT SIZE & SPACING
+ //, size: 100 // MUST be pane-specific -initial size of pane
+ , minSize: 0 // when manually resizing a pane
+ , maxSize: 0 // ditto, 0 = no limit
+ , spacing_open: 6 // space between pane and adjacent panes - when pane is 'open'
+ , spacing_closed: 6 // ditto - when pane is 'closed'
+ , togglerLength_open: 50 // Length = WIDTH of toggler button on north/south sides - HEIGHT on east/west sides
+ , togglerLength_closed: 50 // 100% OR -1 means 'full height/width of resizer bar' - 0 means 'hidden'
+ , togglerAlign_open: "center" // top/left, bottom/right, center, OR...
+ , togglerAlign_closed: "center" // 1 => nn = offset from top/left, -1 => -nn == offset from bottom/right
+ , togglerTip_open: lang.Close // Toggler tool-tip (title)
+ , togglerTip_closed: lang.Open // ditto
+ , togglerContent_open: "" // text or HTML to put INSIDE the toggler
+ , togglerContent_closed: "" // ditto
+ // RESIZING OPTIONS
+ , resizerDblClickToggle: true //
+ , autoResize: true // IF size is 'auto' or a percentage, then recalc 'pixel size' whenever the layout resizes
+ , autoReopen: true // IF a pane was auto-closed due to noRoom, reopen it when there is room? False = leave it closed
+ , resizerDragOpacity: 1 // option for ui.draggable
+ //, resizerCursor: "" // MUST be pane-specific - cursor when over resizer-bar
+ , maskContents: false // true = add DIV-mask over-or-inside this pane so can 'drag' over IFRAMES
+ , maskObjects: false // true = add IFRAME-mask over-or-inside this pane to cover objects/applets - content-mask will overlay this mask
+ , maskZindex: null // will override zIndexes.content_mask if specified - not applicable to iframe-panes
+ , resizingGrid: false // grid size that the resizers will snap-to during resizing, eg: [20,20]
+ , livePaneResizing: false // true = LIVE Resizing as resizer is dragged
+ , liveContentResizing: false // true = re-measure header/footer heights as resizer is dragged
+ , liveResizingTolerance: 1 // how many px change before pane resizes, to control performance
+ // TIPS & MESSAGES - also see lang object
+ , noRoomToOpenTip: lang.noRoomToOpenTip
+ , resizerTip: lang.Resize // Resizer tool-tip (title)
+ , sliderTip: lang.Slide // resizer-bar triggers 'sliding' when pane is closed
+ , sliderCursor: "pointer" // cursor when resizer-bar will trigger 'sliding'
+ , slideTrigger_open: "click" // click, dblclick, mouseenter
+ , slideTrigger_close: "mouseleave"// click, mouseleave
+ , slideDelay_open: 300 // applies only for mouseenter event - 0 = instant open
+ , slideDelay_close: 300 // applies only for mouseleave event (300ms is the minimum!)
+ , hideTogglerOnSlide: false // when pane is slid-open, should the toggler show?
+ , preventQuickSlideClose: $.layout.browser.webkit // Chrome triggers slideClosed as it is opening
+ , preventPrematureSlideClose: false // handle incorrect mouseleave trigger, like when over a SELECT-list in IE
+ // HOT-KEYS & MISC
+ , showOverflowOnHover: false // will bind allowOverflow() utility to pane.onMouseOver
+ , enableCursorHotkey: true // enabled 'cursor' hotkeys
+ //, customHotkey: "" // MUST be pane-specific - EITHER a charCode OR a character
+ , customHotkeyModifier: "SHIFT" // either 'SHIFT', 'CTRL' or 'CTRL+SHIFT' - NOT 'ALT'
+ // PANE ANIMATION
+ // NOTE: fxSss_open, fxSss_close & fxSss_size options (eg: fxName_open) are auto-generated if not passed
+ , fxName: "slide" // ('none' or blank), slide, drop, scale -- only relevant to 'open' & 'close', NOT 'size'
+ , fxSpeed: null // slow, normal, fast, 200, nnn - if passed, will OVERRIDE fxSettings.duration
+ , fxSettings: {} // can be passed, eg: { easing: "easeOutBounce", duration: 1500 }
+ , fxOpacityFix: true // tries to fix opacity in IE to restore anti-aliasing after animation
+ , animatePaneSizing: false // true = animate resizing after dragging resizer-bar OR sizePane() is called
+ /* NOTE: Action-specific FX options are auto-generated from the options above if not specifically set:
+ fxName_open: "slide" // 'Open' pane animation
+ fnName_close: "slide" // 'Close' pane animation
+ fxName_size: "slide" // 'Size' pane animation - when animatePaneSizing = true
+ fxSpeed_open: null
+ fxSpeed_close: null
+ fxSpeed_size: null
+ fxSettings_open: {}
+ fxSettings_close: {}
+ fxSettings_size: {}
+ */
+ // CHILD/NESTED LAYOUTS
+ , childOptions: null // Layout-options for nested/child layout - even {} is valid as options
+ , initChildLayout: true // true = child layout will be created as soon as _this_ layout completes initialization
+ , destroyChildLayout: true // true = destroy child-layout if this pane is destroyed
+ , resizeChildLayout: true // true = trigger child-layout.resizeAll() when this pane is resized
+ // PANE CALLBACKS
+ , triggerEventsOnLoad: false // true = trigger onopen OR onclose callbacks when layout initializes
+ , triggerEventsDuringLiveResize: true // true = trigger onresize callback REPEATEDLY if livePaneResizing==true
+ , onshow_start: null // CALLBACK when pane STARTS to Show - BEFORE onopen/onhide_start
+ , onshow_end: null // CALLBACK when pane ENDS being Shown - AFTER onopen/onhide_end
+ , onhide_start: null // CALLBACK when pane STARTS to Close - BEFORE onclose_start
+ , onhide_end: null // CALLBACK when pane ENDS being Closed - AFTER onclose_end
+ , onopen_start: null // CALLBACK when pane STARTS to Open
+ , onopen_end: null // CALLBACK when pane ENDS being Opened
+ , onclose_start: null // CALLBACK when pane STARTS to Close
+ , onclose_end: null // CALLBACK when pane ENDS being Closed
+ , onresize_start: null // CALLBACK when pane STARTS being Resized ***FOR ANY REASON***
+ , onresize_end: null // CALLBACK when pane ENDS being Resized ***FOR ANY REASON***
+ , onsizecontent_start: null // CALLBACK when sizing of content-element STARTS
+ , onsizecontent_end: null // CALLBACK when sizing of content-element ENDS
+ , onswap_start: null // CALLBACK when pane STARTS to Swap
+ , onswap_end: null // CALLBACK when pane ENDS being Swapped
+ , ondrag_start: null // CALLBACK when pane STARTS being ***MANUALLY*** Resized
+ , ondrag_end: null // CALLBACK when pane ENDS being ***MANUALLY*** Resized
+ }
+/*
+ * PANE-SPECIFIC SETTINGS
+ * - options listed below MUST be specified per-pane - they CANNOT be set under 'panes'
+ * - all options under the 'panes' key can also be set specifically for any pane
+ * - most options under the 'panes' key apply only to 'border-panes' - NOT the the center-pane
+ */
+, north: {
+ paneSelector: ".ui-layout-north"
+ , size: "auto" // eg: "auto", "30%", .30, 200
+ , resizerCursor: "n-resize" // custom = url(myCursor.cur)
+ , customHotkey: "" // EITHER a charCode (43) OR a character ("o")
+ }
+, south: {
+ paneSelector: ".ui-layout-south"
+ , size: "auto"
+ , resizerCursor: "s-resize"
+ , customHotkey: ""
+ }
+, east: {
+ paneSelector: ".ui-layout-east"
+ , size: 200
+ , resizerCursor: "e-resize"
+ , customHotkey: ""
+ }
+, west: {
+ paneSelector: ".ui-layout-west"
+ , size: 200
+ , resizerCursor: "w-resize"
+ , customHotkey: ""
+ }
+, center: {
+ paneSelector: ".ui-layout-center"
+ , minWidth: 0
+ , minHeight: 0
+ }
+};
+
+$.layout.optionsMap = {
+ // layout/global options - NOT pane-options
+ layout: ("stateManagement,effects,zIndexes,"
+ + "name,zIndex,scrollToBookmarkOnLoad,showErrorMessages,"
+ + "resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay,"
+ + "onresizeall,onresizeall_start,onresizeall_end,onload,onunload,autoBindCustomButtons").split(",")
+// borderPanes: [ ALL options that are NOT specified as 'layout' ]
+ // default.panes options that apply to the center-pane (most options apply _only_ to border-panes)
+, center: ("paneClass,contentSelector,contentIgnoreSelector,findNestedContent,applyDemoStyles,triggerEventsOnLoad,"
+ + "showOverflowOnHover,maskContents,maskObjects,liveContentResizing,"
+ + "childOptions,initChildLayout,resizeChildLayout,destroyChildLayout,"
+ + "onresize,onresize_start,onresize_end,onsizecontent,onsizecontent_start,onsizecontent_end").split(",")
+ // options that MUST be specifically set 'per-pane' - CANNOT set in the panes (defaults) key
+, noDefault: ("paneSelector,resizerCursor,customHotkey").split(",")
+};
+
+/**
+ * Processes options passed in converts flat-format data into subkey (JSON) format
+ * In flat-format, subkeys are _currently_ separated with 2 underscores, like north__optName
+ * Plugins may also call this method so they can transform their own data
+ *
+ * @param {!Object} hash Data/options passed by user - may be a single level or nested levels
+ * @return {Object} Returns hash of minWidth & minHeight
+ */
+$.layout.transformData = function (hash) {
+ var json = { panes: {}, center: {} } // init return object
+ , data, branch, optKey, keys, key, val, i, c;
+
+ if (typeof hash !== "object") return json; // no options passed
+
+ // convert all 'flat-keys' to 'sub-key' format
+ for (optKey in hash) {
+ branch = json;
+ data = $.layout.optionsMap.layout;
+ val = hash[ optKey ];
+ keys = optKey.split("__"); // eg: west__size or north__fxSettings__duration
+ c = keys.length - 1;
+ // convert underscore-delimited to subkeys
+ for (i=0; i <= c; i++) {
+ key = keys[i];
+ if (i === c)
+ branch[key] = val;
+ else if (!branch[key])
+ branch[key] = {}; // create the subkey
+ // recurse to sub-key for next loop - if not done
+ branch = branch[key];
+ }
+ }
+
+ return json;
+}
+
+// INTERNAL CONFIG DATA - DO NOT CHANGE THIS!
+$.layout.backwardCompatibility = {
+ // data used by renameOldOptions()
+ map: {
+ // OLD Option Name: NEW Option Name
+ applyDefaultStyles: "applyDemoStyles"
+ , resizeNestedLayout: "resizeChildLayout"
+ , resizeWhileDragging: "livePaneResizing"
+ , resizeContentWhileDragging: "liveContentResizing"
+ , triggerEventsWhileDragging: "triggerEventsDuringLiveResize"
+ , maskIframesOnResize: "maskContents"
+ , useStateCookie: "stateManagement.enabled"
+ , "cookie.autoLoad": "stateManagement.autoLoad"
+ , "cookie.autoSave": "stateManagement.autoSave"
+ , "cookie.keys": "stateManagement.stateKeys"
+ , "cookie.name": "stateManagement.cookie.name"
+ , "cookie.domain": "stateManagement.cookie.domain"
+ , "cookie.path": "stateManagement.cookie.path"
+ , "cookie.expires": "stateManagement.cookie.expires"
+ , "cookie.secure": "stateManagement.cookie.secure"
+ }
+ /**
+ * @param {Object} opts
+ */
+, renameOptions: function (opts) {
+ var map = $.layout.backwardCompatibility.map
+ , oldData, newData, value
+ ;
+ for (var itemPath in map) {
+ oldData = getBranch( itemPath );
+ value = oldData.branch[ oldData.key ]
+ if (value !== undefined) {
+ newData = getBranch( map[itemPath], true )
+ newData.branch[ newData.key ] = value;
+ delete oldData.branch[ oldData.key ];
+ }
+ }
+
+ /**
+ * @param {string} path
+ * @param {boolean=} [create=false] Create path if does not exist
+ */
+ function getBranch (path, create) {
+ var a = path.split(".") // split keys into array
+ , c = a.length - 1
+ , D = { branch: opts, key: a[c] } // init branch at top & set key (last item)
+ , i = 0, k, undef;
+ for (; i<c; i++) { // skip the last key (data)
+ k = a[i];
+ if (D.branch[ k ] == undefined) { // child-key does not exist
+ if (create) {
+ D.branch = D.branch[ k ] = {}; // create child-branch
+ }
+ else // can't go any farther
+ D.branch = {}; // branch is undefined
+ }
+ else
+ D.branch = D.branch[ k ]; // get child-branch
+ }
+ return D;
+ };
+ }
+ /**
+ * @param {Object} opts
+ */
+, renameAllOptions: function (opts) {
+ var ren = $.layout.backwardCompatibility.renameOptions;
+ // rename root (layout) options
+ ren( opts );
+ // rename 'defaults' to 'panes'
+ if (opts.defaults) {
+ if (typeof opts.panes !== "object")
+ opts.panes = {};
+ $.extend(true, opts.panes, opts.defaults);
+ delete opts.defaults;
+ }
+ // rename options in the the options.panes key
+ if (opts.panes) ren( opts.panes );
+ // rename options inside *each pane key*, eg: options.west
+ $.each($.layout.config.allPanes, function (i, pane) {
+ if (opts[pane]) ren( opts[pane] );
+ });
+ return opts;
+ }
+};
+
+
+
+/* ============================================================
+ * BEGIN WIDGET: $( selector ).layout( {options} );
+ * ============================================================
+ */
+$.fn.layout = function (opts) {
+ var
+
+ // local aliases to global data
+ browser = $.layout.browser
+, lang = $.layout.language // internal alias
+, _c = $.layout.config
+
+ // local aliases to utlity methods
+, cssW = $.layout.cssWidth
+, cssH = $.layout.cssHeight
+, elDims = $.layout.getElementDimensions
+, elCSS = $.layout.getElementCSS
+, evtObj = $.layout.getEventObject
+, evtPane = $.layout.parsePaneName
+
+/**
+ * options - populated by initOptions()
+ */
+, options = $.extend(true, {}, $.layout.defaults)
+, effects = options.effects = $.extend(true, {}, $.layout.effects)
+
+/**
+ * layout-state object
+ */
+, state = {
+ // generate unique ID to use for event.namespace so can unbind only events added by 'this layout'
+ id: "layout"+ $.now() // code uses alias: sID
+ , initialized: false
+ , container: {} // init all keys
+ , north: {}
+ , south: {}
+ , east: {}
+ , west: {}
+ , center: {}
+ }
+
+/**
+ * parent/child-layout pointers
+ */
+//, hasParentLayout = false - exists ONLY inside Instance so can be set externally
+, children = {
+ north: null
+ , south: null
+ , east: null
+ , west: null
+ , center: null
+ }
+
+/*
+ * ###########################
+ * INTERNAL HELPER FUNCTIONS
+ * ###########################
+ */
+
+ /**
+ * Manages all internal timers
+ */
+, timer = {
+ data: {}
+ , set: function (s, fn, ms) { timer.clear(s); timer.data[s] = setTimeout(fn, ms); }
+ , clear: function (s) { var t=timer.data; if (t[s]) {clearTimeout(t[s]); delete t[s];} }
+ }
+
+, _log = function (msg, popup) {
+ $.layout.msg( options.name +' / '+ msg, (popup && options.showErrorMessages) );
+ }
+
+ /**
+ * Executes a Callback function after a trigger event, like resize, open or close
+ *
+ * @param {?string} pane This is passed only so we can pass the 'pane object' to the callback
+ * @param {(string|function())} fn Accepts a function name, OR a comma-delimited array: [0]=function name, [1]=argument
+ */
+, _runCallbacks = function (evtName, pane, skipBoundEvents) {
+ var o = pane ? options[pane] : options
+ // names like onopen and onopen_end separate are interchangeable in options...
+ , long = evtName + (evtName.match(/_/) ? "" : "_end")
+ , short = long.match(/_end$/) ? long.substr(0, long.length - 4) : ""
+ , fn = o[long]
+ , retVal = "NC" // NC = No Callback
+ , args = []
+ ;
+ if (!fn && short)
+ fn = o[short];
+
+ // first trigger the callback set in the options
+ if (fn) {
+ //try {
+ // convert function name (string) to function object
+ if (isStr( fn )) {
+ if (fn.match(/,/)) {
+ // function name cannot contain a comma,
+ // so must be a function name AND a parameter to pass
+ args = fn.split(",")
+ , fn = eval(args[0]);
+ }
+ else // just the name of an external function?
+ fn = eval(fn);
+ }
+ // execute the callback, if exists
+ if ($.isFunction( fn )) {
+ if (args.length)
+ retVal = fn(args[1]); // pass the argument parsed from 'list'
+ else if (pane && $Ps[pane])
+ // pass data: pane-name, pane-element, pane-state, pane-options, and layout-name
+ retVal = fn( pane, $Ps[pane], state[pane], options[pane], options.name );
+ else // must be a layout/container callback - pass suitable info
+ retVal = fn( Instance, state, options, options.name );
+ }
+ //}
+ //catch (ex) {}
+ }
+
+ // trigger additional events bound directly to the pane
+ if (!skipBoundEvents && retVal !== false) {
+ if (pane) { // PANE events can be bound to each pane-elements
+ $Ps[pane].triggerHandler('layoutpane'+ long, [ pane, $Ps[pane], state[pane], options[pane], options.name ]);
+ if (short)
+ $Ps[pane].triggerHandler('layoutpane'+ short, [ pane, $Ps[pane], state[pane], options[pane], options.name ]);
+ }
+ else // LAYOUT events can be bound to the container-element
+ $N.triggerHandler('layout'+ long, [ pane, $Ps[pane], state[pane], options[pane], options.name ]);
+ }
+
+ // ALWAYS resizeChildLayout after a resize event - even during initialization
+ if (evtName === "onresize_end" || evtName === "onsizecontent_end")
+ resizeChildLayout(pane);
+
+ return retVal;
+ }
+
+
+ /**
+ * cure iframe display issues in IE & other browsers
+ */
+, _fixIframe = function (pane) {
+ if (browser.mozilla) return; // skip FireFox - it auto-refreshes iframes onShow
+ var $P = $Ps[pane];
+ // if the 'pane' is an iframe, do it
+ if (state[pane].tagName === "IFRAME")
+ $P.css(_c.hidden).css(_c.visible);
+ else // ditto for any iframes INSIDE the pane
+ $P.find('IFRAME').css(_c.hidden).css(_c.visible);
+ }
+
+ /**
+ * @param {string} pane Can accept ONLY a 'pane' (east, west, etc)
+ * @param {number=} outerSize (optional) Can pass a width, allowing calculations BEFORE element is resized
+ * @return {number} Returns the innerHeight/Width of el by subtracting padding and borders
+ */
+, cssSize = function (pane, outerSize) {
+ var fn = _c[pane].dir=="horz" ? cssH : cssW;
+ return fn($Ps[pane], outerSize);
+ }
+
+ /**
+ * @param {string} pane Can accept ONLY a 'pane' (east, west, etc)
+ * @return {Object} Returns hash of minWidth & minHeight
+ */
+, cssMinDims = function (pane) {
+ // minWidth/Height means CSS width/height = 1px
+ var $P = $Ps[pane]
+ , dir = _c[pane].dir
+ , d = {
+ minWidth: 1001 - cssW($P, 1000)
+ , minHeight: 1001 - cssH($P, 1000)
+ }
+ ;
+ if (dir === "horz") d.minSize = d.minHeight;
+ if (dir === "vert") d.minSize = d.minWidth;
+ return d;
+ }
+
+ // TODO: see if these methods can be made more useful...
+ // TODO: *maybe* return cssW/H from these so caller can use this info
+
+ /**
+ * @param {(string|!Object)} el
+ * @param {number=} outerWidth
+ * @param {boolean=} [autoHide=false]
+ */
+, setOuterWidth = function (el, outerWidth, autoHide) {
+ var $E = el, w;
+ if (isStr(el)) $E = $Ps[el]; // west
+ else if (!el.jquery) $E = $(el);
+ w = cssW($E, outerWidth);
+ $E.css({ width: w });
+ if (w > 0) {
+ if (autoHide && $E.data('autoHidden') && $E.innerHeight() > 0) {
+ $E.show().data('autoHidden', false);
+ if (!browser.mozilla) // FireFox refreshes iframes - IE does not
+ // make hidden, then visible to 'refresh' display after animation
+ $E.css(_c.hidden).css(_c.visible);
+ }
+ }
+ else if (autoHide && !$E.data('autoHidden'))
+ $E.hide().data('autoHidden', true);
+ }
+
+ /**
+ * @param {(string|!Object)} el
+ * @param {number=} outerHeight
+ * @param {boolean=} [autoHide=false]
+ */
+, setOuterHeight = function (el, outerHeight, autoHide) {
+ var $E = el, h;
+ if (isStr(el)) $E = $Ps[el]; // west
+ else if (!el.jquery) $E = $(el);
+ h = cssH($E, outerHeight);
+ $E.css({ height: h, visibility: "visible" }); // may have been 'hidden' by sizeContent
+ if (h > 0 && $E.innerWidth() > 0) {
+ if (autoHide && $E.data('autoHidden')) {
+ $E.show().data('autoHidden', false);
+ if (!browser.mozilla) // FireFox refreshes iframes - IE does not
+ $E.css(_c.hidden).css(_c.visible);
+ }
+ }
+ else if (autoHide && !$E.data('autoHidden'))
+ $E.hide().data('autoHidden', true);
+ }
+
+ /**
+ * @param {(string|!Object)} el
+ * @param {number=} outerSize
+ * @param {boolean=} [autoHide=false]
+ */
+, setOuterSize = function (el, outerSize, autoHide) {
+ if (_c[pane].dir=="horz") // pane = north or south
+ setOuterHeight(el, outerSize, autoHide);
+ else // pane = east or west
+ setOuterWidth(el, outerSize, autoHide);
+ }
+
+
+ /**
+ * Converts any 'size' params to a pixel/integer size, if not already
+ * If 'auto' or a decimal/percentage is passed as 'size', a pixel-size is calculated
+ *
+ /**
+ * @param {string} pane
+ * @param {(string|number)=} size
+ * @param {string=} [dir]
+ * @return {number}
+ */
+, _parseSize = function (pane, size, dir) {
+ if (!dir) dir = _c[pane].dir;
+
+ if (isStr(size) && size.match(/%/))
+ size = (size === '100%') ? -1 : parseInt(size, 10) / 100; // convert % to decimal
+
+ if (size === 0)
+ return 0;
+ else if (size >= 1)
+ return parseInt(size, 10);
+
+ var o = options, avail = 0;
+ if (dir=="horz") // north or south or center.minHeight
+ avail = sC.innerHeight - ($Ps.north ? o.north.spacing_open : 0) - ($Ps.south ? o.south.spacing_open : 0);
+ else if (dir=="vert") // east or west or center.minWidth
+ avail = sC.innerWidth - ($Ps.west ? o.west.spacing_open : 0) - ($Ps.east ? o.east.spacing_open : 0);
+
+ if (size === -1) // -1 == 100%
+ return avail;
+ else if (size > 0) // percentage, eg: .25
+ return round(avail * size);
+ else if (pane=="center")
+ return 0;
+ else { // size < 0 || size=='auto' || size==Missing || size==Invalid
+ // auto-size the pane
+ var dim = (dir === "horz" ? "height" : "width")
+ , $P = $Ps[pane]
+ , $C = dim === 'height' ? $Cs[pane] : false
+ , vis = $.layout.showInvisibly($P) // show pane invisibly if hidden
+ , szP = $P.css(dim) // SAVE current pane size
+ , szC = $C ? $C.css(dim) : 0 // SAVE current content size
+ ;
+ $P.css(dim, "auto");
+ if ($C) $C.css(dim, "auto");
+ size = (dim === "height") ? $P.outerHeight() : $P.outerWidth(); // MEASURE
+ $P.css(dim, szP).css(vis); // RESET size & visibility
+ if ($C) $C.css(dim, szC);
+ return size;
+ }
+ }
+
+ /**
+ * Calculates current 'size' (outer-width or outer-height) of a border-pane - optionally with 'pane-spacing' added
+ *
+ * @param {(string|!Object)} pane
+ * @param {boolean=} [inclSpace=false]
+ * @return {number} Returns EITHER Width for east/west panes OR Height for north/south panes - adjusted for boxModel & browser
+ */
+, getPaneSize = function (pane, inclSpace) {
+ var
+ $P = $Ps[pane]
+ , o = options[pane]
+ , s = state[pane]
+ , oSp = (inclSpace ? o.spacing_open : 0)
+ , cSp = (inclSpace ? o.spacing_closed : 0)
+ ;
+ if (!$P || s.isHidden)
+ return 0;
+ else if (s.isClosed || (s.isSliding && inclSpace))
+ return cSp;
+ else if (_c[pane].dir === "horz")
+ return $P.outerHeight() + oSp;
+ else // dir === "vert"
+ return $P.outerWidth() + oSp;
+ }
+
+ /**
+ * Calculate min/max pane dimensions and limits for resizing
+ *
+ * @param {string} pane
+ * @param {boolean=} [slide=false]
+ */
+, setSizeLimits = function (pane, slide) {
+ if (!isInitialized()) return;
+ var
+ o = options[pane]
+ , s = state[pane]
+ , c = _c[pane]
+ , dir = c.dir
+ , side = c.side.toLowerCase()
+ , type = c.sizeType.toLowerCase()
+ , isSliding = (slide != undefined ? slide : s.isSliding) // only open() passes 'slide' param
+ , $P = $Ps[pane]
+ , paneSpacing = o.spacing_open
+ // measure the pane on the *opposite side* from this pane
+ , altPane = _c.oppositeEdge[pane]
+ , altS = state[altPane]
+ , $altP = $Ps[altPane]
+ , altPaneSize = (!$altP || altS.isVisible===false || altS.isSliding ? 0 : (dir=="horz" ? $altP.outerHeight() : $altP.outerWidth()))
+ , altPaneSpacing = ((!$altP || altS.isHidden ? 0 : options[altPane][ altS.isClosed !== false ? "spacing_closed" : "spacing_open" ]) || 0)
+ // limitSize prevents this pane from 'overlapping' opposite pane
+ , containerSize = (dir=="horz" ? sC.innerHeight : sC.innerWidth)
+ , minCenterDims = cssMinDims("center")
+ , minCenterSize = dir=="horz" ? max(options.center.minHeight, minCenterDims.minHeight) : max(options.center.minWidth, minCenterDims.minWidth)
+ // if pane is 'sliding', then ignore center and alt-pane sizes - because 'overlays' them
+ , limitSize = (containerSize - paneSpacing - (isSliding ? 0 : (_parseSize("center", minCenterSize, dir) + altPaneSize + altPaneSpacing)))
+ , minSize = s.minSize = max( _parseSize(pane, o.minSize), cssMinDims(pane).minSize )
+ , maxSize = s.maxSize = min( (o.maxSize ? _parseSize(pane, o.maxSize) : 100000), limitSize )
+ , r = s.resizerPosition = {} // used to set resizing limits
+ , top = sC.insetTop
+ , left = sC.insetLeft
+ , W = sC.innerWidth
+ , H = sC.innerHeight
+ , rW = o.spacing_open // subtract resizer-width to get top/left position for south/east
+ ;
+ switch (pane) {
+ case "north": r.min = top + minSize;
+ r.max = top + maxSize;
+ break;
+ case "west": r.min = left + minSize;
+ r.max = left + maxSize;
+ break;
+ case "south": r.min = top + H - maxSize - rW;
+ r.max = top + H - minSize - rW;
+ break;
+ case "east": r.min = left + W - maxSize - rW;
+ r.max = left + W - minSize - rW;
+ break;
+ };
+ }
+
+ /**
+ * Returns data for setting the size/position of center pane. Also used to set Height for east/west panes
+ *
+ * @return JSON Returns a hash of all dimensions: top, bottom, left, right, (outer) width and (outer) height
+ */
+, calcNewCenterPaneDims = function () {
+ var d = {
+ top: getPaneSize("north", true) // true = include 'spacing' value for pane
+ , bottom: getPaneSize("south", true)
+ , left: getPaneSize("west", true)
+ , right: getPaneSize("east", true)
+ , width: 0
+ , height: 0
+ };
+
+ // NOTE: sC = state.container
+ // calc center-pane outer dimensions
+ d.width = sC.innerWidth - d.left - d.right; // outerWidth
+ d.height = sC.innerHeight - d.bottom - d.top; // outerHeight
+ // add the 'container border/padding' to get final positions relative to the container
+ d.top += sC.insetTop;
+ d.bottom += sC.insetBottom;
+ d.left += sC.insetLeft;
+ d.right += sC.insetRight;
+
+ return d;
+ }
+
+
+ /**
+ * @param {!Object} el
+ * @param {boolean=} [allStates=false]
+ */
+, getHoverClasses = function (el, allStates) {
+ var
+ $El = $(el)
+ , type = $El.data("layoutRole")
+ , pane = $El.data("layoutEdge")
+ , o = options[pane]
+ , root = o[type +"Class"]
+ , _pane = "-"+ pane // eg: "-west"
+ , _open = "-open"
+ , _closed = "-closed"
+ , _slide = "-sliding"
+ , _hover = "-hover " // NOTE the trailing space
+ , _state = $El.hasClass(root+_closed) ? _closed : _open
+ , _alt = _state === _closed ? _open : _closed
+ , classes = (root+_hover) + (root+_pane+_hover) + (root+_state+_hover) + (root+_pane+_state+_hover)
+ ;
+ if (allStates) // when 'removing' classes, also remove alternate-state classes
+ classes += (root+_alt+_hover) + (root+_pane+_alt+_hover);
+
+ if (type=="resizer" && $El.hasClass(root+_slide))
+ classes += (root+_slide+_hover) + (root+_pane+_slide+_hover);
+
+ return $.trim(classes);
+ }
+, addHover = function (evt, el) {
+ var $E = $(el || this);
+ if (evt && $E.data("layoutRole") === "toggler")
+ evt.stopPropagation(); // prevent triggering 'slide' on Resizer-bar
+ $E.addClass( getHoverClasses($E) );
+ }
+, removeHover = function (evt, el) {
+ var $E = $(el || this);
+ $E.removeClass( getHoverClasses($E, true) );
+ }
+
+, onResizerEnter = function (evt) { // ALSO called by toggler.mouseenter
+ if ($.fn.disableSelection)
+ $("body").disableSelection();
+ }
+, onResizerLeave = function (evt, el) {
+ var
+ e = el || this // el is only passed when called by the timer
+ , pane = $(e).data("layoutEdge")
+ , name = pane +"ResizerLeave"
+ ;
+ timer.clear(pane+"_openSlider"); // cancel slideOpen timer, if set
+ timer.clear(name); // cancel enableSelection timer - may re/set below
+ // this method calls itself on a timer because it needs to allow
+ // enough time for dragging to kick-in and set the isResizing flag
+ // dragging has a 100ms delay set, so this delay must be >100
+ if (!el) // 1st call - mouseleave event
+ timer.set(name, function(){ onResizerLeave(evt, e); }, 200);
+ // if user is resizing, then dragStop will enableSelection(), so can skip it here
+ else if (!state[pane].isResizing && $.fn.enableSelection) // 2nd call - by timer
+ $("body").enableSelection();
+ }
+
+/*
+ * ###########################
+ * INITIALIZATION METHODS
+ * ###########################
+ */
+
+ /**
+ * Initialize the layout - called automatically whenever an instance of layout is created
+ *
+ * @see none - triggered onInit
+ * @return mixed true = fully initialized | false = panes not initialized (yet) | 'cancel' = abort
+ */
+, _create = function () {
+ // initialize config/options
+ initOptions();
+ var o = options;
+
+ // TEMP state so isInitialized returns true during init process
+ state.creatingLayout = true;
+
+ // init plugins for this layout, if there are any (eg: stateManagement)
+ runPluginCallbacks( Instance, $.layout.onCreate );
+
+ // options & state have been initialized, so now run beforeLoad callback
+ // onload will CANCEL layout creation if it returns false
+ if (false === _runCallbacks("onload_start"))
+ return 'cancel';
+
+ // initialize the container element
+ _initContainer();
+
+ // bind hotkey function - keyDown - if required
+ initHotkeys();
+
+ // bind window.onunload
+ $(window).bind("unload."+ sID, unload);
+
+ // init plugins for this layout, if there are any (eg: customButtons)
+ runPluginCallbacks( Instance, $.layout.onLoad );
+
+ // if layout elements are hidden, then layout WILL NOT complete initialization!
+ // initLayoutElements will set initialized=true and run the onload callback IF successful
+ if (o.initPanes) _initLayoutElements();
+
+ delete state.creatingLayout;
+
+ return state.initialized;
+ }
+
+ /**
+ * Initialize the layout IF not already
+ *
+ * @see All methods in Instance run this test
+ * @return boolean true = layoutElements have been initialized | false = panes are not initialized (yet)
+ */
+, isInitialized = function () {
+ if (state.initialized || state.creatingLayout) return true; // already initialized
+ else return _initLayoutElements(); // try to init panes NOW
+ }
+
+ /**
+ * Initialize the layout - called automatically whenever an instance of layout is created
+ *
+ * @see _create() & isInitialized
+ * @return An object pointer to the instance created
+ */
+, _initLayoutElements = function (retry) {
+ // initialize config/options
+ var o = options;
+
+ // CANNOT init panes inside a hidden container!
+ if (!$N.is(":visible")) {
+ // handle Chrome bug where popup window 'has no height'
+ // if layout is BODY element, try again in 50ms
+ // SEE: http://layout.jquery-dev.net/samples/test_popup_window.html
+ if ( !retry && browser.webkit && $N[0].tagName === "BODY" )
+ setTimeout(function(){ _initLayoutElements(true); }, 50);
+ return false;
+ }
+
+ // a center pane is required, so make sure it exists
+ if (!getPane("center").length) {
+ if (options.showErrorMessages)
+ _log( lang.errCenterPaneMissing, true );
+ return false;
+ }
+
+ // TEMP state so isInitialized returns true during init process
+ state.creatingLayout = true;
+
+ // update Container dims
+ $.extend(sC, elDims( $N ));
+
+ // initialize all layout elements
+ initPanes(); // size & position panes - calls initHandles() - which calls initResizable()
+
+ if (o.scrollToBookmarkOnLoad) {
+ var l = self.location;
+ if (l.hash) l.replace( l.hash ); // scrollTo Bookmark
+ }
+
+ // check to see if this layout 'nested' inside a pane
+ if (Instance.hasParentLayout)
+ o.resizeWithWindow = false;
+ // bind resizeAll() for 'this layout instance' to window.resize event
+ else if (o.resizeWithWindow)
+ $(window).bind("resize."+ sID, windowResize);
+
+ delete state.creatingLayout;
+ state.initialized = true;
+
+ // init plugins for this layout, if there are any
+ runPluginCallbacks( Instance, $.layout.onReady );
+
+ // now run the onload callback, if exists
+ _runCallbacks("onload_end");
+
+ return true; // elements initialized successfully
+ }
+
+ /**
+ * Initialize nested layouts - called when _initLayoutElements completes
+ *
+ * NOT CURRENTLY USED
+ *
+ * @see _initLayoutElements
+ * @return An object pointer to the instance created
+ */
+, _initChildLayouts = function () {
+ $.each(_c.allPanes, function (idx, pane) {
+ if (options[pane].initChildLayout)
+ createChildLayout( pane );
+ });
+ }
+
+ /**
+ * Initialize nested layouts for a specific pane - can optionally pass layout-options
+ *
+ * @see _initChildLayouts
+ * @param {string} pane The pane being opened, ie: north, south, east, or west
+ * @param {Object=} [opts] Layout-options - if passed, will OVERRRIDE options[pane].childOptions
+ * @return An object pointer to the layout instance created - or null
+ */
+, createChildLayout = function (evt_or_pane, opts) {
+ var pane = evtPane.call(this, evt_or_pane)
+ , $P = $Ps[pane]
+ , C = children
+ ;
+ if ($P) {
+ var $C = $Cs[pane]
+ , o = opts || options[pane].childOptions
+ , d = "layout"
+ // determine which element is supposed to be the 'child container'
+ // if pane has a 'containerSelector' OR a 'content-div', use those instead of the pane
+ , $Cont = o.containerSelector ? $P.find( o.containerSelector ) : ($C || $P)
+ , containerFound = $Cont.length
+ // see if a child-layout ALREADY exists on this element
+ , child = containerFound ? (C[pane] = $Cont.data(d) || null) : null
+ ;
+ // if no layout exists, but childOptions are set, try to create the layout now
+ if (!child && containerFound && o)
+ child = C[pane] = $Cont.eq(0).layout(o) || null;
+ if (child)
+ child.hasParentLayout = true; // set parent-flag in child
+ }
+ Instance[pane].child = C[pane]; // ALWAYS set pane-object pointer, even if null
+ }
+
+, windowResize = function () {
+ var delay = Number(options.resizeWithWindowDelay);
+ if (delay < 10) delay = 100; // MUST have a delay!
+ // resizing uses a delay-loop because the resize event fires repeatly - except in FF, but delay anyway
+ timer.clear("winResize"); // if already running
+ timer.set("winResize", function(){
+ timer.clear("winResize");
+ timer.clear("winResizeRepeater");
+ var dims = elDims( $N );
+ // only trigger resizeAll() if container has changed size
+ if (dims.innerWidth !== sC.innerWidth || dims.innerHeight !== sC.innerHeight)
+ resizeAll();
+ }, delay);
+ // ALSO set fixed-delay timer, if not already running
+ if (!timer.data["winResizeRepeater"]) setWindowResizeRepeater();
+ }
+
+, setWindowResizeRepeater = function () {
+ var delay = Number(options.resizeWithWindowMaxDelay);
+ if (delay > 0)
+ timer.set("winResizeRepeater", function(){ setWindowResizeRepeater(); resizeAll(); }, delay);
+ }
+
+, unload = function () {
+ var o = options;
+
+ _runCallbacks("onunload_start");
+
+ // trigger plugin callabacks for this layout (eg: stateManagement)
+ runPluginCallbacks( Instance, $.layout.onUnload );
+
+ _runCallbacks("onunload_end");
+ }
+
+ /**
+ * Validate and initialize container CSS and events
+ *
+ * @see _create()
+ */
+, _initContainer = function () {
+ var
+ N = $N[0]
+ , tag = sC.tagName = N.tagName
+ , id = sC.id = N.id
+ , cls = sC.className = N.className
+ , o = options
+ , name = o.name
+ , fullPage= (tag === "BODY")
+ , props = "overflow,position,margin,padding,border"
+ , css = "layoutCSS"
+ , CSS = {}
+ , hid = "hidden" // used A LOT!
+ // see if this container is a 'pane' inside an outer-layout
+ , parent = $N.data("parentLayout") // parent-layout Instance
+ , pane = $N.data("layoutEdge") // pane-name in parent-layout
+ , isChild = parent && pane
+ ;
+ // sC -> state.container
+ sC.selector = $N.selector.split(".slice")[0];
+ sC.ref = (o.name ? o.name +' layout / ' : '') + tag + (id ? "#"+id : cls ? '.['+cls+']' : ''); // used in messages
+
+ $N .data({
+ layout: Instance
+ , layoutContainer: sID // FLAG to indicate this is a layout-container - contains unique internal ID
+ })
+ .addClass(o.containerClass)
+ ;
+ var layoutMethods = {
+ destroy: ''
+ , initPanes: ''
+ , resizeAll: 'resizeAll'
+ , resize: 'resizeAll'
+ }
+ , name;
+ // loop hash and bind all methods - include layoutID namespacing
+ for (name in layoutMethods) {
+ $N.bind("layout"+ name.toLowerCase() +"."+ sID, Instance[ layoutMethods[name] || name ]);
+ }
+
+ // if this container is another layout's 'pane', then set child/parent pointers
+ if (isChild) {
+ // update parent flag
+ Instance.hasParentLayout = true;
+ // set pointers to THIS child-layout (Instance) in parent-layout
+ // NOTE: parent.PANE.child is an ALIAS to parent.children.PANE
+ parent[pane].child = parent.children[pane] = $N.data("layout");
+ }
+
+ // SAVE original container CSS for use in destroy()
+ if (!$N.data(css)) {
+ // handle props like overflow different for BODY & HTML - has 'system default' values
+ if (fullPage) {
+ CSS = $.extend( elCSS($N, props), {
+ height: $N.css("height")
+ , overflow: $N.css("overflow")
+ , overflowX: $N.css("overflowX")
+ , overflowY: $N.css("overflowY")
+ });
+ // ALSO SAVE <HTML> CSS
+ var $H = $("html");
+ $H.data(css, {
+ height: "auto" // FF would return a fixed px-size!
+ , overflow: $H.css("overflow")
+ , overflowX: $H.css("overflowX")
+ , overflowY: $H.css("overflowY")
+ });
+ }
+ else // handle props normally for non-body elements
+ CSS = elCSS($N, props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY");
+
+ $N.data(css, CSS);
+ }
+
+ try { // format html/body if this is a full page layout
+ if (fullPage) {
+ $("html").css({
+ height: "100%"
+ , overflow: hid
+ , overflowX: hid
+ , overflowY: hid
+ });
+ $("body").css({
+ position: "relative"
+ , height: "100%"
+ , overflow: hid
+ , overflowX: hid
+ , overflowY: hid
+ , margin: 0
+ , padding: 0 // TODO: test whether body-padding could be handled?
+ , border: "none" // a body-border creates problems because it cannot be measured!
+ });
+
+ // set current layout-container dimensions
+ $.extend(sC, elDims( $N ));
+ }
+ else { // set required CSS for overflow and position
+ // ENSURE container will not 'scroll'
+ CSS = { overflow: hid, overflowX: hid, overflowY: hid }
+ var
+ p = $N.css("position")
+ , h = $N.css("height")
+ ;
+ // if this is a NESTED layout, then container/outer-pane ALREADY has position and height
+ if (!isChild) {
+ if (!p || !p.match(/fixed|absolute|relative/))
+ CSS.position = "relative"; // container MUST have a 'position'
+ /*
+ if (!h || h=="auto")
+ CSS.height = "100%"; // container MUST have a 'height'
+ */
+ }
+ $N.css( CSS );
+
+ // set current layout-container dimensions
+ if ( $N.is(":visible") ) {
+ $.extend(sC, elDims( $N ));
+ if (o.showErrorMessages && sC.innerHeight < 1)
+ _log( lang.errContainerHeight.replace(/CONTAINER/, sC.ref), true );
+ }
+ }
+ } catch (ex) {}
+ }
+
+ /**
+ * Bind layout hotkeys - if options enabled
+ *
+ * @see _create() and addPane()
+ * @param {string=} [panes=""] The edge(s) to process
+ */
+, initHotkeys = function (panes) {
+ panes = panes ? panes.split(",") : _c.borderPanes;
+ // bind keyDown to capture hotkeys, if option enabled for ANY pane
+ $.each(panes, function (i, pane) {
+ var o = options[pane];
+ if (o.enableCursorHotkey || o.customHotkey) {
+ $(document).bind("keydown."+ sID, keyDown); // only need to bind this ONCE
+ return false; // BREAK - binding was done
+ }
+ });
+ }
+
+ /**
+ * Build final OPTIONS data
+ *
+ * @see _create()
+ */
+, initOptions = function () {
+ var data, d, pane, key, val, i, c, o;
+
+ // reprocess user's layout-options to have correct options sub-key structure
+ opts = $.layout.transformData( opts ); // panes = default subkey
+
+ // auto-rename old options for backward compatibility
+ opts = $.layout.backwardCompatibility.renameAllOptions( opts );
+
+ // if user-options has 'panes' key (pane-defaults), process it...
+ if (!$.isEmptyObject(opts.panes)) {
+ // REMOVE any pane-defaults that MUST be set per-pane
+ data = $.layout.optionsMap.noDefault;
+ for (i=0, c=data.length; i<c; i++) {
+ key = data[i];
+ delete opts.panes[key]; // OK if does not exist
+ }
+ // REMOVE any layout-options specified under opts.panes
+ data = $.layout.optionsMap.layout;
+ for (i=0, c=data.length; i<c; i++) {
+ key = data[i];
+ delete opts.panes[key]; // OK if does not exist
+ }
+ }
+
+ // MOVE any NON-layout-options to opts.panes
+ data = $.layout.optionsMap.layout;
+ var rootKeys = $.layout.config.optionRootKeys;
+ for (key in opts) {
+ val = opts[key];
+ if ($.inArray(key, rootKeys) < 0 && $.inArray(key, data) < 0) {
+ if (!opts.panes[key])
+ opts.panes[key] = $.isPlainObject(val) ? $.extend(true, {}, val) : val;
+ delete opts[key]
+ }
+ }
+
+ // START by updating ALL options from opts
+ $.extend(true, options, opts);
+
+ // CREATE final options (and config) for EACH pane
+ $.each(_c.allPanes, function (i, pane) {
+
+ // apply 'pane-defaults' to CONFIG.[PANE]
+ _c[pane] = $.extend( true, {}, _c.panes, _c[pane] );
+
+ d = options.panes;
+ o = options[pane];
+
+ // center-pane uses SOME keys in defaults.panes branch
+ if (pane === 'center') {
+ // ONLY copy keys from opts.panes listed in: $.layout.optionsMap.center
+ data = $.layout.optionsMap.center; // list of 'center-pane keys'
+ for (i=0, c=data.length; i<c; i++) { // loop the list...
+ key = data[i];
+ // only need to use pane-default if pane-specific value not set
+ if (!opts.center[key] && (opts.panes[key] || !o[key]))
+ o[key] = d[key]; // pane-default
+ }
+ }
+ else {
+ // border-panes use ALL keys in defaults.panes branch
+ o = options[pane] = $.extend({}, d, o); // re-apply pane-specific opts AFTER pane-defaults
+ createFxOptions( pane );
+ // ensure all border-pane-specific base-classes exist
+ if (!o.resizerClass) o.resizerClass = "ui-layout-resizer";
+ if (!o.togglerClass) o.togglerClass = "ui-layout-toggler";
+ }
+ // ensure we have base pane-class (ALL panes)
+ if (!o.paneClass) o.paneClass = "ui-layout-pane";
+ });
+
+ // update options.zIndexes if a zIndex-option specified
+ var zo = opts.zIndex
+ , z = options.zIndexes;
+ if (zo > 0) {
+ z.pane_normal = zo;
+ z.content_mask = max(zo+1, z.content_mask); // MIN = +1
+ z.resizer_normal = max(zo+2, z.resizer_normal); // MIN = +2
+ }
+
+ function createFxOptions ( pane ) {
+ var o = options[pane]
+ , d = options.panes;
+ // ensure fxSettings key to avoid errors
+ if (!o.fxSettings) o.fxSettings = {};
+ if (!d.fxSettings) d.fxSettings = {};
+
+ $.each(["_open","_close","_size"], function (i,n) {
+ var
+ sName = "fxName"+ n
+ , sSpeed = "fxSpeed"+ n
+ , sSettings = "fxSettings"+ n
+ // recalculate fxName according to specificity rules
+ , fxName = o[sName] =
+ o[sName] // options.west.fxName_open
+ || d[sName] // options.panes.fxName_open
+ || o.fxName // options.west.fxName
+ || d.fxName // options.panes.fxName
+ || "none" // MEANS $.layout.defaults.panes.fxName == "" || false || null || 0
+ ;
+ // validate fxName to ensure is valid effect - MUST have effect-config data in options.effects
+ if (fxName === "none" || !$.effects || !$.effects[fxName] || !options.effects[fxName])
+ fxName = o[sName] = "none"; // effect not loaded OR unrecognized fxName
+
+ // set vars for effects subkeys to simplify logic
+ var fx = options.effects[fxName] || {} // effects.slide
+ , fx_all = fx.all || null // effects.slide.all
+ , fx_pane = fx[pane] || null // effects.slide.west
+ ;
+ // create fxSpeed[_open|_close|_size]
+ o[sSpeed] =
+ o[sSpeed] // options.west.fxSpeed_open
+ || d[sSpeed] // options.west.fxSpeed_open
+ || o.fxSpeed // options.west.fxSpeed
+ || d.fxSpeed // options.panes.fxSpeed
+ || null // DEFAULT - let fxSetting.duration control speed
+ ;
+ // create fxSettings[_open|_close|_size]
+ o[sSettings] = $.extend(
+ {}
+ , fx_all // effects.slide.all
+ , fx_pane // effects.slide.west
+ , d.fxSettings // options.panes.fxSettings
+ , o.fxSettings // options.west.fxSettings
+ , d[sSettings] // options.panes.fxSettings_open
+ , o[sSettings] // options.west.fxSettings_open
+ );
+ });
+
+ // DONE creating action-specific-settings for this pane,
+ // so DELETE generic options - are no longer meaningful
+ delete o.fxName;
+ delete o.fxSpeed;
+ delete o.fxSettings;
+ }
+
+ // DELETE 'panes' key now that we are done - values were copied to EACH pane
+ delete options.panes;
+ }
+
+ /**
+ * Initialize module objects, styling, size and position for all panes
+ *
+ * @see _initElements()
+ * @param {string} pane The pane to process
+ */
+, getPane = function (pane) {
+ var sel = options[pane].paneSelector
+ if (sel.substr(0,1)==="#") // ID selector
+ // NOTE: elements selected 'by ID' DO NOT have to be 'children'
+ return $N.find(sel).eq(0);
+ else { // class or other selector
+ var $P = $N.children(sel).eq(0);
+ // look for the pane nested inside a 'form' element
+ return $P.length ? $P : $N.children("form:first").children(sel).eq(0);
+ }
+ }
+
+, initPanes = function () {
+ // NOTE: do north & south FIRST so we can measure their height - do center LAST
+ $.each(_c.allPanes, function (idx, pane) {
+ addPane( pane, true );
+ });
+
+ // init the pane-handles NOW in case we have to hide or close the pane below
+ initHandles();
+
+ // now that all panes have been initialized and initially-sized,
+ // make sure there is really enough space available for each pane
+ $.each(_c.borderPanes, function (i, pane) {
+ if ($Ps[pane] && state[pane].isVisible) { // pane is OPEN
+ setSizeLimits(pane);
+ makePaneFit(pane); // pane may be Closed, Hidden or Resized by makePaneFit()
+ }
+ });
+ // size center-pane AGAIN in case we 'closed' a border-pane in loop above
+ sizeMidPanes("center");
+
+ // Chrome/Webkit sometimes fires callbacks BEFORE it completes resizing!
+ // Before RC30.3, there was a 10ms delay here, but that caused layout
+ // to load asynchrously, which is BAD, so try skipping delay for now
+
+ // process pane contents and callbacks, and init/resize child-layout if exists
+ $.each(_c.allPanes, function (i, pane) {
+ var o = options[pane];
+ if ($Ps[pane]) {
+ if (state[pane].isVisible) { // pane is OPEN
+ sizeContent(pane);
+ // trigger pane.onResize if triggerEventsOnLoad = true
+ if (o.triggerEventsOnLoad)
+ _runCallbacks("onresize_end", pane);
+ else // automatic if onresize called, otherwise call it specifically
+ // resize child - IF inner-layout already exists (created before this layout)
+ resizeChildLayout(pane);
+ }
+ // init childLayout - even if pane is not visible
+ if (o.initChildLayout && o.childOptions)
+ createChildLayout(pane);
+ }
+ });
+ }
+
+ /**
+ * Add a pane to the layout - subroutine of initPanes()
+ *
+ * @see initPanes()
+ * @param {string} pane The pane to process
+ * @param {boolean=} [force=false] Size content after init
+ */
+, addPane = function (pane, force) {
+ if (!force && !isInitialized()) return;
+ var
+ o = options[pane]
+ , s = state[pane]
+ , c = _c[pane]
+ , fx = s.fx
+ , dir = c.dir
+ , spacing = o.spacing_open || 0
+ , isCenter = (pane === "center")
+ , CSS = {}
+ , $P = $Ps[pane]
+ , size, minSize, maxSize
+ ;
+ // if pane-pointer already exists, remove the old one first
+ if ($P)
+ removePane( pane, false, true, false );
+ else
+ $Cs[pane] = false; // init
+
+ $P = $Ps[pane] = getPane(pane);
+ if (!$P.length) {
+ $Ps[pane] = false; // logic
+ return;
+ }
+
+ // SAVE original Pane CSS
+ if (!$P.data("layoutCSS")) {
+ var props = "position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border";
+ $P.data("layoutCSS", elCSS($P, props));
+ }
+
+ // create alias for pane data in Instance - initHandles will add more
+ Instance[pane] = { name: pane, pane: $Ps[pane], content: $Cs[pane], options: options[pane], state: state[pane], child: children[pane] };
+
+ // add classes, attributes & events
+ $P .data({
+ parentLayout: Instance // pointer to Layout Instance
+ , layoutPane: Instance[pane] // NEW pointer to pane-alias-object
+ , layoutEdge: pane
+ , layoutRole: "pane"
+ })
+ .css(c.cssReq).css("zIndex", options.zIndexes.pane_normal)
+ .css(o.applyDemoStyles ? c.cssDemo : {}) // demo styles
+ .addClass( o.paneClass +" "+ o.paneClass+"-"+pane ) // default = "ui-layout-pane ui-layout-pane-west" - may be a dupe of 'paneSelector'
+ .bind("mouseenter."+ sID, addHover )
+ .bind("mouseleave."+ sID, removeHover )
+ ;
+ var paneMethods = {
+ hide: ''
+ , show: ''
+ , toggle: ''
+ , close: ''
+ , open: ''
+ , slideOpen: ''
+ , slideClose: ''
+ , slideToggle: ''
+ , size: 'manualSizePane'
+ , sizePane: 'manualSizePane'
+ , sizeContent: ''
+ , sizeHandles: ''
+ , enableClosable: ''
+ , disableClosable: ''
+ , enableSlideable: ''
+ , disableSlideable: ''
+ , enableResizable: ''
+ , disableResizable: ''
+ , swapPanes: 'swapPanes'
+ , swap: 'swapPanes'
+ , move: 'swapPanes'
+ , removePane: 'removePane'
+ , remove: 'removePane'
+ , createChildLayout: ''
+ , resizeChildLayout: ''
+ , resizeAll: 'resizeAll'
+ , resizeLayout: 'resizeAll'
+ }
+ , name;
+ // loop hash and bind all methods - include layoutID namespacing
+ for (name in paneMethods) {
+ $P.bind("layoutpane"+ name.toLowerCase() +"."+ sID, Instance[ paneMethods[name] || name ]);
+ }
+
+ // see if this pane has a 'scrolling-content element'
+ initContent(pane, false); // false = do NOT sizeContent() - called later
+
+ if (!isCenter) {
+ // call _parseSize AFTER applying pane classes & styles - but before making visible (if hidden)
+ // if o.size is auto or not valid, then MEASURE the pane and use that as its 'size'
+ size = s.size = _parseSize(pane, o.size);
+ minSize = _parseSize(pane,o.minSize) || 1;
+ maxSize = _parseSize(pane,o.maxSize) || 100000;
+ if (size > 0) size = max(min(size, maxSize), minSize);
+
+ // state for border-panes
+ s.isClosed = false; // true = pane is closed
+ s.isSliding = false; // true = pane is currently open by 'sliding' over adjacent panes
+ s.isResizing= false; // true = pane is in process of being resized
+ s.isHidden = false; // true = pane is hidden - no spacing, resizer or toggler is visible!
+
+ // array for 'pin buttons' whose classNames are auto-updated on pane-open/-close
+ if (!s.pins) s.pins = [];
+ }
+ // states common to ALL panes
+ s.tagName = $P[0].tagName;
+ s.edge = pane; // useful if pane is (or about to be) 'swapped' - easy find out where it is (or is going)
+ s.noRoom = false; // true = pane 'automatically' hidden due to insufficient room - will unhide automatically
+ s.isVisible = true; // false = pane is invisible - closed OR hidden - simplify logic
+
+ // set css-position to account for container borders & padding
+ switch (pane) {
+ case "north": CSS.top = sC.insetTop;
+ CSS.left = sC.insetLeft;
+ CSS.right = sC.insetRight;
+ break;
+ case "south": CSS.bottom = sC.insetBottom;
+ CSS.left = sC.insetLeft;
+ CSS.right = sC.insetRight;
+ break;
+ case "west": CSS.left = sC.insetLeft; // top, bottom & height set by sizeMidPanes()
+ break;
+ case "east": CSS.right = sC.insetRight; // ditto
+ break;
+ case "center": // top, left, width & height set by sizeMidPanes()
+ }
+
+ if (dir === "horz") // north or south pane
+ CSS.height = cssH($P, size);
+ else if (dir === "vert") // east or west pane
+ CSS.width = cssW($P, size);
+ //else if (isCenter) {}
+
+ $P.css(CSS); // apply size -- top, bottom & height will be set by sizeMidPanes
+ if (dir != "horz") sizeMidPanes(pane, true); // true = skipCallback
+
+ // close or hide the pane if specified in settings
+ if (o.initClosed && o.closable && !o.initHidden)
+ close(pane, true, true); // true, true = force, noAnimation
+ else if (o.initHidden || o.initClosed)
+ hide(pane); // will be completely invisible - no resizer or spacing
+ else if (!s.noRoom)
+ // make the pane visible - in case was initially hidden
+ $P.css("display","block");
+ // ELSE setAsOpen() - called later by initHandles()
+
+ // RESET visibility now - pane will appear IF display:block
+ $P.css("visibility","visible");
+
+ // check option for auto-handling of pop-ups & drop-downs
+ if (o.showOverflowOnHover)
+ $P.hover( allowOverflow, resetOverflow );
+
+ // if manually adding a pane AFTER layout initialization, then...
+ if (state.initialized) {
+ initHandles( pane );
+ initHotkeys( pane );
+ resizeAll(); // will sizeContent if pane is visible
+ if (s.isVisible) { // pane is OPEN
+ if (o.triggerEventsOnLoad)
+ _runCallbacks("onresize_end", pane);
+ else // automatic if onresize called, otherwise call it specifically
+ // resize child - IF inner-layout already exists (created before this layout)
+ resizeChildLayout(pane); // a previously existing childLayout
+ }
+ if (o.initChildLayout && o.childOptions)
+ createChildLayout(pane);
+ }
+ }
+
+ /**
+ * Initialize module objects, styling, size and position for all resize bars and toggler buttons
+ *
+ * @see _create()
+ * @param {string=} [panes=""] The edge(s) to process
+ */
+, initHandles = function (panes) {
+ panes = panes ? panes.split(",") : _c.borderPanes;
+
+ // create toggler DIVs for each pane, and set object pointers for them, eg: $R.north = north toggler DIV
+ $.each(panes, function (i, pane) {
+ var $P = $Ps[pane];
+ $Rs[pane] = false; // INIT
+ $Ts[pane] = false;
+ if (!$P) return; // pane does not exist - skip
+
+ var
+ o = options[pane]
+ , s = state[pane]
+ , c = _c[pane]
+ , rClass = o.resizerClass
+ , tClass = o.togglerClass
+ , side = c.side.toLowerCase()
+ , spacing = (s.isVisible ? o.spacing_open : o.spacing_closed)
+ , _pane = "-"+ pane // used for classNames
+ , _state = (s.isVisible ? "-open" : "-closed") // used for classNames
+ , I = Instance[pane]
+ // INIT RESIZER BAR
+ , $R = I.resizer = $Rs[pane] = $("<div></div>")
+ // INIT TOGGLER BUTTON
+ , $T = I.toggler = (o.closable ? $Ts[pane] = $("<div></div>") : false)
+ ;
+
+ //if (s.isVisible && o.resizable) ... handled by initResizable
+ if (!s.isVisible && o.slidable)
+ $R.attr("title", o.sliderTip).css("cursor", o.sliderCursor);
+
+ $R // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "paneLeft-resizer"
+ .attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-resizer" : ""))
+ .data({
+ parentLayout: Instance
+ , layoutPane: Instance[pane] // NEW pointer to pane-alias-object
+ , layoutEdge: pane
+ , layoutRole: "resizer"
+ })
+ .css(_c.resizers.cssReq).css("zIndex", options.zIndexes.resizer_normal)
+ .css(o.applyDemoStyles ? _c.resizers.cssDemo : {}) // add demo styles
+ .addClass(rClass +" "+ rClass+_pane)
+ .hover(addHover, removeHover) // ALWAYS add hover-classes, even if resizing is not enabled - handle with CSS instead
+ .hover(onResizerEnter, onResizerLeave) // ALWAYS NEED resizer.mouseleave to balance toggler.mouseenter
+ .appendTo($N) // append DIV to container
+ ;
+
+ if ($T) {
+ $T // if paneSelector is an ID, then create a matching ID for the resizer, eg: "#paneLeft" => "#paneLeft-toggler"
+ .attr("id", (o.paneSelector.substr(0,1)=="#" ? o.paneSelector.substr(1) + "-toggler" : ""))
+ .data({
+ parentLayout: Instance
+ , layoutPane: Instance[pane] // NEW pointer to pane-alias-object
+ , layoutEdge: pane
+ , layoutRole: "toggler"
+ })
+ .css(_c.togglers.cssReq) // add base/required styles
+ .css(o.applyDemoStyles ? _c.togglers.cssDemo : {}) // add demo styles
+ .addClass(tClass +" "+ tClass+_pane)
+ .hover(addHover, removeHover) // ALWAYS add hover-classes, even if toggling is not enabled - handle with CSS instead
+ .bind("mouseenter", onResizerEnter) // NEED toggler.mouseenter because mouseenter MAY NOT fire on resizer
+ .appendTo($R) // append SPAN to resizer DIV
+ ;
+ // ADD INNER-SPANS TO TOGGLER
+ if (o.togglerContent_open) // ui-layout-open
+ $("<span>"+ o.togglerContent_open +"</span>")
+ .data({
+ layoutEdge: pane
+ , layoutRole: "togglerContent"
+ })
+ .data("layoutRole", "togglerContent")
+ .data("layoutEdge", pane)
+ .addClass("content content-open")
+ .css("display","none")
+ .appendTo( $T )
+ //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-open instead!
+ ;
+ if (o.togglerContent_closed) // ui-layout-closed
+ $("<span>"+ o.togglerContent_closed +"</span>")
+ .data({
+ layoutEdge: pane
+ , layoutRole: "togglerContent"
+ })
+ .addClass("content content-closed")
+ .css("display","none")
+ .appendTo( $T )
+ //.hover( addHover, removeHover ) // use ui-layout-toggler-west-hover .content-closed instead!
+ ;
+ // ADD TOGGLER.click/.hover
+ enableClosable(pane);
+ }
+
+ // add Draggable events
+ initResizable(pane);
+
+ // ADD CLASSNAMES & SLIDE-BINDINGS - eg: class="resizer resizer-west resizer-open"
+ if (s.isVisible)
+ setAsOpen(pane); // onOpen will be called, but NOT onResize
+ else {
+ setAsClosed(pane); // onClose will be called
+ bindStartSlidingEvent(pane, true); // will enable events IF option is set
+ }
+
+ });
+
+ // SET ALL HANDLE DIMENSIONS
+ sizeHandles();
+ }
+
+
+ /**
+ * Initialize scrolling ui-layout-content div - if exists
+ *
+ * @see initPane() - or externally after an Ajax injection
+ * @param {string} [pane] The pane to process
+ * @param {boolean=} [resize=true] Size content after init
+ */
+, initContent = function (pane, resize) {
+ if (!isInitialized()) return;
+ var
+ o = options[pane]
+ , sel = o.contentSelector
+ , I = Instance[pane]
+ , $P = $Ps[pane]
+ , $C
+ ;
+ if (sel) $C = I.content = $Cs[pane] = (o.findNestedContent)
+ ? $P.find(sel).eq(0) // match 1-element only
+ : $P.children(sel).eq(0)
+ ;
+ if ($C && $C.length) {
+ $C.data("layoutRole", "content");
+ // SAVE original Pane CSS
+ if (!$C.data("layoutCSS"))
+ $C.data("layoutCSS", elCSS($C, "height"));
+ $C.css( _c.content.cssReq );
+ if (o.applyDemoStyles) {
+ $C.css( _c.content.cssDemo ); // add padding & overflow: auto to content-div
+ $P.css( _c.content.cssDemoPane ); // REMOVE padding/scrolling from pane
+ }
+ state[pane].content = {}; // init content state
+ if (resize !== false) sizeContent(pane);
+ // sizeContent() is called AFTER init of all elements
+ }
+ else
+ I.content = $Cs[pane] = false;
+ }
+
+
+ /**
+ * Add resize-bars to all panes that specify it in options
+ * -dependancy: $.fn.resizable - will skip if not found
+ *
+ * @see _create()
+ * @param {string=} [panes=""] The edge(s) to process
+ */
+, initResizable = function (panes) {
+ var draggingAvailable = $.layout.plugins.draggable
+ , side // set in start()
+ ;
+ panes = panes ? panes.split(",") : _c.borderPanes;
+
+ $.each(panes, function (idx, pane) {
+ var o = options[pane];
+ if (!draggingAvailable || !$Ps[pane] || !o.resizable) {
+ o.resizable = false;
+ return true; // skip to next
+ }
+
+ var s = state[pane]
+ , z = options.zIndexes
+ , c = _c[pane]
+ , side = c.dir=="horz" ? "top" : "left"
+ , opEdge = _c.oppositeEdge[pane]
+ , masks = pane +",center,"+ opEdge + (c.dir=="horz" ? ",west,east" : "")
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , base = o.resizerClass
+ , lastPos = 0 // used when live-resizing
+ , r, live // set in start because may change
+ // 'drag' classes are applied to the ORIGINAL resizer-bar while dragging is in process
+ , resizerClass = base+"-drag" // resizer-drag
+ , resizerPaneClass = base+"-"+pane+"-drag" // resizer-north-drag
+ // 'helper' class is applied to the CLONED resizer-bar while it is being dragged
+ , helperClass = base+"-dragging" // resizer-dragging
+ , helperPaneClass = base+"-"+pane+"-dragging" // resizer-north-dragging
+ , helperLimitClass = base+"-dragging-limit" // resizer-drag
+ , helperPaneLimitClass = base+"-"+pane+"-dragging-limit" // resizer-north-drag
+ , helperClassesSet = false // logic var
+ ;
+
+ if (!s.isClosed)
+ $R.attr("title", o.resizerTip)
+ .css("cursor", o.resizerCursor); // n-resize, s-resize, etc
+
+ $R.draggable({
+ containment: $N[0] // limit resizing to layout container
+ , axis: (c.dir=="horz" ? "y" : "x") // limit resizing to horz or vert axis
+ , delay: 0
+ , distance: 1
+ , grid: o.resizingGrid
+ // basic format for helper - style it using class: .ui-draggable-dragging
+ , helper: "clone"
+ , opacity: o.resizerDragOpacity
+ , addClasses: false // avoid ui-state-disabled class when disabled
+ //, iframeFix: o.draggableIframeFix // TODO: consider using when bug is fixed
+ , zIndex: z.resizer_drag
+
+ , start: function (e, ui) {
+ // REFRESH options & state pointers in case we used swapPanes
+ o = options[pane];
+ s = state[pane];
+ // re-read options
+ live = o.livePaneResizing;
+
+ // ondrag_start callback - will CANCEL hide if returns false
+ // TODO: dragging CANNOT be cancelled like this, so see if there is a way?
+ if (false === _runCallbacks("ondrag_start", pane)) return false;
+
+ s.isResizing = true; // prevent pane from closing while resizing
+ timer.clear(pane+"_closeSlider"); // just in case already triggered
+
+ // SET RESIZER LIMITS - used in drag()
+ setSizeLimits(pane); // update pane/resizer state
+ r = s.resizerPosition;
+ lastPos = ui.position[ side ]
+
+ $R.addClass( resizerClass +" "+ resizerPaneClass ); // add drag classes
+ helperClassesSet = false; // reset logic var - see drag()
+
+ // DISABLE TEXT SELECTION (probably already done by resizer.mouseOver)
+ $('body').disableSelection();
+
+ // MASK PANES CONTAINING IFRAMES, APPLETS OR OTHER TROUBLESOME ELEMENTS
+ showMasks( masks );
+ }
+
+ , drag: function (e, ui) {
+ if (!helperClassesSet) { // can only add classes after clone has been added to the DOM
+ //$(".ui-draggable-dragging")
+ ui.helper
+ .addClass( helperClass +" "+ helperPaneClass ) // add helper classes
+ .css({ right: "auto", bottom: "auto" }) // fix dir="rtl" issue
+ .children().css("visibility","hidden") // hide toggler inside dragged resizer-bar
+ ;
+ helperClassesSet = true;
+ // draggable bug!? RE-SET zIndex to prevent E/W resize-bar showing through N/S pane!
+ if (s.isSliding) $Ps[pane].css("zIndex", z.pane_sliding);
+ }
+ // CONTAIN RESIZER-BAR TO RESIZING LIMITS
+ var limit = 0;
+ if (ui.position[side] < r.min) {
+ ui.position[side] = r.min;
+ limit = -1;
+ }
+ else if (ui.position[side] > r.max) {
+ ui.position[side] = r.max;
+ limit = 1;
+ }
+ // ADD/REMOVE dragging-limit CLASS
+ if (limit) {
+ ui.helper.addClass( helperLimitClass +" "+ helperPaneLimitClass ); // at dragging-limit
+ window.defaultStatus = (limit>0 && pane.match(/north|west/)) || (limit<0 && pane.match(/south|east/)) ? lang.maxSizeWarning : lang.minSizeWarning;
+ }
+ else {
+ ui.helper.removeClass( helperLimitClass +" "+ helperPaneLimitClass ); // not at dragging-limit
+ window.defaultStatus = "";
+ }
+ // DYNAMICALLY RESIZE PANES IF OPTION ENABLED
+ // won't trigger unless resizer has actually moved!
+ if (live && Math.abs(ui.position[side] - lastPos) >= o.liveResizingTolerance) {
+ lastPos = ui.position[side];
+ resizePanes(e, ui, pane)
+ }
+ }
+
+ , stop: function (e, ui) {
+ $('body').enableSelection(); // RE-ENABLE TEXT SELECTION
+ window.defaultStatus = ""; // clear 'resizing limit' message from statusbar
+ $R.removeClass( resizerClass +" "+ resizerPaneClass ); // remove drag classes from Resizer
+ s.isResizing = false;
+ resizePanes(e, ui, pane, true, masks); // true = resizingDone
+ }
+
+ });
+ });
+
+ /**
+ * resizePanes
+ *
+ * Sub-routine called from stop() - and drag() if livePaneResizing
+ *
+ * @param {!Object} evt
+ * @param {!Object} ui
+ * @param {string} pane
+ * @param {boolean=} [resizingDone=false]
+ */
+ var resizePanes = function (evt, ui, pane, resizingDone, masks) {
+ var dragPos = ui.position
+ , c = _c[pane]
+ , o = options[pane]
+ , s = state[pane]
+ , resizerPos
+ ;
+ switch (pane) {
+ case "north": resizerPos = dragPos.top; break;
+ case "west": resizerPos = dragPos.left; break;
+ case "south": resizerPos = sC.offsetHeight - dragPos.top - o.spacing_open; break;
+ case "east": resizerPos = sC.offsetWidth - dragPos.left - o.spacing_open; break;
+ };
+ // remove container margin from resizer position to get the pane size
+ var newSize = resizerPos - sC["inset"+ c.side];
+
+ // Disable OR Resize Mask(s) created in drag.start
+ if (!resizingDone) {
+ // ensure we meet liveResizingTolerance criteria
+ if (Math.abs(newSize - s.size) < o.liveResizingTolerance)
+ return; // SKIP resize this time
+ // resize the pane
+ manualSizePane(pane, newSize, false, true); // true = noAnimation
+ sizeMasks(); // resize all visible masks
+ }
+ else { // resizingDone
+ // ondrag_end callback
+ if (false !== _runCallbacks("ondrag_end", pane))
+ manualSizePane(pane, newSize, false, true); // true = noAnimation
+ hideMasks(); // hide all masks, which include panes with 'content/iframe-masks'
+ if (s.isSliding && masks) // RE-SHOW only 'object-masks' so objects won't show through sliding pane
+ showMasks( masks, true ); // true = onlyForObjects
+ }
+ };
+ }
+
+ /**
+ * sizeMask
+ *
+ * Needed to overlay a DIV over an IFRAME-pane because mask CANNOT be *inside* the pane
+ * Called when mask created, and during livePaneResizing
+ */
+, sizeMask = function () {
+ var $M = $(this)
+ , pane = $M.data("layoutMask") // eg: "west"
+ , s = state[pane]
+ ;
+ // only masks over an IFRAME-pane need manual resizing
+ if (s.tagName == "IFRAME" && s.isVisible) // no need to mask closed/hidden panes
+ $M.css({
+ top: s.offsetTop
+ , left: s.offsetLeft
+ , width: s.outerWidth
+ , height: s.outerHeight
+ });
+ /* ALT Method...
+ var $P = $Ps[pane];
+ $M.css( $P.position() ).css({ width: $P[0].offsetWidth, height: $P[0].offsetHeight });
+ */
+ }
+, sizeMasks = function () {
+ $Ms.each( sizeMask ); // resize all 'visible' masks
+ }
+
+, showMasks = function (panes, onlyForObjects) {
+ var a = panes ? panes.split(",") : $.layout.config.allPanes
+ , z = options.zIndexes
+ , o, s;
+ $.each(a, function(i,p){
+ s = state[p];
+ o = options[p];
+ if (s.isVisible && ( (!onlyForObjects && o.maskContents) || o.maskObjects )) {
+ getMasks(p).each(function(){
+ sizeMask.call(this);
+ this.style.zIndex = s.isSliding ? z.pane_sliding+1 : z.pane_normal+1
+ this.style.display = "block";
+ });
+ }
+ });
+ }
+
+, hideMasks = function () {
+ // ensure no pane is resizing - could be a timing issue
+ var skip;
+ $.each( $.layout.config.borderPanes, function(i,p){
+ if (state[p].isResizing) {
+ skip = true;
+ return false; // BREAK
+ }
+ });
+ if (!skip)
+ $Ms.hide(); // hide ALL masks
+ }
+
+, getMasks = function (pane) {
+ var $Masks = $([])
+ , $M, i = 0, c = $Ms.length
+ ;
+ for (; i<c; i++) {
+ $M = $Ms.eq(i);
+ if ($M.data("layoutMask") === pane)
+ $Masks = $Masks.add( $M );
+ }
+ if ($Masks.length)
+ return $Masks;
+ else
+ return createMasks(pane);
+ }
+
+ /**
+ * createMasks
+ *
+ * Generates both DIV (ALWAYS used) and IFRAME (optional) elements as masks
+ * An IFRAME mask is created *under* the DIV when maskObjects=true, because a DIV cannot mask an applet
+ */
+, createMasks = function (pane) {
+ var
+ $P = $Ps[pane]
+ , s = state[pane]
+ , o = options[pane]
+ , z = options.zIndexes
+ //, objMask = o.maskObjects && s.tagName != "IFRAME" // check for option
+ , $Masks = $([])
+ , isIframe, el, $M, css, i
+ ;
+ if (!o.maskContents && !o.maskObjects) return $Masks;
+ // if o.maskObjects=true, then loop TWICE to create BOTH kinds of mask, else only create a DIV
+ for (i=0; i < (o.maskObjects ? 2 : 1); i++) {
+ isIframe = o.maskObjects && i==0;
+ el = document.createElement( isIframe ? "iframe" : "div" );
+ $M = $(el).data("layoutMask", pane); // add data to relate mask to pane
+ el.className = "ui-layout-mask ui-layout-mask-"+ pane; // for user styling
+ css = el.style;
+ // styles common to both DIVs and IFRAMES
+ css.display = "block";
+ css.position = "absolute";
+ if (isIframe) { // IFRAME-only props
+ el.frameborder = 0;
+ el.src = "about:blank";
+ css.opacity = 0;
+ css.filter = "Alpha(Opacity='0')";
+ css.border = 0;
+ }
+ // if pane is an IFRAME, then must mask the pane itself
+ if (s.tagName == "IFRAME") {
+ // NOTE sizing done by a subroutine so can be called during live-resizing
+ css.zIndex = z.pane_normal+1; // 1-higher than pane
+ $N.append( el ); // append to LAYOUT CONTAINER
+ }
+ // otherwise put masks *inside the pane* to mask its contents
+ else {
+ $M.addClass("ui-layout-mask-inside-pane");
+ css.zIndex = o.maskZindex || z.content_mask; // usually 1, but customizable
+ css.top = 0;
+ css.left = 0;
+ css.width = "100%";
+ css.height = "100%";
+ $P.append( el ); // append INSIDE pane element
+ }
+ // add to return object
+ $Masks = $Masks.add( el );
+ // add Mask to cached array so can be resized & reused
+ $Ms = $Ms.add( el );
+ }
+ return $Masks;
+ }
+
+
+ /**
+ * Destroy this layout and reset all elements
+ *
+ * @param {boolean=} [destroyChildren=false] Destory Child-Layouts first?
+ */
+, destroy = function (destroyChildren) {
+ // UNBIND layout events and remove global object
+ $(window).unbind("."+ sID); // resize & unload
+ $(document).unbind("."+ sID); // keyDown (hotkeys)
+
+ // need to look for parent layout BEFORE we remove the container data, else skips a level
+ //var parentPane = Instance.hasParentLayout ? $.layout.getParentPaneInstance( $N ) : null;
+
+ // reset layout-container
+ $N .clearQueue()
+ .removeData("layout")
+ .removeData("layoutContainer")
+ .removeClass(options.containerClass)
+ .unbind("."+ sID) // remove ALL Layout events
+ ;
+
+ // remove all mask elements that have been created
+ $Ms.remove();
+
+ // loop all panes to remove layout classes, attributes and bindings
+ $.each(_c.allPanes, function (i, pane) {
+ removePane( pane, false, true, destroyChildren ); // true = skipResize
+ });
+
+ // do NOT reset container CSS if is a 'pane' (or 'content') in an outer-layout - ie, THIS layout is 'nested'
+ var css = "layoutCSS";
+ if ($N.data(css) && !$N.data("layoutRole")) // RESET CSS
+ $N.css( $N.data(css) ).removeData(css);
+
+ // for full-page layouts, also reset the <HTML> CSS
+ if (sC.tagName === "BODY" && ($N = $("html")).data(css)) // RESET <HTML> CSS
+ $N.css( $N.data(css) ).removeData(css);
+
+ // trigger plugins for this layout, if there are any
+ runPluginCallbacks( Instance, $.layout.onDestroy );
+
+ // trigger state-management and onunload callback
+ unload();
+
+ // clear the Instance of everything except for container & options (so could recreate)
+ // RE-CREATE: myLayout = myLayout.container.layout( myLayout.options );
+ for (n in Instance)
+ if (!n.match(/^(container|options)$/)) delete Instance[ n ];
+ // add a 'destroyed' flag to make it easy to check
+ Instance.destroyed = true;
+
+ // if this is a child layout, CLEAR the child-pointer in the parent
+ /* for now the pointer REMAINS, but with only container, options and destroyed keys
+ if (parentPane) {
+ var layout = parentPane.pane.data("parentLayout");
+ parentPane.child = layout.children[ parentPane.name ] = null;
+ }
+ */
+
+ return Instance; // for coding convenience
+ }
+
+ /**
+ * Remove a pane from the layout - subroutine of destroy()
+ *
+ * @see destroy()
+ * @param {string} pane The pane to process
+ * @param {boolean=} [remove=false] Remove the DOM element?
+ * @param {boolean=} [skipResize=false] Skip calling resizeAll()?
+ */
+, removePane = function (evt_or_pane, remove, skipResize, destroyChild) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $P = $Ps[pane]
+ , $C = $Cs[pane]
+ , $R = $Rs[pane]
+ , $T = $Ts[pane]
+ ;
+ //alert( '$P.length = '+ $P.length );
+ // NOTE: elements can still exist even after remove()
+ // so check for missing data(), which is cleared by removed()
+ if ($P && $.isEmptyObject( $P.data() )) $P = false;
+ if ($C && $.isEmptyObject( $C.data() )) $C = false;
+ if ($R && $.isEmptyObject( $R.data() )) $R = false;
+ if ($T && $.isEmptyObject( $T.data() )) $T = false;
+
+ if ($P) $P.stop(true, true);
+
+ // check for a child layout
+ var o = options[pane]
+ , s = state[pane]
+ , d = "layout"
+ , css = "layoutCSS"
+ , child = children[pane] || ($P ? $P.data(d) : 0) || ($C ? $C.data(d) : 0) || null
+ , destroy = destroyChild !== undefined ? destroyChild : o.destroyChildLayout
+ ;
+
+ // FIRST destroy the child-layout(s)
+ if (destroy && child && !child.destroyed) {
+ child.destroy(true); // tell child-layout to destroy ALL its child-layouts too
+ if (child.destroyed) // destroy was successful
+ child = null; // clear pointer for logic below
+ }
+
+ if ($P && remove && !child)
+ $P.remove();
+ else if ($P && $P[0]) {
+ // create list of ALL pane-classes that need to be removed
+ var root = o.paneClass // default="ui-layout-pane"
+ , pRoot = root +"-"+ pane // eg: "ui-layout-pane-west"
+ , _open = "-open"
+ , _sliding= "-sliding"
+ , _closed = "-closed"
+ , classes = [ root, root+_open, root+_closed, root+_sliding, // generic classes
+ pRoot, pRoot+_open, pRoot+_closed, pRoot+_sliding ] // pane-specific classes
+ ;
+ $.merge(classes, getHoverClasses($P, true)); // ADD hover-classes
+ // remove all Layout classes from pane-element
+ $P .removeClass( classes.join(" ") ) // remove ALL pane-classes
+ .removeData("parentLayout")
+ .removeData("layoutPane")
+ .removeData("layoutRole")
+ .removeData("layoutEdge")
+ .removeData("autoHidden") // in case set
+ .unbind("."+ sID) // remove ALL Layout events
+ // TODO: remove these extra unbind commands when jQuery is fixed
+ //.unbind("mouseenter"+ sID)
+ //.unbind("mouseleave"+ sID)
+ ;
+ // do NOT reset CSS if this pane/content is STILL the container of a nested layout!
+ // the nested layout will reset its 'container' CSS when/if it is destroyed
+ if ($C && $C.data(d)) {
+ // a content-div may not have a specific width, so give it one to contain the Layout
+ $C.width( $C.width() );
+ child.resizeAll(); // now resize the Layout
+ }
+ else if ($C)
+ $C.css( $C.data(css) ).removeData(css).removeData("layoutRole");
+ // remove pane AFTER content in case there was a nested layout
+ if (!$P.data(d))
+ $P.css( $P.data(css) ).removeData(css);
+ }
+
+ // REMOVE pane resizer and toggler elements
+ if ($T) $T.remove();
+ if ($R) $R.remove();
+
+ // CLEAR all pointers and state data
+ Instance[pane] = $Ps[pane] = $Cs[pane] = $Rs[pane] = $Ts[pane] = children[pane] = false;
+ s = { removed: true };
+
+ if (!skipResize)
+ resizeAll();
+ }
+
+
+/*
+ * ###########################
+ * ACTION METHODS
+ * ###########################
+ */
+
+, _hidePane = function (pane) {
+ var $P = $Ps[pane]
+ , o = options[pane]
+ , s = $P[0].style
+ ;
+ if (o.useOffscreenClose) {
+ if (!$P.data(_c.offscreenReset))
+ $P.data(_c.offscreenReset, { left: s.left, right: s.right });
+ $P.css( _c.offscreenCSS );
+ }
+ else
+ $P.hide().removeData(_c.offscreenReset);
+ }
+
+, _showPane = function (pane) {
+ var $P = $Ps[pane]
+ , o = options[pane]
+ , off = _c.offscreenCSS
+ , old = $P.data(_c.offscreenReset)
+ , s = $P[0].style
+ ;
+ $P .show() // ALWAYS show, just in case
+ .removeData(_c.offscreenReset);
+ if (o.useOffscreenClose && old) {
+ if (s.left == off.left)
+ s.left = old.left;
+ if (s.right == off.right)
+ s.right = old.right;
+ }
+ }
+
+
+ /**
+ * Completely 'hides' a pane, including its spacing - as if it does not exist
+ * The pane is not actually 'removed' from the source, so can use 'show' to un-hide it
+ *
+ * @param {string} pane The pane being hidden, ie: north, south, east, or west
+ * @param {boolean=} [noAnimation=false]
+ */
+, hide = function (evt_or_pane, noAnimation) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , o = options[pane]
+ , s = state[pane]
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ ;
+ if (!$P || s.isHidden) return; // pane does not exist OR is already hidden
+
+ // onhide_start callback - will CANCEL hide if returns false
+ if (state.initialized && false === _runCallbacks("onhide_start", pane)) return;
+
+ s.isSliding = false; // just in case
+
+ // now hide the elements
+ if ($R) $R.hide(); // hide resizer-bar
+ if (!state.initialized || s.isClosed) {
+ s.isClosed = true; // to trigger open-animation on show()
+ s.isHidden = true;
+ s.isVisible = false;
+ if (!state.initialized)
+ _hidePane(pane); // no animation when loading page
+ sizeMidPanes(_c[pane].dir === "horz" ? "" : "center");
+ if (state.initialized || o.triggerEventsOnLoad)
+ _runCallbacks("onhide_end", pane);
+ }
+ else {
+ s.isHiding = true; // used by onclose
+ close(pane, false, noAnimation); // adjust all panes to fit
+ }
+ }
+
+ /**
+ * Show a hidden pane - show as 'closed' by default unless openPane = true
+ *
+ * @param {string} pane The pane being opened, ie: north, south, east, or west
+ * @param {boolean=} [openPane=false]
+ * @param {boolean=} [noAnimation=false]
+ * @param {boolean=} [noAlert=false]
+ */
+, show = function (evt_or_pane, openPane, noAnimation, noAlert) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , o = options[pane]
+ , s = state[pane]
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ ;
+ if (!$P || !s.isHidden) return; // pane does not exist OR is not hidden
+
+ // onshow_start callback - will CANCEL show if returns false
+ if (false === _runCallbacks("onshow_start", pane)) return;
+
+ s.isSliding = false; // just in case
+ s.isShowing = true; // used by onopen/onclose
+ //s.isHidden = false; - will be set by open/close - if not cancelled
+
+ // now show the elements
+ //if ($R) $R.show(); - will be shown by open/close
+ if (openPane === false)
+ close(pane, true); // true = force
+ else
+ open(pane, false, noAnimation, noAlert); // adjust all panes to fit
+ }
+
+
+ /**
+ * Toggles a pane open/closed by calling either open or close
+ *
+ * @param {string} pane The pane being toggled, ie: north, south, east, or west
+ * @param {boolean=} [slide=false]
+ */
+, toggle = function (evt_or_pane, slide) {
+ if (!isInitialized()) return;
+ var evt = evtObj(evt_or_pane)
+ , pane = evtPane.call(this, evt_or_pane)
+ , s = state[pane]
+ ;
+ if (evt) // called from to $R.dblclick OR triggerPaneEvent
+ evt.stopImmediatePropagation();
+ if (s.isHidden)
+ show(pane); // will call 'open' after unhiding it
+ else if (s.isClosed)
+ open(pane, !!slide);
+ else
+ close(pane);
+ }
+
+
+ /**
+ * Utility method used during init or other auto-processes
+ *
+ * @param {string} pane The pane being closed
+ * @param {boolean=} [setHandles=false]
+ */
+, _closePane = function (pane, setHandles) {
+ var
+ $P = $Ps[pane]
+ , s = state[pane]
+ ;
+ _hidePane(pane);
+ s.isClosed = true;
+ s.isVisible = false;
+ // UNUSED: if (setHandles) setAsClosed(pane, true); // true = force
+ }
+
+ /**
+ * Close the specified pane (animation optional), and resize all other panes as needed
+ *
+ * @param {string} pane The pane being closed, ie: north, south, east, or west
+ * @param {boolean=} [force=false]
+ * @param {boolean=} [noAnimation=false]
+ * @param {boolean=} [skipCallback=false]
+ */
+, close = function (evt_or_pane, force, noAnimation, skipCallback) {
+ var pane = evtPane.call(this, evt_or_pane);
+ // if pane has been initialized, but NOT the complete layout, close pane instantly
+ if (!state.initialized && $Ps[pane]) {
+ _closePane(pane); // INIT pane as closed
+ return;
+ }
+ if (!isInitialized()) return;
+
+ var
+ $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , $T = $Ts[pane]
+ , o = options[pane]
+ , s = state[pane]
+ , c = _c[pane]
+ , doFX, isShowing, isHiding, wasSliding;
+
+ // QUEUE in case another action/animation is in progress
+ $N.queue(function( queueNext ){
+
+ if ( !$P
+ || (!o.closable && !s.isShowing && !s.isHiding) // invalid request // (!o.resizable && !o.closable) ???
+ || (!force && s.isClosed && !s.isShowing) // already closed
+ ) return queueNext();
+
+ // onclose_start callback - will CANCEL hide if returns false
+ // SKIP if just 'showing' a hidden pane as 'closed'
+ var abort = !s.isShowing && false === _runCallbacks("onclose_start", pane);
+
+ // transfer logic vars to temp vars
+ isShowing = s.isShowing;
+ isHiding = s.isHiding;
+ wasSliding = s.isSliding;
+ // now clear the logic vars (REQUIRED before aborting)
+ delete s.isShowing;
+ delete s.isHiding;
+
+ if (abort) return queueNext();
+
+ doFX = !noAnimation && !s.isClosed && (o.fxName_close != "none");
+ s.isMoving = true;
+ s.isClosed = true;
+ s.isVisible = false;
+ // update isHidden BEFORE sizing panes
+ if (isHiding) s.isHidden = true;
+ else if (isShowing) s.isHidden = false;
+
+ if (s.isSliding) // pane is being closed, so UNBIND trigger events
+ bindStopSlidingEvents(pane, false); // will set isSliding=false
+ else // resize panes adjacent to this one
+ sizeMidPanes(_c[pane].dir === "horz" ? "" : "center", false); // false = NOT skipCallback
+
+ // if this pane has a resizer bar, move it NOW - before animation
+ setAsClosed(pane);
+
+ // CLOSE THE PANE
+ if (doFX) { // animate the close
+ // mask panes with objects
+ var masks = "center"+ (c.dir=="horz" ? ",west,east" : "");
+ showMasks( masks, true ); // true = ONLY mask panes with maskObjects=true
+ lockPaneForFX(pane, true); // need to set left/top so animation will work
+ $P.hide( o.fxName_close, o.fxSettings_close, o.fxSpeed_close, function () {
+ lockPaneForFX(pane, false); // undo
+ if (s.isClosed) close_2();
+ queueNext();
+ });
+ }
+ else { // hide the pane without animation
+ _hidePane(pane);
+ close_2();
+ queueNext();
+ };
+ });
+
+ // SUBROUTINE
+ function close_2 () {
+ s.isMoving = false;
+ bindStartSlidingEvent(pane, true); // will enable if o.slidable = true
+
+ // if opposite-pane was autoClosed, see if it can be autoOpened now
+ var altPane = _c.oppositeEdge[pane];
+ if (state[ altPane ].noRoom) {
+ setSizeLimits( altPane );
+ makePaneFit( altPane );
+ }
+
+ // hide any masks shown while closing
+ hideMasks();
+
+ if (!skipCallback && (state.initialized || o.triggerEventsOnLoad)) {
+ // onclose callback - UNLESS just 'showing' a hidden pane as 'closed'
+ if (!isShowing) _runCallbacks("onclose_end", pane);
+ // onhide OR onshow callback
+ if (isShowing) _runCallbacks("onshow_end", pane);
+ if (isHiding) _runCallbacks("onhide_end", pane);
+ }
+ }
+ }
+
+ /**
+ * @param {string} pane The pane just closed, ie: north, south, east, or west
+ */
+, setAsClosed = function (pane) {
+ var
+ $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , $T = $Ts[pane]
+ , o = options[pane]
+ , s = state[pane]
+ , side = _c[pane].side.toLowerCase()
+ , inset = "inset"+ _c[pane].side
+ , rClass = o.resizerClass
+ , tClass = o.togglerClass
+ , _pane = "-"+ pane // used for classNames
+ , _open = "-open"
+ , _sliding= "-sliding"
+ , _closed = "-closed"
+ ;
+ $R
+ .css(side, sC[inset]) // move the resizer
+ .removeClass( rClass+_open +" "+ rClass+_pane+_open )
+ .removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
+ .addClass( rClass+_closed +" "+ rClass+_pane+_closed )
+ .unbind("dblclick."+ sID)
+ ;
+ // DISABLE 'resizing' when closed - do this BEFORE bindStartSlidingEvent?
+ if (o.resizable && $.layout.plugins.draggable)
+ $R
+ .draggable("disable")
+ .removeClass("ui-state-disabled") // do NOT apply disabled styling - not suitable here
+ .css("cursor", "default")
+ .attr("title","")
+ ;
+
+ // if pane has a toggler button, adjust that too
+ if ($T) {
+ $T
+ .removeClass( tClass+_open +" "+ tClass+_pane+_open )
+ .addClass( tClass+_closed +" "+ tClass+_pane+_closed )
+ .attr("title", o.togglerTip_closed) // may be blank
+ ;
+ // toggler-content - if exists
+ $T.children(".content-open").hide();
+ $T.children(".content-closed").css("display","block");
+ }
+
+ // sync any 'pin buttons'
+ syncPinBtns(pane, false);
+
+ if (state.initialized) {
+ // resize 'length' and position togglers for adjacent panes
+ sizeHandles();
+ }
+ }
+
+ /**
+ * Open the specified pane (animation optional), and resize all other panes as needed
+ *
+ * @param {string} pane The pane being opened, ie: north, south, east, or west
+ * @param {boolean=} [slide=false]
+ * @param {boolean=} [noAnimation=false]
+ * @param {boolean=} [noAlert=false]
+ */
+, open = function (evt_or_pane, slide, noAnimation, noAlert) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , $T = $Ts[pane]
+ , o = options[pane]
+ , s = state[pane]
+ , c = _c[pane]
+ , doFX, isShowing
+ ;
+ // QUEUE in case another action/animation is in progress
+ $N.queue(function( queueNext ){
+
+ if ( !$P
+ || (!o.resizable && !o.closable && !s.isShowing) // invalid request
+ || (s.isVisible && !s.isSliding) // already open
+ ) return queueNext();
+
+ // pane can ALSO be unhidden by just calling show(), so handle this scenario
+ if (s.isHidden && !s.isShowing) {
+ queueNext(); // call before show() because it needs the queue free
+ show(pane, true);
+ return;
+ }
+
+ if (o.autoResize && s.size != o.size) // resize pane to original size set in options
+ sizePane(pane, o.size, true, true, true); // true=skipCallback/forceResize/noAnimation
+ else
+ // make sure there is enough space available to open the pane
+ setSizeLimits(pane, slide);
+
+ // onopen_start callback - will CANCEL open if returns false
+ var cbReturn = _runCallbacks("onopen_start", pane);
+
+ if (cbReturn === "abort")
+ return queueNext();
+
+ // update pane-state again in case options were changed in onopen_start
+ if (cbReturn !== "NC") // NC = "No Callback"
+ setSizeLimits(pane, slide);
+
+ if (s.minSize > s.maxSize) { // INSUFFICIENT ROOM FOR PANE TO OPEN!
+ syncPinBtns(pane, false); // make sure pin-buttons are reset
+ if (!noAlert && o.noRoomToOpenTip)
+ alert(o.noRoomToOpenTip);
+ return queueNext(); // ABORT
+ }
+
+ if (slide) // START Sliding - will set isSliding=true
+ bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane
+ else if (s.isSliding) // PIN PANE (stop sliding) - open pane 'normally' instead
+ bindStopSlidingEvents(pane, false); // UNBIND trigger events - will set isSliding=false
+ else if (o.slidable)
+ bindStartSlidingEvent(pane, false); // UNBIND trigger events
+
+ s.noRoom = false; // will be reset by makePaneFit if 'noRoom'
+ makePaneFit(pane);
+
+ // transfer logic var to temp var
+ isShowing = s.isShowing;
+ // now clear the logic var
+ delete s.isShowing;
+
+ doFX = !noAnimation && s.isClosed && (o.fxName_open != "none");
+ s.isMoving = true;
+ s.isVisible = true;
+ s.isClosed = false;
+ // update isHidden BEFORE sizing panes - WHY??? Old?
+ if (isShowing) s.isHidden = false;
+
+ if (doFX) { // ANIMATE
+ // mask panes with objects
+ var masks = "center"+ (c.dir=="horz" ? ",west,east" : "");
+ if (s.isSliding) masks += ","+ _c.oppositeEdge[pane];
+ showMasks( masks, true ); // true = ONLY mask panes with maskObjects=true
+ lockPaneForFX(pane, true); // need to set left/top so animation will work
+ $P.show( o.fxName_open, o.fxSettings_open, o.fxSpeed_open, function() {
+ lockPaneForFX(pane, false); // undo
+ if (s.isVisible) open_2(); // continue
+ queueNext();
+ });
+ }
+ else { // no animation
+ _showPane(pane);// just show pane and...
+ open_2(); // continue
+ queueNext();
+ };
+ });
+
+ // SUBROUTINE
+ function open_2 () {
+ s.isMoving = false;
+
+ // cure iframe display issues
+ _fixIframe(pane);
+
+ // NOTE: if isSliding, then other panes are NOT 'resized'
+ if (!s.isSliding) { // resize all panes adjacent to this one
+ hideMasks(); // remove any masks shown while opening
+ sizeMidPanes(_c[pane].dir=="vert" ? "center" : "", false); // false = NOT skipCallback
+ }
+
+ // set classes, position handles and execute callbacks...
+ setAsOpen(pane);
+ };
+
+ }
+
+ /**
+ * @param {string} pane The pane just opened, ie: north, south, east, or west
+ * @param {boolean=} [skipCallback=false]
+ */
+, setAsOpen = function (pane, skipCallback) {
+ var
+ $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , $T = $Ts[pane]
+ , o = options[pane]
+ , s = state[pane]
+ , side = _c[pane].side.toLowerCase()
+ , inset = "inset"+ _c[pane].side
+ , rClass = o.resizerClass
+ , tClass = o.togglerClass
+ , _pane = "-"+ pane // used for classNames
+ , _open = "-open"
+ , _closed = "-closed"
+ , _sliding= "-sliding"
+ ;
+ $R
+ .css(side, sC[inset] + getPaneSize(pane)) // move the resizer
+ .removeClass( rClass+_closed +" "+ rClass+_pane+_closed )
+ .addClass( rClass+_open +" "+ rClass+_pane+_open )
+ ;
+ if (s.isSliding)
+ $R.addClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
+ else // in case 'was sliding'
+ $R.removeClass( rClass+_sliding +" "+ rClass+_pane+_sliding )
+
+ if (o.resizerDblClickToggle)
+ $R.bind("dblclick", toggle );
+ removeHover( 0, $R ); // remove hover classes
+ if (o.resizable && $.layout.plugins.draggable)
+ $R .draggable("enable")
+ .css("cursor", o.resizerCursor)
+ .attr("title", o.resizerTip);
+ else if (!s.isSliding)
+ $R.css("cursor", "default"); // n-resize, s-resize, etc
+
+ // if pane also has a toggler button, adjust that too
+ if ($T) {
+ $T .removeClass( tClass+_closed +" "+ tClass+_pane+_closed )
+ .addClass( tClass+_open +" "+ tClass+_pane+_open )
+ .attr("title", o.togglerTip_open); // may be blank
+ removeHover( 0, $T ); // remove hover classes
+ // toggler-content - if exists
+ $T.children(".content-closed").hide();
+ $T.children(".content-open").css("display","block");
+ }
+
+ // sync any 'pin buttons'
+ syncPinBtns(pane, !s.isSliding);
+
+ // update pane-state dimensions - BEFORE resizing content
+ $.extend(s, elDims($P));
+
+ if (state.initialized) {
+ // resize resizer & toggler sizes for all panes
+ sizeHandles();
+ // resize content every time pane opens - to be sure
+ sizeContent(pane, true); // true = remeasure headers/footers, even if 'pane.isMoving'
+ }
+
+ if (!skipCallback && (state.initialized || o.triggerEventsOnLoad) && $P.is(":visible")) {
+ // onopen callback
+ _runCallbacks("onopen_end", pane);
+ // onshow callback - TODO: should this be here?
+ if (s.isShowing) _runCallbacks("onshow_end", pane);
+
+ // ALSO call onresize because layout-size *may* have changed while pane was closed
+ if (state.initialized)
+ _runCallbacks("onresize_end", pane);
+ }
+
+ // TODO: Somehow sizePane("north") is being called after this point???
+ }
+
+
+ /**
+ * slideOpen / slideClose / slideToggle
+ *
+ * Pass-though methods for sliding
+ */
+, slideOpen = function (evt_or_pane) {
+ if (!isInitialized()) return;
+ var evt = evtObj(evt_or_pane)
+ , pane = evtPane.call(this, evt_or_pane)
+ , s = state[pane]
+ , delay = options[pane].slideDelay_open
+ ;
+ // prevent event from triggering on NEW resizer binding created below
+ if (evt) evt.stopImmediatePropagation();
+
+ if (s.isClosed && evt && evt.type === "mouseenter" && delay > 0)
+ // trigger = mouseenter - use a delay
+ timer.set(pane+"_openSlider", open_NOW, delay);
+ else
+ open_NOW(); // will unbind events if is already open
+
+ /**
+ * SUBROUTINE for timed open
+ */
+ function open_NOW () {
+ if (!s.isClosed) // skip if no longer closed!
+ bindStopSlidingEvents(pane, true); // BIND trigger events to close sliding-pane
+ else if (!s.isMoving)
+ open(pane, true); // true = slide - open() will handle binding
+ };
+ }
+
+, slideClose = function (evt_or_pane) {
+ if (!isInitialized()) return;
+ var evt = evtObj(evt_or_pane)
+ , pane = evtPane.call(this, evt_or_pane)
+ , o = options[pane]
+ , s = state[pane]
+ , delay = s.isMoving ? 1000 : 300 // MINIMUM delay - option may override
+ ;
+ if (s.isClosed || s.isResizing)
+ return; // skip if already closed OR in process of resizing
+ else if (o.slideTrigger_close === "click")
+ close_NOW(); // close immediately onClick
+ else if (o.preventQuickSlideClose && s.isMoving)
+ return; // handle Chrome quick-close on slide-open
+ else if (o.preventPrematureSlideClose && evt && $.layout.isMouseOverElem(evt, $Ps[pane]))
+ return; // handle incorrect mouseleave trigger, like when over a SELECT-list in IE
+ else if (evt) // trigger = mouseleave - use a delay
+ // 1 sec delay if 'opening', else .3 sec
+ timer.set(pane+"_closeSlider", close_NOW, max(o.slideDelay_close, delay));
+ else // called programically
+ close_NOW();
+
+ /**
+ * SUBROUTINE for timed close
+ */
+ function close_NOW () {
+ if (s.isClosed) // skip 'close' if already closed!
+ bindStopSlidingEvents(pane, false); // UNBIND trigger events - TODO: is this needed here?
+ else if (!s.isMoving)
+ close(pane); // close will handle unbinding
+ };
+ }
+
+ /**
+ * @param {string} pane The pane being opened, ie: north, south, east, or west
+ */
+, slideToggle = function (evt_or_pane) {
+ var pane = evtPane.call(this, evt_or_pane);
+ toggle(pane, true);
+ }
+
+
+ /**
+ * Must set left/top on East/South panes so animation will work properly
+ *
+ * @param {string} pane The pane to lock, 'east' or 'south' - any other is ignored!
+ * @param {boolean} doLock true = set left/top, false = remove
+ */
+, lockPaneForFX = function (pane, doLock) {
+ var $P = $Ps[pane]
+ , s = state[pane]
+ , o = options[pane]
+ , z = options.zIndexes
+ ;
+ if (doLock) {
+ $P.css({ zIndex: z.pane_animate }); // overlay all elements during animation
+ if (pane=="south")
+ $P.css({ top: sC.insetTop + sC.innerHeight - $P.outerHeight() });
+ else if (pane=="east")
+ $P.css({ left: sC.insetLeft + sC.innerWidth - $P.outerWidth() });
+ }
+ else { // animation DONE - RESET CSS
+ // TODO: see if this can be deleted. It causes a quick-close when sliding in Chrome
+ $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) });
+ if (pane=="south")
+ $P.css({ top: "auto" });
+ // if pane is positioned 'off-screen', then DO NOT screw with it!
+ else if (pane=="east" && !$P.css("left").match(/\-99999/))
+ $P.css({ left: "auto" });
+ // fix anti-aliasing in IE - only needed for animations that change opacity
+ if (browser.msie && o.fxOpacityFix && o.fxName_open != "slide" && $P.css("filter") && $P.css("opacity") == 1)
+ $P[0].style.removeAttribute('filter');
+ }
+ }
+
+
+ /**
+ * Toggle sliding functionality of a specific pane on/off by adding removing 'slide open' trigger
+ *
+ * @see open(), close()
+ * @param {string} pane The pane to enable/disable, 'north', 'south', etc.
+ * @param {boolean} enable Enable or Disable sliding?
+ */
+, bindStartSlidingEvent = function (pane, enable) {
+ var o = options[pane]
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , evtName = o.slideTrigger_open.toLowerCase()
+ ;
+ if (!$R || (enable && !o.slidable)) return;
+
+ // make sure we have a valid event
+ if (evtName.match(/mouseover/))
+ evtName = o.slideTrigger_open = "mouseenter";
+ else if (!evtName.match(/click|dblclick|mouseenter/))
+ evtName = o.slideTrigger_open = "click";
+
+ $R
+ // add or remove event
+ [enable ? "bind" : "unbind"](evtName +'.'+ sID, slideOpen)
+ // set the appropriate cursor & title/tip
+ .css("cursor", enable ? o.sliderCursor : "default")
+ .attr("title", enable ? o.sliderTip : "")
+ ;
+ }
+
+ /**
+ * Add or remove 'mouseleave' events to 'slide close' when pane is 'sliding' open or closed
+ * Also increases zIndex when pane is sliding open
+ * See bindStartSlidingEvent for code to control 'slide open'
+ *
+ * @see slideOpen(), slideClose()
+ * @param {string} pane The pane to process, 'north', 'south', etc.
+ * @param {boolean} enable Enable or Disable events?
+ */
+, bindStopSlidingEvents = function (pane, enable) {
+ var o = options[pane]
+ , s = state[pane]
+ , c = _c[pane]
+ , z = options.zIndexes
+ , evtName = o.slideTrigger_close.toLowerCase()
+ , action = (enable ? "bind" : "unbind")
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ ;
+ s.isSliding = enable; // logic
+ timer.clear(pane+"_closeSlider"); // just in case
+
+ // remove 'slideOpen' event from resizer
+ // ALSO will raise the zIndex of the pane & resizer
+ if (enable) bindStartSlidingEvent(pane, false);
+
+ // RE/SET zIndex - increases when pane is sliding-open, resets to normal when not
+ $P.css("zIndex", enable ? z.pane_sliding : z.pane_normal);
+ $R.css("zIndex", enable ? z.pane_sliding+2 : z.resizer_normal); // NOTE: mask = pane_sliding+1
+
+ // make sure we have a valid event
+ if (!evtName.match(/click|mouseleave/))
+ evtName = o.slideTrigger_close = "mouseleave"; // also catches 'mouseout'
+
+ // add/remove slide triggers
+ $R[action](evtName, slideClose); // base event on resize
+ // need extra events for mouseleave
+ if (evtName === "mouseleave") {
+ // also close on pane.mouseleave
+ $P[action]("mouseleave."+ sID, slideClose);
+ // cancel timer when mouse moves between 'pane' and 'resizer'
+ $R[action]("mouseenter."+ sID, cancelMouseOut);
+ $P[action]("mouseenter."+ sID, cancelMouseOut);
+ }
+
+ if (!enable)
+ timer.clear(pane+"_closeSlider");
+ else if (evtName === "click" && !o.resizable) {
+ // IF pane is not resizable (which already has a cursor and tip)
+ // then set the a cursor & title/tip on resizer when sliding
+ $R.css("cursor", enable ? o.sliderCursor : "default");
+ $R.attr("title", enable ? o.togglerTip_open : ""); // use Toggler-tip, eg: "Close Pane"
+ }
+
+ // SUBROUTINE for mouseleave timer clearing
+ function cancelMouseOut (evt) {
+ timer.clear(pane+"_closeSlider");
+ evt.stopPropagation();
+ }
+ }
+
+
+ /**
+ * Hides/closes a pane if there is insufficient room - reverses this when there is room again
+ * MUST have already called setSizeLimits() before calling this method
+ *
+ * @param {string} pane The pane being resized
+ * @param {boolean=} [isOpening=false] Called from onOpen?
+ * @param {boolean=} [skipCallback=false] Should the onresize callback be run?
+ * @param {boolean=} [force=false]
+ */
+, makePaneFit = function (pane, isOpening, skipCallback, force) {
+ var
+ o = options[pane]
+ , s = state[pane]
+ , c = _c[pane]
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , isSidePane = c.dir==="vert"
+ , hasRoom = false
+ ;
+ // special handling for center & east/west panes
+ if (pane === "center" || (isSidePane && s.noVerticalRoom)) {
+ // see if there is enough room to display the pane
+ // ERROR: hasRoom = s.minHeight <= s.maxHeight && (isSidePane || s.minWidth <= s.maxWidth);
+ hasRoom = (s.maxHeight >= 0);
+ if (hasRoom && s.noRoom) { // previously hidden due to noRoom, so show now
+ _showPane(pane);
+ if ($R) $R.show();
+ s.isVisible = true;
+ s.noRoom = false;
+ if (isSidePane) s.noVerticalRoom = false;
+ _fixIframe(pane);
+ }
+ else if (!hasRoom && !s.noRoom) { // not currently hidden, so hide now
+ _hidePane(pane);
+ if ($R) $R.hide();
+ s.isVisible = false;
+ s.noRoom = true;
+ }
+ }
+
+ // see if there is enough room to fit the border-pane
+ if (pane === "center") {
+ // ignore center in this block
+ }
+ else if (s.minSize <= s.maxSize) { // pane CAN fit
+ hasRoom = true;
+ if (s.size > s.maxSize) // pane is too big - shrink it
+ sizePane(pane, s.maxSize, skipCallback, force, true); // true = noAnimation
+ else if (s.size < s.minSize) // pane is too small - enlarge it
+ sizePane(pane, s.minSize, skipCallback, force, true);
+ // need s.isVisible because new pseudoClose method keeps pane visible, but off-screen
+ else if ($R && s.isVisible && $P.is(":visible")) {
+ // make sure resizer-bar is positioned correctly
+ // handles situation where nested layout was 'hidden' when initialized
+ var side = c.side.toLowerCase()
+ , pos = s.size + sC["inset"+ c.side]
+ ;
+ if ($.layout.cssNum($R, side) != pos) $R.css( side, pos );
+ }
+
+ // if was previously hidden due to noRoom, then RESET because NOW there is room
+ if (s.noRoom) {
+ // s.noRoom state will be set by open or show
+ if (s.wasOpen && o.closable) {
+ if (o.autoReopen)
+ open(pane, false, true, true); // true = noAnimation, true = noAlert
+ else // leave the pane closed, so just update state
+ s.noRoom = false;
+ }
+ else
+ show(pane, s.wasOpen, true, true); // true = noAnimation, true = noAlert
+ }
+ }
+ else { // !hasRoom - pane CANNOT fit
+ if (!s.noRoom) { // pane not set as noRoom yet, so hide or close it now...
+ s.noRoom = true; // update state
+ s.wasOpen = !s.isClosed && !s.isSliding;
+ if (s.isClosed){} // SKIP
+ else if (o.closable) // 'close' if possible
+ close(pane, true, true); // true = force, true = noAnimation
+ else // 'hide' pane if cannot just be closed
+ hide(pane, true); // true = noAnimation
+ }
+ }
+ }
+
+
+ /**
+ * sizePane / manualSizePane
+ * sizePane is called only by internal methods whenever a pane needs to be resized
+ * manualSizePane is an exposed flow-through method allowing extra code when pane is 'manually resized'
+ *
+ * @param {string} pane The pane being resized
+ * @param {number} size The *desired* new size for this pane - will be validated
+ * @param {boolean=} [skipCallback=false] Should the onresize callback be run?
+ * @param {boolean=} [noAnimation=false]
+ */
+, manualSizePane = function (evt_or_pane, size, skipCallback, noAnimation) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , o = options[pane]
+ , s = state[pane]
+ // if resizing callbacks have been delayed and resizing is now DONE, force resizing to complete...
+ , forceResize = o.livePaneResizing && !s.isResizing
+ ;
+ // ANY call to manualSizePane disables autoResize - ie, percentage sizing
+ o.autoResize = false;
+ // flow-through...
+ sizePane(pane, size, skipCallback, forceResize, noAnimation); // will animate resize if option enabled
+ }
+
+ /**
+ * @param {string} pane The pane being resized
+ * @param {number} size The *desired* new size for this pane - will be validated
+ * @param {boolean=} [skipCallback=false] Should the onresize callback be run?
+ * @param {boolean=} [force=false] Force resizing even if does not seem necessary
+ * @param {boolean=} [noAnimation=false]
+ */
+, sizePane = function (evt_or_pane, size, skipCallback, force, noAnimation) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane) // probably NEVER called from event?
+ , o = options[pane]
+ , s = state[pane]
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , side = _c[pane].side.toLowerCase()
+ , dimName = _c[pane].sizeType.toLowerCase()
+ , inset = "inset"+ _c[pane].side
+ , skipResizeWhileDragging = s.isResizing && !o.triggerEventsDuringLiveResize
+ , doFX = noAnimation !== true && o.animatePaneSizing
+ , oldSize, newSize
+ ;
+ // QUEUE in case another action/animation is in progress
+ $N.queue(function( queueNext ){
+ // calculate 'current' min/max sizes
+ setSizeLimits(pane); // update pane-state
+ oldSize = s.size;
+ size = _parseSize(pane, size); // handle percentages & auto
+ size = max(size, _parseSize(pane, o.minSize));
+ size = min(size, s.maxSize);
+ if (size < s.minSize) { // not enough room for pane!
+ queueNext(); // call before makePaneFit() because it needs the queue free
+ makePaneFit(pane, false, skipCallback); // will hide or close pane
+ return;
+ }
+
+ // IF newSize is same as oldSize, then nothing to do - abort
+ if (!force && size === oldSize)
+ return queueNext();
+
+ // onresize_start callback CANNOT cancel resizing because this would break the layout!
+ if (!skipCallback && state.initialized && s.isVisible)
+ _runCallbacks("onresize_start", pane);
+
+ // resize the pane, and make sure its visible
+ newSize = cssSize(pane, size);
+
+ if (doFX && $P.is(":visible")) { // ANIMATE
+ var fx = $.layout.effects.size[pane] || $.layout.effects.size.all
+ , easing = o.fxSettings_size.easing || fx.easing
+ , z = options.zIndexes
+ , props = {};
+ props[ dimName ] = newSize +'px';
+ s.isMoving = true;
+ // overlay all elements during animation
+ $P.css({ zIndex: z.pane_animate })
+ .show().animate( props, o.fxSpeed_size, easing, function(){
+ // reset zIndex after animation
+ $P.css({ zIndex: (s.isSliding ? z.pane_sliding : z.pane_normal) });
+ s.isMoving = false;
+ sizePane_2(); // continue
+ queueNext();
+ });
+ }
+ else { // no animation
+ $P.css( dimName, newSize ); // resize pane
+ // if pane is visible, then
+ if ($P.is(":visible"))
+ sizePane_2(); // continue
+ else {
+ // pane is NOT VISIBLE, so just update state data...
+ // when pane is *next opened*, it will have the new size
+ s.size = size; // update state.size
+ $.extend(s, elDims($P)); // update state dimensions
+ }
+ queueNext();
+ };
+
+ });
+
+ // SUBROUTINE
+ function sizePane_2 () {
+ /* Panes are sometimes not sized precisely in some browsers!?
+ * This code will resize the pane up to 3 times to nudge the pane to the correct size
+ */
+ var actual = dimName==='width' ? $P.outerWidth() : $P.outerHeight()
+ , tries = [{
+ pane: pane
+ , count: 1
+ , target: size
+ , actual: actual
+ , correct: (size === actual)
+ , attempt: size
+ , cssSize: newSize
+ }]
+ , lastTry = tries[0]
+ , msg = 'Inaccurate size after resizing the '+ pane +'-pane.'
+ ;
+ while ( !lastTry.correct ) {
+ thisTry = { pane: pane, count: lastTry.count+1, target: size };
+
+ if (lastTry.actual > size)
+ thisTry.attempt = max(0, lastTry.attempt - (lastTry.actual - size));
+ else // lastTry.actual < size
+ thisTry.attempt = max(0, lastTry.attempt + (size - lastTry.actual));
+
+ thisTry.cssSize = cssSize(pane, thisTry.attempt);
+ $P.css( dimName, thisTry.cssSize );
+
+ thisTry.actual = dimName=='width' ? $P.outerWidth() : $P.outerHeight();
+ thisTry.correct = (size === thisTry.actual);
+
+ // if showDebugMessages, log attempts and alert the user of this *non-fatal error*
+ if (options.showDebugMessages) {
+ if ( tries.length === 1) {
+ _log(msg, false);
+ _log(lastTry, false);
+ }
+ _log(thisTry, false);
+ }
+
+ // after 4 tries, is as close as its gonna get!
+ if (tries.length > 3) break;
+
+ tries.push( thisTry );
+ lastTry = tries[ tries.length - 1 ];
+ }
+ // END TESTING CODE
+
+ // update pane-state dimensions
+ s.size = size;
+ $.extend(s, elDims($P));
+
+ if (s.isVisible && $P.is(":visible")) {
+ // reposition the resizer-bar
+ if ($R) $R.css( side, size + sC[inset] );
+ // resize the content-div
+ sizeContent(pane);
+ }
+
+ if (!skipCallback && !skipResizeWhileDragging && state.initialized && s.isVisible)
+ _runCallbacks("onresize_end", pane);
+
+ // resize all the adjacent panes, and adjust their toggler buttons
+ // when skipCallback passed, it means the controlling method will handle 'other panes'
+ if (!skipCallback) {
+ // also no callback if live-resize is in progress and NOT triggerEventsDuringLiveResize
+ if (!s.isSliding) sizeMidPanes(_c[pane].dir=="horz" ? "" : "center", skipResizeWhileDragging, force);
+ sizeHandles();
+ }
+
+ // if opposite-pane was autoClosed, see if it can be autoOpened now
+ var altPane = _c.oppositeEdge[pane];
+ if (size < oldSize && state[ altPane ].noRoom) {
+ setSizeLimits( altPane );
+ makePaneFit( altPane, false, skipCallback );
+ }
+
+ // DEBUG - ALERT user/developer so they know there was a sizing problem
+ if (options.showDebugMessages && tries.length > 1)
+ _log(msg +'\nSee the Error Console for details.', true);
+ }
+ }
+
+ /**
+ * @see initPanes(), sizePane(), resizeAll(), open(), close(), hide()
+ * @param {string} panes The pane(s) being resized, comma-delmited string
+ * @param {boolean=} [skipCallback=false] Should the onresize callback be run?
+ * @param {boolean=} [force=false]
+ */
+, sizeMidPanes = function (panes, skipCallback, force) {
+ panes = (panes ? panes : "east,west,center").split(",");
+
+ $.each(panes, function (i, pane) {
+ if (!$Ps[pane]) return; // NO PANE - skip
+ var
+ o = options[pane]
+ , s = state[pane]
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , isCenter= (pane=="center")
+ , hasRoom = true
+ , CSS = {}
+ , newCenter = calcNewCenterPaneDims()
+ ;
+ // update pane-state dimensions
+ $.extend(s, elDims($P));
+
+ if (pane === "center") {
+ if (!force && s.isVisible && newCenter.width === s.outerWidth && newCenter.height === s.outerHeight)
+ return true; // SKIP - pane already the correct size
+ // set state for makePaneFit() logic
+ $.extend(s, cssMinDims(pane), {
+ maxWidth: newCenter.width
+ , maxHeight: newCenter.height
+ });
+ CSS = newCenter;
+ // convert OUTER width/height to CSS width/height
+ CSS.width = cssW($P, CSS.width);
+ // NEW - allow pane to extend 'below' visible area rather than hide it
+ CSS.height = cssH($P, CSS.height);
+ hasRoom = CSS.width >= 0 && CSS.height >= 0; // height >= 0 = ALWAYS TRUE NOW
+ // during layout init, try to shrink east/west panes to make room for center
+ if (!state.initialized && o.minWidth > s.outerWidth) {
+ var
+ reqPx = o.minWidth - s.outerWidth
+ , minE = options.east.minSize || 0
+ , minW = options.west.minSize || 0
+ , sizeE = state.east.size
+ , sizeW = state.west.size
+ , newE = sizeE
+ , newW = sizeW
+ ;
+ if (reqPx > 0 && state.east.isVisible && sizeE > minE) {
+ newE = max( sizeE-minE, sizeE-reqPx );
+ reqPx -= sizeE-newE;
+ }
+ if (reqPx > 0 && state.west.isVisible && sizeW > minW) {
+ newW = max( sizeW-minW, sizeW-reqPx );
+ reqPx -= sizeW-newW;
+ }
+ // IF we found enough extra space, then resize the border panes as calculated
+ if (reqPx === 0) {
+ if (sizeE != minE)
+ sizePane('east', newE, true, force, true); // true = skipCallback/noAnimation - initPanes will handle when done
+ if (sizeW != minW)
+ sizePane('west', newW, true, force, true);
+ // now start over!
+ sizeMidPanes('center', skipCallback, force);
+ return; // abort this loop
+ }
+ }
+ }
+ else { // for east and west, set only the height, which is same as center height
+ // set state.min/maxWidth/Height for makePaneFit() logic
+ if (s.isVisible && !s.noVerticalRoom)
+ $.extend(s, elDims($P), cssMinDims(pane))
+ if (!force && !s.noVerticalRoom && newCenter.height === s.outerHeight)
+ return true; // SKIP - pane already the correct size
+ // east/west have same top, bottom & height as center
+ CSS.top = newCenter.top;
+ CSS.bottom = newCenter.bottom;
+ // NEW - allow pane to extend 'below' visible area rather than hide it
+ CSS.height = cssH($P, newCenter.height);
+ s.maxHeight = CSS.height;
+ hasRoom = (s.maxHeight >= 0); // ALWAYS TRUE NOW
+ if (!hasRoom) s.noVerticalRoom = true; // makePaneFit() logic
+ }
+
+ if (hasRoom) {
+ // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized
+ if (!skipCallback && state.initialized)
+ _runCallbacks("onresize_start", pane);
+
+ $P.css(CSS); // apply the CSS to pane
+ sizeHandles(pane); // also update resizer length
+ if (s.noRoom && !s.isClosed && !s.isHidden)
+ makePaneFit(pane); // will re-open/show auto-closed/hidden pane
+ if (s.isVisible) {
+ $.extend(s, elDims($P)); // update pane dimensions
+ if (state.initialized) sizeContent(pane); // also resize the contents, if exists
+ }
+ }
+ else if (!s.noRoom && s.isVisible) // no room for pane
+ makePaneFit(pane); // will hide or close pane
+
+ if (!s.isVisible)
+ return true; // DONE - next pane
+
+ /*
+ * Extra CSS for IE6 or IE7 in Quirks-mode - add 'width' to NORTH/SOUTH panes
+ * Normally these panes have only 'left' & 'right' positions so pane auto-sizes
+ * ALSO required when pane is an IFRAME because will NOT default to 'full width'
+ */
+ if (pane === "center") { // finished processing midPanes
+ var b = $.layout.browser;
+ var fix = b.isIE6 || (b.msie && !$.support.boxModel);
+ if ($Ps.north && (fix || state.north.tagName=="IFRAME"))
+ $Ps.north.css("width", cssW($Ps.north, sC.innerWidth));
+ if ($Ps.south && (fix || state.south.tagName=="IFRAME"))
+ $Ps.south.css("width", cssW($Ps.south, sC.innerWidth));
+ }
+
+ // resizeAll passes skipCallback because it triggers callbacks after ALL panes are resized
+ if (!skipCallback && state.initialized)
+ _runCallbacks("onresize_end", pane);
+ });
+ }
+
+
+ /**
+ * @see window.onresize(), callbacks or custom code
+ */
+, resizeAll = function () {
+ if (!state.initialized) {
+ _initLayoutElements();
+ return; // no need to resize since we just initialized!
+ }
+ var oldW = sC.innerWidth
+ , oldH = sC.innerHeight
+ ;
+ // cannot size layout when 'container' is hidden or collapsed
+ if (!$N.is(":visible:") ) return;
+ $.extend( state.container, elDims( $N ) ); // UPDATE container dimensions
+ if (!sC.outerHeight) return;
+
+ // onresizeall_start will CANCEL resizing if returns false
+ // state.container has already been set, so user can access this info for calcuations
+ if (false === _runCallbacks("onresizeall_start")) return false;
+
+ var // see if container is now 'smaller' than before
+ shrunkH = (sC.innerHeight < oldH)
+ , shrunkW = (sC.innerWidth < oldW)
+ , $P, o, s, dir
+ ;
+ // NOTE special order for sizing: S-N-E-W
+ $.each(["south","north","east","west"], function (i, pane) {
+ if (!$Ps[pane]) return; // no pane - SKIP
+ s = state[pane];
+ o = options[pane];
+ dir = _c[pane].dir;
+
+ if (o.autoResize && s.size != o.size) // resize pane to original size set in options
+ sizePane(pane, o.size, true, true, true); // true=skipCallback/forceResize/noAnimation
+ else {
+ setSizeLimits(pane);
+ makePaneFit(pane, false, true, true); // true=skipCallback/forceResize
+ }
+ });
+
+ sizeMidPanes("", true, true); // true=skipCallback, true=forceResize
+ sizeHandles(); // reposition the toggler elements
+
+ // trigger all individual pane callbacks AFTER layout has finished resizing
+ o = options; // reuse alias
+ $.each(_c.allPanes, function (i, pane) {
+ $P = $Ps[pane];
+ if (!$P) return; // SKIP
+ if (state[pane].isVisible) // undefined for non-existent panes
+ _runCallbacks("onresize_end", pane); // callback - if exists
+ });
+
+ _runCallbacks("onresizeall_end");
+ //_triggerLayoutEvent(pane, 'resizeall');
+ }
+
+ /**
+ * Whenever a pane resizes or opens that has a nested layout, trigger resizeAll
+ *
+ * @param {string} pane The pane just resized or opened
+ */
+, resizeChildLayout = function (evt_or_pane) {
+ var pane = evtPane.call(this, evt_or_pane);
+ if (!options[pane].resizeChildLayout) return;
+ var $P = $Ps[pane]
+ , $C = $Cs[pane]
+ , d = "layout"
+ , P = Instance[pane]
+ , L = children[pane]
+ ;
+ // user may have manually set EITHER instance pointer, so handle that
+ if (P.child && !L) {
+ // have to reverse the pointers!
+ var el = P.child.container;
+ L = children[pane] = (el ? el.data(d) : 0) || null; // set pointer _directly_ to layout instance
+ }
+
+ // if a layout-pointer exists, see if child has been destroyed
+ if (L && L.destroyed)
+ L = children[pane] = null; // clear child pointers
+ // no child layout pointer is set - see if there is a child layout NOW
+ if (!L) L = children[pane] = $P.data(d) || ($C ? $C.data(d) : 0) || null; // set/update child pointers
+
+ // ALWAYS refresh the pane.child alias
+ P.child = children[pane];
+
+ if (L) L.resizeAll();
+ }
+
+
+ /**
+ * IF pane has a content-div, then resize all elements inside pane to fit pane-height
+ *
+ * @param {string=} [panes=""] The pane(s) being resized
+ * @param {boolean=} [remeasure=false] Should the content (header/footer) be remeasured?
+ */
+, sizeContent = function (evt_or_panes, remeasure) {
+ if (!isInitialized()) return;
+
+ var panes = evtPane.call(this, evt_or_panes);
+ panes = panes ? panes.split(",") : _c.allPanes;
+
+ $.each(panes, function (idx, pane) {
+ var
+ $P = $Ps[pane]
+ , $C = $Cs[pane]
+ , o = options[pane]
+ , s = state[pane]
+ , m = s.content // m = measurements
+ ;
+ if (!$P || !$C || !$P.is(":visible")) return true; // NOT VISIBLE - skip
+
+ // if content-element was REMOVED, update OR remove the pointer
+ if (!$C.length) {
+ initContent(pane, false); // false = do NOT sizeContent() - already there!
+ if (!$C) return; // no replacement element found - pointer have been removed
+ }
+
+ // onsizecontent_start will CANCEL resizing if returns false
+ if (false === _runCallbacks("onsizecontent_start", pane)) return;
+
+ // skip re-measuring offsets if live-resizing
+ if ((!s.isMoving && !s.isResizing) || o.liveContentResizing || remeasure || m.top == undefined) {
+ _measure();
+ // if any footers are below pane-bottom, they may not measure correctly,
+ // so allow pane overflow and re-measure
+ if (m.hiddenFooters > 0 && $P.css("overflow") === "hidden") {
+ $P.css("overflow", "visible");
+ _measure(); // remeasure while overflowing
+ $P.css("overflow", "hidden");
+ }
+ }
+ // NOTE: spaceAbove/Below *includes* the pane paddingTop/Bottom, but not pane.borders
+ var newH = s.innerHeight - (m.spaceAbove - s.css.paddingTop) - (m.spaceBelow - s.css.paddingBottom);
+
+ if (!$C.is(":visible") || m.height != newH) {
+ // size the Content element to fit new pane-size - will autoHide if not enough room
+ setOuterHeight($C, newH, true); // true=autoHide
+ m.height = newH; // save new height
+ };
+
+ if (state.initialized)
+ _runCallbacks("onsizecontent_end", pane);
+
+ function _below ($E) {
+ return max(s.css.paddingBottom, (parseInt($E.css("marginBottom"), 10) || 0));
+ };
+
+ function _measure () {
+ var
+ ignore = options[pane].contentIgnoreSelector
+ , $Fs = $C.nextAll().not(ignore || ':lt(0)') // not :lt(0) = ALL
+ , $Fs_vis = $Fs.filter(':visible')
+ , $F = $Fs_vis.filter(':last')
+ ;
+ m = {
+ top: $C[0].offsetTop
+ , height: $C.outerHeight()
+ , numFooters: $Fs.length
+ , hiddenFooters: $Fs.length - $Fs_vis.length
+ , spaceBelow: 0 // correct if no content footer ($E)
+ }
+ m.spaceAbove = m.top; // just for state - not used in calc
+ m.bottom = m.top + m.height;
+ if ($F.length)
+ //spaceBelow = (LastFooter.top + LastFooter.height) [footerBottom] - Content.bottom + max(LastFooter.marginBottom, pane.paddingBotom)
+ m.spaceBelow = ($F[0].offsetTop + $F.outerHeight()) - m.bottom + _below($F);
+ else // no footer - check marginBottom on Content element itself
+ m.spaceBelow = _below($C);
+ };
+ });
+ }
+
+
+ /**
+ * Called every time a pane is opened, closed, or resized to slide the togglers to 'center' and adjust their length if necessary
+ *
+ * @see initHandles(), open(), close(), resizeAll()
+ * @param {string=} [panes=""] The pane(s) being resized
+ */
+, sizeHandles = function (evt_or_panes) {
+ var panes = evtPane.call(this, evt_or_panes)
+ panes = panes ? panes.split(",") : _c.borderPanes;
+
+ $.each(panes, function (i, pane) {
+ var
+ o = options[pane]
+ , s = state[pane]
+ , $P = $Ps[pane]
+ , $R = $Rs[pane]
+ , $T = $Ts[pane]
+ , $TC
+ ;
+ if (!$P || !$R) return;
+
+ var
+ dir = _c[pane].dir
+ , _state = (s.isClosed ? "_closed" : "_open")
+ , spacing = o["spacing"+ _state]
+ , togAlign = o["togglerAlign"+ _state]
+ , togLen = o["togglerLength"+ _state]
+ , paneLen
+ , left
+ , offset
+ , CSS = {}
+ ;
+
+ if (spacing === 0) {
+ $R.hide();
+ return;
+ }
+ else if (!s.noRoom && !s.isHidden) // skip if resizer was hidden for any reason
+ $R.show(); // in case was previously hidden
+
+ // Resizer Bar is ALWAYS same width/height of pane it is attached to
+ if (dir === "horz") { // north/south
+ //paneLen = $P.outerWidth(); // s.outerWidth ||
+ paneLen = sC.innerWidth; // handle offscreen-panes
+ s.resizerLength = paneLen;
+ left = $.layout.cssNum($P, "left")
+ $R.css({
+ width: cssW($R, paneLen) // account for borders & padding
+ , height: cssH($R, spacing) // ditto
+ , left: left > -9999 ? left : sC.insetLeft // handle offscreen-panes
+ });
+ }
+ else { // east/west
+ paneLen = $P.outerHeight(); // s.outerHeight ||
+ s.resizerLength = paneLen;
+ $R.css({
+ height: cssH($R, paneLen) // account for borders & padding
+ , width: cssW($R, spacing) // ditto
+ , top: sC.insetTop + getPaneSize("north", true) // TODO: what if no North pane?
+ //, top: $.layout.cssNum($Ps["center"], "top")
+ });
+ }
+
+ // remove hover classes
+ removeHover( o, $R );
+
+ if ($T) {
+ if (togLen === 0 || (s.isSliding && o.hideTogglerOnSlide)) {
+ $T.hide(); // always HIDE the toggler when 'sliding'
+ return;
+ }
+ else
+ $T.show(); // in case was previously hidden
+
+ if (!(togLen > 0) || togLen === "100%" || togLen > paneLen) {
+ togLen = paneLen;
+ offset = 0;
+ }
+ else { // calculate 'offset' based on options.PANE.togglerAlign_open/closed
+ if (isStr(togAlign)) {
+ switch (togAlign) {
+ case "top":
+ case "left": offset = 0;
+ break;
+ case "bottom":
+ case "right": offset = paneLen - togLen;
+ break;
+ case "middle":
+ case "center":
+ default: offset = round((paneLen - togLen) / 2); // 'default' catches typos
+ }
+ }
+ else { // togAlign = number
+ var x = parseInt(togAlign, 10); //
+ if (togAlign >= 0) offset = x;
+ else offset = paneLen - togLen + x; // NOTE: x is negative!
+ }
+ }
+
+ if (dir === "horz") { // north/south
+ var width = cssW($T, togLen);
+ $T.css({
+ width: width // account for borders & padding
+ , height: cssH($T, spacing) // ditto
+ , left: offset // TODO: VERIFY that toggler positions correctly for ALL values
+ , top: 0
+ });
+ // CENTER the toggler content SPAN
+ $T.children(".content").each(function(){
+ $TC = $(this);
+ $TC.css("marginLeft", round((width-$TC.outerWidth())/2)); // could be negative
+ });
+ }
+ else { // east/west
+ var height = cssH($T, togLen);
+ $T.css({
+ height: height // account for borders & padding
+ , width: cssW($T, spacing) // ditto
+ , top: offset // POSITION the toggler
+ , left: 0
+ });
+ // CENTER the toggler content SPAN
+ $T.children(".content").each(function(){
+ $TC = $(this);
+ $TC.css("marginTop", round((height-$TC.outerHeight())/2)); // could be negative
+ });
+ }
+
+ // remove ALL hover classes
+ removeHover( 0, $T );
+ }
+
+ // DONE measuring and sizing this resizer/toggler, so can be 'hidden' now
+ if (!state.initialized && (o.initHidden || s.noRoom)) {
+ $R.hide();
+ if ($T) $T.hide();
+ }
+ });
+ }
+
+
+ /**
+ * @param {string} pane
+ */
+, enableClosable = function (evt_or_pane) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $T = $Ts[pane]
+ , o = options[pane]
+ ;
+ if (!$T) return;
+ o.closable = true;
+ $T .bind("click."+ sID, function(evt){ evt.stopPropagation(); toggle(pane); })
+ .css("visibility", "visible")
+ .css("cursor", "pointer")
+ .attr("title", state[pane].isClosed ? o.togglerTip_closed : o.togglerTip_open) // may be blank
+ .show();
+ }
+ /**
+ * @param {string} pane
+ * @param {boolean=} [hide=false]
+ */
+, disableClosable = function (evt_or_pane, hide) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $T = $Ts[pane]
+ ;
+ if (!$T) return;
+ options[pane].closable = false;
+ // is closable is disable, then pane MUST be open!
+ if (state[pane].isClosed) open(pane, false, true);
+ $T .unbind("."+ sID)
+ .css("visibility", hide ? "hidden" : "visible") // instead of hide(), which creates logic issues
+ .css("cursor", "default")
+ .attr("title", "");
+ }
+
+
+ /**
+ * @param {string} pane
+ */
+, enableSlidable = function (evt_or_pane) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $R = $Rs[pane]
+ ;
+ if (!$R || !$R.data('draggable')) return;
+ options[pane].slidable = true;
+ if (s.isClosed)
+ bindStartSlidingEvent(pane, true);
+ }
+ /**
+ * @param {string} pane
+ */
+, disableSlidable = function (evt_or_pane) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $R = $Rs[pane]
+ ;
+ if (!$R) return;
+ options[pane].slidable = false;
+ if (state[pane].isSliding)
+ close(pane, false, true);
+ else {
+ bindStartSlidingEvent(pane, false);
+ $R .css("cursor", "default")
+ .attr("title", "");
+ removeHover(null, $R[0]); // in case currently hovered
+ }
+ }
+
+
+ /**
+ * @param {string} pane
+ */
+, enableResizable = function (evt_or_pane) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $R = $Rs[pane]
+ , o = options[pane]
+ ;
+ if (!$R || !$R.data('draggable')) return;
+ o.resizable = true;
+ $R.draggable("enable");
+ if (!state[pane].isClosed)
+ $R .css("cursor", o.resizerCursor)
+ .attr("title", o.resizerTip);
+ }
+ /**
+ * @param {string} pane
+ */
+, disableResizable = function (evt_or_pane) {
+ if (!isInitialized()) return;
+ var pane = evtPane.call(this, evt_or_pane)
+ , $R = $Rs[pane]
+ ;
+ if (!$R || !$R.data('draggable')) return;
+ options[pane].resizable = false;
+ $R .draggable("disable")
+ .css("cursor", "default")
+ .attr("title", "");
+ removeHover(null, $R[0]); // in case currently hovered
+ }
+
+
+ /**
+ * Move a pane from source-side (eg, west) to target-side (eg, east)
+ * If pane exists on target-side, move that to source-side, ie, 'swap' the panes
+ *
+ * @param {string} pane1 The pane/edge being swapped
+ * @param {string} pane2 ditto
+ */
+, swapPanes = function (evt_or_pane1, pane2) {
+ if (!isInitialized()) return;
+ var pane1 = evtPane.call(this, evt_or_pane1);
+ // change state.edge NOW so callbacks can know where pane is headed...
+ state[pane1].edge = pane2;
+ state[pane2].edge = pane1;
+ // run these even if NOT state.initialized
+ if (false === _runCallbacks("onswap_start", pane1)
+ || false === _runCallbacks("onswap_start", pane2)
+ ) {
+ state[pane1].edge = pane1; // reset
+ state[pane2].edge = pane2;
+ return;
+ }
+
+ var
+ oPane1 = copy( pane1 )
+ , oPane2 = copy( pane2 )
+ , sizes = {}
+ ;
+ sizes[pane1] = oPane1 ? oPane1.state.size : 0;
+ sizes[pane2] = oPane2 ? oPane2.state.size : 0;
+
+ // clear pointers & state
+ $Ps[pane1] = false;
+ $Ps[pane2] = false;
+ state[pane1] = {};
+ state[pane2] = {};
+
+ // ALWAYS remove the resizer & toggler elements
+ if ($Ts[pane1]) $Ts[pane1].remove();
+ if ($Ts[pane2]) $Ts[pane2].remove();
+ if ($Rs[pane1]) $Rs[pane1].remove();
+ if ($Rs[pane2]) $Rs[pane2].remove();
+ $Rs[pane1] = $Rs[pane2] = $Ts[pane1] = $Ts[pane2] = false;
+
+ // transfer element pointers and data to NEW Layout keys
+ move( oPane1, pane2 );
+ move( oPane2, pane1 );
+
+ // cleanup objects
+ oPane1 = oPane2 = sizes = null;
+
+ // make panes 'visible' again
+ if ($Ps[pane1]) $Ps[pane1].css(_c.visible);
+ if ($Ps[pane2]) $Ps[pane2].css(_c.visible);
+
+ // fix any size discrepancies caused by swap
+ resizeAll();
+
+ // run these even if NOT state.initialized
+ _runCallbacks("onswap_end", pane1);
+ _runCallbacks("onswap_end", pane2);
+
+ return;
+
+ function copy (n) { // n = pane
+ var
+ $P = $Ps[n]
+ , $C = $Cs[n]
+ ;
+ return !$P ? false : {
+ pane: n
+ , P: $P ? $P[0] : false
+ , C: $C ? $C[0] : false
+ , state: $.extend(true, {}, state[n])
+ , options: $.extend(true, {}, options[n])
+ }
+ };
+
+ function move (oPane, pane) {
+ if (!oPane) return;
+ var
+ P = oPane.P
+ , C = oPane.C
+ , oldPane = oPane.pane
+ , c = _c[pane]
+ , side = c.side.toLowerCase()
+ , inset = "inset"+ c.side
+ // save pane-options that should be retained
+ , s = $.extend({}, state[pane])
+ , o = options[pane]
+ // RETAIN side-specific FX Settings - more below
+ , fx = { resizerCursor: o.resizerCursor }
+ , re, size, pos
+ ;
+ $.each("fxName,fxSpeed,fxSettings".split(","), function (i, k) {
+ fx[k +"_open"] = o[k +"_open"];
+ fx[k +"_close"] = o[k +"_close"];
+ fx[k +"_size"] = o[k +"_size"];
+ });
+
+ // update object pointers and attributes
+ $Ps[pane] = $(P)
+ .data({
+ layoutPane: Instance[pane] // NEW pointer to pane-alias-object
+ , layoutEdge: pane
+ })
+ .css(_c.hidden)
+ .css(c.cssReq)
+ ;
+ $Cs[pane] = C ? $(C) : false;
+
+ // set options and state
+ options[pane] = $.extend({}, oPane.options, fx);
+ state[pane] = $.extend({}, oPane.state);
+
+ // change classNames on the pane, eg: ui-layout-pane-east ==> ui-layout-pane-west
+ re = new RegExp(o.paneClass +"-"+ oldPane, "g");
+ P.className = P.className.replace(re, o.paneClass +"-"+ pane);
+
+ // ALWAYS regenerate the resizer & toggler elements
+ initHandles(pane); // create the required resizer & toggler
+
+ // if moving to different orientation, then keep 'target' pane size
+ if (c.dir != _c[oldPane].dir) {
+ size = sizes[pane] || 0;
+ setSizeLimits(pane); // update pane-state
+ size = max(size, state[pane].minSize);
+ // use manualSizePane to disable autoResize - not useful after panes are swapped
+ manualSizePane(pane, size, true, true); // true/true = skipCallback/noAnimation
+ }
+ else // move the resizer here
+ $Rs[pane].css(side, sC[inset] + (state[pane].isVisible ? getPaneSize(pane) : 0));
+
+
+ // ADD CLASSNAMES & SLIDE-BINDINGS
+ if (oPane.state.isVisible && !s.isVisible)
+ setAsOpen(pane, true); // true = skipCallback
+ else {
+ setAsClosed(pane);
+ bindStartSlidingEvent(pane, true); // will enable events IF option is set
+ }
+
+ // DESTROY the object
+ oPane = null;
+ };
+ }
+
+
+ /**
+ * INTERNAL method to sync pin-buttons when pane is opened or closed
+ * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
+ *
+ * @see open(), setAsOpen(), setAsClosed()
+ * @param {string} pane These are the params returned to callbacks by layout()
+ * @param {boolean} doPin True means set the pin 'down', False means 'up'
+ */
+, syncPinBtns = function (pane, doPin) {
+ if ($.layout.plugins.buttons)
+ $.each(state[pane].pins, function (i, selector) {
+ $.layout.buttons.setPinState(Instance, $(selector), pane, doPin);
+ });
+ }
+
+; // END var DECLARATIONS
+
+ /**
+ * Capture keys when enableCursorHotkey - toggle pane if hotkey pressed
+ *
+ * @see document.keydown()
+ */
+ function keyDown (evt) {
+ if (!evt) return true;
+ var code = evt.keyCode;
+ if (code < 33) return true; // ignore special keys: ENTER, TAB, etc
+
+ var
+ PANE = {
+ 38: "north" // Up Cursor - $.ui.keyCode.UP
+ , 40: "south" // Down Cursor - $.ui.keyCode.DOWN
+ , 37: "west" // Left Cursor - $.ui.keyCode.LEFT
+ , 39: "east" // Right Cursor - $.ui.keyCode.RIGHT
+ }
+ , ALT = evt.altKey // no worky!
+ , SHIFT = evt.shiftKey
+ , CTRL = evt.ctrlKey
+ , CURSOR = (CTRL && code >= 37 && code <= 40)
+ , o, k, m, pane
+ ;
+
+ if (CURSOR && options[PANE[code]].enableCursorHotkey) // valid cursor-hotkey
+ pane = PANE[code];
+ else if (CTRL || SHIFT) // check to see if this matches a custom-hotkey
+ $.each(_c.borderPanes, function (i, p) { // loop each pane to check its hotkey
+ o = options[p];
+ k = o.customHotkey;
+ m = o.customHotkeyModifier; // if missing or invalid, treated as "CTRL+SHIFT"
+ if ((SHIFT && m=="SHIFT") || (CTRL && m=="CTRL") || (CTRL && SHIFT)) { // Modifier matches
+ if (k && code === (isNaN(k) || k <= 9 ? k.toUpperCase().charCodeAt(0) : k)) { // Key matches
+ pane = p;
+ return false; // BREAK
+ }
+ }
+ });
+
+ // validate pane
+ if (!pane || !$Ps[pane] || !options[pane].closable || state[pane].isHidden)
+ return true;
+
+ toggle(pane);
+
+ evt.stopPropagation();
+ evt.returnValue = false; // CANCEL key
+ return false;
+ };
+
+
+/*
+ * ######################################
+ * UTILITY METHODS
+ * called externally or by initButtons
+ * ######################################
+ */
+
+ /**
+ * Change/reset a pane overflow setting & zIndex to allow popups/drop-downs to work
+ *
+ * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event
+ */
+ function allowOverflow (el) {
+ if (!isInitialized()) return;
+ if (this && this.tagName) el = this; // BOUND to element
+ var $P;
+ if (isStr(el))
+ $P = $Ps[el];
+ else if ($(el).data("layoutRole"))
+ $P = $(el);
+ else
+ $(el).parents().each(function(){
+ if ($(this).data("layoutRole")) {
+ $P = $(this);
+ return false; // BREAK
+ }
+ });
+ if (!$P || !$P.length) return; // INVALID
+
+ var
+ pane = $P.data("layoutEdge")
+ , s = state[pane]
+ ;
+
+ // if pane is already raised, then reset it before doing it again!
+ // this would happen if allowOverflow is attached to BOTH the pane and an element
+ if (s.cssSaved)
+ resetOverflow(pane); // reset previous CSS before continuing
+
+ // if pane is raised by sliding or resizing, or its closed, then abort
+ if (s.isSliding || s.isResizing || s.isClosed) {
+ s.cssSaved = false;
+ return;
+ }
+
+ var
+ newCSS = { zIndex: (options.zIndexes.resizer_normal + 1) }
+ , curCSS = {}
+ , of = $P.css("overflow")
+ , ofX = $P.css("overflowX")
+ , ofY = $P.css("overflowY")
+ ;
+ // determine which, if any, overflow settings need to be changed
+ if (of != "visible") {
+ curCSS.overflow = of;
+ newCSS.overflow = "visible";
+ }
+ if (ofX && !ofX.match(/visible|auto/)) {
+ curCSS.overflowX = ofX;
+ newCSS.overflowX = "visible";
+ }
+ if (ofY && !ofY.match(/visible|auto/)) {
+ curCSS.overflowY = ofX;
+ newCSS.overflowY = "visible";
+ }
+
+ // save the current overflow settings - even if blank!
+ s.cssSaved = curCSS;
+
+ // apply new CSS to raise zIndex and, if necessary, make overflow 'visible'
+ $P.css( newCSS );
+
+ // make sure the zIndex of all other panes is normal
+ $.each(_c.allPanes, function(i, p) {
+ if (p != pane) resetOverflow(p);
+ });
+
+ };
+ /**
+ * @param {Object=} [el] (optional) Can also be 'bound' to a click, mouseOver, or other event
+ */
+ function resetOverflow (el) {
+ if (!isInitialized()) return;
+ if (this && this.tagName) el = this; // BOUND to element
+ var $P;
+ if (isStr(el))
+ $P = $Ps[el];
+ else if ($(el).data("layoutRole"))
+ $P = $(el);
+ else
+ $(el).parents().each(function(){
+ if ($(this).data("layoutRole")) {
+ $P = $(this);
+ return false; // BREAK
+ }
+ });
+ if (!$P || !$P.length) return; // INVALID
+
+ var
+ pane = $P.data("layoutEdge")
+ , s = state[pane]
+ , CSS = s.cssSaved || {}
+ ;
+ // reset the zIndex
+ if (!s.isSliding && !s.isResizing)
+ $P.css("zIndex", options.zIndexes.pane_normal);
+
+ // reset Overflow - if necessary
+ $P.css( CSS );
+
+ // clear var
+ s.cssSaved = false;
+ };
+
+/*
+ * #####################
+ * CREATE/RETURN LAYOUT
+ * #####################
+ */
+
+ // validate that container exists
+ var $N = $(this).eq(0); // FIRST matching Container element
+ if (!$N.length) {
+ if (options.showErrorMessages)
+ _log( lang.errContainerMissing, true );
+ return null;
+ };
+
+ // Users retrieve Instance of a layout with: $N.layout() OR $N.data("layout")
+ // return the Instance-pointer if layout has already been initialized
+ if ($N.data("layoutContainer") && $N.data("layout"))
+ return $N.data("layout"); // cached pointer
+
+ // init global vars
+ var
+ $Ps = {} // Panes x5 - set in initPanes()
+ , $Cs = {} // Content x5 - set in initPanes()
+ , $Rs = {} // Resizers x4 - set in initHandles()
+ , $Ts = {} // Togglers x4 - set in initHandles()
+ , $Ms = $([]) // Masks - up to 2 masks per pane (IFRAME + DIV)
+ // aliases for code brevity
+ , sC = state.container // alias for easy access to 'container dimensions'
+ , sID = state.id // alias for unique layout ID/namespace - eg: "layout435"
+ ;
+
+ // create Instance object to expose data & option Properties, and primary action Methods
+ var Instance = {
+ // layout data
+ options: options // property - options hash
+ , state: state // property - dimensions hash
+ // object pointers
+ , container: $N // property - object pointers for layout container
+ , panes: $Ps // property - object pointers for ALL Panes: panes.north, panes.center
+ , contents: $Cs // property - object pointers for ALL Content: contents.north, contents.center
+ , resizers: $Rs // property - object pointers for ALL Resizers, eg: resizers.north
+ , togglers: $Ts // property - object pointers for ALL Togglers, eg: togglers.north
+ // border-pane open/close
+ , hide: hide // method - ditto
+ , show: show // method - ditto
+ , toggle: toggle // method - pass a 'pane' ("north", "west", etc)
+ , open: open // method - ditto
+ , close: close // method - ditto
+ , slideOpen: slideOpen // method - ditto
+ , slideClose: slideClose // method - ditto
+ , slideToggle: slideToggle // method - ditto
+ // pane actions
+ , setSizeLimits: setSizeLimits // method - pass a 'pane' - update state min/max data
+ , _sizePane: sizePane // method -intended for user by plugins only!
+ , sizePane: manualSizePane // method - pass a 'pane' AND an 'outer-size' in pixels or percent, or 'auto'
+ , sizeContent: sizeContent // method - pass a 'pane'
+ , swapPanes: swapPanes // method - pass TWO 'panes' - will swap them
+ // pane element methods
+ , initContent: initContent // method - ditto
+ , addPane: addPane // method - pass a 'pane'
+ , removePane: removePane // method - pass a 'pane' to remove from layout, add 'true' to delete the pane-elem
+ , createChildLayout: createChildLayout// method - pass a 'pane' and (optional) layout-options (OVERRIDES options[pane].childOptions
+ // special pane option setting
+ , enableClosable: enableClosable // method - pass a 'pane'
+ , disableClosable: disableClosable // method - ditto
+ , enableSlidable: enableSlidable // method - ditto
+ , disableSlidable: disableSlidable // method - ditto
+ , enableResizable: enableResizable // method - ditto
+ , disableResizable: disableResizable// method - ditto
+ // utility methods for panes
+ , allowOverflow: allowOverflow // utility - pass calling element (this)
+ , resetOverflow: resetOverflow // utility - ditto
+ // layout control
+ , destroy: destroy // method - no parameters
+ , initPanes: isInitialized // method - no parameters
+ , resizeAll: resizeAll // method - no parameters
+ // callback triggering
+ , runCallbacks: _runCallbacks // method - pass evtName & pane (if a pane-event), eg: trigger("onopen", "west")
+ // alias collections of options, state and children - created in addPane and extended elsewhere
+ , hasParentLayout: false // set by initContainer()
+ , children: children // pointers to child-layouts, eg: Instance.children["west"]
+ , north: false // alias group: { name: pane, pane: $Ps[pane], options: options[pane], state: state[pane], child: children[pane] }
+ , south: false // ditto
+ , west: false // ditto
+ , east: false // ditto
+ , center: false // ditto
+ };
+
+ // create the border layout NOW
+ if (_create() === 'cancel') // onload_start callback returned false to CANCEL layout creation
+ return null;
+ else // true OR false -- if layout-elements did NOT init (hidden or do not exist), can auto-init later
+ return Instance; // return the Instance object
+
+}
+
+
+
+
+/**
+ * jquery.layout.state 1.0
+ * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $
+ *
+ * Copyright (c) 2010
+ * Kevin Dalman (http://allpro.net)
+ *
+ * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
+ * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
*
- * $Date: 2010-07-13 08:00:00 (Wed, 14 July 2010) $
- * $Rev: 30293 $
+ * @dependancies: UI Layout 1.3.0.rc30.1 or higher
+ * @dependancies: $.ui.cookie (above)
+ *
+ * @support: http://groups.google.com/group/jquery-ui-layout
+ */
+/*
+ * State-management options stored in options.stateManagement, which includes a .cookie hash
+ * Default options saves ALL KEYS for ALL PANES, ie: pane.size, pane.isClosed, pane.isHidden
+ *
+ * // STATE/COOKIE OPTIONS
+ * @example $(el).layout({
+ stateManagement: {
+ enabled: true
+ , stateKeys: "east.size,west.size,east.isClosed,west.isClosed"
+ , cookie: { name: "appLayout", path: "/" }
+ }
+ })
+ * @example $(el).layout({ stateManagement__enabled: true }) // enable auto-state-management using cookies
+ * @example $(el).layout({ stateManagement__cookie: { name: "appLayout", path: "/" } })
+ * @example $(el).layout({ stateManagement__cookie__name: "appLayout", stateManagement__cookie__path: "/" })
+ *
+ * // STATE/COOKIE METHODS
+ * @example myLayout.saveCookie( "west.isClosed,north.size,south.isHidden", {expires: 7} );
+ * @example myLayout.loadCookie();
+ * @example myLayout.deleteCookie();
+ * @example var JSON = myLayout.readState(); // CURRENT Layout State
+ * @example var JSON = myLayout.readCookie(); // SAVED Layout State (from cookie)
+ * @example var JSON = myLayout.state.stateData; // LAST LOADED Layout State (cookie saved in layout.state hash)
+ *
+ * CUSTOM STATE-MANAGEMENT (eg, saved in a database)
+ * @example var JSON = myLayout.readState( "west.isClosed,north.size,south.isHidden" );
+ * @example myLayout.loadState( JSON );
+ */
+
+/**
+ * UI COOKIE UTILITY
+ *
+ * A $.cookie OR $.ui.cookie namespace *should be standard*, but until then...
+ * This creates $.ui.cookie so Layout does not need the cookie.jquery.js plugin
+ * NOTE: This utility is REQUIRED by the layout.state plugin
+ *
+ * Cookie methods in Layout are created as part of State Management
+ */
+if (!$.ui) $.ui = {};
+$.ui.cookie = {
+
+ // cookieEnabled is not in DOM specs, but DOES works in all browsers,including IE6
+ acceptsCookies: !!navigator.cookieEnabled
+
+, read: function (name) {
+ var
+ c = document.cookie
+ , cs = c ? c.split(';') : []
+ , pair // loop var
+ ;
+ for (var i=0, n=cs.length; i < n; i++) {
+ pair = $.trim(cs[i]).split('='); // name=value pair
+ if (pair[0] == name) // found the layout cookie
+ return decodeURIComponent(pair[1]);
+
+ }
+ return null;
+ }
+
+, write: function (name, val, cookieOpts) {
+ var
+ params = ''
+ , date = ''
+ , clear = false
+ , o = cookieOpts || {}
+ , x = o.expires
+ ;
+ if (x && x.toUTCString)
+ date = x;
+ else if (x === null || typeof x === 'number') {
+ date = new Date();
+ if (x > 0)
+ date.setDate(date.getDate() + x);
+ else {
+ date.setFullYear(1970);
+ clear = true;
+ }
+ }
+ if (date) params += ';expires='+ date.toUTCString();
+ if (o.path) params += ';path='+ o.path;
+ if (o.domain) params += ';domain='+ o.domain;
+ if (o.secure) params += ';secure';
+ document.cookie = name +'='+ (clear ? "" : encodeURIComponent( val )) + params; // write or clear cookie
+ }
+
+, clear: function (name) {
+ $.ui.cookie.write(name, '', {expires: -1});
+ }
+
+};
+// if cookie.jquery.js is not loaded, create an alias to replicate it
+// this may be useful to other plugins or code dependent on that plugin
+if (!$.cookie) $.cookie = function (k, v, o) {
+ var C = $.ui.cookie;
+ if (v === null)
+ C.clear(k);
+ else if (v === undefined)
+ return C.read(k);
+ else
+ C.write(k, v, o);
+};
+
+
+// tell Layout that the state plugin is available
+$.layout.plugins.stateManagement = true;
+
+// Add State-Management options to layout.defaults
+$.layout.config.optionRootKeys.push("stateManagement");
+$.layout.defaults.stateManagement = {
+ enabled: false // true = enable state-management, even if not using cookies
+, autoSave: true // Save a state-cookie when page exits?
+, autoLoad: true // Load the state-cookie when Layout inits?
+ // List state-data to save - must be pane-specific
+, stateKeys: "north.size,south.size,east.size,west.size,"+
+ "north.isClosed,south.isClosed,east.isClosed,west.isClosed,"+
+ "north.isHidden,south.isHidden,east.isHidden,west.isHidden"
+, cookie: {
+ name: "" // If not specified, will use Layout.name, else just "Layout"
+ , domain: "" // blank = current domain
+ , path: "" // blank = current page, '/' = entire website
+ , expires: "" // 'days' to keep cookie - leave blank for 'session cookie'
+ , secure: false
+ }
+};
+// Set stateManagement as a layout-option, NOT a pane-option
+$.layout.optionsMap.layout.push("stateManagement");
+
+/*
+ * State Management methods
+ */
+$.layout.state = {
+
+ /**
+ * Get the current layout state and save it to a cookie
+ *
+ * myLayout.saveCookie( keys, cookieOpts )
+ *
+ * @param {Object} inst
+ * @param {(string|Array)=} keys
+ * @param {Object=} opts
+ */
+ saveCookie: function (inst, keys, cookieOpts) {
+ var o = inst.options
+ , oS = o.stateManagement
+ , oC = $.extend(true, {}, oS.cookie, cookieOpts || null)
+ , data = inst.state.stateData = inst.readState( keys || oS.stateKeys ) // read current panes-state
+ ;
+ $.ui.cookie.write( oC.name || o.name || "Layout", $.layout.state.encodeJSON(data), oC );
+ return $.extend(true, {}, data); // return COPY of state.stateData data
+ }
+
+ /**
+ * Remove the state cookie
+ *
+ * @param {Object} inst
+ */
+, deleteCookie: function (inst) {
+ var o = inst.options;
+ $.ui.cookie.clear( o.stateManagement.cookie.name || o.name || "Layout" );
+ }
+
+ /**
+ * Read & return data from the cookie - as JSON
+ *
+ * @param {Object} inst
+ */
+, readCookie: function (inst) {
+ var o = inst.options;
+ var c = $.ui.cookie.read( o.stateManagement.cookie.name || o.name || "Layout" );
+ // convert cookie string back to a hash and return it
+ return c ? $.layout.state.decodeJSON(c) : {};
+ }
+
+ /**
+ * Get data from the cookie and USE IT to loadState
+ *
+ * @param {Object} inst
+ */
+, loadCookie: function (inst) {
+ var c = $.layout.state.readCookie(inst); // READ the cookie
+ if (c) {
+ inst.state.stateData = $.extend(true, {}, c); // SET state.stateData
+ inst.loadState(c); // LOAD the retrieved state
+ }
+ return c;
+ }
+
+ /**
+ * Update layout options from the cookie, if one exists
+ *
+ * @param {Object} inst
+ * @param {Object=} stateData
+ * @param {boolean=} animate
+ */
+, loadState: function (inst, stateData, animate) {
+ stateData = $.layout.transformData( stateData ); // panes = default subkey
+ if ($.isEmptyObject( stateData )) return;
+ $.extend(true, inst.options, stateData); // update layout options
+ // if layout has already been initialized, then UPDATE layout state
+ if (inst.state.initialized) {
+ var pane, vis, o, s, h, c
+ , noAnimate = (animate===false)
+ ;
+ $.each($.layout.config.borderPanes, function (idx, pane) {
+ state = inst.state[pane];
+ o = stateData[ pane ];
+ if (typeof o != 'object') return; // no key, continue
+ s = o.size;
+ c = o.initClosed;
+ h = o.initHidden;
+ vis = state.isVisible;
+ // resize BEFORE opening
+ if (!vis)
+ inst.sizePane(pane, s, false, false);
+ if (h === true) inst.hide(pane, noAnimate);
+ else if (c === false) inst.open (pane, false, noAnimate);
+ else if (c === true) inst.close(pane, false, noAnimate);
+ else if (h === false) inst.show (pane, false, noAnimate);
+ // resize AFTER any other actions
+ if (vis)
+ inst.sizePane(pane, s, false, noAnimate); // animate resize if option passed
+ });
+ };
+ }
+
+ /**
+ * Get the *current layout state* and return it as a hash
+ *
+ * @param {Object=} inst
+ * @param {(string|Array)=} keys
+ */
+, readState: function (inst, keys) {
+ var
+ data = {}
+ , alt = { isClosed: 'initClosed', isHidden: 'initHidden' }
+ , state = inst.state
+ , panes = $.layout.config.allPanes
+ , pair, pane, key, val
+ ;
+ if (!keys) keys = inst.options.stateManagement.stateKeys; // if called by user
+ if ($.isArray(keys)) keys = keys.join(",");
+ // convert keys to an array and change delimiters from '__' to '.'
+ keys = keys.replace(/__/g, ".").split(',');
+ // loop keys and create a data hash
+ for (var i=0, n=keys.length; i < n; i++) {
+ pair = keys[i].split(".");
+ pane = pair[0];
+ key = pair[1];
+ if ($.inArray(pane, panes) < 0) continue; // bad pane!
+ val = state[ pane ][ key ];
+ if (val == undefined) continue;
+ if (key=="isClosed" && state[pane]["isSliding"])
+ val = true; // if sliding, then *really* isClosed
+ ( data[pane] || (data[pane]={}) )[ alt[key] ? alt[key] : key ] = val;
+ }
+ return data;
+ }
+
+ /**
+ * Stringify a JSON hash so can save in a cookie or db-field
+ */
+, encodeJSON: function (JSON) {
+ return parse(JSON);
+ function parse (h) {
+ var D=[], i=0, k, v, t; // k = key, v = value
+ for (k in h) {
+ v = h[k];
+ t = typeof v;
+ if (t == 'string') // STRING - add quotes
+ v = '"'+ v +'"';
+ else if (t == 'object') // SUB-KEY - recurse into it
+ v = parse(v);
+ D[i++] = '"'+ k +'":'+ v;
+ }
+ return '{'+ D.join(',') +'}';
+ };
+ }
+
+ /**
+ * Convert stringified JSON back to a hash object
+ * @see $.parseJSON(), adding in jQuery 1.4.1
+ */
+, decodeJSON: function (str) {
+ try { return $.parseJSON ? $.parseJSON(str) : window["eval"]("("+ str +")") || {}; }
+ catch (e) { return {}; }
+ }
+
+
+, _create: function (inst) {
+ var _ = $.layout.state;
+ // ADD State-Management plugin methods to inst
+ $.extend( inst, {
+ // readCookie - update options from cookie - returns hash of cookie data
+ readCookie: function () { return _.readCookie(inst); }
+ // deleteCookie
+ , deleteCookie: function () { _.deleteCookie(inst); }
+ // saveCookie - optionally pass keys-list and cookie-options (hash)
+ , saveCookie: function (keys, cookieOpts) { return _.saveCookie(inst, keys, cookieOpts); }
+ // loadCookie - readCookie and use to loadState() - returns hash of cookie data
+ , loadCookie: function () { return _.loadCookie(inst); }
+ // loadState - pass a hash of state to use to update options
+ , loadState: function (stateData, animate) { _.loadState(inst, stateData, animate); }
+ // readState - returns hash of current layout-state
+ , readState: function (keys) { return _.readState(inst, keys); }
+ // add JSON utility methods too...
+ , encodeJSON: _.encodeJSON
+ , decodeJSON: _.decodeJSON
+ });
+
+ // init state.stateData key, even if plugin is initially disabled
+ inst.state.stateData = {};
+
+ // read and load cookie-data per options
+ var oS = inst.options.stateManagement;
+ if (oS.enabled) {
+ if (oS.autoLoad) // update the options from the cookie
+ inst.loadCookie();
+ else // don't modify options - just store cookie data in state.stateData
+ inst.state.stateData = inst.readCookie();
+ }
+ }
+
+, _unload: function (inst) {
+ var oS = inst.options.stateManagement;
+ if (oS.enabled) {
+ if (oS.autoSave) // save a state-cookie automatically
+ inst.saveCookie();
+ else // don't save a cookie, but do store state-data in state.stateData key
+ inst.state.stateData = inst.readState();
+ }
+ }
+
+};
+
+// add state initialization method to Layout's onCreate array of functions
+$.layout.onCreate.push( $.layout.state._create );
+$.layout.onUnload.push( $.layout.state._unload );
+
+
+
+
+/**
+ * jquery.layout.buttons 1.0
+ * $Date: 2011-07-16 08:00:00 (Sat, 16 July 2011) $
+ *
+ * Copyright (c) 2010
+ * Kevin Dalman (http://allpro.net)
+ *
+ * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
+ * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
+ *
+ * @dependancies: UI Layout 1.3.0.rc30.1 or higher
+ *
+ * @support: http://groups.google.com/group/jquery-ui-layout
+ *
+ * Docs: [ to come ]
+ * Tips: [ to come ]
+ */
+
+// tell Layout that the state plugin is available
+$.layout.plugins.buttons = true;
+
+// Add buttons options to layout.defaults
+$.layout.defaults.autoBindCustomButtons = false;
+// Specify autoBindCustomButtons as a layout-option, NOT a pane-option
+$.layout.optionsMap.layout.push("autoBindCustomButtons");
+
+var lang = $.layout.language;
+
+/*
+ * Button methods
+ */
+$.layout.buttons = {
+
+ /**
+ * Searches for .ui-layout-button-xxx elements and auto-binds them as layout-buttons
+ *
+ * @see _create()
+ *
+ * @param {Object} inst Layout Instance object
+ */
+ init: function (inst) {
+ var pre = "ui-layout-button-"
+ , layout = inst.options.name || ""
+ , name;
+ $.each("toggle,open,close,pin,toggle-slide,open-slide".split(","), function (i, action) {
+ $.each($.layout.config.borderPanes, function (ii, pane) {
+ $("."+pre+action+"-"+pane).each(function(){
+ // if button was previously 'bound', data.layoutName was set, but is blank if layout has no 'name'
+ name = $(this).data("layoutName") || $(this).attr("layoutName");
+ if (name == undefined || name === layout)
+ inst.bindButton(this, action, pane);
+ });
+ });
+ });
+ }
+
+ /**
+ * Helper function to validate params received by addButton utilities
+ *
+ * Two classes are added to the element, based on the buttonClass...
+ * The type of button is appended to create the 2nd className:
+ * - ui-layout-button-pin // action btnClass
+ * - ui-layout-button-pin-west // action btnClass + pane
+ * - ui-layout-button-toggle
+ * - ui-layout-button-open
+ * - ui-layout-button-close
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
+ * @param {string} pane Name of the pane the button is for: 'north', 'south', etc.
+ *
+ * @return {Array.<Object>} If both params valid, the element matching 'selector' in a jQuery wrapper - otherwise returns null
+ */
+, get: function (inst, selector, pane, action) {
+ var $E = $(selector)
+ , o = inst.options
+ , err = o.showErrorMessages
+ ;
+ if (!$E.length) { // element not found
+ if (err) $.layout.msg(lang.errButton + lang.selector +": "+ selector, true);
+ }
+ else if ($.inArray(pane, $.layout.config.borderPanes) < 0) { // invalid 'pane' sepecified
+ if (err) $.layout.msg(lang.errButton + lang.pane +": "+ pane, true);
+ $E = $(""); // NO BUTTON
+ }
+ else { // VALID
+ var btn = o[pane].buttonClass +"-"+ action;
+ $E .addClass( btn +" "+ btn +"-"+ pane )
+ .data("layoutName", o.name); // add layout identifier - even if blank!
+ }
+ return $E;
+ }
+
+
+ /**
+ * NEW syntax for binding layout-buttons - will eventually replace addToggle, addOpen, etc.
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
+ * @param {string} action
+ * @param {string} pane
+ */
+, bind: function (inst, selector, action, pane) {
+ var _ = $.layout.buttons;
+ switch (action.toLowerCase()) {
+ case "toggle": _.addToggle (inst, selector, pane); break;
+ case "open": _.addOpen (inst, selector, pane); break;
+ case "close": _.addClose (inst, selector, pane); break;
+ case "pin": _.addPin (inst, selector, pane); break;
+ case "toggle-slide": _.addToggle (inst, selector, pane, true); break;
+ case "open-slide": _.addOpen (inst, selector, pane, true); break;
+ }
+ return inst;
+ }
+
+ /**
+ * Add a custom Toggler button for a pane
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
+ * @param {string} pane Name of the pane the button is for: 'north', 'south', etc.
+ * @param {boolean=} slide true = slide-open, false = pin-open
+ */
+, addToggle: function (inst, selector, pane, slide) {
+ $.layout.buttons.get(inst, selector, pane, "toggle")
+ .click(function(evt){
+ inst.toggle(pane, !!slide);
+ evt.stopPropagation();
+ });
+ return inst;
+ }
+
+ /**
+ * Add a custom Open button for a pane
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
+ * @param {string} pane Name of the pane the button is for: 'north', 'south', etc.
+ * @param {boolean=} slide true = slide-open, false = pin-open
+ */
+, addOpen: function (inst, selector, pane, slide) {
+ $.layout.buttons.get(inst, selector, pane, "open")
+ .attr("title", lang.Open)
+ .click(function (evt) {
+ inst.open(pane, !!slide);
+ evt.stopPropagation();
+ });
+ return inst;
+ }
+
+ /**
+ * Add a custom Close button for a pane
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
+ * @param {string} pane Name of the pane the button is for: 'north', 'south', etc.
+ */
+, addClose: function (inst, selector, pane) {
+ $.layout.buttons.get(inst, selector, pane, "close")
+ .attr("title", lang.Close)
+ .click(function (evt) {
+ inst.close(pane);
+ evt.stopPropagation();
+ });
+ return inst;
+ }
+
+ /**
+ * Add a custom Pin button for a pane
+ *
+ * Four classes are added to the element, based on the paneClass for the associated pane...
+ * Assuming the default paneClass and the pin is 'up', these classes are added for a west-pane pin:
+ * - ui-layout-pane-pin
+ * - ui-layout-pane-west-pin
+ * - ui-layout-pane-pin-up
+ * - ui-layout-pane-west-pin-up
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {(string|!Object)} selector jQuery selector (or element) for button, eg: ".ui-layout-north .toggle-button"
+ * @param {string} pane Name of the pane the pin is for: 'north', 'south', etc.
+ */
+, addPin: function (inst, selector, pane) {
+ var _ = $.layout.buttons
+ , $E = _.get(inst, selector, pane, "pin");
+ if ($E.length) {
+ var s = inst.state[pane];
+ $E.click(function (evt) {
+ _.setPinState(inst, $(this), pane, (s.isSliding || s.isClosed));
+ if (s.isSliding || s.isClosed) inst.open( pane ); // change from sliding to open
+ else inst.close( pane ); // slide-closed
+ evt.stopPropagation();
+ });
+ // add up/down pin attributes and classes
+ _.setPinState(inst, $E, pane, (!s.isClosed && !s.isSliding));
+ // add this pin to the pane data so we can 'sync it' automatically
+ // PANE.pins key is an array so we can store multiple pins for each pane
+ s.pins.push( selector ); // just save the selector string
+ }
+ return inst;
+ }
+
+ /**
+ * Change the class of the pin button to make it look 'up' or 'down'
+ *
+ * @see addPin(), syncPins()
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {Array.<Object>} $Pin The pin-span element in a jQuery wrapper
+ * @param {string} pane These are the params returned to callbacks by layout()
+ * @param {boolean} doPin true = set the pin 'down', false = set it 'up'
+ */
+, setPinState: function (inst, $Pin, pane, doPin) {
+ var updown = $Pin.attr("pin");
+ if (updown && doPin === (updown=="down")) return; // already in correct state
+ var
+ pin = inst.options[pane].buttonClass +"-pin"
+ , side = pin +"-"+ pane
+ , UP = pin +"-up "+ side +"-up"
+ , DN = pin +"-down "+side +"-down"
+ ;
+ $Pin
+ .attr("pin", doPin ? "down" : "up") // logic
+ .attr("title", doPin ? lang.Unpin : lang.Pin)
+ .removeClass( doPin ? UP : DN )
+ .addClass( doPin ? DN : UP )
+ ;
+ }
+
+ /**
+ * INTERNAL function to sync 'pin buttons' when pane is opened or closed
+ * Unpinned means the pane is 'sliding' - ie, over-top of the adjacent panes
+ *
+ * @see open(), close()
+ *
+ * @param {Object} inst Layout Instance object
+ * @param {string} pane These are the params returned to callbacks by layout()
+ * @param {boolean} doPin True means set the pin 'down', False means 'up'
+ */
+, syncPinBtns: function (inst, pane, doPin) {
+ // REAL METHOD IS _INSIDE_ LAYOUT - THIS IS HERE JUST FOR REFERENCE
+ $.each(state[pane].pins, function (i, selector) {
+ $.layout.buttons.setPinState(inst, $(selector), pane, doPin);
+ });
+ }
+
+
+, _load: function (inst) {
+ var _ = $.layout.buttons;
+ // ADD Button methods to Layout Instance
+ // Note: sel = jQuery Selector string
+ $.extend( inst, {
+ bindButton: function (sel, action, pane) { return _.bind(inst, sel, action, pane); }
+ // DEPRECATED METHODS
+ , addToggleBtn: function (sel, pane, slide) { return _.addToggle(inst, sel, pane, slide); }
+ , addOpenBtn: function (sel, pane, slide) { return _.addOpen(inst, sel, pane, slide); }
+ , addCloseBtn: function (sel, pane) { return _.addClose(inst, sel, pane); }
+ , addPinBtn: function (sel, pane) { return _.addPin(inst, sel, pane); }
+ });
+
+ // init state array to hold pin-buttons
+ for (var i=0; i<4; i++) {
+ var pane = $.layout.config.borderPanes[i];
+ inst.state[pane].pins = [];
+ }
+
+ // auto-init buttons onLoad if option is enabled
+ if ( inst.options.autoBindCustomButtons )
+ _.init(inst);
+ }
+
+, _unload: function (inst) {
+ // TODO: unbind all buttons???
+ }
+
+};
+
+// add initialization method to Layout's onLoad array of functions
+$.layout.onLoad.push( $.layout.buttons._load );
+//$.layout.onUnload.push( $.layout.buttons._unload );
+
+
+
+/**
+ * jquery.layout.browserZoom 1.0
+ * $Date: 2011-12-29 08:00:00 (Thu, 29 Dec 2011) $
+ *
+ * Copyright (c) 2012
+ * Kevin Dalman (http://allpro.net)
+ *
+ * Dual licensed under the GPL (http://www.gnu.org/licenses/gpl.html)
+ * and MIT (http://www.opensource.org/licenses/mit-license.php) licenses.
+ *
+ * @dependancies: UI Layout 1.3.0.rc30.1 or higher
+ *
+ * @support: http://groups.google.com/group/jquery-ui-layout
+ *
+ * @todo: Extend logic to handle other problematic zooming in browsers
+ * @todo: Add hotkey/mousewheel bindings to _instantly_ respond to these zoom event
+ */
+
+// tell Layout that the plugin is available
+$.layout.plugins.browserZoom = true;
+
+$.layout.defaults.browserZoomCheckInterval = 1000;
+$.layout.optionsMap.layout.push("browserZoomCheckInterval");
+
+/*
+ * browserZoom methods
*/
-(function($){$.fn.layout=function(opts){var lang={Pane:"Pane",Open:"Open",Close:"Close",Resize:"Resize",Slide:"Slide Open",Pin:"Pin",Unpin:"Un-Pin",selector:"selector",msgNoRoom:"Not enough room to show this pane.",errContainerMissing:"UI Layout Initialization Error\n\nThe specified layout-container does not exist.",errCenterPaneMissing:"UI Layout Initialization Error\n\nThe center-pane element does not exist.\n\nThe center-pane is a required element.",errContainerHeight:"UI Layout Initialization Warning\n\nThe layout-container \"CONTAINER\" has no height.\n\nTherefore the layout is 0-height and hence 'invisible'!",errButton:"Error Adding Button \n\nInvalid "};var options={name:"",scrollToBookmarkOnLoad:true,resizeWithWindow:true,resizeWithWindowDelay:200,resizeWithWindowMaxDelay:0,onresizeall_start:null,onresizeall_end:null,onload:null,onunload:null,autoBindCustomButtons:false,zIndex:null,defaults:{applyDemoStyles:false,closable:true,resizable:true,slidable:true,initClosed:false,initHidden:false,contentSelector:".ui-layout-content",contentIgnoreSelector:".ui-layout-ignore",findNestedContent:false,paneClass:"ui-layout-pane",resizerClass:"ui-layout-resizer",togglerClass:"ui-layout-toggler",buttonClass:"ui-layout-button",minSize:0,maxSize:0,spacing_open:6,spacing_closed:6,togglerLength_open:50,togglerLength_closed:50,togglerAlign_open:"center",togglerAlign_closed:"center",togglerTip_open:lang.Close,togglerTip_closed:lang.Open,togglerContent_open:"",togglerContent_closed:"",resizerDblClickToggle:true,autoResize:true,autoReopen:true,resizerDragOpacity:1,maskIframesOnResize:true,resizeNestedLayout:true,resizeWhileDragging:false,resizeContentWhileDragging:false,noRoomToOpenTip:lang.msgNoRoom,resizerTip:lang.Resize,sliderTip:lang.Slide,sliderCursor:"pointer",slideTrigger_open:"click",slideTrigger_close:"mouseleave",hideTogglerOnSlide:false,preventQuickSlideClose:!!($.browser.webkit||$.browser.safari),showOverflowOnHover:false,enableCursorHotkey:true,customHotkeyModifier:"SHIFT",fxName:"slide",fxSpeed:null,fxSettings:{},fxOpacityFix:true,triggerEventsOnLoad:false,triggerEventsWhileDragging:true,onshow_start:null,onshow_end:null,onhide_start:null,onhide_end:null,onopen_start:null,onopen_end:null,onclose_start:null,onclose_end:null,onresize_start:null,onresize_end:null,onsizecontent_start:null,onsizecontent_end:null,onswap_start:null,onswap_end:null,ondrag_start:null,ondrag_end:null},north:{paneSelector:".ui-layout-north",size:"auto",resizerCursor:"n-resize",customHotkey:""},south:{paneSelector:".ui-layout-south",size:"auto",resizerCursor:"s-resize",customHotkey:""},east:{paneSelector:".ui-layout-east",size:200,resizerCursor:"e-resize",customHotkey:""},west:{paneSelector:".ui-layout-west",size:200,resizerCursor:"w-resize",customHotkey:""},center:{paneSelector:".ui-layout-center",minWidth:0,minHeight:0},useStateCookie:false,cookie:{name:"",autoSave:true,autoLoad:true,domain:"",path:"",expires:"",secure:false,keys:"north.size,south.size,east.size,west.size,north.isClosed,south.isClosed,east.isClosed,west.isClosed,north.isHidden,south.isHidden,east.isHidden,west.isHidden"}};var effects={slide:{all:{duration:"fast"},north:{direction:"up"},south:{direction:"down"},east:{direction:"right"},west:{direction:"left"}},drop:{all:{duration:"slow"},north:{direction:"up"},south:{direction:"down"},east:{direction:"right"},west:{direction:"left"}},scale:{all:{duration:"fast"}}};var state={id:"layout"+new Date().getTime(),initialized:false,container:{},north:{},south:{},east:{},west:{},center:{},cookie:{}};var _c={allPanes:"north,south,west,east,center",borderPanes:"north,south,west,east",altSide:{north:"south",south:"north",east:"west",west:"east"},hidden:{visibility:"hidden"},visible:{visibility:"visible"},zIndex:{pane_normal:1,resizer_normal:2,iframe_mask:2,pane_sliding:100,pane_animate:1000,resizer_drag:10000},resizers:{cssReq:{position:"absolute",padding:0,margin:0,fontSize:"1px",textAlign:"left",overflow:"hidden"},cssDemo:{background:"#DDD",border:"none"}},togglers:{cssReq:{position:"absolute",display:"block",padding:0,margin:0,overflow:"hidden",textAlign:"center",fontSize:"1px",cursor:"pointer",zIndex:1},cssDemo:{background:"#AAA"}},content:{cssReq:{position:"relative"},cssDemo:{overflow:"auto",padding:"10px"},cssDemoPane:{overflow:"hidden",padding:0}},panes:{cssReq:{position:"absolute",margin:0},cssDemo:{padding:"10px",background:"#FFF",border:"1px solid #BBB",overflow:"auto"}},north:{side:"Top",sizeType:"Height",dir:"horz",cssReq:{top:0,bottom:"auto",left:0,right:0,width:"auto"},pins:[]},south:{side:"Bottom",sizeType:"Height",dir:"horz",cssReq:{top:"auto",bottom:0,left:0,right:0,width:"auto"},pins:[]},east:{side:"Right",sizeType:"Width",dir:"vert",cssReq:{left:"auto",right:0,top:"auto",bottom:"auto",height:"auto"},pins:[]},west:{side:"Left",sizeType:"Width",dir:"vert",cssReq:{left:0,right:"auto",top:"auto",bottom:"auto",height:"auto"},pins:[]},center:{dir:"center",cssReq:{left:"auto",right:"auto",top:"auto",bottom:"auto",height:"auto",width:"auto"}}};var timer={data:{},set:function(s,fn,ms){timer.clear(s);timer.data[s]=setTimeout(fn,ms)},clear:function(s){var t=timer.data;if(t[s]){clearTimeout(t[s]);delete t[s]}}};var isStr=function(o){try{return typeof o=="string"||(typeof o=="object"&&o.constructor.toString().match(/string/i)!==null)}catch(e){return false}};var str=function(o){return isStr(o)?$.trim(o):o==undefined||o==null?"":o};var min=function(x,y){return Math.min(x,y)};var max=function(x,y){return Math.max(x,y)};var _transformData=function(d){var a,json={cookie:{},defaults:{fxSettings:{}},north:{fxSettings:{}},south:{fxSettings:{}},east:{fxSettings:{}},west:{fxSettings:{}},center:{fxSettings:{}}};d=d||{};if(d.effects||d.cookie||d.defaults||d.north||d.south||d.west||d.east||d.center){json=$.extend(true,json,d)}else{$.each(d,function(key,val){a=key.split("__");if(!a[1]||json[a[0]]){json[a[1]?a[0]:"defaults"][a[1]?a[1]:a[0]]=val}})}return json};var _queue=function(action,pane,param){var tried=[];$.each(_c.borderPanes.split(","),function(i,p){if(_c[p].isMoving){bindCallback(p);return false}});function bindCallback(p){var c=_c[p];if(!c.doCallback){c.doCallback=true;c.callback=action+","+pane+","+(param?1:0)}else{tried.push(p);var cbPane=c.callback.split(",")[1];if(cbPane!=pane&&!$.inArray(cbPane,tried)>=0){bindCallback(cbPane)}}}};var _dequeue=function(pane){var c=_c[pane];_c.isLayoutBusy=false;delete c.isMoving;if(!c.doCallback||!c.callback){return}c.doCallback=false;var cb=c.callback.split(","),param=(cb[2]>0?true:false);if(cb[0]=="open"){open(cb[1],param)}else{if(cb[0]=="close"){close(cb[1],param)}}if(!c.doCallback){c.callback=null}};var _execCallback=function(pane,v_fn){if(!v_fn){return}var fn;try{if(typeof v_fn=="function"){fn=v_fn}else{if(!isStr(v_fn)){return}else{if(v_fn.match(/,/)){var args=v_fn.split(","),fn=eval(args[0]);if(typeof fn=="function"&&args.length>1){return fn(args[1])}}else{fn=eval(v_fn)}}}if(typeof fn=="function"){if(pane&&$Ps[pane]){return fn(pane,$Ps[pane],$.extend({},state[pane]),options[pane],options.name)}else{return fn(Instance,$.extend({},state),options,options.name)}}}catch(ex){}};var _showInvisibly=function($E,force){if(!$E){return{}}if(!$E.jquery){$E=$($E)}var CSS={display:$E.css("display"),visibility:$E.css("visibility")};if(force||CSS.display=="none"){$E.css({display:"block",visibility:"hidden"});return CSS}else{return{}}};var _fixIframe=function(pane){if(state.browser.mozilla){return}var $P=$Ps[pane];if(state[pane].tagName=="IFRAME"){$P.css(_c.hidden).css(_c.visible)}else{$P.find("IFRAME").css(_c.hidden).css(_c.visible)}};var _cssNum=function($E,prop){if(!$E.jquery){$E=$($E)}var CSS=_showInvisibly($E);var val=parseInt($.curCSS($E[0],prop,true),10)||0;$E.css(CSS);return val};var _borderWidth=function(E,side){if(E.jquery){E=E[0]}var b="border"+side.substr(0,1).toUpperCase()+side.substr(1);return $.curCSS(E,b+"Style",true)=="none"?0:(parseInt($.curCSS(E,b+"Width",true),10)||0)};var cssW=function(el,outerWidth){var str=isStr(el),$E=str?$Ps[el]:$(el);if(isNaN(outerWidth)){outerWidth=str?getPaneSize(el):$E.outerWidth()}if(outerWidth<=0){return 0}if(!state.browser.boxModel){return outerWidth}var W=outerWidth-_borderWidth($E,"Left")-_borderWidth($E,"Right")-_cssNum($E,"paddingLeft")-_cssNum($E,"paddingRight");return W>0?W:0};var cssH=function(el,outerHeight){var str=isStr(el),$E=str?$Ps[el]:$(el);if(isNaN(outerHeight)){outerHeight=str?getPaneSize(el):$E.outerHeight()}if(outerHeight<=0){return 0}if(!state.browser.boxModel){return outerHeight}var H=outerHeight-_borderWidth($E,"Top")-_borderWidth($E,"Bottom")-_cssNum($E,"paddingTop")-_cssNum($E,"paddingBottom");return H>0?H:0};var cssSize=function(pane,outerSize){if(_c[pane].dir=="horz"){return cssH(pane,outerSize)}else{return cssW(pane,outerSize)}};var cssMinDims=function(pane){var dir=_c[pane].dir,d={minWidth:1001-cssW(pane,1000),minHeight:1001-cssH(pane,1000)};if(dir=="horz"){d.minSize=d.minHeight}if(dir=="vert"){d.minSize=d.minWidth}return d};var setOuterWidth=function(el,outerWidth,autoHide){var $E=el,w;if(isStr(el)){$E=$Ps[el]}else{if(!el.jquery){$E=$(el)}}w=cssW($E,outerWidth);$E.css({width:w});if(w>0){if(autoHide&&$E.data("autoHidden")&&$E.innerHeight()>0){$E.show().data("autoHidden",false);if(!state.browser.mozilla){$E.css(_c.hidden).css(_c.visible)}}}else{if(autoHide&&!$E.data("autoHidden")){$E.hide().data("autoHidden",true)}}};var setOuterHeight=function(el,outerHeight,autoHide){var $E=el,h;if(isStr(el)){$E=$Ps[el]}else{if(!el.jquery){$E=$(el)}}h=cssH($E,outerHeight);$E.css({height:h,visibility:"visible"});if(h>0&&$E.innerWidth()>0){if(autoHide&&$E.data("autoHidden")){$E.show().data("autoHidden",false);if(!state.browser.mozilla){$E.css(_c.hidden).css(_c.visible)}}}else{if(autoHide&&!$E.data("autoHidden")){$E.hide().data("autoHidden",true)}}};var setOuterSize=function(el,outerSize,autoHide){if(_c[pane].dir=="horz"){setOuterHeight(el,outerSize,autoHide)}else{setOuterWidth(el,outerSize,autoHide)}};var _parseSize=function(pane,size,dir){if(!dir){dir=_c[pane].dir}if(isStr(size)&&size.match(/%/)){size=parseInt(size)/100}if(size===0){return 0}else{if(size>=1){return parseInt(size,10)}else{if(size>0){var o=options,avail;if(dir=="horz"){avail=sC.innerHeight-($Ps.north?o.north.spacing_open:0)-($Ps.south?o.south.spacing_open:0)}else{if(dir=="vert"){avail=sC.innerWidth-($Ps.west?o.west.spacing_open:0)-($Ps.east?o.east.spacing_open:0)}}return Math.floor(avail*size)}else{if(pane=="center"){return 0}else{var $P=$Ps[pane],dim=(dir=="horz"?"height":"width"),vis=_showInvisibly($P),s=$P.css(dim);$P.css(dim,"auto");size=(dim=="height")?$P.outerHeight():$P.outerWidth();$P.css(dim,s).css(vis);return size}}}}};var getPaneSize=function(pane,inclSpace){var $P=$Ps[pane],o=options[pane],s=state[pane],oSp=(inclSpace?o.spacing_open:0),cSp=(inclSpace?o.spacing_closed:0);if(!$P||s.isHidden){return 0}else{if(s.isClosed||(s.isSliding&&inclSpace)){return cSp}else{if(_c[pane].dir=="horz"){return $P.outerHeight()+oSp}else{return $P.outerWidth()+oSp}}}};var setSizeLimits=function(pane,slide){var o=options[pane],s=state[pane],c=_c[pane],dir=c.dir,side=c.side.toLowerCase(),type=c.sizeType.toLowerCase(),isSliding=(slide!=undefined?slide:s.isSliding),$P=$Ps[pane],paneSpacing=o.spacing_open,altPane=_c.altSide[pane],altS=state[altPane],$altP=$Ps[altPane],altPaneSize=(!$altP||altS.isVisible===false||altS.isSliding?0:(dir=="horz"?$altP.outerHeight():$altP.outerWidth())),altPaneSpacing=((!$altP||altS.isHidden?0:options[altPane][altS.isClosed!==false?"spacing_closed":"spacing_open"])||0),containerSize=(dir=="horz"?sC.innerHeight:sC.innerWidth),minCenterDims=cssMinDims("center"),minCenterSize=dir=="horz"?max(options.center.minHeight,minCenterDims.minHeight):max(options.center.minWidth,minCenterDims.minWidth),limitSize=(containerSize-paneSpacing-(isSliding?0:(_parseSize("center",minCenterSize,dir)+altPaneSize+altPaneSpacing))),minSize=s.minSize=max(_parseSize(pane,o.minSize),cssMinDims(pane).minSize),maxSize=s.maxSize=min((o.maxSize?_parseSize(pane,o.maxSize):100000),limitSize),r=s.resizerPosition={},top=sC.insetTop,left=sC.insetLeft,W=sC.innerWidth,H=sC.innerHeight,rW=o.spacing_open;switch(pane){case"north":r.min=top+minSize;r.max=top+maxSize;break;case"west":r.min=left+minSize;r.max=left+maxSize;break;case"south":r.min=top+H-maxSize-rW;r.max=top+H-minSize-rW;break;case"east":r.min=left+W-maxSize-rW;r.max=left+W-minSize-rW;break}};var calcNewCenterPaneDims=function(){var d={top:getPaneSize("north",true),bottom:getPaneSize("south",true),left:getPaneSize("west",true),right:getPaneSize("east",true),width:0,height:0};with(d){width=sC.innerWidth-left-right;height=sC.innerHeight-bottom-top;top+=sC.insetTop;bottom+=sC.insetBottom;left+=sC.insetLeft;right+=sC.insetRight}return d};var getElemDims=function($E){var d={},x=d.css={},i={},b,p,off=$E.offset();d.offsetLeft=off.left;d.offsetTop=off.top;$.each("Left,Right,Top,Bottom".split(","),function(idx,e){b=x["border"+e]=_borderWidth($E,e);p=x["padding"+e]=_cssNum($E,"padding"+e);i[e]=b+p;d["inset"+e]=p});d.offsetWidth=$E.innerWidth(true);d.offsetHeight=$E.innerHeight(true);d.outerWidth=$E.outerWidth();d.outerHeight=$E.outerHeight();d.innerWidth=d.outerWidth-i.Left-i.Right;d.innerHeight=d.outerHeight-i.Top-i.Bottom;x.width=$E.width();x.height=$E.height();return d};var getElemCSS=function($E,list){var CSS={},style=$E[0].style,props=list.split(","),sides="Top,Bottom,Left,Right".split(","),attrs="Color,Style,Width".split(","),p,s,a,i,j,k;for(i=0;i<props.length;i++){p=props[i];if(p.match(/(border|padding|margin)$/)){for(j=0;j<4;j++){s=sides[j];if(p=="border"){for(k=0;k<3;k++){a=attrs[k];CSS[p+s+a]=style[p+s+a]}}else{CSS[p+s]=style[p+s]}}}else{CSS[p]=style[p]}}return CSS};var getHoverClasses=function(el,allStates){var $El=$(el),type=$El.data("layoutRole"),pane=$El.data("layoutEdge"),o=options[pane],root=o[type+"Class"],_pane="-"+pane,_open="-open",_closed="-closed",_slide="-sliding",_hover="-hover ",_state=$El.hasClass(root+_closed)?_closed:_open,_alt=_state==_closed?_open:_closed,classes=(root+_hover)+(root+_pane+_hover)+(root+_state+_hover)+(root+_pane+_state+_hover);if(allStates){classes+=(root+_alt+_hover)+(root+_pane+_alt+_hover)}if(type=="resizer"&&$El.hasClass(root+_slide)){classes+=(root+_slide+_hover)+(root+_pane+_slide+_hover)}return $.trim(classes)};var addHover=function(evt,el){var e=el||this;$(e).addClass(getHoverClasses(e))};var removeHover=function(evt,el){var e=el||this;$(e).removeClass(getHoverClasses(e,true))};var onResizerEnter=function(evt){$("body").disableSelection();addHover(evt,this)};var onResizerLeave=function(evt,el){var e=el||this,pane=$(e).data("layoutEdge"),name=pane+"ResizerLeave";timer.clear(name);if(!el){removeHover(evt,this);timer.set(name,function(){onResizerLeave(evt,e)},200)}else{if(!state[pane].isResizing){$("body").enableSelection()}}};var _create=function(){initOptions();var o=options;if(false===_execCallback(null,o.onload)){return false}if(!getPane("center").length){alert(lang.errCenterPaneMissing);return null}if(o.useStateCookie&&o.cookie.autoLoad){loadCookie()}state.browser={mozilla:$.browser.mozilla,webkit:$.browser.webkit||$.browser.safari,msie:$.browser.msie,isIE6:$.browser.msie&&$.browser.version==6,boxModel:$.support.boxModel};initContainer();initPanes();initResizable();sizeContent();if(o.scrollToBookmarkOnLoad){with(self.location){if(hash){replace(hash)}}}if(o.autoBindCustomButtons){initButtons()}initHotkeys();if(o.resizeWithWindow&&!$Container.data("layoutRole")){$(window).bind("resize."+sID,windowResize)}$(window).bind("unload."+sID,unload);state.initialized=true};var windowResize=function(){var delay=Number(options.resizeWithWindowDelay)||100;if(delay>0){timer.clear("winResize");timer.set("winResize",function(){timer.clear("winResize");timer.clear("winResizeRepeater");resizeAll()},delay);if(!timer.data.winResizeRepeater){setWindowResizeRepeater()}}};var setWindowResizeRepeater=function(){var delay=Number(options.resizeWithWindowMaxDelay);if(delay>0){timer.set("winResizeRepeater",function(){setWindowResizeRepeater();resizeAll()},delay)}};var unload=function(){var o=options;state.cookie=getState();if(o.useStateCookie&&o.cookie.autoSave){saveCookie()}_execCallback(null,o.onunload)};var initContainer=function(){var $C=$Container,tag=sC.tagName=$C.attr("tagName"),fullPage=(tag=="BODY"),props="position,margin,padding,border",CSS={};sC.selector=$C.selector.split(".slice")[0];sC.ref=tag+"/"+sC.selector;$C.data("layoutContainer",sID).data("layoutName",options.name);if(!$C.data("layoutCSS")){if(fullPage){CSS=$.extend(getElemCSS($C,props),{height:$C.css("height"),overflow:$C.css("overflow"),overflowX:$C.css("overflowX"),overflowY:$C.css("overflowY")});var $H=$("html");$H.data("layoutCSS",{height:"auto",overflow:$H.css("overflow"),overflowX:$H.css("overflowX"),overflowY:$H.css("overflowY")})}else{CSS=getElemCSS($C,props+",top,bottom,left,right,width,height,overflow,overflowX,overflowY")}$C.data("layoutCSS",CSS)}try{if(fullPage){$("html").css({height:"100%",overflow:"hidden",overflowX:"hidden",overflowY:"hidden"});$("body").css({position:"relative",height:"100%",overflow:"hidden",overflowX:"hidden",overflowY:"hidden",margin:0,padding:0,border:"none"})}else{var CSS={overflow:"hidden"},p=$C.css("position"),h=$C.css("height");if(!$C.data("layoutRole")){if(!p||!p.match(/fixed|absolute|relative/)){CSS.position="relative"}}$C.css(CSS);if($C.is(":visible")&&$C.innerHeight()<2){alert(lang.errContainerHeight.replace(/CONTAINER/,sC.ref))}}}catch(ex){}$.extend(state.container,getElemDims($C))};var initHotkeys=function(){$.each(_c.borderPanes.split(","),function(i,pane){var o=options[pane];if(o.enableCursorHotkey||o.customHotkey){$(document).bind("keydown."+sID,keyDown);return false}})};var initOptions=function(){opts=_transformData(opts);var newOpts={applyDefaultStyles:"applyDemoStyles"};renameOpts(opts.defaults);$.each(_c.allPanes.split(","),function(i,pane){renameOpts(opts[pane])});if(opts.effects){$.extend(effects,opts.effects);delete opts.effects}$.extend(options.cookie,opts.cookie);var globals="name,zIndex,scrollToBookmarkOnLoad,resizeWithWindow,resizeWithWindowDelay,resizeWithWindowMaxDelay,onresizeall,onresizeall_start,onresizeall_end,onload,onunload,autoBindCustomButtons,useStateCookie";$.each(globals.split(","),function(i,key){if(opts[key]!==undefined){options[key]=opts[key]}else{if(opts.defaults[key]!==undefined){options[key]=opts.defaults[key];delete opts.defaults[key]}}});$.each("paneSelector,resizerCursor,customHotkey".split(","),function(i,key){delete opts.defaults[key]});$.extend(true,options.defaults,opts.defaults);_c.center=$.extend(true,{},_c.panes,_c.center);var z=options.zIndex;if(z===0||z>0){_c.zIndex.pane_normal=z;_c.zIndex.resizer_normal=z+1;_c.zIndex.iframe_mask=z+1}$.extend(options.center,opts.center);var o_Center=$.extend(true,{},options.defaults,opts.defaults,options.center);var optionsCenter=("paneClass,contentSelector,applyDemoStyles,triggerEventsOnLoad,showOverflowOnHover,onresize,onresize_start,onresize_end,resizeNestedLayout,resizeContentWhileDragging,onsizecontent,onsizecontent_start,onsizecontent_end").split(",");$.each(optionsCenter,function(i,key){options.center[key]=o_Center[key]});var o,defs=options.defaults;$.each(_c.borderPanes.split(","),function(i,pane){_c[pane]=$.extend(true,{},_c.panes,_c[pane]);o=options[pane]=$.extend(true,{},options.defaults,options[pane],opts.defaults,opts[pane]);if(!o.paneClass){o.paneClass="ui-layout-pane"}if(!o.resizerClass){o.resizerClass="ui-layout-resizer"}if(!o.togglerClass){o.togglerClass="ui-layout-toggler"}$.each(["_open","_close",""],function(i,n){var sName="fxName"+n,sSpeed="fxSpeed"+n,sSettings="fxSettings"+n;o[sName]=opts[pane][sName]||opts[pane].fxName||opts.defaults[sName]||opts.defaults.fxName||o[sName]||o.fxName||defs[sName]||defs.fxName||"none";var fxName=o[sName];if(fxName=="none"||!$.effects||!$.effects[fxName]||(!effects[fxName]&&!o[sSettings]&&!o.fxSettings)){fxName=o[sName]="none"}var fx=effects[fxName]||{},fx_all=fx.all||{},fx_pane=fx[pane]||{};o[sSettings]=$.extend({},fx_all,fx_pane,defs.fxSettings||{},defs[sSettings]||{},o.fxSettings,o[sSettings],opts.defaults.fxSettings,opts.defaults[sSettings]||{},opts[pane].fxSettings,opts[pane][sSettings]||{});o[sSpeed]=opts[pane][sSpeed]||opts[pane].fxSpeed||opts.defaults[sSpeed]||opts.defaults.fxSpeed||o[sSpeed]||o[sSettings].duration||o.fxSpeed||o.fxSettings.duration||defs.fxSpeed||defs.fxSettings.duration||fx_pane.duration||fx_all.duration||"normal"})});function renameOpts(O){for(var key in newOpts){if(O[key]!=undefined){O[newOpts[key]]=O[key];delete O[key]}}}};var getPane=function(pane){var sel=options[pane].paneSelector;if(sel.substr(0,1)==="#"){return $Container.find(sel).eq(0)}else{var $P=$Container.children(sel).eq(0);return $P.length?$P:$Container.children("form:first").children(sel).eq(0)}};var initPanes=function(){$.each(_c.allPanes.split(","),function(idx,pane){var o=options[pane],s=state[pane],c=_c[pane],fx=s.fx,dir=c.dir,spacing=o.spacing_open||0,isCenter=(pane=="center"),CSS={},$P,$C,size,minSize,maxSize;$Cs[pane]=false;$P=$Ps[pane]=getPane(pane);if(!$P.length){$Ps[pane]=false;return true}if(!$P.data("layoutCSS")){var props="position,top,left,bottom,right,width,height,overflow,zIndex,display,backgroundColor,padding,margin,border";$P.data("layoutCSS",getElemCSS($P,props))}$P.data("layoutName",options.name).data("layoutRole","pane").data("layoutEdge",pane).css(c.cssReq).css("zIndex",_c.zIndex.pane_normal).css(o.applyDemoStyles?c.cssDemo:{}).addClass(o.paneClass+" "+o.paneClass+"-"+pane).bind("mouseenter."+sID,addHover).bind("mouseleave."+sID,removeHover);initContent(pane,false);if(!isCenter){size=s.size=_parseSize(pane,o.size);minSize=_parseSize(pane,o.minSize)||1;maxSize=_parseSize(pane,o.maxSize)||100000;if(size>0){size=max(min(size,maxSize),minSize)}}s.tagName=$P.attr("tagName");s.edge=pane;s.noRoom=false;s.isVisible=true;if(!isCenter){s.isClosed=false;s.isSliding=false;s.isResizing=false;s.isHidden=false}switch(pane){case"north":CSS.top=sC.insetTop;CSS.left=sC.insetLeft;CSS.right=sC.insetRight;break;case"south":CSS.bottom=sC.insetBottom;CSS.left=sC.insetLeft;CSS.right=sC.insetRight;break;case"west":CSS.left=sC.insetLeft;break;case"east":CSS.right=sC.insetRight;break;case"center":}if(dir=="horz"){CSS.height=max(1,cssH(pane,size))}else{if(dir=="vert"){CSS.width=max(1,cssW(pane,size))}}$P.css(CSS);if(dir!="horz"){sizeMidPanes(pane,true)}$P.css({visibility:"visible",display:"block"});if(o.initClosed&&o.closable){close(pane,true,true)}else{if(o.initHidden||o.initClosed){hide(pane)}}if(o.showOverflowOnHover){$P.hover(allowOverflow,resetOverflow)}});initHandles();$.each(_c.borderPanes.split(","),function(i,pane){if($Ps[pane]&&state[pane].isVisible){setSizeLimits(pane);makePaneFit(pane)}});sizeMidPanes("center");$.each(_c.allPanes.split(","),function(i,pane){var o=options[pane];if($Ps[pane]&&o.triggerEventsOnLoad&&state[pane].isVisible){_execCallback(pane,o.onresize_end||o.onresize)}});if($Container.innerHeight()<2){alert(lang.errContainerHeight.replace(/CONTAINER/,sC.ref))}};var initHandles=function(panes){if(!panes||panes=="all"){panes=_c.borderPanes}$.each(panes.split(","),function(i,pane){var $P=$Ps[pane];$Rs[pane]=false;$Ts[pane]=false;if(!$P){return}var o=options[pane],s=state[pane],c=_c[pane],rClass=o.resizerClass,tClass=o.togglerClass,side=c.side.toLowerCase(),spacing=(s.isVisible?o.spacing_open:o.spacing_closed),_pane="-"+pane,_state=(s.isVisible?"-open":"-closed"),$R=$Rs[pane]=$("<div></div>"),$T=(o.closable?$Ts[pane]=$("<div></div>"):false);if(s.isVisible&&o.resizable){}else{if(!s.isVisible&&o.slidable){$R.attr("title",o.sliderTip).css("cursor",o.sliderCursor)}}$R.attr("id",(o.paneSelector.substr(0,1)=="#"?o.paneSelector.substr(1)+"-resizer":"")).data("layoutRole","resizer").data("layoutEdge",pane).css(_c.resizers.cssReq).css("zIndex",_c.zIndex.resizer_normal).css(o.applyDemoStyles?_c.resizers.cssDemo:{}).addClass(rClass+" "+rClass+_pane).appendTo($Container);if($T){$T.attr("id",(o.paneSelector.substr(0,1)=="#"?o.paneSelector.substr(1)+"-toggler":"")).data("layoutRole","toggler").data("layoutEdge",pane).css(_c.togglers.cssReq).css(o.applyDemoStyles?_c.togglers.cssDemo:{}).addClass(tClass+" "+tClass+_pane).appendTo($R).click(function(evt){toggle(pane);evt.stopPropagation()}).hover(addHover,removeHover);if(o.togglerContent_open){$("<span>"+o.togglerContent_open+"</span>").data("layoutRole","togglerContent").data("layoutEdge",pane).addClass("content content-open").css("display","none").appendTo($T).hover(addHover,removeHover)}if(o.togglerContent_closed){$("<span>"+o.togglerContent_closed+"</span>").data("layoutRole","togglerContent").data("layoutEdge",pane).addClass("content content-closed").css("display","none").appendTo($T).hover(addHover,removeHover)}}if(s.isVisible){setAsOpen(pane)}else{setAsClosed(pane);bindStartSlidingEvent(pane,true)}});sizeHandles("all")};var initContent=function(pane,resize){var o=options[pane],sel=o.contentSelector,$P=$Ps[pane],$C;if(sel){$C=$Cs[pane]=(o.findNestedContent)?$P.find(sel).eq(0):$P.children(sel).eq(0)}if($C&&$C.length){$C.css(_c.content.cssReq);if(o.applyDemoStyles){$C.css(_c.content.cssDemo);$P.css(_c.content.cssDemoPane)}state[pane].content={};if(resize!==false){sizeContent(pane)}}else{$Cs[pane]=false}};var initButtons=function(){var pre="ui-layout-button-",name;$.each("toggle,open,close,pin,toggle-slide,open-slide".split(","),function(i,action){$.each(_c.borderPanes.split(","),function(ii,pane){$("."+pre+action+"-"+pane).each(function(){name=$(this).data("layoutName")||$(this).attr("layoutName");if(name==undefined||name==options.name){if(action.substr("-slide")>0){bindButton(this,action.split("-")[0],pane,true)}else{bindButton(this,action,pane)}}})})})};var initResizable=function(panes){var draggingAvailable=(typeof $.fn.draggable=="function"),$Frames,side;if(!panes||panes=="all"){panes=_c.borderPanes}$.each(panes.split(","),function(idx,pane){var o=options[pane],s=state[pane],c=_c[pane],side=(c.dir=="horz"?"top":"left"),r,live;if(!draggingAvailable||!$Ps[pane]||!o.resizable){o.resizable=false;return true}var $P=$Ps[pane],$R=$Rs[pane],base=o.resizerClass,resizerClass=base+"-drag",resizerPaneClass=base+"-"+pane+"-drag",helperClass=base+"-dragging",helperPaneClass=base+"-"+pane+"-dragging",helperLimitClass=base+"-dragging-limit",helperClassesSet=false;if(!s.isClosed){$R.attr("title",o.resizerTip).css("cursor",o.resizerCursor)}$R.hover(onResizerEnter,onResizerLeave);$R.draggable({containment:$Container[0],axis:(c.dir=="horz"?"y":"x"),delay:0,distance:1,helper:"clone",opacity:o.resizerDragOpacity,addClasses:false,zIndex:_c.zIndex.resizer_drag,start:function(e,ui){o=options[pane];s=state[pane];live=o.resizeWhileDragging;if(false===_execCallback(pane,o.ondrag_start)){return false}_c.isLayoutBusy=true;s.isResizing=true;timer.clear(pane+"_closeSlider");setSizeLimits(pane);r=s.resizerPosition;$R.addClass(resizerClass+" "+resizerPaneClass);helperClassesSet=false;$Frames=$(o.maskIframesOnResize===true?"iframe":o.maskIframesOnResize).filter(":visible");var id,i=0;$Frames.each(function(){id="ui-layout-mask-"+(++i);$(this).data("layoutMaskID",id);$('<div id="'+id+'" class="ui-layout-mask ui-layout-mask-'+pane+'"/>').css({background:"#fff",opacity:"0.001",zIndex:_c.zIndex.iframe_mask,position:"absolute",width:this.offsetWidth+"px",height:this.offsetHeight+"px"}).css($(this).position()).appendTo(this.parentNode)});$("body").disableSelection()},drag:function(e,ui){if(!helperClassesSet){ui.helper.addClass(helperClass+" "+helperPaneClass).children().css("visibility","hidden");helperClassesSet=true;if(s.isSliding){$Ps[pane].css("zIndex",_c.zIndex.pane_sliding)}}var limit=0;if(ui.position[side]<r.min){ui.position[side]=r.min;limit=-1}else{if(ui.position[side]>r.max){ui.position[side]=r.max;limit=1}}if(limit){ui.helper.addClass(helperLimitClass);window.defaultStatus="Panel has reached its "+((limit>0&&pane.match(/north|west/))||(limit<0&&pane.match(/south|east/))?"maximum":"minimum")+" size"}else{ui.helper.removeClass(helperLimitClass);window.defaultStatus=""}if(live){resizePanes(e,ui,pane)}},stop:function(e,ui){$("body").enableSelection();window.defaultStatus="";$R.removeClass(resizerClass+" "+resizerPaneClass+" "+helperLimitClass);s.isResizing=false;_c.isLayoutBusy=false;resizePanes(e,ui,pane,true)}});var resizePanes=function(e,ui,pane,resizingDone){var dragPos=ui.position,c=_c[pane],resizerPos,newSize,i=0;switch(pane){case"north":resizerPos=dragPos.top;break;case"west":resizerPos=dragPos.left;break;case"south":resizerPos=sC.offsetHeight-dragPos.top-o.spacing_open;break;case"east":resizerPos=sC.offsetWidth-dragPos.left-o.spacing_open;break}if(resizingDone){$("div.ui-layout-mask").each(function(){this.parentNode.removeChild(this)});if(false===_execCallback(pane,o.ondrag_end||o.ondrag)){return false}}else{$Frames.each(function(){$("#"+$(this).data("layoutMaskID")).css($(this).position()).css({width:this.offsetWidth+"px",height:this.offsetHeight+"px"})})}newSize=resizerPos-sC["inset"+c.side];manualSizePane(pane,newSize)}})};var destroy=function(){$(window).unbind("."+sID);$(document).unbind("."+sID);window[sID]=null;var fullPage=(sC.tagName=="BODY"),_open="-open",_sliding="-sliding",_closed="-closed",$P,root,pRoot,pClasses;$.each(_c.allPanes.split(","),function(i,pane){$P=$Ps[pane];if(!$P){return true}if(pane!="center"){if($Ts[pane]){$Ts[pane].remove()}$Rs[pane].remove()}root=options[pane].paneClass;pRoot=root+"-"+pane;pClasses=[root,root+_open,root+_closed,root+_sliding,pRoot,pRoot+_open,pRoot+_closed,pRoot+_sliding];$.merge(pClasses,getHoverClasses($P,true));$P.removeClass(pClasses.join(" ")).removeData("layoutRole").removeData("layoutEdge").unbind("."+sID).unbind("mouseenter").unbind("mouseleave");if(!$P.data("layoutContainer")){$P.css($P.data("layoutCSS"))}});$Container.removeData("layoutContainer");if(!$Container.data("layoutEdge")){$Container.css($Container.data("layoutCSS"))}if(fullPage){$("html").css($("html").data("layoutCSS"))}unload();var n=options.name;if(n&&window[n]){window[n]=null}};var hide=function(pane,noAnimation){var o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane];if(!$P||s.isHidden){return}if(state.initialized&&false===_execCallback(pane,o.onhide_start)){return}s.isSliding=false;if($R){$R.hide()}if(!state.initialized||s.isClosed){s.isClosed=true;s.isHidden=true;s.isVisible=false;$P.hide();sizeMidPanes(_c[pane].dir=="horz"?"all":"center");if(state.initialized||o.triggerEventsOnLoad){_execCallback(pane,o.onhide_end||o.onhide)}}else{s.isHiding=true;close(pane,false,noAnimation)}};var show=function(pane,openPane,noAnimation,noAlert){var o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane];if(!$P||!s.isHidden){return}if(false===_execCallback(pane,o.onshow_start)){return}s.isSliding=false;s.isShowing=true;if(openPane===false){close(pane,true)}else{open(pane,false,noAnimation,noAlert)}};var toggle=function(pane,slide){if(!isStr(pane)){pane.stopImmediatePropagation();pane=$(this).data("layoutEdge")}var s=state[str(pane)];if(s.isHidden){show(pane)}else{if(s.isClosed){open(pane,!!slide)}else{close(pane)}}};var _closePane=function(pane,setHandles){var $P=$Ps[pane],s=state[pane];$P.hide();s.isClosed=true;s.isVisible=false};var close=function(pane,force,noAnimation,skipCallback){if(!state.initialized){_closePane(pane);return}var $P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],doFX=!noAnimation&&!s.isClosed&&(o.fxName_close!="none"),isShowing=s.isShowing,isHiding=s.isHiding,wasSliding=s.isSliding;delete s.isShowing;delete s.isHiding;if(!$P||!o.closable){return}else{if(!force&&s.isClosed&&!isShowing){return}}if(_c.isLayoutBusy){_queue("close",pane,force);return}if(!isShowing&&false===_execCallback(pane,o.onclose_start)){return}_c[pane].isMoving=true;_c.isLayoutBusy=true;s.isClosed=true;s.isVisible=false;if(isHiding){s.isHidden=true}else{if(isShowing){s.isHidden=false}}if(s.isSliding){bindStopSlidingEvents(pane,false)}else{sizeMidPanes(_c[pane].dir=="horz"?"all":"center",false)}setAsClosed(pane);if(doFX){lockPaneForFX(pane,true);$P.hide(o.fxName_close,o.fxSettings_close,o.fxSpeed_close,function(){lockPaneForFX(pane,false);close_2()})}else{$P.hide();close_2()}function close_2(){if(s.isClosed){bindStartSlidingEvent(pane,true);var altPane=_c.altSide[pane];if(state[altPane].noRoom){setSizeLimits(altPane);makePaneFit(altPane)}if(!skipCallback&&(state.initialized||o.triggerEventsOnLoad)){if(!isShowing&&!wasSliding){_execCallback(pane,o.onclose_end||o.onclose)}if(isShowing){_execCallback(pane,o.onshow_end||o.onshow)}if(isHiding){_execCallback(pane,o.onhide_end||o.onhide)}}}_dequeue(pane)}};var setAsClosed=function(pane){var $P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],side=_c[pane].side.toLowerCase(),inset="inset"+_c[pane].side,rClass=o.resizerClass,tClass=o.togglerClass,_pane="-"+pane,_open="-open",_sliding="-sliding",_closed="-closed";$R.css(side,sC[inset]).removeClass(rClass+_open+" "+rClass+_pane+_open).removeClass(rClass+_sliding+" "+rClass+_pane+_sliding).addClass(rClass+_closed+" "+rClass+_pane+_closed).unbind("dblclick."+sID);if(o.resizable&&typeof $.fn.draggable=="function"){$R.draggable("disable").removeClass("ui-state-disabled").css("cursor","default").attr("title","")}if($T){$T.removeClass(tClass+_open+" "+tClass+_pane+_open).addClass(tClass+_closed+" "+tClass+_pane+_closed).attr("title",o.togglerTip_closed);$T.children(".content-open").hide();$T.children(".content-closed").css("display","block")}syncPinBtns(pane,false);if(state.initialized){sizeHandles("all")}};var open=function(pane,slide,noAnimation,noAlert){var $P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],doFX=!noAnimation&&s.isClosed&&(o.fxName_open!="none"),isShowing=s.isShowing;delete s.isShowing;if(!$P||(!o.resizable&&!o.closable)){return}else{if(s.isVisible&&!s.isSliding){return}}if(s.isHidden&&!isShowing){show(pane,true);return}if(_c.isLayoutBusy){_queue("open",pane,slide);return}if(false===_execCallback(pane,o.onopen_start)){return}setSizeLimits(pane,slide);if(s.minSize>s.maxSize){syncPinBtns(pane,false);if(!noAlert&&o.noRoomToOpenTip){alert(o.noRoomToOpenTip)}return}_c[pane].isMoving=true;_c.isLayoutBusy=true;if(slide){bindStopSlidingEvents(pane,true)}else{if(s.isSliding){bindStopSlidingEvents(pane,false)}else{if(o.slidable){bindStartSlidingEvent(pane,false)}}}s.noRoom=false;makePaneFit(pane);s.isVisible=true;s.isClosed=false;if(isShowing){s.isHidden=false}if(doFX){lockPaneForFX(pane,true);$P.show(o.fxName_open,o.fxSettings_open,o.fxSpeed_open,function(){lockPaneForFX(pane,false);open_2()})}else{$P.show();open_2()}function open_2(){if(s.isVisible){_fixIframe(pane);if(!s.isSliding){sizeMidPanes(_c[pane].dir=="vert"?"center":"all",false)}setAsOpen(pane)}_dequeue(pane)}};var setAsOpen=function(pane,skipCallback){var $P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],o=options[pane],s=state[pane],side=_c[pane].side.toLowerCase(),inset="inset"+_c[pane].side,rClass=o.resizerClass,tClass=o.togglerClass,_pane="-"+pane,_open="-open",_closed="-closed",_sliding="-sliding";$R.css(side,sC[inset]+getPaneSize(pane)).removeClass(rClass+_closed+" "+rClass+_pane+_closed).addClass(rClass+_open+" "+rClass+_pane+_open);if(s.isSliding){$R.addClass(rClass+_sliding+" "+rClass+_pane+_sliding)}else{$R.removeClass(rClass+_sliding+" "+rClass+_pane+_sliding)}if(o.resizerDblClickToggle){$R.bind("dblclick",toggle)}removeHover(0,$R);if(o.resizable&&typeof $.fn.draggable=="function"){$R.draggable("enable").css("cursor",o.resizerCursor).attr("title",o.resizerTip)}else{if(!s.isSliding){$R.css("cursor","default")}}if($T){$T.removeClass(tClass+_closed+" "+tClass+_pane+_closed).addClass(tClass+_open+" "+tClass+_pane+_open).attr("title",o.togglerTip_open);removeHover(0,$T);$T.children(".content-closed").hide();$T.children(".content-open").css("display","block")}syncPinBtns(pane,!s.isSliding);$.extend(s,getElemDims($P));if(state.initialized){sizeHandles("all");sizeContent(pane,true)}if(!skipCallback&&(state.initialized||o.triggerEventsOnLoad)&&$P.is(":visible")){_execCallback(pane,o.onopen_end||o.onopen);if(s.isShowing){_execCallback(pane,o.onshow_end||o.onshow)}if(state.initialized){_execCallback(pane,o.onresize_end||o.onresize)}}};var slideOpen=function(evt_or_pane){var type=typeof evt_or_pane,pane=(type=="string"?evt_or_pane:$(this).data("layoutEdge"));if(type=="object"){evt_or_pane.stopImmediatePropagation()}if(state[pane].isClosed){open(pane,true)}else{bindStopSlidingEvents(pane,true)}};var slideClose=function(evt_or_pane){var $E=(isStr(evt_or_pane)?$Ps[evt_or_pane]:$(this)),pane=$E.data("layoutEdge"),o=options[pane],s=state[pane],$P=$Ps[pane];if(s.isClosed||s.isResizing){return}else{if(o.slideTrigger_close=="click"){close_NOW()}else{if(o.preventQuickSlideClose&&_c.isLayoutBusy){return}else{timer.set(pane+"_closeSlider",close_NOW,300)}}}function close_NOW(e){if(s.isClosed){bindStopSlidingEvents(pane,false)}else{close(pane)}}};var slideToggle=function(pane){toggle(pane,true)};var lockPaneForFX=function(pane,doLock){var $P=$Ps[pane];if(doLock){$P.css({zIndex:_c.zIndex.pane_animate});if(pane=="south"){$P.css({top:sC.insetTop+sC.innerHeight-$P.outerHeight()})}else{if(pane=="east"){$P.css({left:sC.insetLeft+sC.innerWidth-$P.outerWidth()})}}}else{if(pane=="south"){$P.css({top:"auto"})}else{if(pane=="east"){$P.css({left:"auto"})}}var o=options[pane];if(state.browser.msie&&o.fxOpacityFix&&o.fxName_open!="slide"&&$P.css("filter")&&$P.css("opacity")==1){$P[0].style.removeAttribute("filter")}}};var bindStartSlidingEvent=function(pane,enable){var o=options[pane],z=_c.zIndex,$P=$Ps[pane],$R=$Rs[pane],trigger=o.slideTrigger_open;if(!$R||!o.slidable){return}if(trigger.match(/mouseover/)){trigger=o.slideTrigger_open="mouseenter"}else{if(!trigger.match(/click|dblclick|mouseenter/)){trigger=o.slideTrigger_open="click"}}$R.css("zIndex",!enable?z.pane_sliding:z.resizer_normal);$P.css("zIndex",!enable?z.pane_sliding:z.pane_normal);$R[enable?"bind":"unbind"](trigger+"."+sID,slideOpen).css("cursor",enable?o.sliderCursor:"default").attr("title",enable?o.sliderTip:"")};var bindStopSlidingEvents=function(pane,enable){var o=options[pane],s=state[pane],trigger=o.slideTrigger_close,action=(enable?"bind":"unbind"),$P=$Ps[pane],$R=$Rs[pane];s.isSliding=enable;timer.clear(pane+"_closeSlider");if(enable){bindStartSlidingEvent(pane,false)}if(!trigger.match(/click|mouseleave/)){trigger=o.slideTrigger_close="mouseleave"}$R[action](trigger,slideClose);if(trigger=="mouseleave"){$P[action]("mouseleave."+sID,slideClose);$R[action]("mouseenter."+sID,cancelMouseOut);$P[action]("mouseenter."+sID,cancelMouseOut)}if(!enable){timer.clear(pane+"_closeSlider")}else{if(trigger=="click"&&!o.resizable){$R.css("cursor",enable?o.sliderCursor:"default");$R.attr("title",enable?o.togglerTip_open:"")}}function cancelMouseOut(evt){timer.clear(pane+"_closeSlider");evt.stopPropagation()}};var makePaneFit=function(pane,isOpening,skipCallback,force){var o=options[pane],s=state[pane],c=_c[pane],$P=$Ps[pane],$R=$Rs[pane],isSidePane=c.dir=="vert",hasRoom=false;if(pane=="center"||(isSidePane&&s.noVerticalRoom)){hasRoom=s.minHeight<=s.maxHeight&&(isSidePane||s.minWidth<=s.maxWidth);if(hasRoom&&s.noRoom){$P.show();if($R){$R.show()}s.isVisible=true;s.noRoom=false;if(isSidePane){s.noVerticalRoom=false}_fixIframe(pane)}else{if(!hasRoom&&!s.noRoom){$P.hide();if($R){$R.hide()}s.isVisible=false;s.noRoom=true}}}if(pane=="center"){}else{if(s.minSize<=s.maxSize){hasRoom=true;if(s.size>s.maxSize){sizePane(pane,s.maxSize,skipCallback,force)}else{if(s.size<s.minSize){sizePane(pane,s.minSize,skipCallback,force)}else{if($R&&$P.is(":visible")){var side=c.side.toLowerCase(),pos=s.size+sC["inset"+c.side];if(_cssNum($R,side)!=pos){$R.css(side,pos)}}}}if(s.noRoom){if(s.wasOpen&&o.closable){if(o.autoReopen){open(pane,false,true,true)}else{s.noRoom=false}}else{show(pane,s.wasOpen,true,true)}}}else{if(!s.noRoom){s.noRoom=true;s.wasOpen=!s.isClosed&&!s.isSliding;if(o.closable){close(pane,true,true)}else{hide(pane,true)}}}}};var manualSizePane=function(pane,size,skipCallback){var o=options[pane],forceResize=o.resizeWhileDragging&&!_c.isLayoutBusy;o.autoResize=false;sizePane(pane,size,skipCallback,forceResize)};var sizePane=function(pane,size,skipCallback,force){var o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane],side=_c[pane].side.toLowerCase(),inset="inset"+_c[pane].side,skipResizeWhileDragging=_c.isLayoutBusy&&!o.triggerEventsWhileDragging,oldSize;setSizeLimits(pane);oldSize=s.size;size=_parseSize(pane,size);size=max(size,_parseSize(pane,o.minSize));size=min(size,s.maxSize);if(size<s.minSize){makePaneFit(pane,false,skipCallback);return}if(!force&&size==oldSize){return}if(!skipCallback&&state.initialized&&s.isVisible){_execCallback(pane,o.onresize_start)}$P.css(_c[pane].sizeType.toLowerCase(),max(1,cssSize(pane,size)));s.size=size;$.extend(s,getElemDims($P));if($R&&$P.is(":visible")){$R.css(side,size+sC[inset])}sizeContent(pane);if(!skipCallback&&!skipResizeWhileDragging&&state.initialized&&s.isVisible){_execCallback(pane,o.onresize_end||o.onresize);if(o.resizeNestedLayout&&$P.data("layoutContainer")){$P.layout().resizeAll()}}if(!skipCallback){if(!s.isSliding){sizeMidPanes(_c[pane].dir=="horz"?"all":"center",skipResizeWhileDragging,force)}sizeHandles("all")}var altPane=_c.altSide[pane];if(size<oldSize&&state[altPane].noRoom){setSizeLimits(altPane);makePaneFit(altPane,false,skipCallback)}};var sizeMidPanes=function(panes,skipCallback,force){if(!panes||panes=="all"){panes="east,west,center"}$.each(panes.split(","),function(i,pane){if(!$Ps[pane]){return}var o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane],isCenter=(pane=="center"),hasRoom=true,CSS={},d=calcNewCenterPaneDims();$.extend(s,getElemDims($P));if(pane=="center"){if(!force&&s.isVisible&&d.width==s.outerWidth&&d.height==s.outerHeight){return true}$.extend(s,cssMinDims(pane),{maxWidth:d.width,maxHeight:d.height});CSS=d;CSS.width=cssW(pane,d.width);CSS.height=cssH(pane,d.height);hasRoom=CSS.width>0&&CSS.height>0;if(!hasRoom&&!state.initialized&&o.minWidth>0){var reqPx=o.minWidth-s.outerWidth,minE=options.east.minSize||0,minW=options.west.minSize||0,sizeE=state.east.size,sizeW=state.west.size,newE=sizeE,newW=sizeW;if(reqPx>0&&state.east.isVisible&&sizeE>minE){newE=max(sizeE-minE,sizeE-reqPx);reqPx-=sizeE-newE}if(reqPx>0&&state.west.isVisible&&sizeW>minW){newW=max(sizeW-minW,sizeW-reqPx);reqPx-=sizeW-newW}if(reqPx==0){if(sizeE!=minE){sizePane("east",newE,true)}if(sizeW!=minW){sizePane("west",newW,true)}sizeMidPanes("center",skipCallback,force);return}}}else{$.extend(s,getElemDims($P),cssMinDims(pane));if(!force&&!s.noVerticalRoom&&d.height==s.outerHeight){return true}CSS.top=d.top;CSS.bottom=d.bottom;CSS.height=cssH(pane,d.height);s.maxHeight=max(0,CSS.height);hasRoom=(s.maxHeight>0);if(!hasRoom){s.noVerticalRoom=true}}if(hasRoom){if(!skipCallback&&state.initialized){_execCallback(pane,o.onresize_start)}$P.css(CSS);$.extend(s,getElemDims($P));if(s.noRoom){makePaneFit(pane)}if(state.initialized){sizeContent(pane)}}else{if(!s.noRoom&&s.isVisible){makePaneFit(pane)}}if(pane=="center"){var b=state.browser;var fix=b.isIE6||(b.msie&&!b.boxModel);if($Ps.north&&(fix||state.north.tagName=="IFRAME")){$Ps.north.css("width",cssW($Ps.north,sC.innerWidth))}if($Ps.south&&(fix||state.south.tagName=="IFRAME")){$Ps.south.css("width",cssW($Ps.south,sC.innerWidth))}}if(!skipCallback&&state.initialized&&s.isVisible){_execCallback(pane,o.onresize_end||o.onresize);if(o.resizeNestedLayout&&$P.data("layoutContainer")){$P.layout().resizeAll()}}})};var resizeAll=function(){var oldW=sC.innerWidth,oldH=sC.innerHeight;$.extend(state.container,getElemDims($Container));if(!sC.outerHeight){return}if(false===_execCallback(null,options.onresizeall_start)){return false}var shrunkH=(sC.innerHeight<oldH),shrunkW=(sC.innerWidth<oldW),$P,o,s,dir;$.each(["south","north","east","west"],function(i,pane){if(!$Ps[pane]){return}s=state[pane];o=options[pane];dir=_c[pane].dir;if(o.autoResize&&s.size!=o.size){sizePane(pane,o.size,true,true)}else{setSizeLimits(pane);makePaneFit(pane,false,true,true)}});sizeMidPanes("all",true,true);sizeHandles("all");o=options;$.each(_c.allPanes.split(","),function(i,pane){$P=$Ps[pane];if(!$P){return}if(state[pane].isVisible){_execCallback(pane,o[pane].onresize_end||o[pane].onresize)}if(o[pane].resizeNestedLayout&&$P.data("layoutContainer")){$P.layout().resizeAll()}});_execCallback(null,o.onresizeall_end||o.onresizeall)};var sizeContent=function(panes,remeasure){if(!panes||panes=="all"){panes=_c.allPanes}$.each(panes.split(","),function(idx,pane){var $P=$Ps[pane],$C=$Cs[pane],o=options[pane],s=state[pane],m=s.content;if(!$P||!$C||!$P.is(":visible")){return true}if(false===_execCallback(null,o.onsizecontent_start)){return}if(!_c.isLayoutBusy||m.top==undefined||remeasure||o.resizeContentWhileDragging){_measure();if(m.hiddenFooters>0&&$P.css("overflow")=="hidden"){$P.css("overflow","visible");_measure();$P.css("overflow","hidden")}}var newH=s.innerHeight-(m.spaceAbove-s.css.paddingTop)-(m.spaceBelow-s.css.paddingBottom);if(!$C.is(":visible")||m.height!=newH){setOuterHeight($C,newH,true);m.height=newH}if(state.initialized){_execCallback(pane,o.onsizecontent_end||o.onsizecontent);if(o.resizeNestedLayout&&$C.data("layoutContainer")){$C.layout().resizeAll()}}function _below($E){return max(s.css.paddingBottom,(parseInt($E.css("marginBottom"))||0))}function _measure(){var ignore=options[pane].contentIgnoreSelector,$Fs=$C.nextAll().not(ignore||":lt(0)"),$Fs_vis=$Fs.filter(":visible"),$F=$Fs_vis.filter(":last");m={top:$C[0].offsetTop,height:$C.outerHeight(),numFooters:$Fs.length,hiddenFooters:$Fs.length-$Fs_vis.length,spaceBelow:0};m.spaceAbove=m.top;m.bottom=m.top+m.height;if($F.length){m.spaceBelow=($F[0].offsetTop+$F.outerHeight())-m.bottom+_below($F)}else{m.spaceBelow=_below($C)}}})};var sizeHandles=function(panes){if(!panes||panes=="all"){panes=_c.borderPanes}$.each(panes.split(","),function(i,pane){var o=options[pane],s=state[pane],$P=$Ps[pane],$R=$Rs[pane],$T=$Ts[pane],$TC;if(!$P||!$R){return}var dir=_c[pane].dir,_state=(s.isClosed?"_closed":"_open"),spacing=o["spacing"+_state],togAlign=o["togglerAlign"+_state],togLen=o["togglerLength"+_state],paneLen,offset,CSS={};if(spacing==0){$R.hide();return}else{if(!s.noRoom&&!s.isHidden){$R.show()}}if(dir=="horz"){paneLen=$P.outerWidth();s.resizerLength=paneLen;$R.css({width:max(1,cssW($R,paneLen)),height:max(0,cssH($R,spacing)),left:_cssNum($P,"left")})}else{paneLen=$P.outerHeight();s.resizerLength=paneLen;$R.css({height:max(1,cssH($R,paneLen)),width:max(0,cssW($R,spacing)),top:sC.insetTop+getPaneSize("north",true)})}removeHover(o,$R);if($T){if(togLen==0||(s.isSliding&&o.hideTogglerOnSlide)){$T.hide();return}else{$T.show()}if(!(togLen>0)||togLen=="100%"||togLen>paneLen){togLen=paneLen;offset=0}else{if(isStr(togAlign)){switch(togAlign){case"top":case"left":offset=0;break;case"bottom":case"right":offset=paneLen-togLen;break;case"middle":case"center":default:offset=Math.floor((paneLen-togLen)/2)}}else{var x=parseInt(togAlign);if(togAlign>=0){offset=x}else{offset=paneLen-togLen+x}}}if(dir=="horz"){var width=cssW($T,togLen);$T.css({width:max(0,width),height:max(1,cssH($T,spacing)),left:offset,top:0});$T.children(".content").each(function(){$TC=$(this);$TC.css("marginLeft",Math.floor((width-$TC.outerWidth())/2))})}else{var height=cssH($T,togLen);$T.css({height:max(0,height),width:max(1,cssW($T,spacing)),top:offset,left:0});$T.children(".content").each(function(){$TC=$(this);$TC.css("marginTop",Math.floor((height-$TC.outerHeight())/2))})}removeHover(0,$T)}if(!state.initialized&&o.initHidden){$R.hide();if($T){$T.hide()}}})};var swapPanes=function(pane1,pane2){state[pane1].edge=pane2;state[pane2].edge=pane1;var cancelled=false;if(false===_execCallback(pane1,options[pane1].onswap_start)){cancelled=true}if(!cancelled&&false===_execCallback(pane2,options[pane2].onswap_start)){cancelled=true}if(cancelled){state[pane1].edge=pane1;state[pane2].edge=pane2;return}var oPane1=copy(pane1),oPane2=copy(pane2),sizes={};sizes[pane1]=oPane1?oPane1.state.size:0;sizes[pane2]=oPane2?oPane2.state.size:0;$Ps[pane1]=false;$Ps[pane2]=false;state[pane1]={};state[pane2]={};if($Ts[pane1]){$Ts[pane1].remove()}if($Ts[pane2]){$Ts[pane2].remove()}if($Rs[pane1]){$Rs[pane1].remove()}if($Rs[pane2]){$Rs[pane2].remove()}$Rs[pane1]=$Rs[pane2]=$Ts[pane1]=$Ts[pane2]=false;move(oPane1,pane2);move(oPane2,pane1);oPane1=oPane2=sizes=null;if($Ps[pane1]){$Ps[pane1].css(_c.visible)}if($Ps[pane2]){$Ps[pane2].css(_c.visible)}resizeAll();_execCallback(pane1,options[pane1].onswap_end||options[pane1].onswap);_execCallback(pane2,options[pane2].onswap_end||options[pane2].onswap);return;function copy(n){var $P=$Ps[n],$C=$Cs[n];return !$P?false:{pane:n,P:$P?$P[0]:false,C:$C?$C[0]:false,state:$.extend({},state[n]),options:$.extend({},options[n])}}function move(oPane,pane){if(!oPane){return}var P=oPane.P,C=oPane.C,oldPane=oPane.pane,c=_c[pane],side=c.side.toLowerCase(),inset="inset"+c.side,s=$.extend({},state[pane]),o=options[pane],fx={resizerCursor:o.resizerCursor},re,size,pos;$.each("fxName,fxSpeed,fxSettings".split(","),function(i,k){fx[k]=o[k];fx[k+"_open"]=o[k+"_open"];fx[k+"_close"]=o[k+"_close"]});$Ps[pane]=$(P).data("layoutEdge",pane).css(_c.hidden).css(c.cssReq);$Cs[pane]=C?$(C):false;options[pane]=$.extend({},oPane.options,fx);state[pane]=$.extend({},oPane.state);re=new RegExp(o.paneClass+"-"+oldPane,"g");P.className=P.className.replace(re,o.paneClass+"-"+pane);initHandles(pane);initResizable(pane);if(c.dir!=_c[oldPane].dir){size=sizes[pane]||0;setSizeLimits(pane);size=max(size,state[pane].minSize);manualSizePane(pane,size,true)}else{$Rs[pane].css(side,sC[inset]+(state[pane].isVisible?getPaneSize(pane):0))}if(oPane.state.isVisible&&!s.isVisible){setAsOpen(pane,true)}else{setAsClosed(pane,true);bindStartSlidingEvent(pane,true)}oPane=null}};function keyDown(evt){if(!evt){return true}var code=evt.keyCode;if(code<33){return true}var PANE={38:"north",40:"south",37:"west",39:"east"},ALT=evt.altKey,SHIFT=evt.shiftKey,CTRL=evt.ctrlKey,CURSOR=(CTRL&&code>=37&&code<=40),o,k,m,pane;if(CURSOR&&options[PANE[code]].enableCursorHotkey){pane=PANE[code]}else{if(CTRL||SHIFT){$.each(_c.borderPanes.split(","),function(i,p){o=options[p];k=o.customHotkey;m=o.customHotkeyModifier;if((SHIFT&&m=="SHIFT")||(CTRL&&m=="CTRL")||(CTRL&&SHIFT)){if(k&&code==(isNaN(k)||k<=9?k.toUpperCase().charCodeAt(0):k)){pane=p;return false}}})}}if(!pane||!$Ps[pane]||!options[pane].closable||state[pane].isHidden){return true}toggle(pane);evt.stopPropagation();evt.returnValue=false;return false}function allowOverflow(el){if(this&&this.tagName){el=this}var $P;if(isStr(el)){$P=$Ps[el]}else{if($(el).data("layoutRole")){$P=$(el)}else{$(el).parents().each(function(){if($(this).data("layoutRole")){$P=$(this);return false}})}}if(!$P||!$P.length){return}var pane=$P.data("layoutEdge"),s=state[pane];if(s.cssSaved){resetOverflow(pane)}if(s.isSliding||s.isResizing||s.isClosed){s.cssSaved=false;return}var newCSS={zIndex:(_c.zIndex.pane_normal+2)},curCSS={},of=$P.css("overflow"),ofX=$P.css("overflowX"),ofY=$P.css("overflowY");if(of!="visible"){curCSS.overflow=of;newCSS.overflow="visible"}if(ofX&&!ofX.match(/visible|auto/)){curCSS.overflowX=ofX;newCSS.overflowX="visible"}if(ofY&&!ofY.match(/visible|auto/)){curCSS.overflowY=ofX;newCSS.overflowY="visible"}s.cssSaved=curCSS;$P.css(newCSS);$.each(_c.allPanes.split(","),function(i,p){if(p!=pane){resetOverflow(p)}})}function resetOverflow(el){if(this&&this.tagName){el=this}var $P;if(isStr(el)){$P=$Ps[el]}else{if($(el).data("layoutRole")){$P=$(el)}else{$(el).parents().each(function(){if($(this).data("layoutRole")){$P=$(this);return false}})}}if(!$P||!$P.length){return}var pane=$P.data("layoutEdge"),s=state[pane],CSS=s.cssSaved||{};if(!s.isSliding&&!s.isResizing){$P.css("zIndex",_c.zIndex.pane_normal)}$P.css(CSS);s.cssSaved=false}function getBtn(selector,pane,action){var $E=$(selector);if(!$E.length){alert(lang.errButton+lang.selector+": "+selector)}else{if(_c.borderPanes.indexOf(pane)==-1){alert(lang.errButton+lang.Pane.toLowerCase()+": "+pane)}else{var btn=options[pane].buttonClass+"-"+action;$E.addClass(btn+" "+btn+"-"+pane).data("layoutName",options.name);return $E}}return false}function bindButton(selector,action,pane){switch(action.toLowerCase()){case"toggle":addToggleBtn(selector,pane);break;case"open":addOpenBtn(selector,pane);break;case"close":addCloseBtn(selector,pane);break;case"pin":addPinBtn(selector,pane);break;case"toggle-slide":addToggleBtn(selector,pane,true);break;case"open-slide":addOpenBtn(selector,pane,true);break}}function addToggleBtn(selector,pane,slide){var $E=getBtn(selector,pane,"toggle");if($E){$E.click(function(evt){toggle(pane,!!slide);evt.stopPropagation()})}}function addOpenBtn(selector,pane,slide){var $E=getBtn(selector,pane,"open");if($E){$E.attr("title",lang.Open).click(function(evt){open(pane,!!slide);evt.stopPropagation()})}}function addCloseBtn(selector,pane){var $E=getBtn(selector,pane,"close");if($E){$E.attr("title",lang.Close).click(function(evt){close(pane);evt.stopPropagation()})}}function addPinBtn(selector,pane){var $E=getBtn(selector,pane,"pin");if($E){var s=state[pane];$E.click(function(evt){setPinState($(this),pane,(s.isSliding||s.isClosed));if(s.isSliding||s.isClosed){open(pane)}else{close(pane)}evt.stopPropagation()});setPinState($E,pane,(!s.isClosed&&!s.isSliding));_c[pane].pins.push(selector)}}function syncPinBtns(pane,doPin){$.each(_c[pane].pins,function(i,selector){setPinState($(selector),pane,doPin)})}function setPinState($Pin,pane,doPin){var updown=$Pin.attr("pin");if(updown&&doPin==(updown=="down")){return}var pin=options[pane].buttonClass+"-pin",side=pin+"-"+pane,UP=pin+"-up "+side+"-up",DN=pin+"-down "+side+"-down";$Pin.attr("pin",doPin?"down":"up").attr("title",doPin?lang.Unpin:lang.Pin).removeClass(doPin?UP:DN).addClass(doPin?DN:UP)}function isCookiesEnabled(){return(navigator.cookieEnabled!=0)}function getCookie(opts){var o=$.extend({},options.cookie,opts||{}),name=o.name||options.name||"Layout",c=document.cookie,cs=c?c.split(";"):[],pair;for(var i=0,n=cs.length;i<n;i++){pair=$.trim(cs[i]).split("=");if(pair[0]==name){return decodeJSON(decodeURIComponent(pair[1]))}}return""}function saveCookie(keys,opts){var o=$.extend({},options.cookie,opts||{}),name=o.name||options.name||"Layout",params="",date="",clear=false;if(o.expires.toUTCString){date=o.expires}else{if(typeof o.expires=="number"){date=new Date();if(o.expires>0){date.setDate(date.getDate()+o.expires)}else{date.setYear(1970);clear=true}}}if(date){params+=";expires="+date.toUTCString()}if(o.path){params+=";path="+o.path}if(o.domain){params+=";domain="+o.domain}if(o.secure){params+=";secure"}if(clear){state.cookie={};document.cookie=name+"="+params}else{state.cookie=getState(keys||o.keys);document.cookie=name+"="+encodeURIComponent(encodeJSON(state.cookie))+params}return $.extend({},state.cookie)}function deleteCookie(){saveCookie("",{expires:-1})}function loadCookie(opts){var o=getCookie(opts);if(o){state.cookie=$.extend({},o);loadState(o)}return o}function loadState(opts){$.extend(true,options,opts)}function getState(keys){var data={},alt={isClosed:"initClosed",isHidden:"initHidden"},pair,pane,key,val;if(!keys){keys=options.cookie.keys}if($.isArray(keys)){keys=keys.join(",")}keys=keys.replace(/__/g,".").split(",");for(var i=0,n=keys.length;i<n;i++){pair=keys[i].split(".");pane=pair[0];key=pair[1];if(_c.allPanes.indexOf(pane)<0){continue}val=state[pane][key];if(val==undefined){continue}if(key=="isClosed"&&state[pane]["isSliding"]){val=true}(data[pane]||(data[pane]={}))[alt[key]?alt[key]:key]=val}return data}function encodeJSON(JSON){return parse(JSON);function parse(h){var D=[],i=0,k,v,t;for(k in h){v=h[k];t=typeof v;if(t=="string"){v='"'+v+'"'}else{if(t=="object"){v=parse(v)}}D[i++]='"'+k+'":'+v}return"{"+D.join(",")+"}"}}function decodeJSON(str){try{return window["eval"]("("+str+")")||{}}catch(e){return{}}}var $Container=$(this).eq(0);if(!$Container.length){return null}if($Container.data("layoutContainer")){return $.extend({},window[$Container.data("layoutContainer")])}var $Ps={},$Cs={},$Rs={},$Ts={},sC=state.container,sID=state.id;_create();var Instance={options:options,state:state,container:$Container,panes:$Ps,contents:$Cs,resizers:$Rs,togglers:$Ts,toggle:toggle,hide:hide,show:show,open:open,close:close,slideOpen:slideOpen,slideClose:slideClose,slideToggle:slideToggle,initContent:initContent,sizeContent:sizeContent,sizePane:manualSizePane,swapPanes:swapPanes,resizeAll:resizeAll,destroy:destroy,setSizeLimits:setSizeLimits,bindButton:bindButton,addToggleBtn:addToggleBtn,addOpenBtn:addOpenBtn,addCloseBtn:addCloseBtn,addPinBtn:addPinBtn,allowOverflow:allowOverflow,resetOverflow:resetOverflow,encodeJSON:encodeJSON,decodeJSON:decodeJSON,getState:getState,getCookie:getCookie,saveCookie:saveCookie,deleteCookie:deleteCookie,loadCookie:loadCookie,loadState:loadState,cssWidth:cssW,cssHeight:cssH};window[sID]=Instance;return Instance}})(jQuery);
+$.layout.browserZoom = {
+
+ _init: function (inst) {
+ // abort if browser does not need this check
+ if ($.layout.browserZoom.ratio() !== false)
+ $.layout.browserZoom._setTimer(inst);
+ }
+
+, _setTimer: function (inst) {
+ // abort if layout destroyed or browser does not need this check
+ if (inst.destroyed) return;
+ var o = inst.options
+ , s = inst.state
+ // don't need check if inst has parentLayout, but check occassionally in case parent destroyed!
+ // MINIMUM 100ms interval, for performance
+ , ms = inst.hasParentLayout ? 5000 : Math.max( o.browserZoomCheckInterval, 100 )
+ ;
+ // set the timer
+ setTimeout(function(){
+ if (inst.destroyed || !o.resizeWithWindow) return;
+ var d = $.layout.browserZoom.ratio();
+ if (d !== s.browserZoom) {
+ s.browserZoom = d;
+ inst.resizeAll();
+ }
+ // set a NEW timeout
+ $.layout.browserZoom._setTimer(inst);
+ }
+ , ms );
+ }
+
+, ratio: function () {
+ var w = window
+ , s = screen
+ , d = document
+ , dE = d.documentElement || d.body
+ , b = $.layout.browser
+ , v = b.version
+ , r, sW, cW
+ ;
+ // we can ignore all browsers that fire window.resize event onZoom
+ if ((b.msie && v > 8)
+ || !b.msie
+ ) return false; // don't need to track zoom
+
+ if (s.deviceXDPI)
+ return calc(s.deviceXDPI, s.systemXDPI);
+ // everything below is just for future reference!
+ if (b.webkit && (r = d.body.getBoundingClientRect))
+ return calc((r.left - r.right), d.body.offsetWidth);
+ if (b.webkit && (sW = w.outerWidth))
+ return calc(sW, w.innerWidth);
+ if ((sW = s.width) && (cW = dE.clientWidth))
+ return calc(sW, cW);
+ return false; // no match, so cannot - or don't need to - track zoom
+
+ function calc (x,y) { return (parseInt(x,10) / parseInt(y,10) * 100).toFixed(); }
+ }
+
+};
+// add initialization method to Layout's onLoad array of functions
+$.layout.onReady.push( $.layout.browserZoom._init );
+
+
+
+})( jQuery ); \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-implicits.png b/src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-implicits.png
new file mode 100644
index 0000000000..bc29efb3e6
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-implicits.png
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-right-implicits.png b/src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-right-implicits.png
new file mode 100644
index 0000000000..8313f4975b
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/selected-right-implicits.png
Binary files differ
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
index 6fb83c133e..5a1779bba5 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
@@ -106,7 +106,7 @@ a[href]:hover {
font-size: 24pt;
text-shadow: black 0px 2px 0px;
/* text-shadow: black 0px 0px 0px;*/
-text-decoration: none;
+text-decoration: none;
}
#definition #owner {
@@ -162,7 +162,7 @@ text-decoration: none;
padding-left: 15px;
background: url("arrow-right.png") no-repeat 0 3px transparent;
}
-
+
.toggleContainer.open .toggle {
background: url("arrow-down.png") no-repeat 0 3px transparent;
}
@@ -205,6 +205,11 @@ dl.attributes > dt {
font-style: italic;
}
+dl.attributes > dt.implicit {
+ font-weight: bold;
+ color: darkgreen;
+}
+
dl.attributes > dd {
display: block;
padding-left: 10em;
@@ -241,6 +246,17 @@ dl.attributes > dd {
color: white;
}
+#inheritedMembers > div.conversion > h3 {
+ background: #dadada url("conversionbg.gif") repeat-x bottom left; /* gray */
+ height: 17px;
+ font-style: italic;
+ font-size: 12pt;
+}
+
+#inheritedMembers > div.conversion > h3 * {
+ color: white;
+}
+
/* Member cells */
div.members > ol {
@@ -310,10 +326,21 @@ div.members > ol > li:last-child {
font-weight: bold;
}
-.signature .symbol .params .implicit {
+.signature .symbol > .implicit {
+ display: inline-block;
+ font-weight: bold;
+ text-decoration: underline;
+ color: darkgreen;
+}
+
+.signature .symbol .params > .implicit {
font-style: italic;
}
+.signature .symbol .implicit.deprecated {
+ text-decoration: line-through;
+}
+
.signature .symbol .name.deprecated {
text-decoration: line-through;
}
@@ -369,15 +396,15 @@ div.members > ol > li:last-child {
.cmt {}
.cmt p {
- margin: 0.7em 0;
+ margin: 0.7em 0;
}
.cmt p:first-child {
- margin-top: 0;
+ margin-top: 0;
}
.cmt p:last-child {
- margin-bottom: 0;
+ margin-bottom: 0;
}
.cmt h3,
@@ -539,7 +566,7 @@ div.fullcommenttop .block {
margin-bottom: 5px
}
-div.fullcomment div.block ol li p,
+div.fullcomment div.block ol li p,
div.fullcomment div.block ol li {
display:inline
}
@@ -583,10 +610,10 @@ div.fullcomment dl.paramcmts > dd {
/* Members filter tool */
#textfilter {
- position: relative;
- display: block;
+ position: relative;
+ display: block;
height: 20px;
- margin-bottom: 5px;
+ margin-bottom: 5px;
}
#textfilter > .pre {
@@ -600,7 +627,7 @@ div.fullcomment dl.paramcmts > dd {
}
#textfilter > .input {
- display: block;
+ display: block;
position: absolute;
top: 0;
right: 20px;
@@ -608,10 +635,10 @@ div.fullcomment dl.paramcmts > dd {
}
#textfilter > .input > input {
- height: 20px;
- padding: 1px;
- font-weight: bold;
- color: #000000;
+ height: 20px;
+ padding: 1px;
+ font-weight: bold;
+ color: #000000;
background: #ffffff url("filterboxbarbg.png") repeat-x top left;
width: 100%;
}
@@ -660,6 +687,13 @@ div.fullcomment dl.paramcmts > dd {
display: inline-block;
}
+#mbrsel > div > a {
+ position:relative;
+ top: -8px;
+ font-size: 11px;
+ text-shadow: #ffffff 0 1px 0;
+}
+
#mbrsel > div > ol#linearization {
display: table;
margin-left: 70px;
@@ -683,9 +717,32 @@ div.fullcomment dl.paramcmts > dd {
text-shadow: #ffffff 0 1px 0;
}
+#mbrsel > div > ol#implicits {
+ display: table;
+ margin-left: 70px;
+}
+
+#mbrsel > div > ol#implicits > li.in {
+ text-decoration: none;
+ float: left;
+ padding-right: 10px;
+ margin-right: 5px;
+ background: url(selected-right-implicits.png) no-repeat;
+ background-position: right 0px;
+}
+
+#mbrsel > div > ol#implicits > li.in > span{
+ color: #404040;
+ float: left;
+ padding: 1px 0 1px 10px;
+ background: url(selected-implicits.png) no-repeat;
+ background-position: 0px 0px;
+ text-shadow: #ffffff 0 1px 0;
+}
+
#mbrsel > div > ol > li {
/* padding: 3px 10px;*/
- line-height: 16pt;
+ line-height: 16pt;
display: inline-block;
cursor: pointer;
}
@@ -709,10 +766,10 @@ div.fullcomment dl.paramcmts > dd {
}
#mbrsel > div > ol > li.out {
- text-decoration: none;
- float: left;
- padding-right: 10px;
- margin-right: 5px;
+ text-decoration: none;
+ float: left;
+ padding-right: 10px;
+ margin-right: 5px;
}
#mbrsel > div > ol > li.out > span{
@@ -739,10 +796,10 @@ div.fullcomment dl.paramcmts > dd {
#mbrsel .showall {
color: #4C4C4C;
line-height: 16px;
- font-weight: bold;
+ font-weight: bold;
}
#mbrsel .showall span {
color: #4C4C4C;
- font-weight: bold;
+ font-weight: bold;
}*/ \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
index 3cdd9a7f27..fd5a981cb0 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
@@ -2,21 +2,23 @@
// code by Gilles Dubochet with contributions by Pedro Furlanetto
$(document).ready(function(){
- var isHiddenClass;
- if (document.title == 'scala.AnyRef') {
- isHiddenClass = function (name) {
- return name == 'scala.Any';
- };
- } else {
- isHiddenClass = function (name) {
- return name == 'scala.Any' || name == 'scala.AnyRef';
- };
- }
+ var isHiddenClass = function (name) {
+ return name == 'scala.Any' ||
+ name == 'scala.AnyRef' ||
+ name == 'scala.Predef.any2stringfmt' ||
+ name == 'scala.Predef.any2stringadd' ||
+ name == 'scala.Predef.any2ArrowAssoc' ||
+ name == 'scala.Predef.any2Ensuring'
+ };
+
+ $("#linearization li:gt(0)").filter(function(){
+ return isHiddenClass($(this).attr("name"));
+ }).removeClass("in").addClass("out");
- $("#linearization li").filter(function(){
+ $("#implicits li").filter(function(){
return isHiddenClass($(this).attr("name"));
}).removeClass("in").addClass("out");
-
+
// Pre-filter members
filter();
@@ -54,17 +56,38 @@ $(document).ready(function(){
};
filter();
});
- $("#ancestors > ol > li.hideall").click(function() {
+
+ $("#implicits li").click(function(){
+ if ($(this).hasClass("in")) {
+ $(this).removeClass("in");
+ $(this).addClass("out");
+ }
+ else if ($(this).hasClass("out")) {
+ $(this).removeClass("out");
+ $(this).addClass("in");
+ };
+ filter();
+ });
+
+ $("#mbrsel > div[id=ancestors] > ol > li.hideall").click(function() {
$("#linearization li.in").removeClass("in").addClass("out");
$("#linearization li:first").removeClass("out").addClass("in");
+ $("#implicits li.in").removeClass("in").addClass("out");
filter();
})
- $("#ancestors > ol > li.showall").click(function() {
- var filtered =
+ $("#mbrsel > div[id=ancestors] > ol > li.showall").click(function() {
+ var filteredLinearization =
$("#linearization li.out").filter(function() {
return ! isHiddenClass($(this).attr("name"));
});
- filtered.removeClass("out").addClass("in");
+ filteredLinearization.removeClass("out").addClass("in");
+
+ var filteredImplicits =
+ $("#implicits li.out").filter(function() {
+ return ! isHiddenClass($(this).attr("name"));
+ });
+ filteredImplicits.removeClass("out").addClass("in");
+
filter();
});
$("#visbl > ol > li.public").click(function() {
@@ -108,8 +131,10 @@ $(document).ready(function(){
});
/* Add toggle arrows */
- var docAllSigs = $("#template li").has(".fullcomment").find(".signature");
-
+ //var docAllSigs = $("#template li").has(".fullcomment").find(".signature");
+ // trying to speed things up a little bit
+ var docAllSigs = $("#template li[fullComment=yes] .signature");
+
function commentToggleFct(signature){
var parent = signature.parent();
var shortComment = $(".shortcomment", parent);
@@ -129,7 +154,7 @@ $(document).ready(function(){
docAllSigs.click(function() {
commentToggleFct($(this));
});
-
+
/* Linear super types and known subclasses */
function toggleShowContentFct(outerElement){
var content = $(".hiddenContent", outerElement);
@@ -148,20 +173,22 @@ $(document).ready(function(){
$(".toggleContainer").click(function() {
toggleShowContentFct($(this));
});
-
+
// Set parent window title
windowTitle();
});
function orderAlpha() {
$("#template > div.parent").hide();
- $("#ancestors").show();
+ $("#template > div.conversion").hide();
+ $("#mbrsel > div[id=ancestors]").show();
filter();
};
function orderInherit() {
$("#template > div.parent").show();
- $("#ancestors").hide();
+ $("#template > div.conversion").show();
+ $("#mbrsel > div[id=ancestors]").hide();
filter();
};
@@ -177,6 +204,9 @@ function initInherit() {
$("#inheritedMembers > div.parent").each(function(){
parents[$(this).attr("name")] = $(this);
});
+ $("#inheritedMembers > div.conversion").each(function(){
+ parents[$(this).attr("name")] = $(this);
+ });
$("#types > ol > li").each(function(){
var mbr = $(this);
this.mbrText = mbr.find("> .fullcomment .cmt").text();
@@ -216,6 +246,9 @@ function initInherit() {
$("#inheritedMembers > div.parent").each(function() {
if ($("> div.members", this).length == 0) { $(this).remove(); };
});
+ $("#inheritedMembers > div.conversion").each(function() {
+ if ($("> div.members", this).length == 0) { $(this).remove(); };
+ });
};
function filter(scrollToMember) {
@@ -224,13 +257,17 @@ function filter(scrollToMember) {
var queryRegExp = new RegExp(query, "i");
var privateMembersHidden = $("#visbl > ol > li.public").hasClass("in");
var orderingAlphabetic = $("#order > ol > li.alpha").hasClass("in");
- var hiddenSuperclassElements = orderingAlphabetic ? $("#linearization > li.out") : $("#linearization > li:gt(0)");
- var hiddenSuperclasses = hiddenSuperclassElements.map(function() {
+ var hiddenSuperclassElementsLinearization = orderingAlphabetic ? $("#linearization > li.out") : $("#linearization > li:gt(0)");
+ var hiddenSuperclassesLinearization = hiddenSuperclassElementsLinearization.map(function() {
+ return $(this).attr("name");
+ }).get();
+ var hiddenSuperclassElementsImplicits = orderingAlphabetic ? $("#implicits > li.out") : $("#implicits > li");
+ var hiddenSuperclassesImplicits = hiddenSuperclassElementsImplicits.map(function() {
return $(this).attr("name");
}).get();
var hideInheritedMembers;
-
+
if(orderingAlphabetic) {
$("#inheritedMembers").hide();
hideInheritedMembers = true;
@@ -242,9 +279,10 @@ function filter(scrollToMember) {
$("#allMembers > .members").each(filterFunc);
hideInheritedMembers = false;
$("#inheritedMembers > .parent > .members").each(filterFunc);
+ $("#inheritedMembers > .conversion > .members").each(filterFunc);
}
-
+
function filterFunc() {
var membersVisible = false;
var members = $(this);
@@ -262,12 +300,18 @@ function filter(scrollToMember) {
ownerIndex = name.lastIndexOf(".");
}
var owner = name.slice(0, ownerIndex);
- for (var i = 0; i < hiddenSuperclasses.length; i++) {
- if (hiddenSuperclasses[i] == owner) {
+ for (var i = 0; i < hiddenSuperclassesLinearization.length; i++) {
+ if (hiddenSuperclassesLinearization[i] == owner) {
mbr.hide();
return;
}
- }
+ };
+ for (var i = 0; i < hiddenSuperclassesImplicits.length; i++) {
+ if (hiddenSuperclassesImplicits[i] == owner) {
+ mbr.hide();
+ return;
+ }
+ };
}
if (query && !(queryRegExp.test(name) || queryRegExp.test(this.mbrText))) {
mbr.hide();
@@ -276,7 +320,7 @@ function filter(scrollToMember) {
mbr.show();
membersVisible = true;
});
-
+
if (membersVisible)
members.show();
else
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index 6eb14a4907..6488847049 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -167,6 +167,8 @@ trait MemberEntity extends Entity {
/** Whether this member is abstract. */
def isAbstract: Boolean
+ /** If this member originates from an implicit conversion, we set the implicit information to the correct origin */
+ def byConversion: Option[ImplicitConversion]
}
object MemberEntity {
// Oh contravariance, contravariance, wherefore art thou contravariance?
@@ -246,6 +248,8 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
* other entity of the pair is the companion. */
def companion: Option[DocTemplateEntity]
+ /** The implicit conversions this template (class or trait, objects and packages are not affected) */
+ def conversions: List[ImplicitConversion]
}
@@ -413,3 +417,106 @@ trait Annotation extends Entity {
def arguments: List[ValueArgument]
}
+
+/** A trait that signals the member results from an implicit conversion */
+trait ImplicitConversion {
+
+ /** The source of the implicit conversion*/
+ def source: DocTemplateEntity
+
+ /** The result type after the conversion */
+ def targetType: TypeEntity
+
+ /** The entity for the method that performed the conversion, if it's documented (or just its name, otherwise) */
+ def convertorMethod: Either[MemberEntity, String]
+
+ /** A short name of the convertion */
+ def conversionShortName: String
+
+ /** A qualified name uniquely identifying the convertion (currently: the conversion method's qualified name) */
+ def conversionQualifiedName: String
+
+ /** The entity that performed the conversion */
+ def convertorOwner: TemplateEntity
+
+ /** The constraints that the transformations puts on the type parameters */
+ def constraints: List[Constraint]
+
+ /** The members inherited by this implicit conversion */
+ def members: List[MemberEntity]
+}
+
+/** A trait that encapsulates a constraint necessary for implicit conversion */
+trait Constraint {
+ // /** The implicit conversion during which this constraint appears */
+ // def conversion: ImplicitConversion
+}
+
+/** A constraint involving a type parameter which must be in scope */
+trait ImplicitInScopeConstraint extends Constraint {
+ /** The type of the implicit value required */
+ def implicitType: TypeEntity
+
+ /** toString for debugging */
+ override def toString = "an implicit _: " + implicitType.name + " must be in scope"
+}
+
+trait TypeClassConstraint extends ImplicitInScopeConstraint with TypeParamConstraint {
+ /** Type class name */
+ def typeClassEntity: TemplateEntity
+
+ /** toString for debugging */
+ override def toString = typeParamName + " is a class of type " + typeClassEntity.qualifiedName + " (" +
+ typeParamName + ": " + typeClassEntity.name + ")"
+}
+
+trait KnownTypeClassConstraint extends TypeClassConstraint {
+ /** Type explanation, takes the type parameter name and generates the explanation */
+ def typeExplanation: (String) => String
+
+ /** toString for debugging */
+ override def toString = typeExplanation(typeParamName) + " (" + typeParamName + ": " + typeClassEntity.name + ")"
+}
+
+/** A constraint involving a type parameter */
+trait TypeParamConstraint extends Constraint {
+ /** The type parameter involved */
+ def typeParamName: String
+}
+
+trait EqualTypeParamConstraint extends TypeParamConstraint {
+ /** The rhs */
+ def rhs: TypeEntity
+ /** toString for debugging */
+ override def toString = typeParamName + " is " + rhs.name + " (" + typeParamName + " =:= " + rhs.name + ")"
+}
+
+trait BoundedTypeParamConstraint extends TypeParamConstraint {
+ /** The lower bound */
+ def lowerBound: TypeEntity
+
+ /** The upper bound */
+ def upperBound: TypeEntity
+
+ /** toString for debugging */
+ override def toString = typeParamName + " is a superclass of " + lowerBound.name + " and a subclass of " +
+ upperBound.name + " (" + typeParamName + " >: " + lowerBound.name + " <: " + upperBound.name + ")"
+}
+
+trait LowerBoundedTypeParamConstraint extends TypeParamConstraint {
+ /** The lower bound */
+ def lowerBound: TypeEntity
+
+ /** toString for debugging */
+ override def toString = typeParamName + " is a superclass of " + lowerBound.name + " (" + typeParamName + " >: " +
+ lowerBound.name + ")"
+}
+
+trait UpperBoundedTypeParamConstraint extends TypeParamConstraint {
+ /** The lower bound */
+ def upperBound: TypeEntity
+
+ /** toString for debugging */
+ override def toString = typeParamName + " is a subclass of " + upperBound.name + " (" + typeParamName + " <: " +
+ upperBound.name + ")"
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala
index ef3c2beffb..6392de22ff 100755
--- a/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/IndexModelFactory.scala
@@ -8,6 +8,7 @@ package doc
package model
import scala.collection._
+import language.reflectiveCalls
object IndexModelFactory {
@@ -15,7 +16,7 @@ object IndexModelFactory {
lazy val firstLetterIndex: Map[Char, SymbolMap] = {
- val result = new mutable.HashMap[Char,SymbolMap] {
+ object result extends mutable.HashMap[Char,SymbolMap] {
/* Owner template ordering */
implicit def orderingSet = math.Ordering.String.on { x: MemberEntity => x.name.toLowerCase }
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 702d643fb4..9062203dcd 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -17,7 +17,7 @@ import model.{ RootPackage => RootPackageEntity }
/** This trait extracts all required information for documentation from compilation units */
class ModelFactory(val global: Global, val settings: doc.Settings) {
- thisFactory: ModelFactory with CommentFactory with TreeFactory =>
+ thisFactory: ModelFactory with ModelFactoryImplicitSupport with CommentFactory with TreeFactory =>
import global._
import definitions.{ ObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyValClass, AnyRefClass }
@@ -42,7 +42,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
memberSym.isOmittablePrefix || (closestPackage(memberSym) == closestPackage(templateSym))
}
- private lazy val noSubclassCache = Set(AnyClass, AnyRefClass, ObjectClass)
+ private lazy val noSubclassCache = Set[Symbol](AnyClass, AnyRefClass, ObjectClass)
/** */
def makeModel: Option[Universe] = {
@@ -95,7 +95,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def isDocTemplate = false
}
- abstract class MemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
+ abstract class MemberImpl(sym: Symbol, implConv: ImplicitConversionImpl = null, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
lazy val comment =
if (inTpl == null) None else thisFactory.comment(sym, inTpl)
override def inTemplate = inTpl
@@ -128,7 +128,14 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
if (sym.isImplicit) fgs += Paragraph(Text("implicit"))
if (sym.isSealed) fgs += Paragraph(Text("sealed"))
if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract"))
- if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract"))
+ /* Resetting the DEFERRED flag is a little trick here for refined types: (example from scala.collections)
+ * {{{
+ * implicit def traversable2ops[T](t: collection.GenTraversableOnce[T]) = new TraversableOps[T] {
+ * def isParallel = ...
+ * }}}
+ * the type the method returns is TraversableOps, which has all-abstract symbols. But in reality, it couldn't have
+ * any abstract terms, otherwise it would fail compilation. So we reset the DEFERRED flag. */
+ if (!sym.isTrait && (sym hasFlag Flags.DEFERRED) && (implConv eq null)) fgs += Paragraph(Text("abstract"))
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
fgs.toList
}
@@ -162,7 +169,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
case NullaryMethodType(res) => resultTpe(res)
case _ => tpe
}
- makeTypeInTemplateContext(resultTpe(sym.tpe), inTemplate, sym)
+ val tpe = if (implConv eq null) sym.tpe else implConv.toType memberInfo sym
+ makeTypeInTemplateContext(resultTpe(tpe), inTemplate, sym)
}
def isDef = false
def isVal = false
@@ -173,15 +181,17 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
def isAliasType = false
def isAbstractType = false
def isAbstract =
- ((!sym.isTrait && ((sym hasFlag Flags.ABSTRACT) || (sym hasFlag Flags.DEFERRED))) ||
+ // for the explanation of implConv == null see comment on flags
+ ((!sym.isTrait && ((sym hasFlag Flags.ABSTRACT) || (sym hasFlag Flags.DEFERRED)) && (implConv == null)) ||
sym.isAbstractClass || sym.isAbstractType) && !sym.isSynthetic
def isTemplate = false
+ def byConversion = if (implConv ne null) Some(implConv) else None
}
/** The instantiation of `TemplateImpl` triggers the creation of the following entities:
* All ancestors of the template and all non-package members.
*/
- abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with HigherKindedImpl with DocTemplateEntity {
+ abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, null, inTpl) with TemplateImpl with HigherKindedImpl with DocTemplateEntity {
//if (inTpl != null) println("mbr " + sym + " in " + (inTpl.toRoot map (_.sym)).mkString(" > "))
if (settings.verbose.value)
inform("Creating doc template for " + sym)
@@ -221,9 +231,10 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
Some(makeType(RefinedType(tps, EmptyScope), inTpl))
}
}
- val linearization: List[(TemplateEntity, TypeEntity)] = {
- sym.ancestors map { ancestor =>
- val typeEntity = makeType(sym.info.baseType(ancestor), this)
+
+ protected def linearizationFromSymbol(symbol: Symbol) = {
+ symbol.ancestors map { ancestor =>
+ val typeEntity = makeType(symbol.info.baseType(ancestor), this)
val tmplEntity = makeTemplate(ancestor) match {
case tmpl: DocTemplateImpl => tmpl registerSubClass this ; tmpl
case tmpl => tmpl
@@ -232,6 +243,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
}
+ val linearization = linearizationFromSymbol(sym)
def linearizationTemplates = linearization map { _._1 }
def linearizationTypes = linearization map { _._2 }
@@ -245,16 +257,20 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
def subClasses = if (subClassesCache == null) Nil else subClassesCache.toList
- protected lazy val memberSyms =
+ val conversions = if (settings.docImplicits.value) makeImplicitConversions(sym, this) else Nil
+
+ lazy val memberSyms =
// Only this class's constructors are part of its members, inherited constructors are not.
sym.info.members.filter(s => localShouldDocument(s) && (!s.isConstructor || s.owner == sym) && !isPureBridge(sym) )
- val members = memberSyms flatMap (makeMember(_, this))
- val templates = members collect { case c: DocTemplateEntity => c }
- val methods = members collect { case d: Def => d }
- val values = members collect { case v: Val => v }
- val abstractTypes = members collect { case t: AbstractType => t }
- val aliasTypes = members collect { case t: AliasType => t }
+ val members = (memberSyms.flatMap(makeMember(_, null, this))) :::
+ (conversions.flatMap((_.members))) // also take in the members from implicit conversions
+
+ val templates = members collect { case c: DocTemplateEntity => c }
+ val methods = members collect { case d: Def => d }
+ val values = members collect { case v: Val => v }
+ val abstractTypes = members collect { case t: AbstractType => t }
+ val aliasTypes = members collect { case t: AliasType => t }
override def isTemplate = true
def isDocTemplate = true
def companion = sym.companionSymbol match {
@@ -268,23 +284,33 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
abstract class PackageImpl(sym: Symbol, inTpl: => PackageImpl) extends DocTemplateImpl(sym, inTpl) with Package {
override def inTemplate = inTpl
override def toRoot: List[PackageImpl] = this :: inTpl.toRoot
+ override val linearization = {
+ val symbol = sym.info.members.find {
+ s => s.isPackageObject
+ } getOrElse sym
+ linearizationFromSymbol(symbol)
+ }
val packages = members collect { case p: Package => p }
}
abstract class RootPackageImpl(sym: Symbol) extends PackageImpl(sym, null) with RootPackageEntity
- abstract class NonTemplateMemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity {
+ abstract class NonTemplateMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: => DocTemplateImpl) extends MemberImpl(sym, implConv, inTpl) with NonTemplateMemberEntity {
override def qualifiedName = optimize(inTemplate.qualifiedName + "#" + name)
- lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "#" + name)
+ lazy val definitionName =
+ if (implConv == null) optimize(inDefinitionTemplates.head.qualifiedName + "#" + name)
+ else optimize(implConv.conversionQualifiedName + "#" + name)
def isUseCase = sym.isSynthetic
def isBridge = sym.isBridge
}
- abstract class NonTemplateParamMemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends NonTemplateMemberImpl(sym, inTpl) {
- def valueParams =
- sym.paramss map { ps => (ps.zipWithIndex) map { case (p, i) =>
+ abstract class NonTemplateParamMemberImpl(sym: Symbol, implConv: ImplicitConversionImpl, inTpl: => DocTemplateImpl) extends NonTemplateMemberImpl(sym, implConv, inTpl) {
+ def valueParams = {
+ val info = if (implConv eq null) sym.info else implConv.toType memberInfo sym
+ info.paramss map { ps => (ps.zipWithIndex) map { case (p, i) =>
if (p.nameString contains "$") makeValueParam(p, inTpl, optimize("arg" + i)) else makeValueParam(p, inTpl)
}}
+ }
}
abstract class ParameterImpl(sym: Symbol, inTpl: => TemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity {
@@ -356,7 +382,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
override def qualifiedName = "_root_"
override def inheritedFrom = Nil
override def isRootPackage = true
- override protected lazy val memberSyms =
+ override lazy val memberSyms =
(bSym.info.members ++ EmptyPackage.info.members) filter { s =>
s != EmptyPackage && s != RootPackage
}
@@ -380,11 +406,13 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
else if (bSym.isPackage)
makeTemplate(bSym.owner) match {
case inPkg: PackageImpl => makePackage(bSym, inPkg) getOrElse (new NoDocTemplateImpl(bSym, inPkg))
+ case inNoDocTpl: NoDocTemplateImpl => new NoDocTemplateImpl(bSym, inNoDocTpl)
case _ => throw new Error("'" + bSym + "' must be in a package")
}
else if (templateShouldDocument(bSym))
makeTemplate(bSym.owner) match {
case inDTpl: DocTemplateImpl => makeDocTemplate(bSym, inDTpl)
+ case inNoDocTpl: NoDocTemplateImpl => new NoDocTemplateImpl(bSym, inNoDocTpl)
case _ => throw new Error("'" + bSym + "' must be in documentable template")
}
else
@@ -454,18 +482,19 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
/** */
- def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): List[MemberImpl] = {
+ // TODO: Should be able to override the type
+ def makeMember(aSym: Symbol, implConv: ImplicitConversionImpl, inTpl: => DocTemplateImpl): List[MemberImpl] = {
def makeMember0(bSym: Symbol, _useCaseOf: Option[MemberImpl]): Option[MemberImpl] = {
if (bSym.isGetter && bSym.isLazy)
- Some(new NonTemplateMemberImpl(bSym, inTpl) with Val {
+ Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with Val {
override lazy val comment = // The analyser does not duplicate the lazy val's DocDef when it introduces its accessor.
thisFactory.comment(bSym.accessed, inTpl) // This hack should be removed after analyser is fixed.
override def isLazyVal = true
override def useCaseOf = _useCaseOf
})
else if (bSym.isGetter && bSym.accessed.isMutable)
- Some(new NonTemplateMemberImpl(bSym, inTpl) with Val {
+ Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with Val {
override def isVar = true
override def useCaseOf = _useCaseOf
})
@@ -474,43 +503,43 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
if (bSym == definitions.Object_synchronized) {
val cSymInfo = (bSym.info: @unchecked) match {
case PolyType(ts, MethodType(List(bp), mt)) =>
- val cp = bp.cloneSymbol.setInfo(appliedType(definitions.ByNameParamClass.typeConstructor, List(bp.info)))
+ val cp = bp.cloneSymbol.setInfo(definitions.byNameType(bp.info))
PolyType(ts, MethodType(List(cp), mt))
}
bSym.cloneSymbol.setInfo(cSymInfo)
}
else bSym
}
- Some(new NonTemplateParamMemberImpl(cSym, inTpl) with HigherKindedImpl with Def {
+ Some(new NonTemplateParamMemberImpl(cSym, implConv, inTpl) with HigherKindedImpl with Def {
override def isDef = true
override def useCaseOf = _useCaseOf
})
}
- else if (bSym.isConstructor)
- Some(new NonTemplateParamMemberImpl(bSym, inTpl) with Constructor {
+ else if (bSym.isConstructor && (implConv == null))
+ Some(new NonTemplateParamMemberImpl(bSym, implConv, inTpl) with Constructor {
override def isConstructor = true
def isPrimary = sym.isPrimaryConstructor
override def useCaseOf = _useCaseOf
})
else if (bSym.isGetter) // Scala field accessor or Java field
- Some(new NonTemplateMemberImpl(bSym, inTpl) with Val {
+ Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with Val {
override def isVal = true
override def useCaseOf = _useCaseOf
})
else if (bSym.isAbstractType)
- Some(new NonTemplateMemberImpl(bSym, inTpl) with TypeBoundsImpl with HigherKindedImpl with AbstractType {
+ Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with TypeBoundsImpl with HigherKindedImpl with AbstractType {
override def isAbstractType = true
override def useCaseOf = _useCaseOf
})
- else if (bSym.isAliasType)
- Some(new NonTemplateMemberImpl(bSym, inTpl) with HigherKindedImpl with AliasType {
+ else if (bSym.isAliasType && bSym != AnyRefClass)
+ Some(new NonTemplateMemberImpl(bSym, implConv, inTpl) with HigherKindedImpl with AliasType {
override def isAliasType = true
def alias = makeTypeInTemplateContext(sym.tpe.dealias, inTpl, sym)
override def useCaseOf = _useCaseOf
})
else if (bSym.isPackage)
inTpl match { case inPkg: PackageImpl => makePackage(bSym, inPkg) }
- else if ((bSym.isClass || bSym.isModule) && templateShouldDocument(bSym))
+ else if ((bSym.isClass || bSym.isModule || bSym == AnyRefClass) && templateShouldDocument(bSym))
Some(makeDocTemplate(bSym, inTpl))
else
None
@@ -520,16 +549,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
Nil
else {
val allSyms = useCases(aSym, inTpl.sym) map { case (bSym, bComment, bPos) =>
- docComments.put(bSym, DocComment(bComment, bPos)) // put the comment in the list, don't parse it yet, closes SI-4898
+ docComments.put(bSym, DocComment(bComment, bPos)) // put the comment in the list, don't parse it yet, closes SI-4898
bSym
}
val member = makeMember0(aSym, None)
- if (allSyms.isEmpty)
- member.toList
- else
- // Use cases replace the original definitions - SI-5054
- allSyms flatMap { makeMember0(_, member) }
+ if (allSyms.isEmpty)
+ member.toList
+ else
+ // Use cases replace the original definitions - SI-5054
+ allSyms flatMap { makeMember0(_, member) }
}
}
@@ -639,9 +668,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
// nameBuffer append stripPrefixes.foldLeft(pre.prefixString)(_ stripPrefix _)
// }
val bSym = normalizeTemplate(aSym)
- if (bSym.isNonClassType)
+ if (bSym.isNonClassType) {
nameBuffer append bSym.decodedName
- else {
+ } else {
val tpl = makeTemplate(bSym)
val pos0 = nameBuffer.length
refBuffer += pos0 -> (tpl, tpl.name.length)
@@ -654,7 +683,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
/* Refined types */
case RefinedType(parents, defs) =>
- val ignoreParents = Set(AnyClass, ObjectClass)
+ val ignoreParents = Set[Symbol](AnyClass, ObjectClass)
val filtParents = parents filterNot (x => ignoreParents(x.typeSymbol)) match {
case Nil => parents
case ps => ps
@@ -674,9 +703,9 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
nameBuffer append '⇒'
appendType0(result)
/* Polymorphic types */
- case PolyType(tparams, result) => assert(tparams nonEmpty)
+ case PolyType(tparams, result) => assert(tparams.nonEmpty)
// throw new Error("Polymorphic type '" + tpe + "' cannot be printed as a type")
- def typeParamsToString(tps: List[Symbol]): String = if(tps isEmpty) "" else
+ def typeParamsToString(tps: List[Symbol]): String = if (tps.isEmpty) "" else
tps.map{tparam =>
tparam.varianceString + tparam.name + typeParamsToString(tparam.typeParams)
}.mkString("[", ", ", "]")
@@ -692,8 +721,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) {
}
def templateShouldDocument(aSym: Symbol): Boolean = {
- // TODO: document sourceless entities (e.g., Any, etc), based on a new Setting to be added
- (aSym.isPackageClass || (aSym.sourceFile != null)) && localShouldDocument(aSym) &&
+ // TODO: document sourceless entities (e.g., Any, etc), based on a new Setting to be added
+ (aSym.isPackageClass || (aSym.sourceFile != null)) && localShouldDocument(aSym) &&
( aSym.owner == NoSymbol || templateShouldDocument(aSym.owner) ) && !isEmptyJavaObject(aSym)
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
new file mode 100644
index 0000000000..61f3670f5f
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactoryImplicitSupport.scala
@@ -0,0 +1,520 @@
+/* NSC -- new Scala compiler -- Copyright 2007-2012 LAMP/EPFL
+ *
+ * This trait finds implicit conversions for a class in the default scope and creates scaladoc entries for each of them.
+ *
+ * @author Vlad Ureche
+ * @author Adriaan Moors
+ */
+
+package scala.tools.nsc
+package doc
+package model
+
+import comment._
+
+import scala.collection._
+import scala.util.matching.Regex
+
+import symtab.Flags
+import io._
+
+import model.{ RootPackage => RootPackageEntity }
+
+/**
+ * This trait finds implicit conversions for a class in the default scope and creates scaladoc entries for each of them.
+ *
+ * Let's take this as an example:
+ * {{{
+ * object Test {
+ * class A
+ *
+ * class B {
+ * def foo = 1
+ * }
+ *
+ * class C extends B {
+ * def bar = 2
+ * class implicit
+ * }
+ *
+ * D def conv(a: A) = new C
+ * }
+ * }}}
+ *
+ * Overview:
+ * - scaladoc-ing the above classes, `A` will get two more methods: foo and bar, over its default methods
+ * - the nested classes (specifically `D` above), abstract types, type aliases and constructor members are not added to
+ * `A` (see makeMember0 in ModelFactory, last 3 cases)
+ * - the members added by implicit conversion are always listed under the implicit conversion, not under the class they
+ * actually come from (`foo` will be listed as coming from the implicit conversion to `C` instead of `B`) - see
+ * `definitionName` in MemberImpl
+ *
+ * Internals:
+ * TODO: Give an overview here
+ */
+trait ModelFactoryImplicitSupport {
+ thisFactory: ModelFactory with CommentFactory with TreeFactory =>
+
+ import global._
+ import global.analyzer._
+ import global.definitions._
+ import settings.hardcoded
+
+ // debugging:
+ val DEBUG: Boolean = settings.docImplicitsDebug.value
+ val ERROR: Boolean = true // currently we show all errors
+ @inline final def debug(msg: => String) = if (DEBUG) println(msg)
+ @inline final def error(msg: => String) = if (ERROR) println(msg)
+
+ /** This is a flag that indicates whether to eliminate implicits that cannot be satisfied within the current scope.
+ * For example, if an implicit conversion requires that there is a Numeric[T] in scope:
+ * {{{
+ * class A[T]
+ * class B extends A[Int]
+ * class C extends A[String]
+ * implicit def pimpA[T: Numeric](a: A[T]): D
+ * }}}
+ * For B, no constraints are generated as Numeric[Int] is already in the default scope. On the other hand, for the
+ * conversion from C to D, depending on -implicits-show-all, the conversion can:
+ * - not be generated at all, since there's no Numeric[String] in scope (if ran without -implicits-show-all)
+ * - generated with a *weird* constraint, Numeric[String] as the user might add it by hand (if flag is enabled)
+ */
+ val implicitsShowAll: Boolean = settings.docImplicitsShowAll.value
+ class ImplicitNotFound(tpe: Type) extends Exception("No implicit of type " + tpe + " found in scope.")
+
+ /* ============== IMPLEMENTATION PROVIDING ENTITY TYPES ============== */
+
+ class ImplicitConversionImpl(
+ val sym: Symbol,
+ val convSym: Symbol,
+ val toType: Type,
+ val constrs: List[Constraint],
+ inTpl: => DocTemplateImpl)
+ extends ImplicitConversion {
+
+ def source: DocTemplateEntity = inTpl
+
+ def targetType: TypeEntity = makeType(toType, inTpl)
+
+ def convertorOwner: TemplateEntity =
+ if (convSym != NoSymbol)
+ makeTemplate(convSym.owner)
+ else {
+ error("Scaladoc implicits: Implicit conversion from " + sym.tpe + " to " + toType + " done by " + convSym + " = NoSymbol!")
+ makeRootPackage.get // surely the root package was created :)
+ }
+
+ def convertorMethod: Either[MemberEntity, String] = {
+ var convertor: MemberEntity = null
+
+ convertorOwner match {
+ case doc: DocTemplateImpl =>
+ val convertors = members.collect { case m: MemberImpl if m.sym == convSym => m }
+ if (convertors.length == 1)
+ convertor = convertors.head
+ case _ =>
+ }
+ if (convertor ne null)
+ Left(convertor)
+ else
+ Right(convSym.nameString)
+ }
+
+ def conversionShortName = convSym.nameString
+
+ def conversionQualifiedName = convertorOwner.qualifiedName + "." + convSym.nameString
+
+ lazy val constraints: List[Constraint] = constrs
+
+ val members: List[MemberEntity] = {
+ // Obtain the members inherited by the implicit conversion
+ var memberSyms = toType.members.filter(implicitShouldDocument(_))
+ val existingMembers = sym.info.members
+
+ // Debugging part :)
+ debug(sym.nameString + "\n" + "=" * sym.nameString.length())
+ debug(" * conversion " + convSym + " from " + sym.tpe + " to " + toType)
+
+ // Members inherited by implicit conversions cannot override actual members
+ memberSyms = memberSyms.filterNot((sym1: Symbol) =>
+ existingMembers.exists(sym2 => sym1.name == sym2.name &&
+ !isDistinguishableFrom(toType.memberInfo(sym1), sym.info.memberInfo(sym2))))
+
+ debug(" -> full type: " + toType)
+ if (constraints.length != 0) {
+ debug(" -> constraints: ")
+ constraints foreach { constr => debug(" - " + constr) }
+ }
+ debug(" -> members:")
+ memberSyms foreach (sym => debug(" - "+ sym.decodedName +" : " + sym.info))
+ debug("")
+
+ memberSyms.flatMap((makeMember(_, this, inTpl)))
+ }
+ }
+
+ /* ============== MAKER METHODS ============== */
+
+ /**
+ * Make the implicit conversion objects
+ *
+ * A word about the scope of the implicit conversions: currently we look at a very basic context composed of the
+ * default Scala imports (Predef._ for example) and the companion object of the current class, if one exists. In the
+ * future we might want to extend this to more complex scopes.
+ */
+ def makeImplicitConversions(sym: Symbol, inTpl: => DocTemplateImpl): List[ImplicitConversion] =
+ // Nothing and Null are somewhat special -- they can be transformed by any implicit conversion available in scope.
+ // But we don't want that, so we'll simply refuse to find implicit conversions on for Nothing and Null
+ if (!(sym.isClass || sym.isTrait || sym == AnyRefClass) || sym == NothingClass || sym == NullClass) Nil
+ else {
+ var context: global.analyzer.Context = global.analyzer.rootContext(NoCompilationUnit)
+
+ val results = global.analyzer.allViewsFrom(sym.tpe, context, sym.typeParams)
+ var conversions = results.flatMap(result => makeImplicitConversion(sym, result._1, result._2, context, inTpl))
+ conversions = conversions.filterNot(_.members.isEmpty)
+
+ // Filter out specialized conversions from array
+ if (sym == ArrayClass)
+ conversions = conversions.filterNot((conv: ImplicitConversion) =>
+ hardcoded.arraySkipConversions.contains(conv.conversionQualifiedName))
+
+ // Filter out non-sensical conversions from value types
+ if (isScalaValueType(sym.tpe))
+ conversions = conversions.filter((ic: ImplicitConversion) =>
+ hardcoded.valueClassFilter(sym.nameString, ic.conversionQualifiedName))
+
+ // Put the class-specific conversions in front
+ val (ownConversions, commonConversions) =
+ conversions.partition(conv => !hardcoded.commonConversionTargets.contains(conv.conversionQualifiedName))
+
+ ownConversions ::: commonConversions
+ }
+
+ /** makeImplicitConversion performs the heavier lifting to get the implicit listing:
+ * - for each possible conversion function (also called view)
+ * * figures out the final result of the view (to what is our class transformed?)
+ * * figures out the necessary constraints on the type parameters (such as T <: Int) and the context (such as Numeric[T])
+ * * lists all inherited members
+ *
+ * What? in details:
+ * - say we start from a class A[T1, T2, T3, T4]
+ * - we have an implicit function (view) in scope:
+ * def pimpA[T3 <: Long, T4](a: A[Int, Foo[Bar[X]], T3, T4])(implicit ev1: TypeTag[T4], ev2: Numeric[T4]): PimpedA
+ * - A is converted to PimpedA ONLY if a couple of constraints are satisfied:
+ * * T1 must be equal to Int
+ * * T2 must be equal to Foo[Bar[X]]
+ * * T3 must be upper bounded by Long
+ * * there must be evidence of Numeric[T4] and a TypeTag[T4] within scope
+ * - the final type is PimpedA and A therefore inherits a couple of members from pimpedA
+ *
+ * How?
+ * some notes:
+ * - Scala's type inference will want to solve all type parameters down to actual types, but we only want constraints
+ * to maintain generality
+ * - therefore, allViewsFrom wraps type parameters into "untouchable" type variables that only gather constraints,
+ * but are never solved down to a type
+ * - these must be reverted back to the type parameters and the constraints must be extracted and simplified (this is
+ * done by the uniteConstraints and boundedTParamsConstraints. Be sure to check them out
+ * - we also need to transform implicit parameters in the view's signature into constraints, such that Numeric[T4]
+ * appears as a constraint
+ */
+ def makeImplicitConversion(sym: Symbol, result: SearchResult, constrs: List[TypeConstraint], context: Context, inTpl: => DocTemplateImpl): List[ImplicitConversion] =
+ if (result.tree == EmptyTree) Nil
+ else {
+ // `result` will contain the type of the view (= implicit conversion method)
+ // the search introduces untouchable type variables, but we want to get back to type parameters
+ val viewFullType = result.tree.tpe
+ // set the previously implicit parameters to being explicit
+
+ val (viewSimplifiedType, viewImplicitTypes) = removeImplicitParameters(viewFullType)
+
+ // TODO: Isolate this corner case :) - Predef.<%< and put it in the testsuite
+ if (viewSimplifiedType.params.length != 1) {
+ // This is known to be caused by the `<%<` object in Predef:
+ // {{{
+ // sealed abstract class <%<[-From, +To] extends (From => To) with Serializable
+ // object <%< {
+ // implicit def conformsOrViewsAs[A <% B, B]: A <%< B = new (A <%< B) {def apply(x: A) = x}
+ // }
+ // }}}
+ // so we just won't generate an implicit conversion for implicit methods that only take implicit parameters
+ return Nil
+ }
+
+ // type the view application so we get the exact type of the result (not the formal type)
+ val viewTree = result.tree.setType(viewSimplifiedType)
+ val appliedTree = new ApplyImplicitView(viewTree, List(Ident("<argument>") setType viewTree.tpe.paramTypes.head))
+ val appliedTreeTyped: Tree = {
+ val newContext = context.makeImplicit(context.ambiguousErrors)
+ newContext.macrosEnabled = false // [Eugene] I assume you want macro signature, not macro expansion
+ val newTyper = global.analyzer.newTyper(newContext)
+ newTyper.silent(_.typed(appliedTree, global.analyzer.EXPRmode, WildcardType), false) match {
+
+ case global.analyzer.SilentResultValue(t: Tree) => t
+ case global.analyzer.SilentTypeError(err) =>
+ global.reporter.warning(sym.pos, err.toString)
+ return Nil
+ }
+ }
+
+ // now we have the final type:
+ val toType = wildcardToNothing(typeVarToOriginOrWildcard(appliedTreeTyped.tpe.finalResultType))
+
+ try {
+ // Transform bound constraints into scaladoc constraints
+ val implParamConstraints = makeImplicitConstraints(viewImplicitTypes, sym, context, inTpl)
+ val boundsConstraints = makeBoundedConstraints(sym.typeParams, constrs, inTpl)
+ // TODO: no substitution constraints appear in the library and compiler scaladoc. Maybe they can be removed?
+ val substConstraints = makeSubstitutionConstraints(result.subst, inTpl)
+ val constraints = implParamConstraints ::: boundsConstraints ::: substConstraints
+
+ List(new ImplicitConversionImpl(sym, result.tree.symbol, toType, constraints, inTpl))
+ } catch {
+ case i: ImplicitNotFound =>
+ //println(" Eliminating: " + toType)
+ Nil
+ }
+ }
+
+ def makeImplicitConstraints(types: List[Type], sym: Symbol, context: Context, inTpl: => DocTemplateImpl): List[Constraint] =
+ types.flatMap((tpe:Type) => {
+ // TODO: Before creating constraints, map typeVarToOriginOrWildcard on the implicitTypes
+ val implType = typeVarToOriginOrWildcard(tpe)
+ val qualifiedName = implType.typeSymbol.ownerChain.reverse.map(_.nameString).mkString(".")
+
+ var available: Option[Boolean] = None
+
+ // see: https://groups.google.com/forum/?hl=en&fromgroups#!topic/scala-internals/gm_fr0RKzC4
+ //
+ // println(implType + " => " + implType.isTrivial)
+ // var tpes: List[Type] = List(implType)
+ // while (!tpes.isEmpty) {
+ // val tpe = tpes.head
+ // tpes = tpes.tail
+ // tpe match {
+ // case TypeRef(pre, sym, args) =>
+ // tpes = pre :: args ::: tpes
+ // println(tpe + " => " + tpe.isTrivial)
+ // case _ =>
+ // println(tpe + " (of type" + tpe.getClass + ") => " + tpe.isTrivial)
+ // }
+ // }
+ // println("\n")
+
+ // look for type variables in the type. If there are none, we can decide if the implicit is there or not
+ if (implType.isTrivial) {
+ try {
+ context.flushBuffer() /* any errors here should not prevent future findings */
+ // TODO: Not sure this is the right thing to do -- seems similar to what scalac should be doing
+ val context2 = context.make(context.unit, context.tree, sym.owner, context.scope, context.imports)
+ val search = inferImplicit(EmptyTree, tpe, false, false, context2, false)
+ context.flushBuffer() /* any errors here should not prevent future findings */
+
+ available = Some(search.tree != EmptyTree)
+ } catch {
+ case _ =>
+ }
+ }
+
+ available match {
+ case Some(true) =>
+ Nil
+ case Some(false) if (!implicitsShowAll) =>
+ // if -implicits-show-all is not set, we get rid of impossible conversions (such as Numeric[String])
+ throw new ImplicitNotFound(implType)
+ case _ =>
+ val typeParamNames = sym.typeParams.map(_.name)
+
+ // TODO: This is maybe the worst hack I ever did - it's as dirty as hell, but it seems to work, so until I
+ // learn more about symbols, it'll have to do.
+ implType match {
+ case TypeRef(pre, sym, List(TypeRef(NoPrefix, targ, Nil))) if (typeParamNames contains targ.name) =>
+ hardcoded.knownTypeClasses.get(qualifiedName) match {
+ case Some(explanation) =>
+ List(new KnownTypeClassConstraint {
+ val typeParamName = targ.nameString
+ val typeExplanation = explanation
+ val typeClassEntity = makeTemplate(sym)
+ val implicitType: TypeEntity = makeType(implType, inTpl)
+ })
+ case None =>
+ List(new TypeClassConstraint {
+ val typeParamName = targ.nameString
+ val typeClassEntity = makeTemplate(sym)
+ val implicitType: TypeEntity = makeType(implType, inTpl)
+ })
+ }
+ case _ =>
+ List(new ImplicitInScopeConstraint{
+ val implicitType: TypeEntity = makeType(implType, inTpl)
+ })
+ }
+ }
+ })
+
+ def makeSubstitutionConstraints(subst: TreeTypeSubstituter, inTpl: => DocTemplateImpl): List[Constraint] =
+ (subst.from zip subst.to) map {
+ case (from, to) =>
+ new EqualTypeParamConstraint {
+ error("Scaladoc implicits: Unexpected type substitution constraint from: " + from + " to: " + to)
+ val typeParamName = from.toString
+ val rhs = makeType(to, inTpl)
+ }
+ }
+
+ def makeBoundedConstraints(tparams: List[Symbol], constrs: List[TypeConstraint], inTpl: => DocTemplateImpl): List[Constraint] =
+ (tparams zip constrs) flatMap {
+ case (tparam, constr) => {
+ uniteConstraints(constr) match {
+ case (loBounds, upBounds) => (loBounds filter (_ != NothingClass.tpe), upBounds filter (_ != AnyClass.tpe)) match {
+ case (Nil, Nil) =>
+ Nil
+ case (List(lo), List(up)) if (lo == up) =>
+ List(new EqualTypeParamConstraint {
+ val typeParamName = tparam.nameString
+ val rhs = makeType(lo, inTpl)
+ })
+ case (List(lo), List(up)) =>
+ List(new BoundedTypeParamConstraint {
+ val typeParamName = tparam.nameString
+ val lowerBound = makeType(lo, inTpl)
+ val upperBound = makeType(up, inTpl)
+ })
+ case (List(lo), Nil) =>
+ List(new LowerBoundedTypeParamConstraint {
+ val typeParamName = tparam.nameString
+ val lowerBound = makeType(lo, inTpl)
+ })
+ case (Nil, List(up)) =>
+ List(new UpperBoundedTypeParamConstraint {
+ val typeParamName = tparam.nameString
+ val upperBound = makeType(up, inTpl)
+ })
+ case other =>
+ // this is likely an error on the lub/glb side
+ error("Scaladoc implicits: Error computing lub/glb for: " + (tparam, constr) + ":\n" + other)
+ Nil
+ }
+ }
+ }
+ }
+
+ /**
+ * uniteConstraints takes a TypeConstraint instance and simplifies the constraints inside
+ *
+ * Normally TypeConstraint contains multiple lower and upper bounds, and we want to reduce this to a lower and an
+ * upper bound. Here are a couple of catches we need to be aware of:
+ * - before finding a view (implicit method in scope that maps class A[T1,T2,.. Tn] to something else) the type
+ * parameters are transformed into "untouchable" type variables so that type inference does not attempt to
+ * fully solve them down to a type but rather constrains them on both sides just enough for the view to be
+ * applicable -- now, we want to transform those type variables back to the original type parameters
+ * - some of the bounds fail type inference and therefore refer to Nothing => when performing unification (lub, glb)
+ * they start looking ugly => we (unsoundly) transform Nothing to WildcardType so we fool the unification algorithms
+ * into thinking there's nothing there
+ * - we don't want the wildcard types surviving the unification so we replace them back to Nothings
+ */
+ def uniteConstraints(constr: TypeConstraint): (List[Type], List[Type]) =
+ try {
+ (List(wildcardToNothing(lub(constr.loBounds map typeVarToOriginOrWildcard))),
+ List(wildcardToNothing(glb(constr.hiBounds map typeVarToOriginOrWildcard))))
+ } catch {
+ // does this actually ever happen? (probably when type vars occur in the bounds)
+ case x: Throwable => (constr.loBounds.distinct, constr.hiBounds.distinct)
+ }
+
+ /**
+ * Make implicits explicit - Not used curently
+ */
+ object implicitToExplicit extends TypeMap {
+ def apply(tp: Type): Type = mapOver(tp) match {
+ case MethodType(params, resultType) =>
+ MethodType(params.map(param => if (param.isImplicit) param.cloneSymbol.resetFlag(Flags.IMPLICIT) else param), resultType)
+ case other =>
+ other
+ }
+ }
+
+ /**
+ * removeImplicitParameters transforms implicit parameters from the view result type into constraints and
+ * returns the simplified type of the view
+ *
+ * for the example view:
+ * implicit def pimpMyClass[T](a: MyClass[T])(implicit ev: Numeric[T]): PimpedMyClass[T]
+ * the implicit view result type is:
+ * (a: MyClass[T])(implicit ev: Numeric[T]): PimpedMyClass[T]
+ * and the simplified type will be:
+ * MyClass[T] => PimpedMyClass[T]
+ */
+ def removeImplicitParameters(viewType: Type): (Type, List[Type]) = {
+
+ val params = viewType.paramss.flatten
+ val (normalParams, implParams) = params.partition(!_.isImplicit)
+ val simplifiedType = MethodType(normalParams, viewType.finalResultType)
+ val implicitTypes = implParams.map(_.tpe)
+
+ (simplifiedType, implicitTypes)
+ }
+
+ /**
+ * typeVarsToOriginOrWildcard transforms the "untouchable" type variables into either their origins (the original
+ * type parameters) or into wildcard types if nothing matches
+ */
+ object typeVarToOriginOrWildcard extends TypeMap {
+ def apply(tp: Type): Type = mapOver(tp) match {
+ case tv: TypeVar =>
+ if (tv.constr.inst.typeSymbol == NothingClass)
+ WildcardType
+ else
+ tv.origin //appliedType(tv.origin.typeConstructor, tv.typeArgs map this)
+ case other =>
+ if (other.typeSymbol == NothingClass)
+ WildcardType
+ else
+ other
+ }
+ }
+
+ /**
+ * wildcardToNothing transforms wildcard types back to Nothing
+ */
+ object wildcardToNothing extends TypeMap {
+ def apply(tp: Type): Type = mapOver(tp) match {
+ case WildcardType =>
+ NothingClass.tpe
+ case other =>
+ other
+ }
+ }
+
+ /** implicitShouldDocument decides whether a member inherited by implicit conversion should be documented */
+ def implicitShouldDocument(aSym: Symbol): Boolean = {
+ // We shouldn't document:
+ // - constructors
+ // - common methods (in Any, AnyRef, Object) as they are automatically removed
+ // - private and protected members (not accessible following an implicit conversion)
+ // - members starting with _ (usually reserved for internal stuff)
+ localShouldDocument(aSym) && (!aSym.isConstructor) && (aSym.owner != ObjectClass) &&
+ (aSym.owner != AnyClass) && (aSym.owner != AnyRefClass) &&
+ (!aSym.isProtected) && (!aSym.isPrivate) && (!aSym.name.startsWith("_")) &&
+ (aSym.isMethod || aSym.isGetter || aSym.isSetter) &&
+ (aSym.nameString != "getClass")
+ }
+
+ /* To put it very bluntly: checks if you can call implicitly added method with t1 when t2 is already there in the
+ * class. We suppose the name of the two members coincides
+ *
+ * The trick here is that the resultType does not matter - the condition for removal it that paramss have the same
+ * structure (A => B => C may not override (A, B) => C) and that all the types involved are
+ * of the implcit conversion's member are subtypes of the parent members' parameters */
+ def isDistinguishableFrom(t1: Type, t2: Type): Boolean =
+ if (t1.paramss.map(_.length) == t2.paramss.map(_.length)) {
+ for ((t1p, t2p) <- t1.paramss.flatten zip t2.paramss.flatten)
+ if (!isSubType(t1 memberInfo t1p, t2 memberInfo t2p))
+ return true // if on the corresponding parameter you give a type that is in t1 but not in t2
+ // example:
+ // def foo(a: Either[Int, Double]): Int = 3
+ // def foo(b: Left[T1]): Int = 6
+ // a.foo(Right(4.5d)) prints out 3 :)
+ false
+ } else true // the member structure is different foo(3, 5) vs foo(3)(5)
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
index 988f2e0ba9..f948d53c8b 100755
--- a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
@@ -52,7 +52,7 @@ trait TreeFactory { thisTreeFactory: ModelFactory with TreeFactory =>
if (asym.isSetter) asym = asym.getter(asym.owner)
makeTemplate(asym.owner) match {
case docTmpl: DocTemplateImpl =>
- val mbrs: List[MemberImpl] = makeMember(asym,docTmpl)
+ val mbrs: List[MemberImpl] = makeMember(asym, null, docTmpl)
mbrs foreach { mbr => refs += ((start, (mbr,end))) }
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
index bc5cd4a958..e6bc76f676 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -13,6 +13,7 @@ import scala.collection._
import scala.util.matching.Regex
import scala.annotation.switch
import util.{NoPosition, Position}
+import language.postfixOps
/** The comment parser transforms raw comment strings into `Comment` objects.
* Call `parse` to run the parser. Note that the parser is stateless and
diff --git a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala
index 2ef34cdd96..0f89236861 100644
--- a/src/compiler/scala/tools/nsc/interactive/BuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/BuildManager.scala
@@ -13,6 +13,7 @@ import util.FakePos
import dependencies._
import io.AbstractFile
+import language.implicitConversions
trait BuildManager {
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 166b38f503..ec73af4dca 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -19,6 +19,7 @@ import scala.tools.nsc.io.Pickler._
import scala.tools.nsc.typechecker.DivergentImplicit
import scala.annotation.tailrec
import symtab.Flags.{ACCESSOR, PARAMACCESSOR}
+import language.implicitConversions
/** The main class of the presentation compiler in an interactive environment such as an IDE
*/
@@ -434,6 +435,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
private def newRunnerThread(): Thread = {
threadId += 1
compileRunner = new PresentationCompilerThread(this, projectName)
+ compileRunner.setDaemon(true)
compileRunner.start()
compileRunner
}
@@ -529,6 +531,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
unit.defined.clear()
unit.synthetics.clear()
unit.toCheck.clear()
+ unit.checkedFeatures = Set()
unit.targetPos = NoPosition
unit.contexts.clear()
unit.problems.clear()
@@ -956,7 +959,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
if (ownerTpe.isErroneous) List()
else new ImplicitSearch(
tree, functionType(List(ownerTpe), AnyClass.tpe), isView = true,
- context.makeImplicit(reportAmbiguousErrors = false)).allImplicits
+ context0 = context.makeImplicit(reportAmbiguousErrors = false)).allImplicits
for (view <- applicableViews) {
val vtree = viewApply(view)
val vpre = stabilizedType(vtree)
diff --git a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala
index 88e3827403..49ba9d0aeb 100644
--- a/src/compiler/scala/tools/nsc/interactive/RangePositions.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RangePositions.scala
@@ -6,7 +6,7 @@ package scala.tools.nsc
package interactive
import ast.Trees
-import symtab.Positions
+import ast.Positions
import scala.tools.nsc.util.{SourceFile, Position, RangePosition, NoPosition, WorkScheduler}
import scala.collection.mutable.ListBuffer
@@ -269,7 +269,8 @@ self: scala.tools.nsc.Global =>
protected def isEligible(t: Tree) = !t.pos.isTransparent
override def traverse(t: Tree) {
t match {
- case tt : TypeTree if tt.original != null => traverse(tt.original)
+ case tt : TypeTree if tt.original != null && (tt.pos includes tt.original.pos) =>
+ traverse(tt.original)
case _ =>
if (t.pos includes pos) {
if (isEligible(t)) last = t
diff --git a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
index 34a0a4abb6..e2dcc48709 100644
--- a/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ScratchPadMaker.scala
@@ -79,7 +79,7 @@ trait ScratchPadMaker { self: Global =>
addSandbox(stat)
} else {
val resName = nextRes()
- val dispResName = resName filter ('$' !=)
+ val dispResName = resName filter ('$' != _)
patches += Patch(stat.pos.start, "val " + resName + " = ")
addSandbox(stat)
toPrint += resultString(nameType(dispResName, stat.tpe), resName)
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
index 7be115e777..9dc2a8de10 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
@@ -55,6 +55,7 @@ abstract class InteractiveTest
with AskShutdown
with AskReload
with AskLoadedTyped
+ with AskType
with PresentationCompilerInstance
with CoreTestDefs
with InteractiveTestSettings { self =>
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
index 35d6723818..657ef23eed 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
@@ -101,13 +101,13 @@ trait AskTypeAt extends AskCommand {
trait AskType extends AskCommand {
import compiler.Tree
- private[tests] def askType(source: SourceFile, forceReload: Boolean)(implicit reporter: Reporter): Response[Tree] = {
+ protected def askType(source: SourceFile, forceReload: Boolean)(implicit reporter: Reporter): Response[Tree] = {
ask {
compiler.askType(source, forceReload, _)
}
}
- private[tests] def askType(sources: Seq[SourceFile], forceReload: Boolean)(implicit reporter: Reporter): Seq[Response[Tree]] = {
+ protected def askType(sources: Seq[SourceFile], forceReload: Boolean)(implicit reporter: Reporter): Seq[Response[Tree]] = {
for(source <- sources) yield
askType(source, forceReload)
}
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala
index 40bbd3fa8e..d6102734ab 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/CoreTestDefs.scala
@@ -17,15 +17,11 @@ private[tests] trait CoreTestDefs
extends PresentationCompilerTestDef
with AskCompletionAt {
- object MemberPrinter {
- def apply(member: compiler.Member): String =
- "`" + (member.sym.toString() + member.tpe.toString()).trim() + "`"
- }
-
- protected val marker = CompletionMarker
+ def memberPrinter(member: compiler.Member): String =
+ "[accessible: %5s] ".format(member.accessible) + "`" + (member.sym.toString() + member.tpe.toString()).trim() + "`"
override def runTest() {
- askAllSources(marker) { pos =>
+ askAllSources(CompletionMarker) { pos =>
askCompletionAt(pos)
} { (pos, members) =>
withResponseDelimiter {
@@ -35,7 +31,7 @@ private[tests] trait CoreTestDefs
reporter.println("retrieved %d members".format(members.size))
compiler ask { () =>
val filtered = members.filterNot(member => member.sym.name.toString == "getClass" || member.sym.isConstructor)
- reporter.println(filtered.map(MemberPrinter(_)).sortBy(_.toString()).mkString("\n"))
+ reporter.println(filtered.map(memberPrinter).sortBy(_.toString()).mkString("\n"))
}
}
}
@@ -48,10 +44,8 @@ private[tests] trait CoreTestDefs
extends PresentationCompilerTestDef
with AskTypeAt {
- protected val marker = TypeMarker
-
override def runTest() {
- askAllSources(marker) { pos =>
+ askAllSources(TypeMarker) { pos =>
askTypeAt(pos)
} { (pos, tree) =>
withResponseDelimiter {
@@ -69,10 +63,8 @@ private[tests] trait CoreTestDefs
with AskTypeAt
with AskCompletionAt {
- protected val marker = HyperlinkMarker
-
override def runTest() {
- askAllSources(marker) { pos =>
+ askAllSources(HyperlinkMarker) { pos =>
askTypeAt(pos)(NullReporter)
} { (pos, tree) =>
if(tree.symbol == compiler.NoSymbol) {
@@ -81,7 +73,7 @@ private[tests] trait CoreTestDefs
else {
reporter.println("\naskHyperlinkPos for `" + tree.symbol.name + "` at " + format(pos) + " " + pos.source.file.name)
val r = new Response[Position]
- // `tree.symbol.sourceFile` was discovered to be null when testing -Yvirtpatmat on the akka presentation test, where a position had shifted to point to `Int`
+ // `tree.symbol.sourceFile` was discovered to be null when testing using virtpatmat on the akka presentation test, where a position had shifted to point to `Int`
// askHyperlinkPos for `Int` at (73,19) pi.scala --> class Int in package scala has null sourceFile!
val treePath = if (tree.symbol.sourceFile ne null) tree.symbol.sourceFile.path else null
val treeName = if (tree.symbol.sourceFile ne null) tree.symbol.sourceFile.name else null
@@ -90,8 +82,9 @@ private[tests] trait CoreTestDefs
compiler.askLinkPos(tree.symbol, source, r)
r.get match {
case Left(pos) =>
+ val resolvedPos = if (tree.symbol.pos.isDefined) tree.symbol.pos else pos
withResponseDelimiter {
- reporter.println("[response] found askHyperlinkPos for `" + tree.symbol.name + "` at " + format(pos) + " " + tree.symbol.sourceFile.name)
+ reporter.println("[response] found askHyperlinkPos for `" + tree.symbol.name + "` at " + format(resolvedPos) + " " + tree.symbol.sourceFile.name)
}
case Right(ex) =>
ex.printStackTrace()
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/FindOccurrences.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/FindOccurrences.scala
deleted file mode 100644
index e2a5a3e3ee..0000000000
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/FindOccurrences.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-package scala.tools.nsc
-package interactive
-package tests.core
-
-import scala.tools.nsc.util.Position
-import scala.tools.nsc.util.SourceFile
-
-/** Find occurrences of `text` in the passed `sources`. */
-private[core] object FindOccurrences {
-
- def apply(sources: Seq[SourceFile])(text: String): Map[SourceFile, Seq[Position]] =
- allPositionsOf(sources, text)
-
- /** All positions of the given string in all source files. */
- private def allPositionsOf(sources: Seq[SourceFile], str: String): Map[SourceFile, Seq[Position]] =
- (for (s <- sources; p <- positionsOf(s, str)) yield p).groupBy(_.source)
-
- /** Return all positions of the given str in the given source file. */
- private def positionsOf(source: SourceFile, str: String): Seq[Position] = {
- val buf = new collection.mutable.ListBuffer[Position]
- var pos = source.content.indexOfSlice(str)
- while (pos >= 0) {
- buf += source.position(pos - 1) // we need the position before the first character of this marker
- pos = source.content.indexOfSlice(str, pos + 1)
- }
- buf.toList
- }
-} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala
index c274e13976..d2baaf32c6 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerRequestsWorkingMode.scala
@@ -16,7 +16,7 @@ trait PresentationCompilerRequestsWorkingMode extends TestResources {
* ask the type at all positions marked with `TypeMarker.marker` and println the result.
*/
private def askAllSourcesAsync[T](marker: TestMarker)(askAt: Position => Response[T])(f: (Position, T) => Unit) {
- val positions = allPositionsOf(marker.marker).valuesIterator.toList.flatten
+ val positions = allPositionsOf(str = marker.marker)
val responses = for (pos <- positions) yield askAt(pos)
for ((pos, r) <- positions zip responses) withResponse(pos, r)(f)
@@ -26,13 +26,25 @@ trait PresentationCompilerRequestsWorkingMode extends TestResources {
* response before going to the next one.
*/
private def askAllSourcesSync[T](marker: TestMarker)(askAt: Position => Response[T])(f: (Position, T) => Unit) {
- val positions = allPositionsOf(marker.marker).valuesIterator.toList.flatten
+ val positions = allPositionsOf(str = marker.marker)
for (pos <- positions) withResponse(pos, askAt(pos))(f)
}
- private def allPositionsOf: String => Map[SourceFile, Seq[Position]] =
- FindOccurrences(sourceFiles) _
-
+ /** All positions of the given string in all source files. */
+ private def allPositionsOf(srcs: Seq[SourceFile] = sourceFiles, str: String): Seq[Position] =
+ for (s <- srcs; p <- positionsOf(s, str)) yield p
+
+ /** Return all positions of the given str in the given source file. */
+ private def positionsOf(source: SourceFile, str: String): Seq[Position] = {
+ val buf = new collection.mutable.ListBuffer[Position]
+ var pos = source.content.indexOfSlice(str)
+ while (pos >= 0) {
+ buf += source.position(pos - 1) // we need the position before the first character of this marker
+ pos = source.content.indexOfSlice(str, pos + 1)
+ }
+ buf.toList
+ }
+
private def withResponse[T](pos: Position, response: Response[T])(f: (Position, T) => Unit) {
/** Return the filename:line:col version of this position. */
def showPos(pos: Position): String =
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala
index 390363eca8..8b8be697cc 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerTestDef.scala
@@ -5,10 +5,6 @@ import scala.tools.nsc.util.Position
trait PresentationCompilerTestDef {
- def compiler: Global
-
- protected val marker: TestMarker
-
private[tests] def runTest(): Unit
protected def withResponseDelimiter(block: => Unit)(implicit reporter: Reporter) {
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala
index 518cb7bd76..21e90fe57f 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/SourcesCollector.scala
@@ -13,7 +13,7 @@ private[tests] object SourcesCollector {
* */
def apply(base: Path, filter: SourceFilter): Array[SourceFile] = {
assert(base.isDirectory)
- base.walk.filter(filter).map(source).toArray
+ base.walk.filter(filter).map(source).toList.toArray.sortBy(_.file.name)
}
private def source(file: Path): SourceFile = source(AbstractFile.getFile(file.toFile))
diff --git a/src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala
index 42a47896a2..453b106808 100644
--- a/src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/CodeHandlers.scala
@@ -17,9 +17,7 @@ import scala.util.control.ControlThrowable
trait CodeHandlers[T] {
self =>
- // Expressions are composed of operators and operands.
- def expr(code: String): T
-
+/*
// A declaration introduces names and assigns them types.
// It can form part of a class definition (§5.1) or of a refinement in a compound type (§3.2.7).
// (Ed: aka abstract members.)
@@ -34,6 +32,10 @@ trait CodeHandlers[T] {
// ‘val’ PatDef | ‘var’ VarDef | ‘def’ FunDef | ‘type’ {nl} TypeDef |
// [‘case’] ‘class’ ClassDef | [‘case’] ‘object’ ObjectDef | ‘trait’ TraitDef
def defn(code: String): T
+*/
+
+ // Expressions are composed of operators and operands.
+ def expr(code: String): T
// An import clause has the form import p.I where p is a stable identifier (§3.1) and I is an import expression.
def impt(code: String): T
@@ -52,9 +54,9 @@ trait CodeHandlers[T] {
case _: NoSuccess => Nil
}
+ // def decl(code: String) = try Some(self.decl(code)) catch handler
+ // def defn(code: String) = try Some(self.defn(code)) catch handler
def expr(code: String) = try Some(self.expr(code)) catch handler
- def decl(code: String) = try Some(self.decl(code)) catch handler
- def defn(code: String) = try Some(self.defn(code)) catch handler
def impt(code: String) = try Some(self.impt(code)) catch handler
def stmt(code: String) = try Some(self.stmt(code)) catch handler
def stmts(code: String) = try (self.stmts(code) map (x => Some(x))) catch handlerSeq
diff --git a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
index 68c8f2fdb8..0cd918b6a5 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ExprTyper.scala
@@ -22,8 +22,7 @@ trait ExprTyper {
object codeParser extends { val global: repl.global.type = repl.global } with CodeHandlers[Tree] {
def applyRule[T](code: String, rule: UnitParser => T): T = {
reporter.reset()
- val unit = new CompilationUnit(new BatchSourceFile("<console>", code))
- val scanner = new UnitParser(unit)
+ val scanner = newUnitParser(code)
val result = rule(scanner)
if (!reporter.hasErrors)
@@ -33,23 +32,17 @@ trait ExprTyper {
}
def tokens(code: String) = {
reporter.reset()
- val unit = new CompilationUnit(new BatchSourceFile("<tokens>", code))
- val in = new UnitScanner(unit)
+ val in = newUnitScanner(code)
in.init()
-
new Tokenizer(in) tokenIterator
}
- def decl(code: String) = CodeHandlers.fail("todo")
- def defn(code: String) = CodeHandlers.fail("todo")
+ def defns(code: String) = stmts(code) collect { case x: DefTree => x }
def expr(code: String) = applyRule(code, _.expr())
def impt(code: String) = applyRule(code, _.importExpr())
def impts(code: String) = applyRule(code, _.importClause())
- def stmts(code: String) = applyRule(code, _.templateStatSeq(false)._2)
- def stmt(code: String) = stmts(code) match {
- case List(t) => t
- case xs => CodeHandlers.fail("Not a single statement: " + xs.mkString(", "))
- }
+ def stmts(code: String) = applyRule(code, _.templateStats())
+ def stmt(code: String) = stmts(code).last // guaranteed nonempty
}
/** Parse a line into a sequence of trees. Returns None if the input is incomplete. */
@@ -62,77 +55,69 @@ trait ExprTyper {
else Some(trees)
}
}
- def tokens(line: String) = beQuietDuring(codeParser.tokens(line))
+ // def parsesAsExpr(line: String) = {
+ // import codeParser._
+ // (opt expr line).isDefined
+ // }
- // TODO: integrate these into a CodeHandler[Type].
+ def symbolOfLine(code: String): Symbol = {
+ def asExpr(): Symbol = {
+ val name = freshInternalVarName()
+ // Typing it with a lazy val would give us the right type, but runs
+ // into compiler bugs with things like existentials, so we compile it
+ // behind a def and strip the NullaryMethodType which wraps the expr.
+ val line = "def " + name + " = {\n" + code + "\n}"
+
+ interpretSynthetic(line) match {
+ case IR.Success =>
+ val sym0 = symbolOfTerm(name)
+ // drop NullaryMethodType
+ val sym = sym0.cloneSymbol setInfo afterTyper(sym0.info.finalResultType)
+ if (sym.info.typeSymbol eq UnitClass) NoSymbol
+ else sym
+ case _ => NoSymbol
+ }
+ }
+ def asDefn(): Symbol = {
+ val old = repl.definedSymbolList.toSet
+
+ interpretSynthetic(code) match {
+ case IR.Success =>
+ repl.definedSymbolList filterNot old match {
+ case Nil => NoSymbol
+ case sym :: Nil => sym
+ case syms => NoSymbol.newOverloaded(NoPrefix, syms)
+ }
+ case _ => NoSymbol
+ }
+ }
+ beQuietDuring(asExpr()) orElse beQuietDuring(asDefn())
+ }
- // XXX literals.
- // 1) Identifiers defined in the repl.
- // 2) A path loadable via getModule.
- // 3) Try interpreting it as an expression.
private var typeOfExpressionDepth = 0
def typeOfExpression(expr: String, silent: Boolean = true): Type = {
- repltrace("typeOfExpression(" + expr + ")")
if (typeOfExpressionDepth > 2) {
repldbg("Terminating typeOfExpression recursion for expression: " + expr)
return NoType
}
-
- def asQualifiedImport: Type = {
- val name = expr.takeWhile(_ != '.')
- typeOfExpression(importedTermNamed(name).fullName + expr.drop(name.length), true)
- }
- def asModule: Type = getModuleIfDefined(expr).tpe
- def asExpr: Type = {
- val lhs = freshInternalVarName()
- val line = "lazy val " + lhs + " =\n" + expr
-
- interpret(line, true) match {
- case IR.Success => typeOfExpression(lhs, true)
- case _ => NoType
- }
- }
-
- def evaluate(): Type = {
- typeOfExpressionDepth += 1
- try typeOfTerm(expr) orElse asModule orElse asExpr orElse asQualifiedImport
- finally typeOfExpressionDepth -= 1
- }
-
+ typeOfExpressionDepth += 1
// Don't presently have a good way to suppress undesirable success output
// while letting errors through, so it is first trying it silently: if there
// is an error, and errors are desired, then it re-evaluates non-silently
// to induce the error message.
- beSilentDuring(evaluate()) orElse beSilentDuring(typeOfDeclaration(expr)) orElse {
- if (!silent)
- evaluate()
-
- NoType
+ try beSilentDuring(symbolOfLine(expr).tpe) match {
+ case NoType if !silent => symbolOfLine(expr).tpe // generate error
+ case tpe => tpe
}
+ finally typeOfExpressionDepth -= 1
}
- // Since people will be giving us ":t def foo = 5" even though that is not an
- // expression, we have a means of typing declarations too.
- private def typeOfDeclaration(code: String): Type = {
- repltrace("typeOfDeclaration(" + code + ")")
- val obname = freshInternalVarName()
- interpret("object " + obname + " {\n" + code + "\n}\n", true) match {
- case IR.Success =>
- val sym = symbolOfTerm(obname)
- if (sym == NoSymbol) NoType else {
- // TODO: bitmap$n is not marked synthetic.
- val decls = sym.tpe.decls.toList filterNot (x => x.isConstructor || x.isPrivate || (x.name.toString contains "$"))
- repltrace("decls: " + decls)
- if (decls.isEmpty) NoType
- else typeCleanser(sym, decls.last.name)
- }
- case _ =>
- NoType
- }
- }
+ def tokens(line: String) = beQuietDuring(codeParser.tokens(line))
+
+ // In the todo column
+ //
// def compileAndTypeExpr(expr: String): Option[Typer] = {
// class TyperRun extends Run {
// override def stopPhase(name: String) = name == "superaccessors"
// }
- // }
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index e1ea69842f..297d6ad1b9 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -23,6 +23,7 @@ import scala.reflect.NameTransformer._
import util.ScalaClassLoader
import ScalaClassLoader._
import scala.tools.util._
+import language.{implicitConversions, existentials}
/** The Scala interactive shell. It provides a read-eval-print loop
* around the Interpreter class.
@@ -48,12 +49,60 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
var settings: Settings = _
var intp: IMain = _
- override def echoCommandMessage(msg: String): Unit =
- intp.reporter.printMessage(msg)
+ /** Having inherited the difficult "var-ness" of the repl instance,
+ * I'm trying to work around it by moving operations into a class from
+ * which it will appear a stable prefix.
+ */
+ private def onIntp[T](f: IMain => T): T = f(intp)
+
+ class IMainOps[T <: IMain](val intp: T) {
+ import intp._
+ import global._
+
+ def printAfterTyper(msg: => String) =
+ intp.reporter printUntruncatedMessage afterTyper(msg)
+
+ /** Strip NullaryMethodType artifacts. */
+ private def replInfo(sym: Symbol) = {
+ sym.info match {
+ case NullaryMethodType(restpe) if sym.isAccessor => restpe
+ case info => info
+ }
+ }
+ def echoTypeStructure(sym: Symbol) =
+ printAfterTyper("" + deconstruct.show(replInfo(sym)))
+
+ def echoTypeSignature(sym: Symbol, verbose: Boolean) = {
+ if (verbose) ILoop.this.echo("// Type signature")
+ printAfterTyper("" + replInfo(sym))
+
+ if (verbose) {
+ ILoop.this.echo("\n// Internal Type structure")
+ echoTypeStructure(sym)
+ }
+ }
+ }
+ implicit def stabilizeIMain(intp: IMain) = new IMainOps[intp.type](intp)
+
+ /** TODO -
+ * -n normalize
+ * -l label with case class parameter names
+ * -c complete - leave nothing out
+ */
+ private def typeCommandInternal(expr: String, verbose: Boolean): Result = {
+ onIntp { intp =>
+ val sym = intp.symbolOfLine(expr)
+ if (sym.exists) intp.echoTypeSignature(sym, verbose)
+ else ""
+ }
+ }
+
+ override def echoCommandMessage(msg: String) {
+ intp.reporter printUntruncatedMessage msg
+ }
def isAsync = !settings.Yreplsync.value
lazy val power = new Power(intp, new StdReplVals(this))
- lazy val NoType = intp.global.NoType
// TODO
// object opt extends AestheticSettings
@@ -248,7 +297,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
// nullary("reset", "reset the interpreter, forgetting session values but retaining session types", replay),
shCommand,
nullary("silent", "disable/enable automatic printing of results", verbosity),
- cmd("type", "<expr>", "display the type of an expression without evaluating it", typeCommand),
+ cmd("type", "[-v] <expr>", "display the type of an expression without evaluating it", typeCommand),
nullary("warnings", "show the suppressed warnings from the most recent line which had any", warningsCommand)
)
@@ -321,10 +370,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
}
- private def implicitsCommand(line: String): Result = {
- val intp = ILoop.this.intp
+ private def implicitsCommand(line: String): Result = onIntp { intp =>
import intp._
- import global.{ Symbol, afterTyper }
+ import global._
def p(x: Any) = intp.reporter.printMessage("" + x)
@@ -435,14 +483,14 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
private lazy val javap = substituteAndLog[Javap]("javap", NoJavap)(newJavap())
// Still todo: modules.
- private def typeCommand(line: String): Result = {
- if (line.trim == "") ":type <expression>"
- else {
- val tp = intp.typeOfExpression(line, false)
- if (tp == NoType) "" // the error message was already printed
- else intp.global.afterTyper(tp.toString)
+ private def typeCommand(line0: String): Result = {
+ line0.trim match {
+ case "" => ":type [-v] <expression>"
+ case s if s startsWith "-v " => typeCommandInternal(s stripPrefix "-v " trim, true)
+ case s => typeCommandInternal(s, false)
}
}
+
private def warningsCommand(): Result = {
intp.lastWarnings foreach { case (pos, msg) => intp.reporter.warning(pos, msg) }
}
@@ -470,33 +518,34 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
private def wrapCommand(line: String): Result = {
def failMsg = "Argument to :wrap must be the name of a method with signature [T](=> T): T"
- val intp = ILoop.this.intp
- val g: intp.global.type = intp.global
- import g._
-
- words(line) match {
- case Nil =>
- intp.executionWrapper match {
- case "" => "No execution wrapper is set."
- case s => "Current execution wrapper: " + s
- }
- case "clear" :: Nil =>
- intp.executionWrapper match {
- case "" => "No execution wrapper is set."
- case s => intp.clearExecutionWrapper() ; "Cleared execution wrapper."
- }
- case wrapper :: Nil =>
- intp.typeOfExpression(wrapper) match {
- case PolyType(List(targ), MethodType(List(arg), restpe)) =>
- intp setExecutionWrapper intp.pathToTerm(wrapper)
- "Set wrapper to '" + wrapper + "'"
- case tp =>
- failMsg + (
- if (tp == g.NoType) "\nFound: <unknown>"
- else "\nFound: <unknown>"
- )
- }
- case _ => failMsg
+ onIntp { intp =>
+ import intp._
+ import global._
+
+ words(line) match {
+ case Nil =>
+ intp.executionWrapper match {
+ case "" => "No execution wrapper is set."
+ case s => "Current execution wrapper: " + s
+ }
+ case "clear" :: Nil =>
+ intp.executionWrapper match {
+ case "" => "No execution wrapper is set."
+ case s => intp.clearExecutionWrapper() ; "Cleared execution wrapper."
+ }
+ case wrapper :: Nil =>
+ intp.typeOfExpression(wrapper) match {
+ case PolyType(List(targ), MethodType(List(arg), restpe)) =>
+ intp setExecutionWrapper intp.pathToTerm(wrapper)
+ "Set wrapper to '" + wrapper + "'"
+ case tp =>
+ failMsg + (
+ if (tp == NoType) "\nFound: <unknown>"
+ else "\nFound: <unknown>"
+ )
+ }
+ case _ => failMsg
+ }
}
}
@@ -797,6 +846,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
})
}
+ def runCompletion =
+ try in.completion execute code map (intp bindSyntheticValue _)
+ catch { case ex: Exception => None }
+
/** Here we place ourselves between the user and the interpreter and examine
* the input they are ostensibly submitting. We intervene in several cases:
*
@@ -814,27 +867,28 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
else if (Completion.looksLikeInvocation(code) && intp.mostRecentVar != "") {
interpretStartingWith(intp.mostRecentVar + code)
}
- else {
- def runCompletion = in.completion execute code map (intp bindValue _)
- /** Due to my accidentally letting file completion execution sneak ahead
- * of actual parsing this now operates in such a way that the scala
- * interpretation always wins. However to avoid losing useful file
- * completion I let it fail and then check the others. So if you
- * type /tmp it will echo a failure and then give you a Directory object.
- * It's not pretty: maybe I'll implement the silence bits I need to avoid
- * echoing the failure.
- */
- if (intp isParseable code) {
- val (code, result) = reallyInterpret
- if (power != null && code == IR.Error)
- runCompletion
-
- result
- }
- else runCompletion match {
- case Some(_) => None // completion hit: avoid the latent error
- case _ => reallyInterpret._2 // trigger the latent error
- }
+ else if (code.trim startsWith "//") {
+ // line comment, do nothing
+ None
+ }
+ /** Due to my accidentally letting file completion execution sneak ahead
+ * of actual parsing this now operates in such a way that the scala
+ * interpretation always wins. However to avoid losing useful file
+ * completion I let it fail and then check the others. So if you
+ * type /tmp it will echo a failure and then give you a Directory object.
+ * It's not pretty: maybe I'll implement the silence bits I need to avoid
+ * echoing the failure.
+ */
+ else if (intp isParseable code) {
+ val (code, result) = reallyInterpret
+ if (power != null && code == IR.Error)
+ runCompletion
+
+ result
+ }
+ else runCompletion match {
+ case Some(_) => None // completion hit: avoid the latent error
+ case _ => reallyInterpret._2 // trigger the latent error
}
}
@@ -881,6 +935,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
case x => x
}
}
+ // Bind intp somewhere out of the regular namespace where
+ // we can get at it in generated code.
+ addThunk(intp.quietBind("$intp" -> intp))
loadFiles(settings)
// it is broken on startup; go ahead and exit
@@ -996,11 +1053,11 @@ object ILoop {
// provide the enclosing type T
// in order to set up the interpreter's classpath and parent class loader properly
- def breakIf[T: Manifest](assertion: => Boolean, args: NamedParam*): Unit =
+ def breakIf[T: ClassTag](assertion: => Boolean, args: NamedParam*): Unit =
if (assertion) break[T](args.toList)
// start a repl, binding supplied args
- def break[T: Manifest](args: List[NamedParam]): Unit = savingContextLoader {
+ def break[T: ClassTag](args: List[NamedParam]): Unit = savingContextLoader {
val msg = if (args.isEmpty) "" else " Binding " + args.size + " value%s.".format(
if (args.size == 1) "" else "s"
)
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
index 2f02748e8f..6a9654732b 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoopInit.scala
@@ -100,7 +100,7 @@ trait ILoopInit {
withLock { while (!initIsComplete) initLoopCondition.await() }
}
// private def warningsThunks = List(
- // () => intp.bind("lastWarnings", "" + manifest[List[(Position, String)]], intp.lastWarnings _),
+ // () => intp.bind("lastWarnings", "" + typeTag[List[(Position, String)]], intp.lastWarnings _),
// )
protected def postInitThunks = List[Option[() => Unit]](
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 9a12bc1471..a9c2ce0d09 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -23,6 +23,8 @@ import scala.collection.{ mutable, immutable }
import scala.util.control.Exception.{ ultimately }
import IMain._
import java.util.concurrent.Future
+import typechecker.Analyzer
+import language.implicitConversions
/** directory to save .class files to */
private class ReplVirtualDirectory(out: JPrintWriter) extends VirtualDirectory("(memory)", None) {
@@ -93,6 +95,11 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
private var _lineManager: Line.Manager = null // logic for individual lines
private val _compiler: Global = newCompiler(settings, reporter) // our private compiler
+ private val nextReqId = {
+ var counter = 0
+ () => { counter += 1 ; counter }
+ }
+
def compilerClasspath: Seq[URL] = (
if (isInitializeComplete) global.classPath.asURLs
else new PathResolver(settings).result.asURLs // the compiler's classpath
@@ -133,7 +140,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
lazy val formatting: Formatting = new Formatting {
val prompt = Properties.shellPromptString
}
- lazy val reporter: ConsoleReporter = new ReplReporter(this)
+ lazy val reporter: ReplReporter = new ReplReporter(this)
import formatting._
import reporter.{ printMessage, withoutTruncating }
@@ -149,6 +156,8 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
catch AbstractOrMissingHandler()
}
+ private def tquoted(s: String) = "\"\"\"" + s + "\"\"\""
+
// argument is a thunk to execute after init is done
def initialize(postInitSignal: => Unit) {
synchronized {
@@ -187,8 +196,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
import global._
import definitions.{
- ScalaPackage, JavaLangPackage, PredefModule, RootClass,
- getClassIfDefined, getModuleIfDefined, getRequiredModule, getRequiredClass
+ ScalaPackage, JavaLangPackage, RootClass,
+ getClassIfDefined, getModuleIfDefined, getRequiredModule, getRequiredClass,
+ termMember, typeMember
}
private implicit def privateTreeOps(t: Tree): List[Tree] = {
@@ -197,8 +207,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}).toList
}
- implicit def installReplTypeOps(tp: Type): ReplTypeOps = new ReplTypeOps(tp)
- class ReplTypeOps(tp: Type) {
+ implicit class ReplTypeOps(tp: Type) {
def orElse(other: => Type): Type = if (tp ne NoType) tp else other
def andAlso(fn: Type => Type): Type = if (tp eq NoType) tp else fn(tp)
}
@@ -220,6 +229,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
import naming._
+ object deconstruct extends {
+ val global: imain.global.type = imain.global
+ } with StructuredTypeStrings
+
// object dossiers extends {
// val intp: imain.type = imain
// } with Dossiers { }
@@ -269,11 +282,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
protected def createLineManager(classLoader: ClassLoader): Line.Manager = new Line.Manager(classLoader)
/** Instantiate a compiler. Overridable. */
- protected def newCompiler(settings: Settings, reporter: Reporter) = {
+ protected def newCompiler(settings: Settings, reporter: Reporter): ReplGlobal = {
settings.outputDirs setSingleOutput virtualDirectory
settings.exposeEmptyPackage.value = true
-
- Global(settings, reporter)
+ new Global(settings, reporter) with ReplGlobal
}
/** Parent classloader. Overridable. */
@@ -335,7 +347,14 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def getInterpreterClassLoader() = classLoader
// Set the current Java "context" class loader to this interpreter's class loader
- def setContextClassLoader() = classLoader.setAsContext()
+ def setContextClassLoader() = {
+ classLoader.setAsContext()
+
+ // this is risky, but it's our only possibility to make default reflexive mirror to work with REPL
+ // so far we have only used the default mirror to create a few tags for the compiler
+ // so it shouldn't be in conflict with our classloader, especially since it respects its parent
+ scala.reflect.mirror.classLoader = classLoader
+ }
/** Given a simple repl-defined name, returns the real name of
* the class representing it, e.g. for "Bippy" it may return
@@ -350,7 +369,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def flatName(id: String) = optFlatName(id) getOrElse id
def optFlatName(id: String) = requestForIdent(id) map (_ fullFlatName id)
- def allDefinedNames = definedNameMap.keys.toList sortBy (_.toString)
+ def allDefinedNames = definedNameMap.keys.toList.sorted
def pathToType(id: String): String = pathToName(newTypeName(id))
def pathToTerm(id: String): String = pathToName(newTermName(id))
def pathToName(name: Name): String = {
@@ -457,7 +476,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** Build a request from the user. `trees` is `line` after being parsed.
*/
- private def buildRequest(line: String, trees: List[Tree]): Request = new Request(line, trees)
+ private def buildRequest(line: String, trees: List[Tree]): Request = {
+ executingRequest = new Request(line, trees)
+ executingRequest
+ }
// rewriting "5 // foo" to "val x = { 5 // foo }" creates broken code because
// the close brace is commented out. Strip single-line comments.
@@ -505,7 +527,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
trees.last match {
case _:Assign => // we don't want to include assignments
case _:TermTree | _:Ident | _:Select => // ... but do want other unnamed terms.
- val varName = if (synthetic) freshInternalVarName() else ("" + freshUserTermName())
+ val varName = if (synthetic) freshInternalVarName() else freshUserVarName()
val rewrittenLine = (
// In theory this would come out the same without the 1-specific test, but
// it's a cushion against any more sneaky parse-tree position vs. code mismatches:
@@ -556,17 +578,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
Right(buildRequest(line, trees))
}
- def typeCleanser(sym: Symbol, memberName: Name): Type = {
- // the types are all =>T; remove the =>
- val tp1 = afterTyper(sym.info.nonPrivateDecl(memberName).tpe match {
- case NullaryMethodType(tp) => tp
- case tp => tp
- })
- // normalize non-public types so we don't see protected aliases like Self
- afterTyper(tp1 match {
- case TypeRef(_, sym, _) if !sym.isPublic => tp1.normalize
- case tp => tp
- })
+ // normalize non-public types so we don't see protected aliases like Self
+ def normalizeNonPublic(tp: Type) = tp match {
+ case TypeRef(_, sym, _) if sym.isAliasType && !sym.isPublic => tp.normalize
+ case _ => tp
}
/**
@@ -578,6 +593,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
* e.g. that there were no parse errors.
*/
def interpret(line: String): IR.Result = interpret(line, false)
+ def interpretSynthetic(line: String): IR.Result = interpret(line, true)
def interpret(line: String, synthetic: Boolean): IR.Result = {
def loadAndRunReq(req: Request) = {
val (result, succeeded) = req.loadAndRun
@@ -623,7 +639,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
* @param value the object value to bind to it
* @return an indication of whether the binding succeeded
*/
- def bind(name: String, boundType: String, value: Any): IR.Result = {
+ def bind(name: String, boundType: String, value: Any, modifiers: List[String] = Nil): IR.Result = {
val bindRep = new ReadEvalPrint()
val run = bindRep.compile("""
|object %s {
@@ -639,7 +655,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
IR.Error
case Right(_) =>
- val line = "val %s = %s.value".format(name, bindRep.evalPath)
+ val line = "%sval %s = %s.value".format(modifiers map (_ + " ") mkString, name, bindRep.evalPath)
repldbg("Interpreting: " + line)
interpret(line)
}
@@ -651,7 +667,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
result
}
def directBind(p: NamedParam): IR.Result = directBind(p.name, p.tpe, p.value)
- def directBind[T: Manifest](name: String, value: T): IR.Result = directBind((name, value))
+ def directBind[T: ClassTag](name: String, value: T): IR.Result = directBind((name, value))
def rebind(p: NamedParam): IR.Result = {
val name = p.name
@@ -667,11 +683,12 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
if (ids.isEmpty) IR.Success
else interpret("import " + ids.mkString(", "))
- def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p))
- def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
- def bind[T: Manifest](name: String, value: T): IR.Result = bind((name, value))
- def bindValue(x: Any): IR.Result = bindValue("" + freshUserTermName(), x)
- def bindValue(name: String, x: Any): IR.Result = bind(name, TypeStrings.fromValue(x), x)
+ def quietBind(p: NamedParam): IR.Result = beQuietDuring(bind(p))
+ def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
+ def bind[T: TypeTag](name: String, value: T): IR.Result = bind((name, value))
+ def bindSyntheticValue(x: Any): IR.Result = bindValue(freshInternalVarName(), x)
+ def bindValue(x: Any): IR.Result = bindValue(freshUserVarName(), x)
+ def bindValue(name: String, x: Any): IR.Result = bind(name, TypeStrings.fromValue(x), x)
/** Reset this interpreter, forgetting all user-specified requests. */
def reset() {
@@ -790,9 +807,9 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
*/
def resolvePathToSymbol(accessPath: String): Symbol = {
val readRoot = getRequiredModule(readPath) // the outermost wrapper
- (accessPath split '.').foldLeft(readRoot) { (sym, name) =>
- if (name == "") sym else
- afterTyper(sym.info member newTermName(name))
+ (accessPath split '.').foldLeft(readRoot: Symbol) {
+ case (sym, "") => sym
+ case (sym, name) => afterTyper(termMember(sym, name))
}
}
/** We get a bunch of repeated warnings for reasons I haven't
@@ -816,7 +833,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
def lastWarnings: List[(Position, String)] = (
if (lastRun == null) Nil
- else removeDupWarnings(lastRun.deprecationWarnings.reverse) ++ lastRun.uncheckedWarnings.reverse
+ else removeDupWarnings(lastRun.allConditionalWarnings flatMap (_.warnings))
)
private var lastRun: Run = _
private def evalMethod(name: String) = evalClass.getMethods filter (_.getName == name) match {
@@ -824,7 +841,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
case xs => sys.error("Internal error: eval object " + evalClass + ", " + xs.mkString("\n", "\n", ""))
}
private def compileAndSaveRun(label: String, code: String) = {
- showCodeIfDebugging(packaged(code))
+ showCodeIfDebugging(code)
val (success, run) = compileSourcesKeepingRun(new BatchSourceFile(label, packaged(code)))
lastRun = run
success
@@ -834,6 +851,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** One line of code submitted by the user for interpretation */
// private
class Request(val line: String, val trees: List[Tree]) {
+ val reqId = nextReqId()
val lineRep = new ReadEvalPrint()
private var _originalLine: String = null
@@ -842,6 +860,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** handlers for each tree in this request */
val handlers: List[MemberHandler] = trees map (memberHandlers chooseHandler _)
+ def defHandlers = handlers collect { case x: MemberDefHandler => x }
/** all (public) names defined by these statements */
val definedNames = handlers flatMap (_.definedNames)
@@ -853,6 +872,10 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def termNames = handlers flatMap (_.definesTerm)
def typeNames = handlers flatMap (_.definesType)
def definedOrImported = handlers flatMap (_.definedOrImported)
+ def definedSymbolList = defHandlers flatMap (_.definedSymbols)
+
+ def definedTypeSymbol(name: String) = definedSymbols(newTypeName(name))
+ def definedTermSymbol(name: String) = definedSymbols(newTermName(name))
/** Code to import bound names from previous lines - accessPath is code to
* append to objectName to access anything bound by request.
@@ -882,10 +905,25 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
/** generate the source code for the object that computes this request */
private object ObjectSourceCode extends CodeAssembler[MemberHandler] {
+ def path = pathToTerm("$intp")
+ def envLines = {
+ if (!isReplPower) Nil // power mode only for now
+ // $intp is not bound; punt, but include the line.
+ else if (path == "$intp") List(
+ "def $line = " + tquoted(originalLine),
+ "def $trees = Nil"
+ )
+ else List(
+ "def $line = " + tquoted(originalLine),
+ "def $req = %s.requestForReqId(%s).orNull".format(path, reqId),
+ "def $trees = if ($req eq null) Nil else $req.trees".format(lineRep.readName, path, reqId)
+ )
+ }
+
val preamble = """
|object %s {
- |%s%s
- """.stripMargin.format(lineRep.readName, importsPreamble, indentCode(toCompute))
+ |%s%s%s
+ """.stripMargin.format(lineRep.readName, envLines.map(" " + _ + ";\n").mkString, importsPreamble, indentCode(toCompute))
val postamble = importsTrailer + "\n}"
val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this
}
@@ -943,6 +981,16 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
typeOf
typesOfDefinedTerms
+ // Assign symbols to the original trees
+ // TODO - just use the new trees.
+ defHandlers foreach { dh =>
+ val name = dh.member.name
+ definedSymbols get name foreach { sym =>
+ dh.member setSymbol sym
+ repldbg("Set symbol of " + name + " to " + sym.defString)
+ }
+ }
+
// compile the result-extraction object
beQuietDuring {
savingSettings(_.nowarn.value = true) {
@@ -959,24 +1007,23 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString)))
def simpleNameOfType(name: TypeName) = (compilerTypeOf get name) map (_.typeSymbol.simpleName)
- private def typeMap[T](f: Type => T): Map[Name, T] =
- termNames ++ typeNames map (x => x -> f(typeCleanser(resultSymbol, x))) toMap
+ private def typeMap[T](f: Type => T) =
+ mapFrom[Name, Name, T](termNames ++ typeNames)(x => f(cleanMemberDecl(resultSymbol, x)))
/** Types of variables defined by this request. */
- lazy val compilerTypeOf = typeMap[Type](x => x)
+ lazy val compilerTypeOf = typeMap[Type](x => x) withDefaultValue NoType
/** String representations of same. */
lazy val typeOf = typeMap[String](tp => afterTyper(tp.toString))
// lazy val definedTypes: Map[Name, Type] = {
// typeNames map (x => x -> afterTyper(resultSymbol.info.nonPrivateDecl(x).tpe)) toMap
// }
- lazy val definedSymbols: Map[Name, Symbol] = (
+ lazy val definedSymbols = (
termNames.map(x => x -> applyToResultMember(x, x => x)) ++
- typeNames.map(x => x -> compilerTypeOf.get(x).map(_.typeSymbol).getOrElse(NoSymbol))
- ).toMap
+ typeNames.map(x => x -> compilerTypeOf(x).typeSymbol)
+ ).toMap[Name, Symbol] withDefaultValue NoSymbol
- lazy val typesOfDefinedTerms: Map[Name, Type] =
- termNames map (x => x -> applyToResultMember(x, _.tpe)) toMap
+ lazy val typesOfDefinedTerms = mapFrom[Name, Name, Type](termNames)(x => applyToResultMember(x, _.tpe))
/** load and run the code using reflection */
def loadAndRun: (String, Boolean) = {
@@ -1023,6 +1070,13 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
getOrElse Nil
)
+ def treesForRequestId(id: Int): List[Tree] =
+ requestForReqId(id).toList flatMap (_.trees)
+
+ def requestForReqId(id: Int): Option[Request] =
+ if (executingRequest != null && executingRequest.reqId == id) Some(executingRequest)
+ else prevRequests find (_.reqId == id)
+
def requestForName(name: Name): Option[Request] = {
assert(definedNameMap != null, "definedNameMap is null")
definedNameMap get name
@@ -1040,18 +1094,21 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
}
def valueOfTerm(id: String): Option[AnyRef] =
- requestForIdent(id) flatMap (_.getEval)
+ requestForName(newTermName(id)) flatMap (_.getEval)
def classOfTerm(id: String): Option[JClass] =
valueOfTerm(id) map (_.getClass)
def typeOfTerm(id: String): Type = newTermName(id) match {
case nme.ROOTPKG => definitions.RootClass.tpe
- case name => requestForName(name) flatMap (_.compilerTypeOf get name) getOrElse NoType
+ case name => requestForName(name).fold(NoType: Type)(_ compilerTypeOf name)
}
+ def symbolOfType(id: String): Symbol =
+ requestForName(newTypeName(id)).fold(NoSymbol: Symbol)(_ definedTypeSymbol id)
+
def symbolOfTerm(id: String): Symbol =
- requestForIdent(id) flatMap (_.definedSymbols get newTermName(id)) getOrElse NoSymbol
+ requestForIdent(newTermName(id)).fold(NoSymbol: Symbol)(_ definedTermSymbol id)
def runtimeClassAndTypeOfTerm(id: String): Option[(JClass, Type)] = {
classOfTerm(id) flatMap { clazz =>
@@ -1072,16 +1129,28 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
else NoType
}
}
+ def cleanMemberDecl(owner: Symbol, member: Name): Type = afterTyper {
+ normalizeNonPublic {
+ owner.info.nonPrivateDecl(member).tpe match {
+ case NullaryMethodType(tp) => tp
+ case tp => tp
+ }
+ }
+ }
object replTokens extends {
val global: imain.global.type = imain.global
} with ReplTokens { }
- private object exprTyper extends {
+ object exprTyper extends {
val repl: IMain.this.type = imain
} with ExprTyper { }
def parse(line: String): Option[List[Tree]] = exprTyper.parse(line)
+
+ def symbolOfLine(code: String): Symbol =
+ exprTyper.symbolOfLine(code)
+
def typeOfExpression(expr: String, silent: Boolean = true): Type =
exprTyper.typeOfExpression(expr, silent)
@@ -1091,14 +1160,15 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
protected def onlyTerms(xs: List[Name]) = xs collect { case x: TermName => x }
protected def onlyTypes(xs: List[Name]) = xs collect { case x: TypeName => x }
- def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalTermName
- def definedTypes = onlyTypes(allDefinedNames)
- def definedSymbols = prevRequests.toSet flatMap ((x: Request) => x.definedSymbols.values)
+ def definedTerms = onlyTerms(allDefinedNames) filterNot isInternalTermName
+ def definedTypes = onlyTypes(allDefinedNames)
+ def definedSymbols = prevRequestList.flatMap(_.definedSymbols.values).toSet[Symbol]
+ def definedSymbolList = prevRequestList flatMap (_.definedSymbolList) filterNot (s => isInternalTermName(s.name))
// Terms with user-given names (i.e. not res0 and not synthetic)
def namedDefinedTerms = definedTerms filterNot (x => isUserVarName("" + x) || directlyBoundNames(x))
- private def findName(name: Name) = definedSymbols find (_.name == name)
+ private def findName(name: Name) = definedSymbols find (_.name == name) getOrElse NoSymbol
/** Translate a repl-defined identifier into a Symbol.
*/
@@ -1107,26 +1177,36 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends
def types(name: String): Symbol = {
val tpname = newTypeName(name)
- findName(tpname) getOrElse getClassIfDefined(tpname)
+ findName(tpname) orElse getClassIfDefined(tpname)
}
def terms(name: String): Symbol = {
val termname = newTypeName(name)
- findName(termname) getOrElse getModuleIfDefined(termname)
+ findName(termname) orElse getModuleIfDefined(termname)
}
- def types[T: ClassManifest] : Symbol = types(classManifest[T].erasure.getName)
- def terms[T: ClassManifest] : Symbol = terms(classManifest[T].erasure.getName)
- def apply[T: ClassManifest] : Symbol = apply(classManifest[T].erasure.getName)
+ // [Eugene to Paul] possibly you could make use of TypeTags here
+ def types[T: ClassTag] : Symbol = types(classTag[T].erasure.getName)
+ def terms[T: ClassTag] : Symbol = terms(classTag[T].erasure.getName)
+ def apply[T: ClassTag] : Symbol = apply(classTag[T].erasure.getName)
+
+ def classSymbols = allDefSymbols collect { case x: ClassSymbol => x }
+ def methodSymbols = allDefSymbols collect { case x: MethodSymbol => x }
/** the previous requests this interpreter has processed */
- private lazy val prevRequests = mutable.ListBuffer[Request]()
- private lazy val referencedNameMap = mutable.Map[Name, Request]()
- private lazy val definedNameMap = mutable.Map[Name, Request]()
- private lazy val directlyBoundNames = mutable.Set[Name]()
- protected def prevRequestList = prevRequests.toList
- private def allHandlers = prevRequestList flatMap (_.handlers)
- def allSeenTypes = prevRequestList flatMap (_.typeOf.values.toList) distinct
- def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames)
- def importHandlers = allHandlers collect { case x: ImportHandler => x }
+ private var executingRequest: Request = _
+ private val prevRequests = mutable.ListBuffer[Request]()
+ private val referencedNameMap = mutable.Map[Name, Request]()
+ private val definedNameMap = mutable.Map[Name, Request]()
+ private val directlyBoundNames = mutable.Set[Name]()
+
+ def allHandlers = prevRequestList flatMap (_.handlers)
+ def allDefHandlers = allHandlers collect { case x: MemberDefHandler => x }
+ def allDefSymbols = allDefHandlers map (_.symbol) filter (_ ne NoSymbol)
+
+ def lastRequest = if (prevRequests.isEmpty) null else prevRequests.last
+ def prevRequestList = prevRequests.toList
+ def allSeenTypes = prevRequestList flatMap (_.typeOf.values.toList) distinct
+ def allImplicits = allHandlers filter (_.definesImplicit) flatMap (_.definedNames)
+ def importHandlers = allHandlers collect { case x: ImportHandler => x }
def visibleTermNames: List[Name] = definedTerms ++ importedTerms distinct
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
index f9c1907696..795b2e3678 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala
@@ -194,14 +194,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
// literal Ints, Strings, etc.
object literals extends CompletionAware {
- def simpleParse(code: String): Tree = {
- val unit = new CompilationUnit(new util.BatchSourceFile("<console>", code))
- val scanner = new syntaxAnalyzer.UnitParser(unit)
- val tss = scanner.templateStatSeq(false)._2
-
- if (tss.size == 1) tss.head else EmptyTree
- }
-
+ def simpleParse(code: String): Tree = newUnitParser(code).templateStats().last
def completions(verbosity: Int) = Nil
override def follow(id: String) = simpleParse(id) match {
@@ -287,7 +280,12 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput
}
// chasing down results which won't parse
+ // This used to work fine, now it reports a type error before any
+ // exception gets to us. See SI-5657. Don't have time to deal with
+ // it, so disabling everything.
def execute(line: String): Option[ExecResult] = {
+ return None // disabled
+
val parsed = Parsed(line)
def noDotOrSlash = line forall (ch => ch != '.' && ch != '/')
diff --git a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala b/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala
index 9469baa4e2..3520a60ee5 100644
--- a/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/LoopCommands.scala
@@ -8,6 +8,7 @@ package interpreter
import collection.{ mutable, immutable }
import mutable.ListBuffer
+import language.implicitConversions
class ProcessResult(val line: String) {
import sys.process._
diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
index 68bfeafbc6..a29eb3ac6d 100644
--- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala
@@ -9,6 +9,7 @@ package interpreter
import scala.collection.{ mutable, immutable }
import scala.PartialFunction.cond
import scala.reflect.internal.Chars
+import language.implicitConversions
trait MemberHandlers {
val intp: IMain
@@ -63,6 +64,7 @@ trait MemberHandlers {
}
sealed abstract class MemberDefHandler(override val member: MemberDef) extends MemberHandler(member) {
+ def symbol = if (member.symbol eq null) NoSymbol else member.symbol
def name: Name = member.name
def mods: Modifiers = member.mods
def keyword = member.keyword
@@ -71,6 +73,7 @@ trait MemberHandlers {
override def definesImplicit = member.mods.isImplicit
override def definesTerm: Option[TermName] = Some(name.toTermName) filter (_ => name.isTermName)
override def definesType: Option[TypeName] = Some(name.toTypeName) filter (_ => name.isTypeName)
+ override def definedSymbols = if (symbol eq NoSymbol) Nil else List(symbol)
}
/** Class to handle one member among all the members included
@@ -88,6 +91,7 @@ trait MemberHandlers {
def importedNames = List[Name]()
def definedNames = definesTerm.toList ++ definesType.toList
def definedOrImported = definedNames ++ importedNames
+ def definedSymbols = List[Symbol]()
def extraCodeToEvaluate(req: Request): String = ""
def resultExtractionCode(req: Request): String = ""
@@ -120,7 +124,7 @@ trait MemberHandlers {
private def vparamss = member.vparamss
private def isMacro = member.mods.hasFlag(scala.reflect.internal.Flags.MACRO)
// true if not a macro and 0-arity
- override def definesValue = !isMacro && (vparamss.isEmpty || vparamss.head.isEmpty)
+ override def definesValue = !isMacro && flattensToEmpty(vparamss)
override def resultExtractionCode(req: Request) =
if (mods.isPublic) codegenln(name, ": ", req.typeOf(name)) else ""
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
index e92888d89b..a3cbfffc3b 100644
--- a/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/NamedParam.scala
@@ -7,24 +7,25 @@ package scala.tools.nsc
package interpreter
import NamedParam._
+import language.implicitConversions
trait NamedParamCreator {
protected def freshName: () => String
def apply(name: String, tpe: String, value: Any): NamedParam = NamedParamClass(name, tpe, value)
- def apply[T: Manifest](name: String, x: T): NamedParam = new Typed[T](name, x)
- def apply[T: Manifest](x: T): NamedParam = apply(freshName(), x)
+ def apply[T: TypeTag](name: String, x: T): NamedParam = new Typed[T](name, x)
+ def apply[T: TypeTag](x: T): NamedParam = apply(freshName(), x)
def clazz(name: String, x: Any): NamedParam = new Untyped(name, x)
def clazz(x: Any): NamedParam = clazz(freshName(), x)
- implicit def namedValue[T: Manifest](name: String, x: T): NamedParam = apply(name, x)
- implicit def tuple[T: Manifest](pair: (String, T)): NamedParam = apply(pair._1, pair._2)
+ implicit def namedValue[T: TypeTag](name: String, x: T): NamedParam = apply(name, x)
+ implicit def tuple[T: TypeTag](pair: (String, T)): NamedParam = apply(pair._1, pair._2)
}
object NamedParam extends NamedParamCreator {
- class Typed[T: Manifest](val name: String, val value: T) extends NamedParam {
- val tpe = TypeStrings.fromManifest[T]
+ class Typed[T: TypeTag](val name: String, val value: T) extends NamedParam {
+ val tpe = TypeStrings.fromTag[T]
}
class Untyped(val name: String, val value: Any) extends NamedParam {
val tpe = TypeStrings.fromValue(value)
@@ -43,4 +44,4 @@ trait NamedParam {
def tpe: String
def value: Any
override def toString = name + ": " + tpe
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Naming.scala b/src/compiler/scala/tools/nsc/interpreter/Naming.scala
index 19266442cb..c3f51c74ec 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Naming.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Naming.scala
@@ -41,10 +41,10 @@ trait Naming {
private def removeIWPackages(s: String) = s.replaceAll("""\$iw[$.]""", "")
trait SessionNames {
- // All values are configurable by passing e.g. -Dscala.repl.naming.read=XXX
+ // All values are configurable by passing e.g. -Dscala.repl.name.read=XXX
final def propOr(name: String): String = propOr(name, "$" + name)
final def propOr(name: String, default: String): String =
- sys.props.getOrElse("scala.repl.naming." + name, default)
+ sys.props.getOrElse("scala.repl.name." + name, default)
// Prefixes used in repl machinery. Default to $line, $read, etc.
def line = propOr("line")
diff --git a/src/compiler/scala/tools/nsc/interpreter/Phased.scala b/src/compiler/scala/tools/nsc/interpreter/Phased.scala
index d164d1cbb0..f39c025a86 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Phased.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Phased.scala
@@ -7,6 +7,7 @@ package scala.tools.nsc
package interpreter
import scala.collection.{ mutable, immutable }
+import language.implicitConversions
/** Mix this into an object and use it as a phasing
* swiss army knife.
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index 14876425f4..659caad1e1 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -6,7 +6,6 @@
package scala.tools.nsc
package interpreter
-import scala.reflect.AnyValManifest
import scala.collection.{ mutable, immutable }
import scala.util.matching.Regex
import scala.tools.nsc.util.{ BatchSourceFile }
@@ -14,6 +13,7 @@ import session.{ History }
import scala.io.Codec
import java.net.{ URL, MalformedURLException }
import io.{ Path }
+import language.implicitConversions
/** Collecting some power mode examples.
@@ -42,10 +42,10 @@ Lost after 18/flatten {
/** A class for methods to be injected into the intp in power mode.
*/
-class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: ReplValsImpl) {
+class Power[ReplValsImpl <: ReplVals : TypeTag](val intp: IMain, replVals: ReplValsImpl) {
import intp.{ beQuietDuring, typeOfExpression, interpret, parse }
import intp.global._
- import definitions.{ manifestToType, manifestToSymbol, getClassIfDefined, getModuleIfDefined }
+ import definitions.{ compilerTypeFromTag, compilerSymbolFromTag, getClassIfDefined, getModuleIfDefined }
abstract class SymSlurper {
def isKeep(sym: Symbol): Boolean
@@ -162,7 +162,7 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl
}
trait LowPriorityInternalInfo {
- implicit def apply[T: Manifest] : InternalInfo[T] = new InternalInfo[T](None)
+ implicit def apply[T: TypeTag] : InternalInfo[T] = new InternalInfo[T](None)
}
object InternalInfo extends LowPriorityInternalInfo { }
@@ -173,21 +173,21 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl
* of the conveniences exist on that wrapper.
*/
trait LowPriorityInternalInfoWrapper {
- implicit def apply[T: Manifest] : InternalInfoWrapper[T] = new InternalInfoWrapper[T](None)
+ implicit def apply[T: TypeTag] : InternalInfoWrapper[T] = new InternalInfoWrapper[T](None)
}
object InternalInfoWrapper extends LowPriorityInternalInfoWrapper {
}
- class InternalInfoWrapper[T: Manifest](value: Option[T] = None) {
+ class InternalInfoWrapper[T: TypeTag](value: Option[T] = None) {
def ? : InternalInfo[T] = new InternalInfo[T](value)
}
/** Todos...
- * translate manifest type arguments into applied types
+ * translate tag type arguments into applied types
* customizable symbol filter (had to hardcode no-spec to reduce noise)
*/
- class InternalInfo[T: Manifest](value: Option[T] = None) {
- private def newInfo[U: Manifest](value: U): InternalInfo[U] = new InternalInfo[U](Some(value))
+ class InternalInfo[T: TypeTag](value: Option[T] = None) {
+ private def newInfo[U: TypeTag](value: U): InternalInfo[U] = new InternalInfo[U](Some(value))
private def isSpecialized(s: Symbol) = s.name.toString contains "$mc"
private def isImplClass(s: Symbol) = s.name.toString endsWith "$class"
@@ -198,8 +198,8 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl
|| s.isAnonOrRefinementClass
|| s.isAnonymousFunction
)
- def symbol = manifestToSymbol(fullManifest)
- def tpe = manifestToType(fullManifest)
+ def symbol = compilerSymbolFromTag(tag)
+ def tpe = compilerTypeFromTag(tag)
def name = symbol.name
def companion = symbol.companionSymbol
def info = symbol.info
@@ -226,19 +226,19 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl
def pkgClasses = pkgMembers filter (s => s.isClass && s.isDefinedInPackage)
def pkgSymbols = new PackageSlurper(pkgClass).slurp() filterNot excludeMember
- def fullManifest = manifest[T]
- def erasure = fullManifest.erasure
+ def tag = typeTag[T]
+ def erasure = tag.erasure
def shortClass = erasure.getName split "[$.]" last
def baseClasses = tpe.baseClasses
- def baseClassDecls = baseClasses map (x => (x, x.info.decls.toList.sortBy(_.name.toString))) toMap
+ def baseClassDecls = mapFrom(baseClasses)(_.info.decls.toList.sortBy(_.name))
def ancestors = baseClasses drop 1
def ancestorDeclares(name: String) = ancestors filter (_.info member newTermName(name) ne NoSymbol)
def baseTypes = tpe.baseTypeSeq.toList
- def <:<[U: Manifest](other: U) = tpe <:< newInfo(other).tpe
- def lub[U: Manifest](other: U) = intp.global.lub(List(tpe, newInfo(other).tpe))
- def glb[U: Manifest](other: U) = intp.global.glb(List(tpe, newInfo(other).tpe))
+ def <:<[U: TypeTag](other: U) = tpe <:< newInfo(other).tpe
+ def lub[U: TypeTag](other: U) = intp.global.lub(List(tpe, newInfo(other).tpe))
+ def glb[U: TypeTag](other: U) = intp.global.glb(List(tpe, newInfo(other).tpe))
override def toString = value match {
case Some(x) => "%s (%s)".format(x, shortClass)
@@ -362,11 +362,10 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl
else if (s1 isLess s2) -1
else 1
}
- implicit lazy val powerNameOrdering: Ordering[Name] = Ordering[String] on (_.toString)
implicit lazy val powerSymbolOrdering: Ordering[Symbol] = Ordering[Name] on (_.name)
implicit lazy val powerTypeOrdering: Ordering[Type] = Ordering[Symbol] on (_.typeSymbol)
- implicit def replInternalInfo[T: Manifest](x: T): InternalInfoWrapper[T] = new InternalInfoWrapper[T](Some(x))
+ implicit def replInternalInfo[T: TypeTag](x: T): InternalInfoWrapper[T] = new InternalInfoWrapper[T](Some(x))
implicit def replEnhancedStrings(s: String): RichReplString = new RichReplString(s)
implicit def replMultiPrinting[T: Prettifier](xs: TraversableOnce[T]): MultiPrettifierClass[T] =
new MultiPrettifierClass[T](xs.toSeq)
@@ -381,10 +380,13 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl
}
trait ReplUtilities {
- def module[T: Manifest] = getModuleIfDefined(manifest[T].erasure.getName stripSuffix nme.MODULE_SUFFIX_STRING)
- def clazz[T: Manifest] = getClassIfDefined(manifest[T].erasure.getName)
- def info[T: Manifest] = InternalInfo[T]
- def ?[T: Manifest] = InternalInfo[T]
+ // [Eugene to Paul] needs review!
+ // def module[T: TypeTag] = getModuleIfDefined(typeTag[T].erasure.getName stripSuffix nme.MODULE_SUFFIX_STRING)
+ // def clazz[T: TypeTag] = getClassIfDefined(typeTag[T].erasure.getName)
+ def module[T: TypeTag] = typeTag[T].sym.suchThat(_.isPackage)
+ def clazz[T: TypeTag] = typeTag[T].sym.suchThat(_.isClass)
+ def info[T: TypeTag] = InternalInfo[T]
+ def ?[T: TypeTag] = InternalInfo[T]
def url(s: String) = {
try new URL(s)
catch { case _: MalformedURLException =>
@@ -410,8 +412,8 @@ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: Repl
lazy val phased: Phased = new { val global: intp.global.type = intp.global } with Phased { }
def context(code: String) = analyzer.rootContext(unit(code))
- def source(code: String) = new BatchSourceFile("<console>", code)
- def unit(code: String) = new CompilationUnit(source(code))
+ def source(code: String) = newSourceFile(code)
+ def unit(code: String) = newCompilationUnit(code)
def trees(code: String) = parse(code) getOrElse Nil
def typeOf(id: String) = intp.typeOfExpression(id)
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala b/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala
index 8c589eba60..0c26aa8b28 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplConfig.scala
@@ -27,6 +27,12 @@ trait ReplConfig {
try Console println msg
catch { case x: AssertionError => Console.println("Assertion error printing debugging output: " + x) }
+ private[nsc] def repldbgex(ex: Throwable): Unit = {
+ if (isReplDebug) {
+ echo("Caught/suppressing: " + ex)
+ ex.printStackTrace
+ }
+ }
private[nsc] def repldbg(msg: => String) = if (isReplDebug) echo(msg)
private[nsc] def repltrace(msg: => String) = if (isReplTrace) echo(msg)
private[nsc] def replinfo(msg: => String) = if (isReplInfo) echo(msg)
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala
new file mode 100644
index 0000000000..05321dd7e6
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplGlobal.scala
@@ -0,0 +1,57 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package interpreter
+
+import reporters._
+import typechecker.Analyzer
+
+/** A layer on top of Global so I can guarantee some extra
+ * functionality for the repl. It doesn't do much yet.
+ */
+trait ReplGlobal extends Global {
+ // This exists mostly because using the reporter too early leads to deadlock.
+ private def echo(msg: String) { Console println msg }
+
+ override def abort(msg: String): Nothing = {
+ echo("ReplGlobal.abort: " + msg)
+ super.abort(msg)
+ }
+
+ override lazy val analyzer = new {
+ val global: ReplGlobal.this.type = ReplGlobal.this
+ } with Analyzer {
+ override def newTyper(context: Context): Typer = new Typer(context) {
+ override def typed(tree: Tree, mode: Int, pt: Type): Tree = {
+ val res = super.typed(tree, mode, pt)
+ tree match {
+ case Ident(name) if !tree.symbol.hasPackageFlag && !name.toString.startsWith("$") =>
+ repldbg("typed %s: %s".format(name, res.tpe))
+ case _ =>
+ }
+ res
+ }
+ }
+ }
+
+ object replPhase extends SubComponent {
+ val global: ReplGlobal.this.type = ReplGlobal.this
+ val phaseName = "repl"
+ val runsAfter = List[String]("typer")
+ val runsRightAfter = None
+ def newPhase(_prev: Phase): StdPhase = new StdPhase(_prev) {
+ def apply(unit: CompilationUnit) {
+ repldbg("Running replPhase on " + unit.body)
+ // newNamer(rootContext(unit)).enterSym(unit.body)
+ }
+ }
+ }
+
+ override protected def computePhaseDescriptors: List[SubComponent] = {
+ addToPhasesSet(replPhase, "repl")
+ super.computePhaseDescriptors
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala b/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala
index 130af990ad..fb61dfb672 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplReporter.scala
@@ -9,7 +9,11 @@ package interpreter
import reporters._
import IMain._
+/** Like ReplGlobal, a layer for ensuring extra functionality.
+ */
class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, Console.in, new ReplStrippingWriter(intp)) {
+ def printUntruncatedMessage(msg: String) = withoutTruncating(printMessage(msg))
+
override def printMessage(msg: String) {
// Avoiding deadlock if the compiler starts logging before
// the lazy val is complete.
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala b/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala
index 1c7b256c33..e63fabf151 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplTokens.scala
@@ -9,6 +9,7 @@ package interpreter
import util.{ BatchSourceFile, Indenter }
import scala.tools.nsc.ast.parser.Tokens._
import java.lang.Integer.toOctalString
+import language.{implicitConversions, existentials}
/** This began as an attempt at a completely minimal
* pretty printer for a token stream, but as it turns out
diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
index a68392f0fb..280247f20c 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala
@@ -6,6 +6,9 @@
package scala.tools.nsc
package interpreter
+import scala.reflect.{mirror => rm}
+import language.implicitConversions
+
/** A class which the repl utilizes to expose predefined objects.
* The base implementation is empty; the standard repl implementation
* is StdReplVals.
@@ -25,20 +28,24 @@ class StdReplVals(final val r: ILoop) extends ReplVals {
final lazy val phased = power.phased
final lazy val analyzer = global.analyzer
- final lazy val treedsl = new { val global: intp.global.type = intp.global } with ast.TreeDSL { }
+ object treedsl extends { val global: intp.global.type = intp.global } with ast.TreeDSL { }
+
final lazy val typer = analyzer.newTyper(
analyzer.rootContext(
power.unit("").asInstanceOf[analyzer.global.CompilationUnit]
)
)
+ def lastRequest = intp.lastRequest
- final lazy val replImplicits = new power.Implicits2 {
+ class ReplImplicits extends power.Implicits2 {
import intp.global._
- private val manifestFn = ReplVals.mkManifestToType[intp.global.type](global)
- implicit def mkManifestToType(sym: Symbol) = manifestFn(sym)
+ private val tagFn = ReplVals.mkCompilerTypeFromTag[intp.global.type](global)
+ implicit def mkCompilerTypeFromTag(sym: Symbol) = tagFn(sym)
}
+ final lazy val replImplicits = new ReplImplicits
+
def typed[T <: analyzer.global.Tree](tree: T): T = typer.typed(tree).asInstanceOf[T]
}
@@ -47,29 +54,29 @@ object ReplVals {
* not being seen as the same type as bar.global.Type even though
* the globals are the same. Dependent method types to the rescue.
*/
- def mkManifestToType[T <: Global](global: T) = {
+ def mkCompilerTypeFromTag[T <: Global](global: T) = {
import global._
import definitions._
- /** We can't use definitions.manifestToType directly because we're passing
+ /** We can't use definitions.compilerTypeFromTag directly because we're passing
* it to map and the compiler refuses to perform eta expansion on a method
* with a dependent return type. (Can this be relaxed?) To get around this
* I have this forwarder which widens the type and then cast the result back
* to the dependent type.
*/
- def manifestToType(m: OptManifest[_]): Global#Type =
- definitions.manifestToType(m)
+ def compilerTypeFromTag(t: rm.TypeTag[_]): Global#Type =
+ definitions.compilerTypeFromTag(t)
- class AppliedTypeFromManifests(sym: Symbol) {
- def apply[M](implicit m1: Manifest[M]): Type =
+ class AppliedTypeFromTags(sym: Symbol) {
+ def apply[M](implicit m1: rm.TypeTag[M]): Type =
if (sym eq NoSymbol) NoType
- else appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x).asInstanceOf[Type]))
+ else appliedType(sym, compilerTypeFromTag(m1).asInstanceOf[Type])
- def apply[M1, M2](implicit m1: Manifest[M1], m2: Manifest[M2]): Type =
+ def apply[M1, M2](implicit m1: rm.TypeTag[M1], m2: rm.TypeTag[M2]): Type =
if (sym eq NoSymbol) NoType
- else appliedType(sym.typeConstructor, List(m1, m2) map (x => manifestToType(x).asInstanceOf[Type]))
+ else appliedType(sym, compilerTypeFromTag(m1).asInstanceOf[Type], compilerTypeFromTag(m2).asInstanceOf[Type])
}
- (sym: Symbol) => new AppliedTypeFromManifests(sym)
+ (sym: Symbol) => new AppliedTypeFromTags(sym)
}
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala b/src/compiler/scala/tools/nsc/interpreter/RichClass.scala
index 5edc8fd202..2e735e3b9b 100644
--- a/src/compiler/scala/tools/nsc/interpreter/RichClass.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/RichClass.scala
@@ -7,18 +7,21 @@ package scala.tools.nsc
package interpreter
class RichClass[T](val clazz: Class[T]) {
- def toManifest: Manifest[T] = Manifest.classType(clazz)
+ def toTag: ClassTag[T] = ClassTag[T](clazz)
def toTypeString: String = TypeStrings.fromClazz(clazz)
// Sadly isAnonymousClass does not return true for scala anonymous
// classes because our naming scheme is not doing well against the
// jvm's many assumptions.
- def isScalaAnonymous = clazz.isAnonymousClass || (clazz.getName contains "$anon$")
+ def isScalaAnonymous = (
+ try clazz.isAnonymousClass || (clazz.getName contains "$anon$")
+ catch { case _: java.lang.InternalError => false } // good ol' "Malformed class name"
+ )
/** It's not easy... to be... me... */
- def supermans: List[Manifest[_]] = supers map (_.toManifest)
- def superNames: List[String] = supers map (_.getName)
- def interfaces: List[JClass] = supers filter (_.isInterface)
+ def supermans: List[ClassTag[_]] = supers map (_.toTag)
+ def superNames: List[String] = supers map (_.getName)
+ def interfaces: List[JClass] = supers filter (_.isInterface)
def hasAncestorName(f: String => Boolean) = superNames exists f
def hasAncestor(f: JClass => Boolean) = supers exists f
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
index 6b56d881fc..5d5123811e 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
@@ -10,6 +10,143 @@ import java.lang.{ reflect => r }
import r.TypeVariable
import scala.reflect.NameTransformer
import NameTransformer._
+import scala.reflect.{mirror => rm}
+import typechecker.DestructureTypes
+import scala.tools.util.StringOps.ojoin
+
+/** A more principled system for turning types into strings.
+ */
+trait StructuredTypeStrings extends DestructureTypes {
+ val global: Global
+ import global._
+ import definitions._
+
+ case class LabelAndType(label: String, typeName: String) { }
+ object LabelAndType {
+ val empty = LabelAndType("", "")
+ }
+ case class Grouping(ldelim: String, mdelim: String, rdelim: String, labels: Boolean) {
+ def join(elems: String*): String = (
+ if (elems.isEmpty) ""
+ else elems.mkString(ldelim, mdelim, rdelim)
+ )
+ }
+ val NoGrouping = Grouping("", "", "", false)
+ val ListGrouping = Grouping("(", ", ", ")", false)
+ val ProductGrouping = Grouping("(", ", ", ")", true)
+ val ParamGrouping = Grouping("(", ", ", ")", true)
+ val BlockGrouping = Grouping(" { ", "; ", "}", false)
+
+ private implicit def lowerName(n: Name): String = "" + n
+ private def str(level: Int)(body: => String): String = " " * level + body
+ private def block(level: Int, grouping: Grouping)(name: String, nodes: List[TypeNode]): String = {
+ val l1 = str(level)(name + grouping.ldelim)
+ val l2 = nodes.map(_ show level + 1)
+ val l3 = str(level)(grouping.rdelim)
+
+ l1 +: l2 :+ l3 mkString "\n"
+ }
+ private def maybeBlock(level: Int, grouping: Grouping)(name: String, nodes: List[TypeNode]): String = {
+ import grouping._
+ val threshold = 70
+
+ val try1 = str(level)(name + grouping.join(nodes map (_.show(0, grouping.labels)): _*))
+ if (try1.length < threshold) try1
+ else block(level, grouping)(name, nodes)
+ }
+ private def shortClass(x: Any) = {
+ if (opt.debug) {
+ val name = (x.getClass.getName split '.').last
+ val isAnon = name.reverse takeWhile (_ != '$') forall (_.isDigit)
+ val str = if (isAnon) name else (name split '$').last
+
+ " // " + str
+ }
+ else ""
+ }
+
+ sealed abstract class TypeNode {
+ def grouping: Grouping
+ def nodes: List[TypeNode]
+
+ def show(indent: Int, showLabel: Boolean): String = maybeBlock(indent, grouping)(mkPrefix(showLabel), nodes)
+ def show(indent: Int): String = show(indent, true)
+ def show(): String = show(0)
+
+ def withLabel(l: String): this.type = modifyNameInfo(_.copy(label = l))
+ def withType(t: String): this.type = modifyNameInfo(_.copy(typeName = t))
+
+ def label = nameInfo.label
+ def typeName = nameInfo.typeName
+
+ protected def mkPrefix(showLabel: Boolean) = {
+ val pre = if (showLabel && label != "") label + " = " else ""
+ pre + typeName
+ }
+ override def toString = show() // + "(toString)"
+ private var nameInfo: LabelAndType = LabelAndType.empty
+ private def modifyNameInfo(f: LabelAndType => LabelAndType): this.type = {
+ nameInfo = f(nameInfo)
+ this
+ }
+ }
+ case class TypeAtom[T](atom: T) extends TypeNode {
+ def grouping = NoGrouping
+ def nodes = Nil
+ override protected def mkPrefix(showLabel: Boolean) =
+ super.mkPrefix(showLabel) + atom + shortClass(atom)
+ }
+ case class TypeProduct(nodes: List[TypeNode]) extends TypeNode {
+ def grouping: Grouping = ProductGrouping
+ def emptyTypeName = ""
+ override def typeName = if (nodes.isEmpty) emptyTypeName else super.typeName
+ }
+
+ /** For a NullaryMethod, in = TypeEmpty; for MethodType(Nil, _) in = TypeNil */
+ class NullaryFunction(out: TypeNode) extends TypeProduct(List(out)) {
+ override def typeName = "NullaryMethodType"
+ }
+ class MonoFunction(in: TypeNode, out: TypeNode) extends TypeProduct(List(in, out)) {
+ override def typeName = "MethodType"
+ }
+ class PolyFunction(in: TypeNode, out: TypeNode) extends TypeProduct(List(in, out)) {
+ override def typeName = "PolyType"
+ }
+
+ class TypeList(nodes: List[TypeNode]) extends TypeProduct(nodes) {
+ override def grouping = ListGrouping
+ override def emptyTypeName = "Nil"
+ override def typeName = "List"
+ }
+ class TypeScope(nodes: List[TypeNode]) extends TypeProduct(nodes) {
+ override def grouping = BlockGrouping
+ override def typeName = "Scope"
+ override def emptyTypeName = "EmptyScope"
+ }
+
+ object TypeEmpty extends TypeNode {
+ override def grouping = NoGrouping
+ override def nodes = Nil
+ override def label = ""
+ override def typeName = ""
+ override def show(indent: Int, showLabel: Boolean) = ""
+ }
+
+ object intoNodes extends DestructureType[TypeNode] {
+ def withLabel(node: TypeNode, label: String): TypeNode = node withLabel label
+ def withType(node: TypeNode, typeName: String): TypeNode = node withType typeName
+
+ def wrapEmpty = TypeEmpty
+ def wrapSequence(nodes: List[TypeNode]) = new TypeList(nodes)
+ def wrapProduct(nodes: List[TypeNode]) = new TypeProduct(nodes)
+ def wrapPoly(in: TypeNode, out: TypeNode) = new PolyFunction(in, out)
+ def wrapMono(in: TypeNode, out: TypeNode) = if (in == wrapEmpty) new NullaryFunction(out) else new MonoFunction(in, out)
+ def wrapAtom[U](value: U) = new TypeAtom(value)
+ }
+
+ def show(tp: Type): String = intoNodes(tp).show
+}
+
/** Logic for turning a type into a String. The goal is to be
* able to take some arbitrary object 'x' and obtain the most precise
@@ -55,8 +192,8 @@ trait TypeStrings {
else enclClass.getName + "." + (name stripPrefix enclPre)
)
}
- def scalaName(m: ClassManifest[_]): String = scalaName(m.erasure)
- def anyClass(x: Any): JClass = if (x == null) null else x.getClass
+ def scalaName(m: ClassTag[_]): String = scalaName(m.erasure)
+ def anyClass(x: Any): JClass = if (x == null) null else x.getClass
private def brackets(tps: String*): String =
if (tps.isEmpty) ""
@@ -72,21 +209,25 @@ trait TypeStrings {
brackets(clazz.getTypeParameters map tvarString: _*)
}
- private def tparamString[T: Manifest] : String =
- brackets(manifest[T].typeArguments map (m => tvarString(List(m.erasure))): _*)
+ private def tparamString[T: TypeTag] : String = {
+ // [Eugene to Paul] needs review!!
+ def typeArguments: List[rm.Type] = typeTag[T].tpe.typeArguments
+ def typeVariables: List[java.lang.Class[_]] = typeArguments map (targ => rm.typeToClass(targ))
+ brackets(typeArguments map (jc => tvarString(List(jc))): _*)
+ }
/** Going for an overabundance of caution right now. Later these types
- * can be a lot more precise, but right now the manifests have a habit of
+ * can be a lot more precise, but right now the tags have a habit of
* introducing material which is not syntactically valid as scala source.
* When this happens it breaks the repl. It would be nice if we mandated
- * that manifest toString methods (or some other method, since it's bad
+ * that tag toString methods (or some other method, since it's bad
* practice to rely on toString for correctness) generated the VALID string
* representation of the type.
*/
- def fromTypedValue[T: Manifest](x: T): String = fromManifest[T]
- def fromValue(value: Any): String = if (value == null) "Null" else fromClazz(anyClass(value))
- def fromClazz(clazz: JClass): String = scalaName(clazz) + tparamString(clazz)
- def fromManifest[T: Manifest] : String = scalaName(manifest[T].erasure) + tparamString[T]
+ def fromTypedValue[T: TypeTag](x: T): String = fromTag[T]
+ def fromValue(value: Any): String = if (value == null) "Null" else fromClazz(anyClass(value))
+ def fromClazz(clazz: JClass): String = scalaName(clazz) + tparamString(clazz)
+ def fromTag[T: TypeTag] : String = scalaName(typeTag[T].erasure) + tparamString[T]
/** Reducing fully qualified noise for some common packages.
*/
diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala
index e78e92c8f8..7d2610e3c8 100644
--- a/src/compiler/scala/tools/nsc/interpreter/package.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/package.scala
@@ -5,6 +5,8 @@
package scala.tools.nsc
+import language.implicitConversions
+
/** The main REPL related classes and values are as follows.
* In addition to standard compiler classes Global and Settings, there are:
*
@@ -33,6 +35,8 @@ package object interpreter extends ReplConfig with ReplStrings {
val IR = Results
+ implicit def postfixOps = language.postfixOps // make all postfix ops in this package compile without warning
+
private[interpreter] implicit def javaCharSeqCollectionToScala(xs: JCollection[_ <: CharSequence]): List[String] = {
import collection.JavaConverters._
xs.asScala.toList map ("" + _)
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/package.scala b/src/compiler/scala/tools/nsc/interpreter/session/package.scala
index 8fbba2f05e..4e5b08c8cb 100644
--- a/src/compiler/scala/tools/nsc/interpreter/session/package.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/session/package.scala
@@ -5,6 +5,7 @@
package scala.tools.nsc
package interpreter
+import language.implicitConversions
/** Files having to do with the state of a repl session:
* lines of text entered, types and terms defined, etc.
diff --git a/src/compiler/scala/tools/nsc/io/AbstractFile.scala b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
index b51cf1228c..deb914f806 100644
--- a/src/compiler/scala/tools/nsc/io/AbstractFile.scala
+++ b/src/compiler/scala/tools/nsc/io/AbstractFile.scala
@@ -10,6 +10,7 @@ package io
import java.io.{ FileOutputStream, IOException, InputStream, OutputStream, BufferedOutputStream }
import java.net.URL
import scala.collection.mutable.ArrayBuffer
+import scala.reflect.api.RequiredFile
/**
* @author Philippe Altherr
@@ -81,7 +82,7 @@ object AbstractFile {
* <code>global.settings.encoding.value</code>.
* </p>
*/
-abstract class AbstractFile extends AnyRef with Iterable[AbstractFile] {
+abstract class AbstractFile extends AnyRef with RequiredFile with Iterable[AbstractFile] {
/** Returns the name of this abstract file. */
def name: String
diff --git a/src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala b/src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala
index d0a0b17494..c9ed535841 100644
--- a/src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala
+++ b/src/compiler/scala/tools/nsc/io/ClassAndJarInfo.scala
@@ -13,9 +13,9 @@ import collection.JavaConverters._
/** A convenience class for finding the jar with the bytecode for
* a given Class object and similar common tasks.
*/
-class ClassAndJarInfo[T: ClassManifest] {
- val man = classManifest[T]
- def clazz = man.erasure
+class ClassAndJarInfo[T: ClassTag] {
+ val tag = classTag[T]
+ def clazz = tag.erasure
def internalName = clazz.getName.replace('.', '/')
def resourceURL = new URLClassLoader(Array[URL]()) getResource internalName + ".class"
diff --git a/src/compiler/scala/tools/nsc/io/File.scala b/src/compiler/scala/tools/nsc/io/File.scala
index cc512493d9..06cb20e4ac 100644
--- a/src/compiler/scala/tools/nsc/io/File.scala
+++ b/src/compiler/scala/tools/nsc/io/File.scala
@@ -15,6 +15,7 @@ import java.io.{
BufferedInputStream, BufferedOutputStream, IOException, PrintStream, PrintWriter, Closeable => JCloseable }
import java.nio.channels.{ Channel, FileChannel }
import scala.io.Codec
+import language.{reflectiveCalls, implicitConversions}
object File {
def pathSeparator = java.io.File.pathSeparator
diff --git a/src/compiler/scala/tools/nsc/io/Jar.scala b/src/compiler/scala/tools/nsc/io/Jar.scala
index bbed5a9e20..b322df986c 100644
--- a/src/compiler/scala/tools/nsc/io/Jar.scala
+++ b/src/compiler/scala/tools/nsc/io/Jar.scala
@@ -11,6 +11,7 @@ import java.util.jar._
import collection.JavaConverters._
import Attributes.Name
import util.ClassPath
+import language.implicitConversions
// Attributes.Name instances:
//
diff --git a/src/compiler/scala/tools/nsc/io/Path.scala b/src/compiler/scala/tools/nsc/io/Path.scala
index a1b8e5e4d5..b8cf15bfcf 100644
--- a/src/compiler/scala/tools/nsc/io/Path.scala
+++ b/src/compiler/scala/tools/nsc/io/Path.scala
@@ -11,6 +11,7 @@ import java.io.{
BufferedInputStream, BufferedOutputStream, RandomAccessFile }
import java.net.{ URI, URL }
import scala.util.Random.alphanumeric
+import language.implicitConversions
/** An abstraction for filesystem paths. The differences between
* Path, File, and Directory are primarily to communicate intent.
diff --git a/src/compiler/scala/tools/nsc/io/Pickler.scala b/src/compiler/scala/tools/nsc/io/Pickler.scala
index 80b6e086da..416b84eec6 100644
--- a/src/compiler/scala/tools/nsc/io/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/io/Pickler.scala
@@ -3,6 +3,7 @@ package scala.tools.nsc.io
import annotation.unchecked
import Lexer._
import java.io.Writer
+import language.implicitConversions
/** An abstract class for writing and reading Scala objects to and
* from a legible representation. The presesentation follows the following grammar:
@@ -168,14 +169,11 @@ object Pickler {
case class ~[+S, +T](fst: S, snd: T)
/** A wrapper class to be able to use `~` s an infix method */
- class TildeDecorator[S](x: S) {
+ implicit class TildeDecorator[S](x: S) {
/** Infix method that forms a `~`-pair. */
def ~ [T](y: T): S ~ T = new ~ (x, y)
}
- /** An implicit wrapper that adds `~` as a method to any value. */
- implicit def tildeDecorator[S](x: S): TildeDecorator[S] = new TildeDecorator(x)
-
/** A converter from binary functions to functions over `~`-pairs
*/
implicit def fromTilde[T1, T2, R](f: (T1, T2) => R): T1 ~ T2 => R = { case x1 ~ x2 => f(x1, x2) }
@@ -418,7 +416,7 @@ object Pickler {
iterPickler[T] .wrapped { Vector() ++ _ } { _.iterator } .labelled ("scala.Vector")
/** A pickler for array values */
- implicit def array[T : ClassManifest : Pickler]: Pickler[Array[T]] =
+ implicit def array[T : ClassTag : Pickler]: Pickler[Array[T]] =
iterPickler[T] .wrapped { _.toArray} { _.iterator } .labelled ("scala.Array")
}
diff --git a/src/compiler/scala/tools/nsc/io/PlainFile.scala b/src/compiler/scala/tools/nsc/io/PlainFile.scala
index 83b8cc32c4..21276e8740 100644
--- a/src/compiler/scala/tools/nsc/io/PlainFile.scala
+++ b/src/compiler/scala/tools/nsc/io/PlainFile.scala
@@ -51,6 +51,7 @@ class PlainFile(val givenPath: Path) extends AbstractFile {
override def output = givenPath.toFile.outputStream()
override def sizeOption = Some(givenPath.length.toInt)
+ override def toString = path
override def hashCode(): Int = fpath.hashCode
override def equals(that: Any): Boolean = that match {
case x: PlainFile => fpath == x.fpath
diff --git a/src/compiler/scala/tools/nsc/io/package.scala b/src/compiler/scala/tools/nsc/io/package.scala
index 88679e6dce..52e6de0bed 100644
--- a/src/compiler/scala/tools/nsc/io/package.scala
+++ b/src/compiler/scala/tools/nsc/io/package.scala
@@ -8,8 +8,11 @@ package scala.tools.nsc
import java.util.concurrent.{ Future, Callable }
import java.util.{ Timer, TimerTask }
import java.util.jar.{ Attributes }
+import language.implicitConversions
package object io {
+ implicit def postfixOps = language.postfixOps // make all postfix ops in this package compile without warning
+
type JManifest = java.util.jar.Manifest
type JFile = java.io.File
@@ -41,4 +44,4 @@ package object io {
alarm.schedule(tt, seconds * 1000)
alarm
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index 06b06c50a6..5c413243e8 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -12,6 +12,7 @@ import scala.tools.nsc.util.OffsetPosition
import scala.collection.mutable.ListBuffer
import symtab.Flags
import JavaTokens._
+import language.implicitConversions
trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
val global : Global
@@ -788,23 +789,24 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
val idefs = members.toList ::: (sdefs flatMap forwarders)
(sdefs, idefs)
}
-
+ def annotationParents = List(
+ gen.scalaAnnotationDot(tpnme.Annotation),
+ Select(javaLangDot(nme.annotation), tpnme.Annotation),
+ gen.scalaAnnotationDot(tpnme.ClassfileAnnotation)
+ )
def annotationDecl(mods: Modifiers): List[Tree] = {
accept(AT)
accept(INTERFACE)
val pos = in.currentPos
val name = identForType()
- val parents = List(scalaDot(tpnme.Annotation),
- Select(javaLangDot(nme.annotation), tpnme.Annotation),
- scalaDot(tpnme.ClassfileAnnotation))
val (statics, body) = typeBody(AT, name)
def getValueMethodType(tree: Tree) = tree match {
case DefDef(_, nme.value, _, _, tpt, _) => Some(tpt.duplicate)
case _ => None
}
- var templ = makeTemplate(parents, body)
+ var templ = makeTemplate(annotationParents, body)
for (stat <- templ.body; tpt <- getValueMethodType(stat))
- templ = makeTemplate(parents, makeConstructor(List(tpt)) :: templ.body)
+ templ = makeTemplate(annotationParents, makeConstructor(List(tpt)) :: templ.body)
addCompanionObject(statics, atPos(pos) {
ClassDef(mods, name, List(), templ)
})
diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
index 45b63b0ca0..d47756e757 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
@@ -10,6 +10,7 @@ import scala.tools.nsc.util._
import scala.reflect.internal.Chars._
import JavaTokens._
import scala.annotation.switch
+import language.implicitConversions
// Todo merge these better with Scanners
trait JavaScanners extends ast.parser.ScannersCommon {
diff --git a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala
index 371f4bc4d8..72e6f32af1 100644
--- a/src/compiler/scala/tools/nsc/matching/MatchSupport.scala
+++ b/src/compiler/scala/tools/nsc/matching/MatchSupport.scala
@@ -10,6 +10,7 @@ import transform.ExplicitOuter
import ast.{ TreePrinters, Trees }
import java.io.{ StringWriter, PrintWriter }
import annotation.elidable
+import language.postfixOps
/** Ancillary bits of ParallelMatching which are better off
* out of the way.
@@ -29,11 +30,10 @@ trait MatchSupport extends ast.TreeDSL { self: ParallelMatching =>
object Types {
import definitions._
- implicit def enrichType(x: Type): RichType = new RichType(x)
- val subrangeTypes = Set(ByteClass, ShortClass, CharClass, IntClass)
+ val subrangeTypes = Set[Symbol](ByteClass, ShortClass, CharClass, IntClass)
- class RichType(undecodedTpe: Type) {
+ implicit class RichType(undecodedTpe: Type) {
def tpe = decodedEqualsType(undecodedTpe)
def isAnyRef = tpe <:< AnyRefClass.tpe
diff --git a/src/compiler/scala/tools/nsc/matching/Matrix.scala b/src/compiler/scala/tools/nsc/matching/Matrix.scala
index e1ff88557e..b29fac225a 100644
--- a/src/compiler/scala/tools/nsc/matching/Matrix.scala
+++ b/src/compiler/scala/tools/nsc/matching/Matrix.scala
@@ -9,6 +9,7 @@ package matching
import transform.ExplicitOuter
import symtab.Flags
import scala.collection.mutable
+import language.implicitConversions
trait Matrix extends MatrixAdditions {
self: ExplicitOuter with ParallelMatching =>
@@ -255,4 +256,4 @@ trait Matrix extends MatrixAdditions {
recordSyntheticSym(owner.newVariable(n, pos, flagsLong) setInfo tpe)
}
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
index 43aad9f591..7346d9c59f 100644
--- a/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
+++ b/src/compiler/scala/tools/nsc/matching/ParallelMatching.scala
@@ -14,6 +14,7 @@ import transform.ExplicitOuter
import symtab.Flags
import mutable.ListBuffer
import annotation.elidable
+import language.postfixOps
trait ParallelMatching extends ast.TreeDSL
with MatchSupport
diff --git a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
index 56297f0195..b2a721c586 100644
--- a/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
+++ b/src/compiler/scala/tools/nsc/matching/PatternBindings.scala
@@ -8,6 +8,7 @@ package matching
import transform.ExplicitOuter
import PartialFunction._
+import language.postfixOps
trait PatternBindings extends ast.TreeDSL
{
@@ -133,4 +134,4 @@ trait PatternBindings extends ast.TreeDSL
}
val NoBinding: Bindings = new Bindings(Nil)
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/matching/Patterns.scala b/src/compiler/scala/tools/nsc/matching/Patterns.scala
index 4f6a4c8dc0..bbe22ca314 100644
--- a/src/compiler/scala/tools/nsc/matching/Patterns.scala
+++ b/src/compiler/scala/tools/nsc/matching/Patterns.scala
@@ -187,9 +187,9 @@ trait Patterns extends ast.TreeDSL {
// As yet I can't testify this is doing any good relative to using
// tpt.tpe, but it doesn't seem to hurt either.
private lazy val packedType = global.typer.computeType(tpt, tpt.tpe)
- private lazy val consRef = appliedType(ConsClass.typeConstructor, List(packedType))
- private lazy val listRef = appliedType(ListClass.typeConstructor, List(packedType))
- private lazy val seqRef = appliedType(SeqClass.typeConstructor, List(packedType))
+ private lazy val consRef = appliedType(ConsClass, packedType)
+ private lazy val listRef = appliedType(ListClass, packedType)
+ private lazy val seqRef = appliedType(SeqClass, packedType)
private def thisSeqRef = {
val tc = (tree.tpe baseType SeqClass).typeConstructor
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugin.scala b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
index 9254ec8628..48c4a9b5b3 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugin.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugin.scala
@@ -138,7 +138,7 @@ object Plugin {
} yield entry)).distinct
val loader = loaderFor(alljars)
- alljars map (loadFrom(_, loader)) flatten
+ (alljars map (loadFrom(_, loader))).flatten
}
/** Instantiate a plugin class, given the class and
diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
index da913a1601..ba042b7b78 100644
--- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala
+++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala
@@ -70,7 +70,7 @@ trait Plugins {
}
}
- val plugs = pick(roughPluginsList, Set(), phasesSet map (_.phaseName) toSet)
+ val plugs = pick(roughPluginsList, Set(), (phasesSet map (_.phaseName)).toSet)
/** Verify requirements are present. */
for (req <- settings.require.value ; if !(plugs exists (_.name == req)))
@@ -112,5 +112,5 @@ trait Plugins {
def pluginOptionsHelp: String =
(for (plug <- roughPluginsList ; help <- plug.optionsHelp) yield {
"\nOptions for plugin '%s':\n%s\n".format(plug.name, help)
- }) mkString
+ }).mkString
}
diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
index 2ba8c8eb6b..ab8fe23909 100644
--- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
@@ -35,17 +35,22 @@ abstract class AbstractReporter extends Reporter {
else _severity
if (severity == INFO) {
- if (isVerbose || force)
+ if (isVerbose || force) {
+ severity.count += 1
display(pos, msg, severity)
+ }
}
else {
val hidden = testAndLog(pos, severity)
if (severity == WARNING && noWarnings) ()
else {
- if (!hidden || isPromptSet)
+ if (!hidden || isPromptSet) {
+ severity.count += 1
display(pos, msg, severity)
- else if (settings.debug.value)
+ } else if (settings.debug.value) {
+ severity.count += 1
display(pos, "[ suppressed ] " + msg, severity)
+ }
if (isPromptSet)
displayPrompt
diff --git a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
index f5335fb0f5..956c43c35a 100644
--- a/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/ConsoleReporter.scala
@@ -75,7 +75,6 @@ class ConsoleReporter(val settings: Settings, reader: BufferedReader, writer: Pr
}
def display(pos: Position, msg: String, severity: Severity) {
- severity.count += 1
if (severity != ERROR || severity.count <= ERROR_LIMIT)
print(pos, msg, severity)
}
diff --git a/src/compiler/scala/tools/nsc/scratchpad/Executor.scala b/src/compiler/scala/tools/nsc/scratchpad/Executor.scala
index ff0f94d897..8a918a829c 100644
--- a/src/compiler/scala/tools/nsc/scratchpad/Executor.scala
+++ b/src/compiler/scala/tools/nsc/scratchpad/Executor.scala
@@ -28,7 +28,7 @@ object Executor {
Console.setOut(newOut)
Console.setErr(newOut)
try {
- singletonInstance(name, classLoader)
+ singletonInstance(classLoader, name)
} catch {
case ex: Throwable =>
unwrapThrowable(ex) match {
diff --git a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala
index 9cea935a63..c1dad2da82 100644
--- a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala
@@ -35,7 +35,7 @@ trait AbsSettings extends scala.reflect.internal.settings.AbsSettings {
case s: AbsSettings => this.userSetSettings == s.userSetSettings
case _ => false
}
- override def toString() = "Settings {\n%s}\n" format (userSetSettings map (" " + _ + "\n") mkString)
+ override def toString() = "Settings {\n%s}\n" format (userSetSettings map (" " + _ + "\n")).mkString
def toConciseString = userSetSettings.mkString("(", " ", ")")
def checkDependencies =
diff --git a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
index c010c6a3ea..63775ff1c5 100644
--- a/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/AestheticSettings.scala
@@ -23,6 +23,7 @@ trait AestheticSettings {
def deprecation = settings.deprecation.value
def experimental = settings.Xexperimental.value
def fatalWarnings = settings.fatalWarnings.value
+ def feature = settings.feature.value
def future = settings.future.value
def logClasspath = settings.Ylogcp.value
def printStats = settings.Ystatistics.value
@@ -30,7 +31,7 @@ trait AestheticSettings {
def target = settings.target.value
def unchecked = settings.unchecked.value
def verbose = settings.verbose.value
- def virtPatmat = settings.YvirtPatmat.value
+ def virtPatmat = !settings.XoldPatmat.value
/** Derived values */
def jvm = target startsWith "jvm"
diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
index e7959f36b2..c4dd9a2a36 100644
--- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala
@@ -28,7 +28,7 @@ class MutableSettings(val errorFn: String => Unit)
settings
}
- protected def copyInto(settings: MutableSettings) {
+ def copyInto(settings: MutableSettings) {
allSettings foreach { thisSetting =>
val otherSetting = settings.allSettings find { _.name == thisSetting.name }
otherSetting foreach { otherSetting =>
@@ -136,7 +136,7 @@ class MutableSettings(val errorFn: String => Unit)
val (p, args) = StringOps.splitWhere(s, _ == ':', true) getOrElse (return None)
// any non-Nil return value means failure and we return s unmodified
- tryToSetIfExists(p, args split "," toList, (s: Setting) => s.tryToSetColon _)
+ tryToSetIfExists(p, (args split ",").toList, (s: Setting) => s.tryToSetColon _)
}
// if arg is of form -Xfoo or -Xfoo bar (name = "-Xfoo")
@@ -183,8 +183,8 @@ class MutableSettings(val errorFn: String => Unit)
* The class loader defining `T` should provide resources `app.class.path`
* and `boot.class.path`. These resources should contain the application
* and boot classpaths in the same form as would be passed on the command line.*/
- def embeddedDefaults[T: Manifest]: Unit =
- embeddedDefaults(implicitly[Manifest[T]].erasure.getClassLoader)
+ def embeddedDefaults[T: ClassTag]: Unit =
+ embeddedDefaults(classTag[T].erasure.getClassLoader)
/** Initializes these settings for embedded use by a class from the given class loader.
* The class loader for `T` should provide resources `app.class.path`
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 14b3bcc8ce..0a9d25af7e 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -11,6 +11,7 @@ package settings
import annotation.elidable
import scala.tools.util.PathResolver.Defaults
import scala.collection.mutable
+import language.{implicitConversions, existentials}
trait ScalaSettings extends AbsScalaSettings
with StandardScalaSettings
@@ -40,11 +41,11 @@ trait ScalaSettings extends AbsScalaSettings
protected def optimiseSettings = List[BooleanSetting](inline, inlineHandlers, Xcloselim, Xdce)
/** Internal use - syntax enhancements. */
- private class EnableSettings[T <: Setting](val s: T) {
- def enabling(toEnable: List[BooleanSetting]): s.type = s withPostSetHook (_ => toEnable foreach (_.value = true))
+ private class EnableSettings[T <: BooleanSetting](val s: T) {
+ def enabling(toEnable: List[BooleanSetting]): s.type = s withPostSetHook (_ => toEnable foreach (_.value = s.value))
def andThen(f: s.T => Unit): s.type = s withPostSetHook (setting => f(setting.value))
}
- private implicit def installEnableSettings[T <: Setting](s: T) = new EnableSettings(s)
+ private implicit def installEnableSettings[T <: BooleanSetting](s: T) = new EnableSettings(s)
/** Disable a setting */
def disable(s: Setting) = allSettings -= s
@@ -62,6 +63,7 @@ trait ScalaSettings extends AbsScalaSettings
val classpath = PathSetting ("-classpath", "Specify where to find user class files.", defaultClasspath) withAbbreviation "-cp"
val d = OutputSetting (outputDirs, ".")
val nospecialization = BooleanSetting ("-no-specialization", "Ignore @specialize annotations.")
+ val language = MultiStringSetting("-language", "feature", "Enable one or more language features.")
/**
* -X "Advanced" settings
@@ -80,6 +82,9 @@ trait ScalaSettings extends AbsScalaSettings
val XlogImplicits = BooleanSetting ("-Xlog-implicits", "Show more detail on why some implicits are not applicable.")
val logImplicitConv = BooleanSetting ("-Xlog-implicit-conversions", "Print a message whenever an implicit conversion is inserted.")
val logReflectiveCalls = BooleanSetting("-Xlog-reflective-calls", "Print a message when a reflective method call is generated")
+ val logRuntimeSplices = BooleanSetting("-Xlog-runtime-splices", "Print a message when Expr.eval or Expr.value cannot be resolved statically.")
+ val logFreeTerms = BooleanSetting ("-Xlog-free-terms", "Print a message when reification creates a free term.")
+ val logFreeTypes = BooleanSetting ("-Xlog-free-types", "Print a message when reification resorts to generating a free type.")
val maxClassfileName = IntSetting ("-Xmax-classfile-name", "Maximum filename length for generated classes", 255, Some((72, 255)), _ => None)
val Xmigration28 = BooleanSetting ("-Xmigration", "Warn about constructs whose behavior may have changed between 2.7 and 2.8.")
val nouescape = BooleanSetting ("-Xno-uescape", "Disable handling of \\u unicode escapes.")
@@ -103,6 +108,8 @@ trait ScalaSettings extends AbsScalaSettings
val showPhases = BooleanSetting ("-Xshow-phases", "Print a synopsis of compiler phases.")
val sourceReader = StringSetting ("-Xsource-reader", "classname", "Specify a custom method for reading source files.", "")
+ val XoldPatmat = BooleanSetting ("-Xoldpatmat", "Use the pre-2.10 pattern matcher. Otherwise, the 'virtualizing' pattern matcher is used in 2.10.")
+
/** Compatibility stubs for options whose value name did
* not previously match the option name.
*/
@@ -116,62 +123,61 @@ trait ScalaSettings extends AbsScalaSettings
/**
* -Y "Private" settings
*/
- val overrideObjects = BooleanSetting ("-Yoverride-objects", "Allow member objects to be overridden.")
- val overrideVars = BooleanSetting ("-Yoverride-vars", "Allow vars to be overridden.")
- val Yhelp = BooleanSetting ("-Y", "Print a synopsis of private options.")
- val browse = PhasesSetting ("-Ybrowse", "Browse the abstract syntax tree after")
- val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
- val Yshow = PhasesSetting ("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after")
- val Xcloselim = BooleanSetting ("-Yclosure-elim", "Perform closure elimination.")
- val Ycompacttrees = BooleanSetting ("-Ycompact-trees", "Use compact tree printer when displaying trees.")
- val noCompletion = BooleanSetting ("-Yno-completion", "Disable tab-completion in the REPL.")
- val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination.")
- val debug = BooleanSetting ("-Ydebug", "Increase the quantity of debugging output.")
- // val doc = BooleanSetting ("-Ydoc", "Generate documentation")
- val termConflict = ChoiceSetting ("-Yresolve-term-conflict", "strategy", "Resolve term conflicts",
- List("package", "object", "error"), "error")
- val inline = BooleanSetting ("-Yinline", "Perform inlining when possible.")
- val inlineHandlers= BooleanSetting ("-Yinline-handlers", "Perform exception handler inlining when possible.")
- val Xlinearizer = ChoiceSetting ("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
- val log = PhasesSetting ("-Ylog", "Log operations during")
- val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.")
- val Ynogenericsig = BooleanSetting ("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.")
- val noimports = BooleanSetting ("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.")
- val nopredef = BooleanSetting ("-Yno-predef", "Compile without importing Predef.")
- val noAdaptedArgs = BooleanSetting ("-Yno-adapted-args", "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.")
- val Yprofile = PhasesSetting ("-Yprofile", "(Requires jvm -agentpath to contain yjgpagent) Profile CPU usage of")
- val YprofileMem = BooleanSetting ("-Yprofile-memory", "Profile memory, get heap snapshot after each compiler run (requires yjpagent, see above).")
- val YprofileClass = StringSetting ("-Yprofile-class", "class", "Name of profiler class.", "scala.tools.util.YourkitProfiling")
- val Yrecursion = IntSetting ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some((0, Int.MaxValue)), (_: String) => None)
- val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.")
- val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs.")
- val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
- val Yshowsymkinds = BooleanSetting ("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
- val skip = PhasesSetting ("-Yskip", "Skip")
- val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "")
- val Ydumpclasses = StringSetting ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "")
- val Ynosqueeze = BooleanSetting ("-Yno-squeeze", "Disable creation of compact code in matching.")
- val Ystatistics = BooleanSetting ("-Ystatistics", "Print compiler statistics.") andThen (util.Statistics.enabled = _)
- val stopAfter = PhasesSetting ("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat
- val stopBefore = PhasesSetting ("-Ystop-before", "Stop before")
- val refinementMethodDispatch =
- ChoiceSetting ("-Ystruct-dispatch", "policy", "structural method dispatch policy",
- List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache")
- val globalClass = StringSetting ("-Yglobal-class", "class", "subclass of scala.tools.nsc.Global to use for compiler", "")
- val Yrangepos = BooleanSetting ("-Yrangepos", "Use range positions for syntax trees.")
- val YrichExes = BooleanSetting ("-Yrich-exceptions",
- "Fancier exceptions. Set source search path with -D" +
- sys.SystemProperties.traceSourcePath.key)
- val Ybuilderdebug = ChoiceSetting("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none")
- val Yreifycopypaste =
- BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
- val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
- val Ynotnull = BooleanSetting ("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.")
- val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
- val etaExpandKeepsStar = BooleanSetting("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.")
- val noSelfCheck = BooleanSetting ("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.")
- val YvirtPatmat = BooleanSetting ("-Yvirtpatmat", "Translate pattern matches into flatMap/orElse calls. See scala.MatchingStrategy.")
- val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes")
+ val overrideObjects = BooleanSetting ("-Yoverride-objects", "Allow member objects to be overridden.")
+ val overrideVars = BooleanSetting ("-Yoverride-vars", "Allow vars to be overridden.")
+ val Yhelp = BooleanSetting ("-Y", "Print a synopsis of private options.")
+ val browse = PhasesSetting ("-Ybrowse", "Browse the abstract syntax tree after")
+ val check = PhasesSetting ("-Ycheck", "Check the tree at the end of")
+ val Yshow = PhasesSetting ("-Yshow", "(Requires -Xshow-class or -Xshow-object) Show after")
+ val Xcloselim = BooleanSetting ("-Yclosure-elim", "Perform closure elimination.")
+ val Ycompacttrees = BooleanSetting ("-Ycompact-trees", "Use compact tree printer when displaying trees.")
+ val noCompletion = BooleanSetting ("-Yno-completion", "Disable tab-completion in the REPL.")
+ val Xdce = BooleanSetting ("-Ydead-code", "Perform dead code elimination.")
+ val debug = BooleanSetting ("-Ydebug", "Increase the quantity of debugging output.")
+ //val doc = BooleanSetting ("-Ydoc", "Generate documentation")
+ val termConflict = ChoiceSetting ("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
+ val inline = BooleanSetting ("-Yinline", "Perform inlining when possible.")
+ val inlineHandlers = BooleanSetting ("-Yinline-handlers", "Perform exception handler inlining when possible.")
+ val YinlinerWarnings= BooleanSetting ("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)")
+ val Xlinearizer = ChoiceSetting ("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo")
+ val log = PhasesSetting ("-Ylog", "Log operations during")
+ val Ylogcp = BooleanSetting ("-Ylog-classpath", "Output information about what classpath is being applied.")
+ val Ynogenericsig = BooleanSetting ("-Yno-generic-signatures", "Suppress generation of generic signatures for Java.")
+ val noimports = BooleanSetting ("-Yno-imports", "Compile without importing scala.*, java.lang.*, or Predef.")
+ val nopredef = BooleanSetting ("-Yno-predef", "Compile without importing Predef.")
+ val noAdaptedArgs = BooleanSetting ("-Yno-adapted-args", "Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.")
+ val Yprofile = PhasesSetting ("-Yprofile", "(Requires jvm -agentpath to contain yjgpagent) Profile CPU usage of")
+ val YprofileMem = BooleanSetting ("-Yprofile-memory", "Profile memory, get heap snapshot after each compiler run (requires yjpagent, see above).")
+ val YprofileClass = StringSetting ("-Yprofile-class", "class", "Name of profiler class.", "scala.tools.util.YourkitProfiling")
+ val Yrecursion = IntSetting ("-Yrecursion", "Set recursion depth used when locking symbols.", 0, Some((0, Int.MaxValue)), (_: String) => None)
+ val selfInAnnots = BooleanSetting ("-Yself-in-annots", "Include a \"self\" identifier inside of annotations.")
+ val Xshowtrees = BooleanSetting ("-Yshow-trees", "(Requires -Xprint:) Print detailed ASTs in formatted form.")
+ val XshowtreesCompact
+ = BooleanSetting ("-Yshow-trees-compact", "(Requires -Xprint:) Print detailed ASTs in compact form.")
+ val XshowtreesStringified
+ = BooleanSetting ("-Yshow-trees-stringified", "(Requires -Xprint:) Print stringifications along with detailed ASTs.")
+ val Yshowsyms = BooleanSetting ("-Yshow-syms", "Print the AST symbol hierarchy after each phase.")
+ val Yshowsymkinds = BooleanSetting ("-Yshow-symkinds", "Print abbreviated symbol kinds next to symbol names.")
+ val skip = PhasesSetting ("-Yskip", "Skip")
+ val Ygenjavap = StringSetting ("-Ygen-javap", "dir", "Generate a parallel output directory of .javap files.", "")
+ val Ydumpclasses = StringSetting ("-Ydump-classes", "dir", "Dump the generated bytecode to .class files (useful for reflective compilation that utilizes in-memory classloaders).", "")
+ val Ynosqueeze = BooleanSetting ("-Yno-squeeze", "Disable creation of compact code in matching.")
+ val Ystatistics = BooleanSetting ("-Ystatistics", "Print compiler statistics.") andThen (util.Statistics.enabled = _)
+ val stopAfter = PhasesSetting ("-Ystop-after", "Stop after") withAbbreviation ("-stop") // backward compat
+ val stopBefore = PhasesSetting ("-Ystop-before", "Stop before")
+ val refinementMethodDispatch
+ = ChoiceSetting ("-Ystruct-dispatch", "policy", "structural method dispatch policy", List("no-cache", "mono-cache", "poly-cache", "invoke-dynamic"), "poly-cache")
+ val globalClass = StringSetting ("-Yglobal-class", "class", "subclass of scala.tools.nsc.Global to use for compiler", "")
+ val Yrangepos = BooleanSetting ("-Yrangepos", "Use range positions for syntax trees.")
+ val YrichExes = BooleanSetting ("-Yrich-exceptions", "Fancier exceptions. Set source search path with -D" + sys.SystemProperties.traceSourcePath.key)
+ val Ybuilderdebug = ChoiceSetting ("-Ybuilder-debug", "manager", "Compile using the specified build manager.", List("none", "refined", "simple"), "none")
+ val Yreifycopypaste = BooleanSetting ("-Yreify-copypaste", "Dump the reified trees in copypasteable representation.")
+ val Yreplsync = BooleanSetting ("-Yrepl-sync", "Do not use asynchronous code for repl startup")
+ val Ynotnull = BooleanSetting ("-Ynotnull", "Enable (experimental and incomplete) scala.NotNull.")
+ val YmethodInfer = BooleanSetting ("-Yinfer-argument-types", "Infer types for arguments of overriden methods.")
+ val etaExpandKeepsStar = BooleanSetting ("-Yeta-expand-keeps-star", "Eta-expand varargs methods to T* rather than Seq[T]. This is a temporary option to ease transition.")
+ val noSelfCheck = BooleanSetting ("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.")
+ val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes")
val exposeEmptyPackage = BooleanSetting("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly()
val YnoProductN = BooleanSetting ("-Yno-productN", "Do not add ProductN to case classes")
@@ -180,26 +186,31 @@ trait ScalaSettings extends AbsScalaSettings
/** Area-specific debug output.
*/
- val Ybuildmanagerdebug = BooleanSetting("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.")
- val Ycompletion = BooleanSetting("-Ycompletion-debug", "Trace all tab completion activity.")
- val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.")
- val Yidedebug = BooleanSetting("-Yide-debug", "Generate, validate and output trees using the interactive compiler.")
- val Yinferdebug = BooleanSetting("-Yinfer-debug", "Trace type inference and implicit search.")
- val Ymacrodebug = BooleanSetting("-Ymacro-debug", "Trace macro-related activities: generation of synthetics, expansion, exceptions.")
- val Ypmatdebug = BooleanSetting("-Ypmat-debug", "Trace all pattern matcher activity.")
- val Yposdebug = BooleanSetting("-Ypos-debug", "Trace position validation.")
- val Yreifydebug = BooleanSetting("-Yreify-debug", "Trace reification.")
- val Yrepldebug = BooleanSetting("-Yrepl-debug", "Trace all repl activity.") andThen (interpreter.replProps.debug setValue _)
- val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
+ val Ybuildmanagerdebug = BooleanSetting("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.")
+ val Ycompletion = BooleanSetting("-Ycompletion-debug", "Trace all tab completion activity.")
+ val Ydocdebug = BooleanSetting("-Ydoc-debug", "Trace all scaladoc activity.")
+ val Yidedebug = BooleanSetting("-Yide-debug", "Generate, validate and output trees using the interactive compiler.")
+ val Yinferdebug = BooleanSetting("-Yinfer-debug", "Trace type inference and implicit search.")
+ val Yissuedebug = BooleanSetting("-Yissue-debug", "Print stack traces when a context issues an error.")
+ val YmacrodebugLite = BooleanSetting("-Ymacro-debug-lite", "Trace essential macro-related activities.")
+ val YmacrodebugVerbose = BooleanSetting("-Ymacro-debug-verbose", "Trace all macro-related activities: compilation, generation of synthetics, classloading, expansion, exceptions.")
+ val Ypmatdebug = BooleanSetting("-Ypmat-debug", "Trace all pattern matcher activity.")
+ val Yposdebug = BooleanSetting("-Ypos-debug", "Trace position validation.")
+ val Yreifydebug = BooleanSetting("-Yreify-debug", "Trace reification.")
+ val Yrepldebug = BooleanSetting("-Yrepl-debug", "Trace all repl activity.") andThen (interpreter.replProps.debug setValue _)
+ val Ytyperdebug = BooleanSetting("-Ytyper-debug", "Trace all type assignments.")
/** Groups of Settings.
*/
- val future = BooleanSetting ("-Xfuture", "Turn on future language features.") enabling futureSettings
- val optimise = BooleanSetting ("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize" enabling optimiseSettings
- val Xexperimental = BooleanSetting ("-Xexperimental", "Enable experimental extensions.") enabling experimentalSettings
+ val future = BooleanSetting("-Xfuture", "Turn on future language features.") enabling futureSettings
+ val optimise = BooleanSetting("-optimise", "Generates faster bytecode by applying optimisations to the program") withAbbreviation "-optimize" enabling optimiseSettings
+ val Xexperimental = BooleanSetting("-Xexperimental", "Enable experimental extensions.") enabling experimentalSettings
// Feature extensions
- val Xmacros = BooleanSetting ("-Xmacros", "Enable macros.")
+ val Xmacros = BooleanSetting("-Xmacros", "Enable macros.") // [Martin] Can be retired now.
+ val XmacroSettings = MultiStringSetting("-Xmacro-settings", "option", "Custom settings for macros.")
+ val XmacroPrimaryClasspath = PathSetting("-Xmacro-primary-classpath", "Classpath to load macros implementations from, defaults to compilation classpath (aka \"library classpath\".", "")
+ val XmacroFallbackClasspath = PathSetting("-Xmacro-fallback-classpath", "Classpath to load macros implementations from if they cannot be loaded from library classpath.", "")
/**
* IDE-specific settings
diff --git a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
index c5b477c7bd..1bb0948168 100644
--- a/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/StandardScalaSettings.scala
@@ -32,6 +32,7 @@ trait StandardScalaSettings {
val deprecation = BooleanSetting ("-deprecation", "Emit warning and location for usages of deprecated APIs.")
val encoding = StringSetting ("-encoding", "encoding", "Specify character encoding used by source files.", Properties.sourceEncoding)
val explaintypes = BooleanSetting ("-explaintypes", "Explain type errors in more detail.")
+ val feature = BooleanSetting ("-feature", "Emit warning and location for usages of features that should be imported explicitly.")
val g = ChoiceSetting ("-g", "level", "Set level of generated debugging info.", List("none", "source", "line", "vars", "notailcalls"), "vars")
val help = BooleanSetting ("-help", "Print a synopsis of standard options")
val make = ChoiceSetting ("-make", "policy", "Recompilation detection policy", List("all", "changed", "immediate", "transitive", "transitivenocp"), "all")
@@ -39,7 +40,7 @@ trait StandardScalaSettings {
val nowarn = BooleanSetting ("-nowarn", "Generate no warnings.")
val optimise: BooleanSetting // depends on post hook which mutates other settings
val print = BooleanSetting ("-print", "Print program with Scala-specific features removed.")
- val target = ChoiceSetting ("-target", "target", "Target platform for object files.", List("jvm-1.5", "msil"), "jvm-1.5")
+ val target = ChoiceSetting ("-target", "target", "Target platform for object files.", List("jvm-1.5", "jvm-1.5-asm", "jvm-1.6", "jvm-1.7", "msil"), "jvm-1.5")
val unchecked = BooleanSetting ("-unchecked", "Enable detailed unchecked (erasure) warnings.")
val uniqid = BooleanSetting ("-uniqid", "Uniquely tag all identifiers in debugging output.")
val usejavacp = BooleanSetting ("-usejavacp", "Utilize the java.class.path in classpath resolution.")
diff --git a/src/compiler/scala/tools/nsc/symtab/Positions.scala b/src/compiler/scala/tools/nsc/symtab/Positions.scala
deleted file mode 100644
index 680b06f8ce..0000000000
--- a/src/compiler/scala/tools/nsc/symtab/Positions.scala
+++ /dev/null
@@ -1,30 +0,0 @@
-package scala.tools.nsc
-package symtab
-
-import scala.tools.nsc.util.{ SourceFile, Position, OffsetPosition, NoPosition }
-
-trait Positions extends scala.reflect.internal.Positions {
-self: scala.tools.nsc.symtab.SymbolTable =>
-
- def rangePos(source: SourceFile, start: Int, point: Int, end: Int) =
- new OffsetPosition(source, point)
-
- def validatePositions(tree: Tree) {}
-
- type Position = scala.tools.nsc.util.Position
- val NoPosition = scala.tools.nsc.util.NoPosition
-
- type TreeAnnotation = scala.tools.nsc.util.TreeAnnotation
- val NoTreeAnnotation: TreeAnnotation = NoPosition
- def positionToAnnotation(pos: Position): TreeAnnotation = pos
- def annotationToPosition(annot: TreeAnnotation): Position = annot.pos
- override def _checkSetAnnotation(tree: Tree, annot: TreeAnnotation): Unit = {
- if (tree.pos != NoPosition && tree.pos != annot.pos) debugwarn("Overwriting annotation "+ tree.annotation +" of tree "+ tree +" with annotation "+ annot)
- // if ((tree.annotation.isInstanceOf[scala.tools.nsc.util.Position] || !annot.isInstanceOf[scala.tools.nsc.util.Position]) && tree.isInstanceOf[Block])
- // println("Updating block from "+ tree.annotation +" to "+ annot)
- }
- def focusPos(pos: Position): Position = pos.focus
- def isRangePos(pos: Position): Boolean = pos.isRange
- def showPos(pos: Position): String = pos.show
-
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 7eb04eaf40..390b1a5ec6 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -232,6 +232,16 @@ abstract class SymbolLoaders {
protected def doComplete(root: Symbol) {
val start = startTimer(classReadNanos)
classfileParser.parse(classfile, root)
+ if (root.associatedFile eq null) {
+ root match {
+ // In fact, the ModuleSymbol forwards its setter to the module class
+ case _: ClassSymbol | _: ModuleSymbol =>
+ debuglog("ClassfileLoader setting %s.associatedFile = %s".format(root.name, classfile))
+ root.associatedFile = classfile
+ case _ =>
+ debuglog("Not setting associatedFile to %s because %s is a %s".format(classfile, root.name, root.shortSymbolClass))
+ }
+ }
stopTimer(classReadNanos, start)
}
override def sourcefile: Option[AbstractFile] = classfileParser.srcfile
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
index fb85ebeeb0..75b486ca7d 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTable.scala
@@ -6,7 +6,4 @@
package scala.tools.nsc
package symtab
-import ast.{Trees, TreePrinters, DocComments}
-import util._
-
abstract class SymbolTable extends reflect.internal.SymbolTable \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
index e62070a239..3cf5cc2f54 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala
@@ -7,6 +7,8 @@ package scala.tools.nsc
package symtab
import scala.collection.{ mutable, immutable }
+import language.implicitConversions
+import language.postfixOps
/** Printing the symbol graph (for those symbols attached to an AST node)
* after each phase.
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 9dee441527..ef73d6db1a 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -9,11 +9,11 @@ package classfile
import java.io.{ File, IOException }
import java.lang.Integer.toHexString
-
import scala.collection.{ mutable, immutable }
import scala.collection.mutable.{ ListBuffer, ArrayBuffer }
import scala.annotation.switch
import scala.reflect.internal.pickling.{PickleBuffer, ByteCodecs}
+import scala.reflect.internal.{ JvmClassInfo, JvmMemberInfo }
import scala.tools.nsc.io.AbstractFile
/** This abstract class implements a class file parser.
@@ -24,91 +24,89 @@ import scala.tools.nsc.io.AbstractFile
abstract class ClassfileParser {
val global: Global
import global._
-
+ import definitions.{ AnnotationClass, ClassfileAnnotationClass }
import scala.reflect.internal.ClassfileConstants._
import Flags._
protected var in: AbstractFileReader = _ // the class file reader
protected var clazz: Symbol = _ // the class symbol containing dynamic members
protected var staticModule: Symbol = _ // the module symbol containing static members
- protected var instanceDefs: Scope = _ // the scope of all instance definitions
- protected var staticDefs: Scope = _ // the scope of all static definitions
+ protected var instanceScope: Scope = _ // the scope of all instance definitions
+ protected var staticScope: Scope = _ // the scope of all static definitions
protected var pool: ConstantPool = _ // the classfile's constant pool
protected var isScala: Boolean = _ // does class file describe a scala class?
protected var isScalaAnnot: Boolean = _ // does class file describe a scala class with its pickled info in an annotation?
protected var isScalaRaw: Boolean = _ // this class file is a scala class with no pickled info
- protected var hasMeta: Boolean = _ // does class file contain jaco meta attribute?s
protected var busy: Option[Symbol] = None // lock to detect recursive reads
- private var externalName: Name = _ // JVM name of the current class
+ protected var currentClass: Name = _ // JVM name of the current class
protected var classTParams = Map[Name,Symbol]()
protected var srcfile0 : Option[AbstractFile] = None
+ protected def moduleClass: Symbol = staticModule.moduleClass
def srcfile = srcfile0
- private object metaParser extends MetaParser {
- val global: ClassfileParser.this.global.type = ClassfileParser.this.global
- }
+ private def currentIsTopLevel = currentClass.toString.indexOf('$') < 0
+
+ private var jvmInfo: JvmClassInfo = _
private object unpickler extends scala.reflect.internal.pickling.UnPickler {
val global: ClassfileParser.this.global.type = ClassfileParser.this.global
}
- def parse(file: AbstractFile, root: Symbol) = try {
- debuglog("[class] >> " + root.fullName)
+ private def handleMissing(e: MissingRequirementError) = {
+ if (settings.debug.value) e.printStackTrace
+ throw new IOException("Missing dependency '" + e.req + "', required by " + in.file)
+ }
+ private def handleError(e: Exception) = {
+ if (settings.debug.value) e.printStackTrace()
+ throw new IOException("class file '%s' is broken\n(%s/%s)".format(
+ in.file,
+ e.getClass,
+ if (e.getMessage eq null) "" else e.getMessage)
+ )
+ }
+ private def mismatchError(c: Symbol) = {
+ throw new IOException("class file '%s' has location not matching its contents: contains ".format(in.file) + c)
+ }
- def handleMissing(e: MissingRequirementError) = {
- if (settings.debug.value) e.printStackTrace
- throw new IOException("Missing dependency '" + e.req + "', required by " + in.file)
+ private def parseErrorHandler[T]: PartialFunction[Throwable, T] = {
+ case e: MissingRequirementError => handleMissing(e)
+ case e: RuntimeException => handleError(e)
+ }
+ @inline private def pushBusy[T](sym: Symbol)(body: => T): T = {
+ busy match {
+ case Some(`sym`) => throw new IOException("unsatisfiable cyclic dependency in '%s'".format(sym))
+ case Some(sym1) => throw new IOException("illegal class file dependency between '%s' and '%s'".format(sym, sym1))
+ case _ => ()
}
- def handleError(e: Exception) = {
- if (settings.debug.value) e.printStackTrace()
- throw new IOException("class file '" + in.file + "' is broken\n(" + {
- if (e.getMessage() != null) e.getMessage()
- else e.getClass.toString
- } + ")")
- }
- assert(!busy.isDefined, {
- val (s1, s2) = (busy.get, root)
- if (s1 eq s2) "unsatisfiable cyclic dependency in '%s'".format(s1)
- else "illegal class file dependency between '%s' and '%s'".format(s1, s2)
- })
-
- busy = Some(root)
- /*root match {
- case cs: ClassSymbol =>
- cs.classFile = file
- case ms: ModuleSymbol =>
- ms.moduleClass.asInstanceOf[ClassSymbol].classFile = file
- case _ =>
- println("Skipping class: " + root + ": " + root.getClass)
- }
-*/
- this.in = new AbstractFileReader(file)
- if (root.isModule) {
- this.clazz = root.companionClass
- this.staticModule = root
- } else {
- this.clazz = root
- this.staticModule = root.companionModule
- }
- this.isScala = false
- this.hasMeta = false
- try {
+ busy = Some(sym)
+ try body
+ catch parseErrorHandler
+ finally busy = None
+ }
+ @inline private def raiseLoaderLevel[T](body: => T): T = {
+ loaders.parentsLevel += 1
+ try body
+ finally loaders.parentsLevel -= 1
+ }
+
+ def parse(file: AbstractFile, root: Symbol): Unit = {
+ debuglog("[class] >> " + root.fullName)
+
+ pushBusy(root) {
+ this.in = new AbstractFileReader(file)
+ this.clazz = if (root.isModule) root.companionClass else root
+ this.staticModule = clazz.companionModule
+ this.jvmInfo = JvmClassInfo.fromBytes(file.toByteArray)
+ this.isScala = false
+
parseHeader
this.pool = new ConstantPool
parseClass()
}
- catch {
- case e: MissingRequirementError => handleMissing(e)
- case e: RuntimeException => handleError(e)
- }
- } finally {
- busy = None
}
- protected def statics: Symbol = staticModule.moduleClass
-
private def parseHeader() {
val magic = in.nextInt
if (magic != JAVA_MAGIC)
@@ -501,12 +499,11 @@ abstract class ClassfileParser {
var sawPrivateConstructor = false
def parseClass() {
- val jflags = in.nextChar
+ val jflags = in.nextChar
val isAnnotation = hasAnnotation(jflags)
- var sflags = toScalaClassFlags(jflags)
- var nameIdx = in.nextChar
- externalName = pool.getClassName(nameIdx)
- val c = if (externalName.toString.indexOf('$') < 0) pool.getClassSymbol(nameIdx) else clazz
+ var sflags = toScalaClassFlags(jflags)
+ var nameIdx = in.nextChar
+ currentClass = pool.getClassName(nameIdx)
/** Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled.
* Updates the read pointer of 'in'. */
@@ -516,39 +513,37 @@ abstract class ClassfileParser {
val ifaces = in.nextChar
in.bp += ifaces * 2 // .. and iface count interfaces
List(definitions.AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information
- } else {
- try {
- loaders.parentsLevel += 1
- val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe }
- else pool.getSuperClass(in.nextChar).tpe
- val ifaceCount = in.nextChar
- var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe
- if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
- superType :: ifaces
- } finally {
- loaders.parentsLevel -= 1
- }
+ }
+ else raiseLoaderLevel {
+ val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe }
+ else pool.getSuperClass(in.nextChar).tpe
+ val ifaceCount = in.nextChar
+ var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe
+ if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
+ superType :: ifaces
}
}
- if (c != clazz && externalName.toString.indexOf("$") < 0) {
- if ((clazz eq NoSymbol) && (c ne NoSymbol)) clazz = c
- else throw new IOException("class file '" + in.file + "' contains wrong " + c)
+ val c = if (currentIsTopLevel) pool.getClassSymbol(nameIdx) else clazz
+ if (currentIsTopLevel) {
+ if (c != clazz) {
+ if ((clazz eq NoSymbol) && (c ne NoSymbol)) clazz = c
+ else mismatchError(c)
+ }
}
addEnclosingTParams(clazz)
- parseInnerClasses() // also sets the isScala / isScalaRaw / hasMeta flags, see r15956
+ parseInnerClasses() // also sets the isScala / isScalaRaw flags, see r15956
// get the class file parser to reuse scopes.
- instanceDefs = newScope
- staticDefs = newScope
+ instanceScope = newScope
+ staticScope = newScope
- val classInfo = ClassInfoType(parseParents, instanceDefs, clazz)
- val staticInfo = ClassInfoType(List(), staticDefs, statics)
+ val classInfo = ClassInfoType(parseParents, instanceScope, clazz)
+ val staticInfo = ClassInfoType(List(), staticScope, moduleClass)
- if (!isScala && !isScalaRaw) {
-// println("Entering inner classes for " + clazz)
+ if (!isScala && !isScalaRaw)
enterOwnInnerClasses
- }
+
val curbp = in.bp
skipMembers() // fields
skipMembers() // methods
@@ -556,34 +551,31 @@ abstract class ClassfileParser {
clazz setFlag sflags
setPrivateWithin(clazz, jflags)
setPrivateWithin(staticModule, jflags)
- if (!hasMeta || isScalaRaw) {
- clazz.setInfo(classInfo)
- }
- statics setInfo staticInfo
- staticModule.setInfo(statics.tpe)
+ clazz.setInfo(classInfo)
+ moduleClass setInfo staticInfo
+ staticModule.setInfo(moduleClass.tpe)
staticModule.setFlag(JAVA)
staticModule.moduleClass.setFlag(JAVA)
// attributes now depend on having infos set already
parseAttributes(clazz, classInfo)
- loaders.pendingLoadActions = { () =>
+ def queueLoad() {
in.bp = curbp
- val fieldCount = in.nextChar
- for (i <- 0 until fieldCount) parseField()
+ 0 until in.nextChar foreach (_ => parseField())
sawPrivateConstructor = false
- val methodCount = in.nextChar
- for (i <- 0 until methodCount) parseMethod()
- if (!sawPrivateConstructor &&
- (instanceDefs.lookup(nme.CONSTRUCTOR) == NoSymbol &&
- (sflags & INTERFACE) == 0L))
- {
- //Console.println("adding constructor to " + clazz);//DEBUG
- instanceDefs enter clazz.newClassConstructor(NoPosition)
- }
- ()
- } :: loaders.pendingLoadActions
+ 0 until in.nextChar foreach (_ => parseMethod())
+ val needsConstructor = (
+ !sawPrivateConstructor
+ && instanceScope.lookup(nme.CONSTRUCTOR) == NoSymbol
+ && (sflags & INTERFACE) == 0
+ )
+ if (needsConstructor)
+ instanceScope enter clazz.newClassConstructor(NoPosition)
+ }
+
+ loaders.pendingLoadActions ::= (queueLoad _)
if (loaders.parentsLevel == 0) {
- while (!loaders.pendingLoadActions.isEmpty) {
+ while (loaders.pendingLoadActions.nonEmpty) {
val item = loaders.pendingLoadActions.head
loaders.pendingLoadActions = loaders.pendingLoadActions.tail
item()
@@ -646,8 +638,6 @@ abstract class ClassfileParser {
sawPrivateConstructor = true
in.skip(2); skipAttributes()
} else {
- if ((jflags & JAVA_ACC_BRIDGE) != 0)
- sflags |= BRIDGE
if ((sflags & PRIVATE) != 0L && global.settings.optimise.value) {
in.skip(4); skipAttributes()
} else {
@@ -658,7 +648,7 @@ abstract class ClassfileParser {
info match {
case MethodType(params, restpe) =>
// if this is a non-static inner class, remove the explicit outer parameter
- val newParams = innerClasses.get(externalName) match {
+ val newParams = innerClasses.get(currentClass) match {
case Some(entry) if !isScalaRaw && !isStatic(entry.jflags) =>
assert(params.head.tpe.typeSymbol == clazz.owner, params.head.tpe.typeSymbol + ": " + clazz.owner)
params.tail
@@ -732,7 +722,7 @@ abstract class ClassfileParser {
}
val newtparam = sym.newExistential(newTypeName("?"+i), sym.pos) setInfo bounds
existentials += newtparam
- xs += newtparam.tpe //@M should probably be .tpeHK
+ xs += newtparam.tpeHK
i += 1
case _ =>
xs += sig2type(tparams, skiptvs)
@@ -746,7 +736,7 @@ abstract class ClassfileParser {
} else {
// raw type - existentially quantify all type parameters
val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams)
- val t = typeRef(pre, classSym, eparams.map(_.tpe))
+ val t = typeRef(pre, classSym, eparams.map(_.tpeHK))
val res = newExistentialType(eparams, t)
if (settings.debug.value && settings.verbose.value)
println("raw type " + classSym + " -> " + res)
@@ -774,9 +764,14 @@ abstract class ClassfileParser {
// make unbounded Array[T] where T is a type variable into Array[T with Object]
// (this is necessary because such arrays have a representation which is incompatible
// with arrays of primitive types.
- if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe))
+ // NOTE that the comparison to Object only works for abstract types bounded by classes that are strict subclasses of Object
+ // if the bound is exactly Object, it will have been converted to Any, and the comparison will fail
+ // see also RestrictJavaArraysMap (when compiling java sources directly)
+ if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) {
elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe))
- appliedType(definitions.ArrayClass.tpe, List(elemtp))
+ }
+
+ definitions.arrayType(elemtp)
case '(' =>
// we need a method symbol. given in line 486 by calling getType(methodSym, ..)
assert(sym ne null, sig)
@@ -842,7 +837,7 @@ abstract class ClassfileParser {
while (index < end) {
parents += sig2type(tparams, false) // here the variance doesnt'matter
}
- ClassInfoType(parents.toList, instanceDefs, sym)
+ ClassInfoType(parents.toList, instanceScope, sym)
}
GenPolyType(ownTypeParams, tpe)
} // sigToType
@@ -869,9 +864,8 @@ abstract class ClassfileParser {
sym.setInfo(newType)
if (settings.debug.value && settings.verbose.value)
println("" + sym + "; signature = " + sig + " type = " + newType)
- hasMeta = true
- } else
- in.skip(attrLen)
+ }
+ else in.skip(attrLen)
case tpnme.SyntheticATTR =>
sym.setFlag(SYNTHETIC)
in.skip(attrLen)
@@ -895,10 +889,6 @@ abstract class ClassfileParser {
in.skip(attrLen)
case tpnme.ScalaATTR =>
isScalaRaw = true
- case tpnme.JacoMetaATTR =>
- val meta = pool.getName(in.nextChar).toString.trim()
- metaParser.parse(meta, sym, symtype)
- this.hasMeta = true
// Attribute on methods of java annotation classes when that method has a default
case tpnme.AnnotationDefaultATTR =>
sym.addAnnotation(definitions.AnnotationDefaultAttr)
@@ -1064,19 +1054,18 @@ abstract class ClassfileParser {
}
// begin parseAttributes
- val attrCount = in.nextChar
- for (i <- 0 until attrCount) parseAttribute()
+ for (i <- 0 until in.nextChar) parseAttribute()
}
/** Enter own inner classes in the right scope. It needs the scopes to be set up,
* and implicitly current class' superclasses.
*/
private def enterOwnInnerClasses() {
- def className(name: Name): Name = {
+ def className(name: Name): Name =
name.subName(name.lastPos('.') + 1, name.length)
- }
- def enterClassAndModule(entry: InnerClassEntry, completer: global.loaders.SymbolLoader, jflags: Int) {
+ def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) {
+ val completer = new global.loaders.ClassfileLoader(file)
val name = entry.originalName
var sflags = toScalaClassFlags(jflags)
val owner = getOwner(jflags)
@@ -1085,6 +1074,8 @@ abstract class ClassfileParser {
val innerModule = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer
innerModule.moduleClass setInfo global.loaders.moduleClassLoader
+ List(innerClass, innerModule.moduleClass) foreach (_.associatedFile = file)
+
scope enter innerClass
scope enter innerModule
@@ -1102,11 +1093,11 @@ abstract class ClassfileParser {
for (entry <- innerClasses.values) {
// create a new class member for immediate inner classes
- if (entry.outerName == externalName) {
+ if (entry.outerName == currentClass) {
val file = global.classPath.findSourceFile(entry.externalName.toString) getOrElse {
throw new AssertionError(entry.externalName)
}
- enterClassAndModule(entry, new global.loaders.ClassfileLoader(file), entry.jflags)
+ enterClassAndModule(entry, file, entry.jflags)
}
}
}
@@ -1125,11 +1116,6 @@ abstract class ClassfileParser {
val attrLen = in.nextInt
attrName match {
case tpnme.SignatureATTR =>
- if (!isScala)
- hasMeta = true
- in.skip(attrLen)
- case tpnme.JacoMetaATTR =>
- this.hasMeta = true
in.skip(attrLen)
case tpnme.ScalaSignatureATTR =>
isScala = true
@@ -1194,10 +1180,10 @@ abstract class ClassfileParser {
def innerSymbol(externalName: Name, innerName: Name, static: Boolean): Symbol = {
def getMember(sym: Symbol, name: Name): Symbol =
if (static)
- if (sym == clazz) staticDefs.lookup(name)
+ if (sym == clazz) staticScope.lookup(name)
else sym.companionModule.info.member(name)
else
- if (sym == clazz) instanceDefs.lookup(name)
+ if (sym == clazz) instanceScope.lookup(name)
else sym.info.member(name)
innerClasses.get(externalName) match {
@@ -1220,16 +1206,13 @@ abstract class ClassfileParser {
s
case None =>
- val cls = classNameToSymbol(externalName)
- cls
- //if (static) cls.companionClass else cls
+ classNameToSymbol(externalName)
}
}
get(externalName) match {
case Some(entry) =>
- val clazz = innerSymbol(entry.externalName, entry.originalName, isStatic(entry.jflags))
- clazz
+ innerSymbol(entry.externalName, entry.originalName, isStatic(entry.jflags))
case None =>
classNameToSymbol(externalName)
}
@@ -1262,11 +1245,14 @@ abstract class ClassfileParser {
in.skip(2 * ifaces)
}
+ protected def getOwner(info: JvmMemberInfo): Symbol =
+ if (info.isStatic) moduleClass else clazz
+
protected def getOwner(flags: Int): Symbol =
- if (isStatic(flags)) statics else clazz
+ if (isStatic(flags)) moduleClass else clazz
protected def getScope(flags: Int): Scope =
- if (isStatic(flags)) staticDefs else instanceDefs
+ if (isStatic(flags)) staticScope else instanceScope
private def setPrivateWithin(sym: Symbol, jflags: Int) {
if ((jflags & (JAVA_ACC_PRIVATE | JAVA_ACC_PROTECTED | JAVA_ACC_PUBLIC)) == 0)
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 68af518d3a..862a3ffdc7 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -165,7 +165,7 @@ abstract class ICodeReader extends ClassfileParser {
else if (name == fulltpnme.RuntimeNull)
definitions.NullClass
else if (nme.isImplClassName(name)) {
- val iface = definitions.getClass(nme.interfaceName(name))
+ val iface = definitions.getClass(tpnme.interfaceName(name))
log("forcing " + iface.owner + " at phase: " + phase + " impl: " + iface.implClass)
iface.owner.info // force the mixin type-transformer
definitions.getClass(name)
@@ -625,11 +625,11 @@ abstract class ICodeReader extends ClassfileParser {
* such as Int.box(5).
*/
def isBox(m: Symbol): Boolean =
- (m.owner == definitions.BoxesRunTimeClass.moduleClass
+ (m.owner == definitions.BoxesRunTimeClass
&& m.name.startsWith("boxTo"))
def isUnbox(m: Symbol): Boolean =
- (m.owner == definitions.BoxesRunTimeClass.moduleClass
+ (m.owner == definitions.BoxesRunTimeClass
&& m.name.startsWith("unboxTo"))
/** Return the icode class that should include members with the given flags.
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
deleted file mode 100644
index eb8e7a14a5..0000000000
--- a/src/compiler/scala/tools/nsc/symtab/classfile/MetaParser.scala
+++ /dev/null
@@ -1,166 +0,0 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
-
-package scala.tools.nsc
-package symtab
-package classfile
-
-import java.util.{StringTokenizer, NoSuchElementException}
-
-import scala.collection.mutable.ListBuffer
-
-abstract class MetaParser{
-
- val global: Global
- import global._
-
- private var scanner: StringTokenizer = _
- private var owner: Symbol = _
- private var ownertype: Type = _
- private var token: String = _
- private var locals: Scope = null
-
- def parse(meta: String, sym: Symbol, symtype: Type) {
- //System.out.println("parse meta for " + sym + ":" + meta + ", locals = " + locals);//DEBUG
- this.scanner = new StringTokenizer(meta, "()[], \t<;", true)
- this.owner = sym
- this.ownertype = symtype
- nextToken()
- if (token == "class") parseClass()
- else if (token == "method") parseMethod()
- else if (token == "field") parseField()
- else if (token == "constr") parseConstr()
- else owner.setInfo(symtype);
- }
-
- protected def nextToken() {
- try {
- do { token = scanner.nextToken().trim() } while (token.length() == 0)
- } catch {
- case ex: NoSuchElementException => token = ""
- }
- }
-
- protected def parseType(): Type = {
- val str = token
- nextToken()
- val sym = locals.lookup(newTypeName(str))
- if (sym != NoSymbol) sym.tpe
- else {
- val tp = definitions.getRequiredClass(str).tpe;
- if (token != "[") tp
- else {
- val args = new ListBuffer[Type];
- do {
- nextToken(); args += parseType();
- } while (token == ",");
- nextToken();
- appliedType(tp, args.toList)
- }
- }
- }
-
- protected def parseTypeParam(): Symbol = {
- val vflag =
- if (token == "+") { nextToken(); Flags.COVARIANT }
- else if (token == "-") { nextToken(); Flags.CONTRAVARIANT }
- else 0;
- assert(token startsWith "?", token)
- val sym = owner.newTypeParameter(newTypeName(token)).setFlag(vflag)
- nextToken()
- val lo =
- if (token == ">") { nextToken(); parseType() }
- else definitions.NothingClass.tpe
- val hi =
- if (token == "<") { nextToken(); parseType() }
- else definitions.AnyClass.tpe
- sym.setInfo(TypeBounds(lo, hi))
- locals enter sym;
- sym
- }
-
- protected def parseTypeParams(): List[Symbol] = {
- nextToken()
- val syms = new ListBuffer[Symbol]
- if (token != "]") {
- syms += parseTypeParam()
- while (token == ",") {
- nextToken(); syms += parseTypeParam();
- }
- }
- assert(token == "]")
- syms.toList
- }
-
- protected def parseParams(): List[Type] = {
- nextToken()
- val tps = new ListBuffer[Type]
- if (token != ")") {
- tps += parseType()
- while (token == ",") {
- nextToken(); tps += parseType()
- }
- }
- assert(token == ")")
- tps.toList
- }
-
- protected def parseClass() {
- locals = newScope
- def parse(): Type = {
- nextToken()
- if (token == "[") {
- PolyType(parseTypeParams(), parse())
- } else if (token == "extends") {
- val tps = new ListBuffer[Type]
- do {
- nextToken(); tps += parseType()
- } while (token == "with");
- ownertype match {
- case ClassInfoType(parents, decls, clazz) =>
- ClassInfoType(tps.toList, decls, clazz)
- }
- } else ownertype
- }
- owner.setInfo(parse())
- assert(token == ";")
- }
-
- protected def parseMethod() {
- val globals = locals
- locals = if (locals eq null) newScope else newNestedScope(locals)
- def parse(): Type = {
- nextToken();
- if (token == "[") PolyType(parseTypeParams(), parse())
- else if (token == "(") {
- val formals = parseParams()
- MethodType(owner.newSyntheticValueParams(formals), parse())
- }
- else parseType()
- }
- owner.setInfo(parse())
- locals = globals
- assert(token == ";")
- }
-
- protected def parseField() {
- nextToken()
- owner.setInfo(parseType())
- assert(token == ";")
- }
-
- protected def parseConstr() {
- def parse(): Type = {
- nextToken()
- if (token == "(") {
- val formals = parseParams()
- MethodType(owner.newSyntheticValueParams(formals), parse())
- }
- else owner.owner.tpe
- }
- owner.setInfo(parse())
- assert(token == ";")
- }
-}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
index 758f870d6b..192cc94b90 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala
@@ -62,9 +62,16 @@ abstract class Pickler extends SubComponent {
// when we pickle it: so let's report an error instead. We know next
// to nothing about what happened, but our supposition is a lot better
// than "bad type: <error>" in terms of explanatory power.
- for (t <- unit.body ; if t.isErroneous) {
- unit.error(t.pos, "erroneous or inaccessible type")
- return
+ for (t <- unit.body) {
+ if (t.isErroneous) {
+ unit.error(t.pos, "erroneous or inaccessible type")
+ return
+ }
+
+ if (!t.isDef && t.hasSymbol && t.symbol.isTermMacro) {
+ unit.error(t.pos, "macro has not been expanded")
+ return
+ }
}
pickle(unit.body)
@@ -149,7 +156,7 @@ abstract class Pickler extends SubComponent {
putChildren(sym, children.toList sortBy (_.sealedSortName))
}
- for (annot <- sym.annotations filter (ann => ann.isStatic && !ann.isErroneous) reverse)
+ for (annot <- (sym.annotations filter (ann => ann.isStatic && !ann.isErroneous)).reverse)
putAnnotation(sym, annot)
}
else if (sym != NoSymbol) {
@@ -425,7 +432,7 @@ abstract class Pickler extends SubComponent {
private def putConstant(c: Constant) {
if (putEntry(c)) {
if (c.tag == StringTag) putEntry(newTermName(c.stringValue))
- else if (c.tag == ClassTag) putType(c.typeValue)
+ else if (c.tag == ClazzTag) putType(c.typeValue)
else if (c.tag == EnumTag) putSymbol(c.symbolValue)
}
}
@@ -606,7 +613,7 @@ abstract class Pickler extends SubComponent {
else if (c.tag == FloatTag) writeLong(floatToIntBits(c.floatValue))
else if (c.tag == DoubleTag) writeLong(doubleToLongBits(c.doubleValue))
else if (c.tag == StringTag) writeRef(newTermName(c.stringValue))
- else if (c.tag == ClassTag) writeRef(c.typeValue)
+ else if (c.tag == ClazzTag) writeRef(c.typeValue)
else if (c.tag == EnumTag) writeRef(c.symbolValue)
LITERAL + c.tag // also treats UnitTag, NullTag; no value required
case AnnotatedType(annotations, tp, selfsym) =>
@@ -1059,7 +1066,7 @@ abstract class Pickler extends SubComponent {
else if (c.tag == FloatTag) print("Float "+c.floatValue)
else if (c.tag == DoubleTag) print("Double "+c.doubleValue)
else if (c.tag == StringTag) { print("String "); printRef(newTermName(c.stringValue)) }
- else if (c.tag == ClassTag) { print("Class "); printRef(c.typeValue) }
+ else if (c.tag == ClazzTag) { print("Class "); printRef(c.typeValue) }
else if (c.tag == EnumTag) { print("Enum "); printRef(c.symbolValue) }
case AnnotatedType(annots, tp, selfsym) =>
if (settings.selfInAnnots.value) {
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 4b847fa94a..028d6f2484 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -12,6 +12,7 @@ import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute,
import scala.collection.{ mutable, immutable }
import scala.reflect.internal.pickling.UnPickler
import ch.epfl.lamp.compiler.msil.Type.TMVarUsage
+import language.implicitConversions
/**
* @author Nikolay Mihaylov
diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
index 39e2cbe694..cb7d64b9fc 100644
--- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
+++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala
@@ -43,11 +43,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
*/
private def isInterfaceMember(sym: Symbol) = (
sym.isType || {
- // !!! Shouldn't the following code be equivalent to leaving
- // out the "sym.info" call and starting with "sym.initialize.isMethod" ?
- // Because, it is not, which I found a little disturbing. The compiler
- // fails to bootstrap with an error somewhere.
- sym.info // initialize to set lateMETHOD flag if necessary
+ sym.info // initialize to set lateMETHOD flag if necessary
( sym.isMethod
&& !sym.isLabel
@@ -68,57 +64,60 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
def implClassPhase = currentRun.erasurePhase.next
- /** Return the implementation class of a trait; create a new one of one does not yet exist */
- def implClass(iface: Symbol): Symbol = {
- iface.info
-
- implClassMap.getOrElse(iface, {
- atPhase(implClassPhase) {
- if (iface.implClass ne NoSymbol)
- log("%s.implClass == %s".format(iface, iface.implClass))
-
- val implName = nme.implClassName(iface.name)
- var impl = if (iface.owner.isClass) iface.owner.info.decl(implName) else NoSymbol
+ private def newImplClass(iface: Symbol): Symbol = {
+ val inClass = iface.owner.isClass
+ val implName = tpnme.implClassName(iface.name)
+ val implFlags = (iface.flags & ~(INTERFACE | lateINTERFACE)) | IMPLCLASS
- // !!! Why does forcing the impl's info here lead to a crash?
- // See test case pos/trait-force-info.scala for a minimization.
- // It crashes like this:
- //
- // [log lazyvals] trait ContextTrees.implClass == class ContextTrees$class
- // error: java.lang.AssertionError: assertion failed: (scala.tools.nsc.typechecker.Contexts$NoContext$,scala.tools.nsc.typechecker.Contexts,NoContext$,trait Contexts in package typechecker) / while parsing (/scala/trunk/build/pack/lib/scala-compiler.jar(scala/tools/nsc/interactive/ContextTrees$class.class),Some(class ContextTrees$class))trait Contexts.NoContext$ linkedModule: <none>List()
-
- val originalImpl = impl
- if (impl != NoSymbol) {
+ val impl0 = (
+ if (!inClass) NoSymbol
+ else iface.owner.info.decl(implName) match {
+ case NoSymbol => NoSymbol
+ case implSym =>
// Unlink a pre-existing symbol only if the implementation class is
// visible on the compilation classpath. In general this is true under
// -optimise and not otherwise, but the classpath can use arbitrary
// logic so the classpath must be queried.
if (classPath.context.isValidName(implName + ".class")) {
- log("unlinking impl class " + impl)
- iface.owner.info.decls.unlink(impl)
- impl = NoSymbol
+ log("unlinking impl class " + implSym)
+ iface.owner.info.decls unlink implSym
+ NoSymbol
+ }
+ else {
+ log("not unlinking existing " + implSym + " as the impl class is not visible on the classpath.")
+ implSym
}
- else log("not unlinking existing " + impl + " as the impl class is not visible on the classpath.")
- }
- if (impl == NoSymbol) {
- impl = iface.cloneSymbolImpl(iface.owner)
- impl.name = implName
- impl.sourceFile = iface.sourceFile
- if (iface.owner.isClass)
- iface.owner.info.decls enter impl
- }
- if (currentRun.compiles(iface)) currentRun.symSource(impl) = iface.sourceFile
- impl setPos iface.pos
- impl.flags = iface.flags & ~(INTERFACE | lateINTERFACE) | IMPLCLASS
- impl setInfo new LazyImplClassType(iface)
- implClassMap(iface) = impl
- debuglog(
- "generating impl class " + impl.debugLocationString + " in " + iface.owner + (
- if (originalImpl == NoSymbol) "" else " (cloned from " + originalImpl.debugLocationString + ")"
- )
- )
- impl
}
+ )
+ val impl = impl0 orElse {
+ val impl = iface.owner.newImplClass(implName, iface.pos, implFlags)
+ if (iface.thisSym != iface) {
+ impl.typeOfThis = iface.typeOfThis
+ impl.thisSym setName iface.thisSym.name
+ }
+ impl.sourceFile = iface.sourceFile
+ if (inClass)
+ iface.owner.info.decls enter impl
+
+ impl
+ }
+ if (currentRun compiles iface)
+ currentRun.symSource(impl) = iface.sourceFile
+
+ implClassMap(iface) = impl
+ impl setInfo new LazyImplClassType(iface)
+ }
+
+ /** Return the implementation class of a trait; create a new one of one does not yet exist */
+ def implClass(iface: Symbol): Symbol = {
+ iface.info
+
+ implClassMap.getOrElse(iface, atPhase(implClassPhase) {
+ log("Creating implClass for " + iface)
+ if (iface.implClass ne NoSymbol)
+ log("%s.implClass already exists: %s".format(iface, iface.implClass))
+
+ newImplClass(iface)
})
}
@@ -138,22 +137,31 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
* given the decls ifaceDecls of its interface.
*/
private def implDecls(implClass: Symbol, ifaceDecls: Scope): Scope = {
+ log("LazyImplClassType calculating decls for " + implClass)
+
val decls = newScope
- if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol)
+ if ((ifaceDecls lookup nme.MIXIN_CONSTRUCTOR) == NoSymbol) {
+ log("Adding mixin constructor to " + implClass)
+
decls enter (
implClass.newMethod(nme.MIXIN_CONSTRUCTOR, implClass.pos)
setInfo MethodType(Nil, UnitClass.tpe)
)
+ }
- for (sym <- ifaceDecls.iterator) {
+ for (sym <- ifaceDecls) {
if (isInterfaceMember(sym)) {
if (needsImplMethod(sym)) {
- val impl = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED)
- if (currentRun.compiles(implClass)) implMethodMap(sym) = impl
- decls enter impl
+ log("Cloning " + sym + " for implementation method in " + implClass)
+ val clone = sym.cloneSymbol(implClass).resetFlag(lateDEFERRED)
+ if (currentRun.compiles(implClass)) implMethodMap(sym) = clone
+ decls enter clone
sym setFlag lateDEFERRED
}
- } else {
+ else log(sym + " needs no implementation method in " + implClass)
+ }
+ else {
+ log("Destructively modifying owner of %s from %s to %s".format(sym, sym.owner, implClass))
sym.owner = implClass
// note: OK to destructively modify the owner here,
// because symbol will not be accessible from outside the sourcefile.
@@ -161,14 +169,17 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
decls enter sym
}
}
+
decls
}
- override def complete(sym: Symbol) {
+ override def complete(implSym: Symbol) {
+ log("LazyImplClassType completing " + implSym)
+
/** If `tp` refers to a non-interface trait, return a
* reference to its implementation class. Otherwise return `tp`.
*/
- def mixinToImplClass(tp: Type): Type = erasure(sym) {
+ def mixinToImplClass(tp: Type): Type = AddInterfaces.this.erasure(implSym) {
tp match { //@MATN: no normalize needed (comes after erasure)
case TypeRef(pre, sym, _) if sym.needsImplClass =>
typeRef(pre, implClass(sym), Nil)
@@ -179,15 +190,13 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
def implType(tp: Type): Type = tp match {
case ClassInfoType(parents, decls, _) =>
assert(phase == implClassPhase, tp)
- ClassInfoType(
- ObjectClass.tpe +: (parents.tail map mixinToImplClass filter (_.typeSymbol != ObjectClass)) :+ iface.tpe,
- implDecls(sym, decls),
- sym
- )
+ // Impl class parents: Object first, matching interface last.
+ val implParents = ObjectClass.tpe +: (parents.tail map mixinToImplClass filter (_.typeSymbol != ObjectClass)) :+ iface.tpe
+ ClassInfoType(implParents, implDecls(implSym, decls), implSym)
case PolyType(_, restpe) =>
implType(restpe)
}
- sym setInfo implType(beforeErasure(iface.info))
+ implSym setInfo implType(beforeErasure(iface.info))
}
override def load(clazz: Symbol) { complete(clazz) }
@@ -195,10 +204,9 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
def transformMixinInfo(tp: Type): Type = tp match {
case ClassInfoType(parents, decls, clazz) =>
- if (clazz.needsImplClass) {
- clazz setFlag lateINTERFACE
- implClass(clazz) // generate an impl class
- }
+ if (clazz.needsImplClass)
+ implClass(clazz setFlag lateINTERFACE) // generate an impl class
+
val parents1 = parents match {
case Nil => Nil
case hd :: tl =>
@@ -206,14 +214,12 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
if (clazz.isTrait) erasedTypeRef(ObjectClass) :: tl
else parents
}
- val decls1 = scopeTransform(clazz) { decls filter (sym =>
- if (clazz.isInterface) isInterfaceMember(sym)
- else (!sym.isType || sym.isClass))
- }
-
- //if (!clazz.isPackageClass) System.out.println("Decls of "+clazz+" after explicitOuter = " + decls1);//DEBUG
- //if ((parents1 eq parents) && (decls1 eq decls)) tp
- //else
+ val decls1 = scopeTransform(clazz)(
+ decls filter (sym =>
+ if (clazz.isInterface) isInterfaceMember(sym)
+ else sym.isClass || sym.isTerm
+ )
+ )
ClassInfoType(parents1, decls1, clazz)
case _ =>
tp
@@ -233,27 +239,29 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
}
}
- private def ifaceMemberDef(tree: Tree): Tree =
- if (!tree.isDef || !isInterfaceMember(tree.symbol)) EmptyTree
- else if (needsImplMethod(tree.symbol)) DefDef(tree.symbol, EmptyTree)
- else tree
+ private def createMemberDef(tree: Tree, isForInterface: Boolean)(create: Tree => Tree) = {
+ val isInterfaceTree = tree.isDef && isInterfaceMember(tree.symbol)
+ if (isInterfaceTree && needsImplMethod(tree.symbol))
+ create(tree)
+ else if (isInterfaceTree == isForInterface)
+ tree
+ else
+ EmptyTree
+ }
+ private def implMemberDef(tree: Tree): Tree = createMemberDef(tree, false)(implMethodDef)
+ private def ifaceMemberDef(tree: Tree): Tree = createMemberDef(tree, true)(t => DefDef(t.symbol, EmptyTree))
private def ifaceTemplate(templ: Template): Template =
treeCopy.Template(templ, templ.parents, emptyValDef, templ.body map ifaceMemberDef)
- private def implMethodDef(tree: Tree, ifaceMethod: Symbol): Tree =
- implMethodMap.get(ifaceMethod) match {
- case Some(implMethod) =>
- tree.symbol = implMethod
- new ChangeOwnerAndReturnTraverser(ifaceMethod, implMethod)(tree)
- case None =>
- abort("implMethod missing for " + ifaceMethod)
- }
-
- private def implMemberDef(tree: Tree): Tree =
- if (!tree.isDef || !isInterfaceMember(tree.symbol)) tree
- else if (needsImplMethod(tree.symbol)) implMethodDef(tree, tree.symbol)
- else EmptyTree
+ /** Transforms the member tree containing the implementation
+ * into a member of the impl class.
+ */
+ private def implMethodDef(tree: Tree): Tree = (
+ implMethodMap get tree.symbol
+ map (impl => new ChangeOwnerAndReturnTraverser(tree.symbol, impl)(tree setSymbol impl))
+ getOrElse abort("implMethod missing for " + tree.symbol)
+ )
/** Add mixin constructor definition
* def $init$(): Unit = ()
@@ -325,14 +333,12 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure =>
case Template(parents, self, body) =>
val parents1 = sym.owner.info.parents map (t => TypeTree(t) setPos tree.pos)
treeCopy.Template(tree, parents1, emptyValDef, body)
- case This(_) =>
- if (sym.needsImplClass) {
- val impl = implClass(sym)
- var owner = currentOwner
- while (owner != sym && owner != impl) owner = owner.owner;
- if (owner == impl) This(impl) setPos tree.pos
- else tree
- } else tree
+ case This(_) if sym.needsImplClass =>
+ val impl = implClass(sym)
+ var owner = currentOwner
+ while (owner != sym && owner != impl) owner = owner.owner;
+ if (owner == impl) This(impl) setPos tree.pos
+ else tree
/* !!!
case Super(qual, mix) =>
val mix1 = mix
diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
index b21fa4bc83..bf01e142c9 100644
--- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala
+++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala
@@ -9,6 +9,7 @@ package transform
import symtab._
import Flags._
import scala.collection._
+import language.postfixOps
abstract class CleanUp extends Transform with ast.TreeDSL {
import global._
@@ -299,11 +300,11 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
def testForName(name: Name): Tree => Tree = t => (
if (nme.CommonOpNames(name))
- gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumberOrBoolean), t :: Nil)
+ gen.mkMethodCall(definitions.Boxes_isNumberOrBool, t :: Nil)
else if (nme.BooleanOpNames(name))
t IS_OBJ BoxedBooleanClass.tpe
else
- gen.mkMethodCall(getMember(BoxesRunTimeClass, nme.isBoxedNumber), t :: Nil)
+ gen.mkMethodCall(definitions.Boxes_isNumber, t :: Nil)
)
/** The Tree => Tree function in the return is necessary to prevent the original qual
@@ -318,8 +319,10 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
else if (params.tail.isEmpty) nme.primitiveInfixMethodName(name)
else nme.NO_NAME
)
- if (methodName == nme.NO_NAME) None
- else Some((getMember(BoxesRunTimeClass, methodName), testForName(name)))
+ definitions.getDeclIfDefined(BoxesRunTimeClass, methodName) match {
+ case NoSymbol => None
+ case sym => assert(!sym.isOverloaded, sym) ; Some((sym, testForName(name)))
+ }
}
/* ### BOXING PARAMS & UNBOXING RESULTS ### */
@@ -540,7 +543,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
if (forMSIL) savingStatics( transformTemplate(tree) )
else transformTemplate(tree)
- case Literal(c) if (c.tag == ClassTag) && !forMSIL=>
+ case Literal(c) if (c.tag == ClazzTag) && !forMSIL=>
val tpe = c.typeValue
typedWithPos(tree.pos) {
if (isPrimitiveValueClass(tpe.typeSymbol)) {
@@ -608,7 +611,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL {
val ntree = typedWithPos(tree.pos)(safeREF(staticFieldSym))
super.transform(ntree)
- // This transform replaces Array(Predef.wrapArray(Array(...)), <manifest>)
+ // This transform replaces Array(Predef.wrapArray(Array(...)), <tag>)
// with just Array(...)
case Apply(appMeth, List(Apply(wrapRefArrayMeth, List(array)), _))
if (wrapRefArrayMeth.symbol == Predef_wrapRefArray &&
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index 4f833c82d3..bc4483923a 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -362,9 +362,8 @@ abstract class Constructors extends Transform with ast.TreeDSL {
val tree =
If(
Apply(
- Select(
- Apply(gen.mkAttributedRef(specializedFlag), List()),
- definitions.getMember(definitions.BooleanClass, nme.UNARY_!)),
+ CODE.NOT (
+ Apply(gen.mkAttributedRef(specializedFlag), List())),
List()),
Block(stats, Literal(Constant())),
EmptyTree)
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 0c867b9e7e..9e7e4b3f4f 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -210,7 +210,7 @@ abstract class Erasure extends AddInterfaces
}
else parents
)
- ps map boxedSig mkString
+ (ps map boxedSig).mkString
}
def boxedSig(tp: Type) = jsig(tp, primitiveOK = false)
def boundsSig(bounds: List[Type]) = traceSig("boundsSig", bounds) {
@@ -480,11 +480,10 @@ abstract class Erasure extends AddInterfaces
// TODO: should we do this for user-defined unapplies as well?
// does the first argument list have exactly one argument -- for user-defined unapplies we can't be sure
def maybeWrap(bridgingCall: Tree): Tree = {
- val canReturnNone = afterErasure(
- member.isSynthetic
- && (member.name == nme.unapply || member.name == nme.unapplySeq)
- && !(member.tpe <:< other.tpe) // no static guarantees (TODO: is the subtype test ever true?)
- )
+ val canReturnNone = ( // can't statically know which member is going to be selected, so don't let this depend on member.isSynthetic
+ (member.name == nme.unapply || member.name == nme.unapplySeq)
+ && !afterErasure((member.tpe <:< other.tpe))) // no static guarantees (TODO: is the subtype test ever true?)
+
if (canReturnNone) {
import CODE._
val typeTest = gen.mkIsInstanceOf(REF(bridge.firstParam), member.tpe.params.head.tpe)
@@ -618,8 +617,12 @@ abstract class Erasure extends AddInterfaces
// See SI-4731 for one example of how this occurs.
log("Attempted to cast to Unit: " + tree)
tree.duplicate setType pt
- }
- else gen.mkAttributedCast(tree, pt)
+ } else if (tree.tpe != null && tree.tpe.typeSymbol == ArrayClass && pt.typeSymbol == ArrayClass) {
+ // See SI-2386 for one example of when this might be necessary.
+ val needsExtraCast = isScalaValueType(tree.tpe.typeArgs.head) && !isScalaValueType(pt.typeArgs.head)
+ val tree1 = if (needsExtraCast) gen.mkRuntimeCall(nme.toObjectArray, List(tree)) else tree
+ gen.mkAttributedCast(tree1, pt)
+ } else gen.mkAttributedCast(tree, pt)
}
/** Adapt `tree` to expected type `pt`.
@@ -640,7 +643,8 @@ abstract class Erasure extends AddInterfaces
else if (isPrimitiveValueType(tree.tpe) && !isPrimitiveValueType(pt)) {
adaptToType(box(tree, pt.toString), pt)
} else if (tree.tpe.isInstanceOf[MethodType] && tree.tpe.params.isEmpty) {
- assert(tree.symbol.isStable, "adapt "+tree+":"+tree.tpe+" to "+pt)
+ // [H] this assert fails when trying to typecheck tree !(SomeClass.this.bitmap) for single lazy val
+ //assert(tree.symbol.isStable, "adapt "+tree+":"+tree.tpe+" to "+pt)
adaptToType(Apply(tree, List()) setPos tree.pos setType tree.tpe.resultType, pt)
// } else if (pt <:< tree.tpe)
// cast(tree, pt)
@@ -665,6 +669,7 @@ abstract class Erasure extends AddInterfaces
*/
private def adaptMember(tree: Tree): Tree = {
//Console.println("adaptMember: " + tree);
+ val x = 2 + 2
tree match {
case Apply(TypeApply(sel @ Select(qual, name), List(targ)), List())
if tree.symbol == Any_asInstanceOf =>
@@ -734,7 +739,7 @@ abstract class Erasure extends AddInterfaces
/** A replacement for the standard typer's `typed1` method.
*/
- override protected def typed1(tree: Tree, mode: Int, pt: Type): Tree = {
+ override def typed1(tree: Tree, mode: Int, pt: Type): Tree = {
val tree1 = try {
tree match {
case InjectDerivedValue(arg) =>
@@ -993,7 +998,7 @@ abstract class Erasure extends AddInterfaces
}
// Rewrite 5.getClass to ScalaRunTime.anyValClass(5)
else if (isPrimitiveValueClass(qual.tpe.typeSymbol))
- global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual)))
+ global.typer.typed(gen.mkRuntimeCall(nme.anyValClass, List(qual, typer.resolveErasureTag(qual.tpe.widen, tree.pos, true))))
else
tree
@@ -1090,7 +1095,7 @@ abstract class Erasure extends AddInterfaces
case Match(selector, cases) =>
Match(Typed(selector, TypeTree(selector.tpe)), cases)
- case Literal(ct) if ct.tag == ClassTag
+ case Literal(ct) if ct.tag == ClazzTag
&& ct.typeValue.typeSymbol != definitions.UnitClass =>
val erased = ct.typeValue match {
case TypeRef(pre, clazz, args) if clazz.isDerivedValueClass => scalaErasure.eraseNormalClassRef(pre, clazz)
@@ -1134,10 +1139,10 @@ abstract class Erasure extends AddInterfaces
*/
override def transform(tree: Tree): Tree = {
val tree1 = preTransformer.transform(tree)
- log("tree after pretransform: "+tree1)
+ // log("tree after pretransform: "+tree1)
afterErasure {
val tree2 = mixinTransformer.transform(tree1)
- debuglog("tree after addinterfaces: \n" + tree2)
+ // debuglog("tree after addinterfaces: \n" + tree2)
newTyper(rootContext(unit, tree, true)).typed(tree2)
}
diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
index 595c1486b6..8daad8a2ac 100644
--- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala
@@ -93,7 +93,7 @@ abstract class ExplicitOuter extends InfoTransform
}
def newOuterAccessor(clazz: Symbol) = {
val accFlags = SYNTHETIC | METHOD | STABLE | ( if (clazz.isTrait) DEFERRED else 0 )
- val sym = clazz.newMethodSymbol(nme.OUTER, clazz.pos, accFlags)
+ val sym = clazz.newMethod(nme.OUTER, clazz.pos, accFlags)
val restpe = if (clazz.isTrait) clazz.outerClass.tpe else clazz.outerClass.thisType
sym expandName clazz
@@ -357,7 +357,7 @@ abstract class ExplicitOuter extends InfoTransform
*/
def mixinOuterAccessorDef(mixinClass: Symbol): Tree = {
val outerAcc = outerAccessor(mixinClass) overridingSymbol currentClass
- def mixinPrefix = currentClass.thisType baseType mixinClass prefix;
+ def mixinPrefix = (currentClass.thisType baseType mixinClass).prefix
assert(outerAcc != NoSymbol, "No outer accessor for inner mixin " + mixinClass + " in " + currentClass)
// I added the mixinPrefix.typeArgs.nonEmpty condition to address the
// crash in SI-4970. I feel quite sure this can be improved.
diff --git a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
index 5104518dd9..007457ef7b 100644
--- a/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
+++ b/src/compiler/scala/tools/nsc/transform/ExtensionMethods.scala
@@ -50,7 +50,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
val index = alts indexOf imeth
assert(index >= 0, alts+" does not contain "+imeth)
def altName(index: Int) = newTermName("extension"+index+"$"+imeth.name)
- altName(index) #:: ((0 until alts.length).toStream filter (index !=) map altName)
+ altName(index) #:: ((0 until alts.length).toStream filter (index != _) map altName)
case tpe =>
assert(tpe != NoType, imeth.name+" not found in "+imeth.owner+"'s decls: "+imeth.owner.info.decls)
Stream(newTermName("extension$"+imeth.name))
@@ -68,7 +68,7 @@ abstract class ExtensionMethods extends Transform with TypingTransformers {
private def normalize(stpe: Type, clazz: Symbol): Type = stpe match {
case PolyType(tparams, restpe) =>
- GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe, clazz))
+ GenPolyType(tparams dropRight clazz.typeParams.length, normalize(restpe.substSym(tparams takeRight clazz.typeParams.length, clazz.typeParams), clazz))
case MethodType(tparams, restpe) =>
restpe
case _ =>
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 8856024a30..c8de25b2ea 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -27,6 +27,7 @@ abstract class Flatten extends InfoTransform {
scope unlink old
scope enter sym
+ log("lifted " + sym.fullLocationString)
old
}
@@ -36,7 +37,7 @@ abstract class Flatten extends InfoTransform {
debuglog("re-enter " + sym.fullLocationString)
val old = replaceSymbolInCurrentScope(sym)
if (old ne NoSymbol)
- debuglog("lifted " + sym.fullLocationString + ", unlinked " + old)
+ log("unlinked " + old.fullLocationString + " after lifting " + sym)
}
}
private def liftSymbol(sym: Symbol) {
@@ -108,7 +109,7 @@ abstract class Flatten extends InfoTransform {
tree match {
case PackageDef(_, _) =>
liftedDefs(tree.symbol.moduleClass) = new ListBuffer
- case Template(_, _, _) if tree.symbol.owner.hasPackageFlag =>
+ case Template(_, _, _) if tree.symbol.isDefinedInPackage =>
liftedDefs(tree.symbol.owner) = new ListBuffer
case _ =>
}
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 13ca8e55bc..618a1cbba4 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -19,19 +19,6 @@ abstract class LambdaLift extends InfoTransform {
/** the following two members override abstract members in Transform */
val phaseName: String = "lambdalift"
- /** Converts types of captured variables to *Ref types.
- */
- def boxIfCaptured(sym: Symbol, tpe: Type, erasedTypes: Boolean) =
- if (sym.isCapturedVariable) {
- val symClass = tpe.typeSymbol
- def refType(valueRef: Map[Symbol, Symbol], objectRefClass: Symbol) =
- if (isPrimitiveValueClass(symClass) && symClass != UnitClass) valueRef(symClass).tpe
- else if (erasedTypes) objectRefClass.tpe
- else appliedType(objectRefClass.typeConstructor, List(tpe))
- if (sym.hasAnnotation(VolatileAttr)) refType(volatileRefClass, VolatileObjectRefClass)
- else refType(refClass, ObjectRefClass)
- } else tpe
-
private val lifted = new TypeMap {
def apply(tp: Type): Type = tp match {
case TypeRef(NoPrefix, sym, Nil) if sym.isClass && !sym.isPackageClass =>
@@ -46,7 +33,8 @@ abstract class LambdaLift extends InfoTransform {
}
def transformInfo(sym: Symbol, tp: Type): Type =
- boxIfCaptured(sym, lifted(tp), erasedTypes = true)
+ if (sym.isCapturedVariable) capturedVariableType(sym, tpe = lifted(tp), erasedTypes = true)
+ else lifted(tp)
protected def newTransformer(unit: CompilationUnit): Transformer =
new LambdaLifter(unit)
@@ -171,7 +159,7 @@ abstract class LambdaLift extends InfoTransform {
// for that failure. There should be exactly one method for any given
// entity which always gives the right answer.
if (sym.isImplClass)
- localImplClasses((sym.owner, nme.interfaceName(sym.name))) = sym
+ localImplClasses((sym.owner, tpnme.interfaceName(sym.name))) = sym
else {
renamable addEntry sym
if (sym.isTrait)
@@ -229,10 +217,10 @@ abstract class LambdaLift extends InfoTransform {
sym.owner.name + nme.NAME_JOIN_STRING
else ""
)
- sym.name =
+ sym setName (
if (sym.name.isTypeName) unit.freshTypeName(base)
else unit.freshTermName(base)
-
+ )
debuglog("renaming in %s: %s => %s".format(sym.owner.fullLocationString, originalName, sym.name))
}
@@ -241,7 +229,7 @@ abstract class LambdaLift extends InfoTransform {
def renameTrait(traitSym: Symbol, implSym: Symbol) {
val originalImplName = implSym.name
renameSym(traitSym)
- implSym.name = nme.implClassName(traitSym.name)
+ implSym setName tpnme.implClassName(traitSym.name)
debuglog("renaming impl class in step with %s: %s => %s".format(traitSym, originalImplName, implSym.name))
}
@@ -471,6 +459,8 @@ abstract class LambdaLift extends InfoTransform {
private def preTransform(tree: Tree) = super.transform(tree) setType lifted(tree.tpe)
override def transform(tree: Tree): Tree = tree match {
+ case Select(ReferenceToBoxed(idt), elem) if elem == nme.elem =>
+ postTransform(preTransform(idt), isBoxedRef = false)
case ReferenceToBoxed(idt) =>
postTransform(preTransform(idt), isBoxedRef = true)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
index 85ba539993..2b26f1590d 100644
--- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala
+++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala
@@ -12,7 +12,8 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
import CODE._
val phaseName: String = "lazyvals"
- val FLAGS_PER_WORD: Int
+ private val FLAGS_PER_BYTE: Int = 8 // Byte
+ private def bitmapKind = ByteClass
def newTransformer(unit: CompilationUnit): Transformer =
new LazyValues(unit)
@@ -53,7 +54,6 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
private val lazyVals = perRunCaches.newMap[Symbol, Int]() withDefaultValue 0
import symtab.Flags._
- import lazyVals._
/** Perform the following transformations:
* - for a lazy accessor inside a method, make it check the initialization bitmap
@@ -68,8 +68,19 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
curTree = tree
tree match {
+
+ case Block(_, _) =>
+ val block1 = super.transform(tree)
+ val Block(stats, expr) = block1
+ val stats1 = stats.flatMap(_ match {
+ case Block(List(d1@DefDef(_, n1, _, _, _, _)), d2@DefDef(_, n2, _, _, _, _)) if (nme.newLazyValSlowComputeName(n2) == n1) =>
+ List(d1, d2)
+ case stat => List(stat)
+ })
+ treeCopy.Block(block1, stats1, expr)
+
case DefDef(_, _, _, _, _, rhs) => atOwner(tree.symbol) {
- val res = if (!sym.owner.isClass && sym.isLazy) {
+ val (res, slowPathDef) = if (!sym.owner.isClass && sym.isLazy) {
val enclosingClassOrDummyOrMethod = {
val enclMethod = sym.enclMethod
@@ -84,13 +95,14 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
}
val idx = lazyVals(enclosingClassOrDummyOrMethod)
lazyVals(enclosingClassOrDummyOrMethod) = idx + 1
- val rhs1 = mkLazyDef(enclosingClassOrDummyOrMethod, super.transform(rhs), idx, sym)
+ val (rhs1, sDef) = mkLazyDef(enclosingClassOrDummyOrMethod, transform(rhs), idx, sym)
sym.resetFlag((if (lazyUnit(sym)) 0 else LAZY) | ACCESSOR)
- rhs1
- } else
- super.transform(rhs)
-
- deriveDefDef(tree)(_ => if (LocalLazyValFinder.find(res)) typed(addBitmapDefs(sym, res)) else res)
+ (rhs1, sDef)
+ } else
+ (transform(rhs), EmptyTree)
+
+ val ddef1 = deriveDefDef(tree)(_ => if (LocalLazyValFinder.find(res)) typed(addBitmapDefs(sym, res)) else res)
+ if (slowPathDef != EmptyTree) Block(slowPathDef, ddef1) else ddef1
}
case Template(_, _, body) => atOwner(currentOwner) {
@@ -175,6 +187,24 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
case _ => prependStats(bmps, rhs)
}
}
+
+ def mkSlowPathDef(clazz: Symbol, lzyVal: Symbol, cond: Tree, syncBody: List[Tree],
+ stats: List[Tree], retVal: Tree): Tree = {
+ val defSym = clazz.newMethod(nme.newLazyValSlowComputeName(lzyVal.name), lzyVal.pos, STABLE | PRIVATE)
+ defSym setInfo MethodType(List(), lzyVal.tpe.resultType)
+ defSym.owner = lzyVal.owner
+ if (bitmaps.contains(lzyVal))
+ bitmaps(lzyVal).map(_.owner = defSym)
+ val rhs: Tree = (gen.mkSynchronizedCheck(clazz, cond, syncBody, stats)).changeOwner(currentOwner -> defSym)
+ DEF(defSym).mkTree(addBitmapDefs(lzyVal, BLOCK(rhs, retVal))) setSymbol defSym
+ }
+
+
+ def mkFastPathBody(clazz: Symbol, lzyVal: Symbol, cond: Tree, syncBody: List[Tree],
+ stats: List[Tree], retVal: Tree): (Tree, Tree) = {
+ val slowPathDef: Tree = mkSlowPathDef(clazz, lzyVal, cond, syncBody, stats, retVal)
+ (If(cond, Apply(ID(slowPathDef.symbol), List()), retVal), slowPathDef)
+ }
/** return a 'lazified' version of rhs. Rhs should conform to the
* following schema:
@@ -185,33 +215,38 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
* <rhs> when the lazy value has type Unit (for which there is no field
* to cache it's value.
*
- * The result will be a tree of the form
- * {
- * if ((bitmap$n & MASK) == 0) {
+ * Similarly as for normal lazy val members (see Mixin), the result will be a tree of the form
+ * { if ((bitmap&n & MASK) == 0) this.l$compute()
+ * else l$
+ *
+ * def l$compute() = { synchronized(enclosing_class_or_dummy) {
+ * if ((bitmap$n & MASK) == 0) {
* l$ = <rhs>
* bitmap$n = bimap$n | MASK
+ * }}
+ * l$
* }
- * l$
* }
- * where bitmap$n is an int value acting as a bitmap of initialized values. It is
- * the 'n' is (offset / 32), the MASK is (1 << (offset % 32)). If the value has type
- * unit, no field is used to cache the value, so the resulting code is:
+ * where bitmap$n is a byte value acting as a bitmap of initialized values. It is
+ * the 'n' is (offset / 8), the MASK is (1 << (offset % 8)). If the value has type
+ * unit, no field is used to cache the value, so the l$compute will now look as following:
* {
- * if ((bitmap$n & MASK) == 0) {
+ * def l$compute() = { synchronized(enclosing_class_or_dummy) {
+ * if ((bitmap$n & MASK) == 0) {
* <rhs>;
* bitmap$n = bimap$n | MASK
- * }
+ * }}
* ()
+ * }
* }
*/
- private def mkLazyDef(methOrClass: Symbol, tree: Tree, offset: Int, lazyVal: Symbol): Tree = {
+ private def mkLazyDef(methOrClass: Symbol, tree: Tree, offset: Int, lazyVal: Symbol): (Tree, Tree) = {
val bitmapSym = getBitmapFor(methOrClass, offset)
- val mask = LIT(1 << (offset % FLAGS_PER_WORD))
+ val mask = LIT(1 << (offset % FLAGS_PER_BYTE))
val bitmapRef = if (methOrClass.isClass) Select(This(methOrClass), bitmapSym) else Ident(bitmapSym)
def mkBlock(stmt: Tree) = BLOCK(stmt, mkSetFlag(bitmapSym, mask, bitmapRef), UNIT)
-
val (block, res) = tree match {
case Block(List(assignment), res) if !lazyUnit(lazyVal) =>
(mkBlock(assignment), res)
@@ -219,16 +254,13 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
(mkBlock(rhs), UNIT)
}
- val cond = (bitmapRef INT_& mask) INT_== ZERO
-
- atPos(tree.pos)(localTyper.typed {
- def body = gen.mkDoubleCheckedLocking(methOrClass.enclClass, cond, List(block), Nil)
- BLOCK(body, res)
- })
+ val cond = (bitmapRef GEN_& (mask, bitmapKind)) GEN_== (ZERO, bitmapKind)
+ val lazyDefs = mkFastPathBody(methOrClass.enclClass, lazyVal, cond, List(block), Nil, res)
+ (atPos(tree.pos)(localTyper.typed {lazyDefs._1 }), atPos(tree.pos)(localTyper.typed {lazyDefs._2 }))
}
private def mkSetFlag(bmp: Symbol, mask: Tree, bmpRef: Tree): Tree =
- bmpRef === (bmpRef INT_| mask)
+ bmpRef === (bmpRef GEN_| (mask, bitmapKind))
val bitmaps = mutable.Map[Symbol, List[Symbol]]() withDefaultValue Nil
@@ -236,12 +268,12 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD
* given offset.
*/
private def getBitmapFor(meth: Symbol, offset: Int): Symbol = {
- val n = offset / FLAGS_PER_WORD
+ val n = offset / FLAGS_PER_BYTE
val bmps = bitmaps(meth)
if (bmps.length > n)
bmps(n)
else {
- val sym = meth.newVariable(nme.newBitmapName(nme.BITMAP_NORMAL, n), meth.pos).setInfo(IntClass.tpe)
+ val sym = meth.newVariable(nme.newBitmapName(nme.BITMAP_NORMAL, n), meth.pos).setInfo(ByteClass.tpe)
beforeTyper {
sym addAnnotation VolatileAttr
}
diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala
index adbb7d43d0..4ce5985af8 100644
--- a/src/compiler/scala/tools/nsc/transform/Mixin.scala
+++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala
@@ -29,9 +29,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
/** Map a lazy, mixedin field accessor to it's trait member accessor */
private val initializer = perRunCaches.newMap[Symbol, Symbol]
- /** Deferred bitmaps that will be added during the transformation of a class */
- private val deferredBitmaps = perRunCaches.newMap[Symbol, List[Tree]]() withDefaultValue Nil
-
// --------- helper functions -----------------------------------------------
/** A member of a trait is implemented statically if its implementation after the
@@ -123,7 +120,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
*/
private def rebindSuper(base: Symbol, member: Symbol, mixinClass: Symbol): Symbol =
afterPickler {
- var bcs = base.info.baseClasses.dropWhile(mixinClass !=).tail
+ var bcs = base.info.baseClasses.dropWhile(mixinClass != _).tail
var sym: Symbol = NoSymbol
debuglog("starting rebindsuper " + base + " " + member + ":" + member.tpe +
" " + mixinClass + " " + base.info.baseClasses + "/" + bcs)
@@ -136,7 +133,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
sym = member.matchingSymbol(bcs.head, base.thisType).suchThat(sym => !sym.hasFlag(DEFERRED | BRIDGE))
bcs = bcs.tail
}
- assert(sym != NoSymbol, member)
sym
}
@@ -339,8 +335,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else if (mixinMember.isSuperAccessor) { // mixin super accessors
val superAccessor = addMember(clazz, mixinMember.cloneSymbol(clazz)) setPos clazz.pos
assert(superAccessor.alias != NoSymbol, superAccessor)
- val alias1 = rebindSuper(clazz, mixinMember.alias, mixinClass)
- superAccessor.asInstanceOf[TermSymbol] setAlias alias1
+
+ rebindSuper(clazz, mixinMember.alias, mixinClass) match {
+ case NoSymbol =>
+ unit.error(clazz.pos, "Member %s of mixin %s is missing a concrete super implementation.".format(
+ mixinMember.alias, mixinClass))
+ case alias1 =>
+ superAccessor.asInstanceOf[TermSymbol] setAlias alias1
+ }
}
else if (mixinMember.isMethod && mixinMember.isModule && mixinMember.hasNoFlags(LIFTED | BRIDGE)) {
// mixin objects: todo what happens with abstract objects?
@@ -384,11 +386,14 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
var sourceModule = clazz.owner.info.decls.lookup(sym.name.toTermName)
if (sourceModule != NoSymbol) {
sourceModule setPos sym.pos
- sourceModule.flags = MODULE | FINAL
+ if (sourceModule.flags != MODULE) {
+ log("!!! Directly setting sourceModule flags from %s to MODULE".format(flagsToString(sourceModule.flags)))
+ sourceModule.flags = MODULE
+ }
}
else {
sourceModule = (
- clazz.owner.newModuleSymbol(sym.name.toTermName, sym.pos, MODULE | FINAL)
+ clazz.owner.newModuleSymbol(sym.name.toTermName, sym.pos, MODULE)
setModuleClass sym.asInstanceOf[ClassSymbol]
)
clazz.owner.info.decls enter sourceModule
@@ -487,6 +492,19 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* fields count as fields defined by the class itself.
*/
private val fieldOffset = perRunCaches.newMap[Symbol, Int]()
+
+ private val bitmapKindForCategory = perRunCaches.newMap[Name, ClassSymbol]()
+
+ // ByteClass, IntClass, LongClass
+ private def bitmapKind(field: Symbol): ClassSymbol = bitmapKindForCategory(bitmapCategory(field))
+
+ private def flagsPerBitmap(field: Symbol): Int = bitmapKind(field) match {
+ case BooleanClass => 1
+ case ByteClass => 8
+ case IntClass => 32
+ case LongClass => 64
+ }
+
/** The first transform; called in a pre-order traversal at phase mixin
* (that is, every node is processed before its children).
@@ -605,12 +623,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
if (field.accessed hasAnnotation TransientAttr) {
if (isNormal) BITMAP_TRANSIENT
else BITMAP_CHECKINIT_TRANSIENT
- }
- else if (field hasFlag PRIVATE | notPRIVATE) {
- if (isNormal) BITMAP_PRIVATE
- else BITMAP_CHECKINIT
- }
- else {
+ } else {
if (isNormal) BITMAP_NORMAL
else BITMAP_CHECKINIT
}
@@ -678,11 +691,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else newDefs ::: (stats filter isNotDuplicate)
}
- def addDeferredBitmap(clazz: Symbol, tree: Tree) {
- // Append the set of deferred defs
- deferredBitmaps(clazz) ::= typedPos(clazz.pos)(tree)
- }
-
/** If `stat` is a superaccessor, complete it by adding a right-hand side.
* Note: superaccessors are always abstract until this point.
* The method to call in a superaccessor is stored in the accessor symbol's alias field.
@@ -700,108 +708,116 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
stat
}
- import lazyVals._
-
- /**
- * Private or transient lazy vals use bitmaps that are private for the class context,
- * unlike public or protected vals, which can use inherited bitmaps.
- * Similarly fields in the checkinit mode use private bitmaps.
- */
- def isLocalBitmapField(field: Symbol) = (
- field.accessed.hasAnnotation(TransientAttr)
- || field.hasFlag(PRIVATE | notPRIVATE)
- || isCheckInitField(field)
- )
-
/**
* Return the bitmap field for 'offset'. Depending on the hierarchy it is possible to reuse
* the bitmap of its parents. If that does not exist yet we create one.
*/
- def bitmapFor(clazz0: Symbol, offset: Int, field: Symbol, searchParents: Boolean = true): Symbol = {
+ def bitmapFor(clazz0: Symbol, offset: Int, field: Symbol): Symbol = {
val category = bitmapCategory(field)
- val bitmapName = nme.newBitmapName(category, offset / FLAGS_PER_WORD)
- val sym = clazz0.info.member(bitmapName)
+ val bitmapName = nme.newBitmapName(category, offset / flagsPerBitmap(field))
+ val sym = clazz0.info.decl(bitmapName)
assert(!sym.isOverloaded, sym)
-
+
def createBitmap: Symbol = {
- val sym = clazz0.newVariable(bitmapName, clazz0.pos) setInfo IntClass.tpe
+ val bitmapKind = bitmapKindForCategory(category)
+ val sym = clazz0.newVariable(bitmapName, clazz0.pos) setInfo bitmapKind.tpe
beforeTyper(sym addAnnotation VolatileAttr)
category match {
case nme.BITMAP_TRANSIENT | nme.BITMAP_CHECKINIT_TRANSIENT => sym addAnnotation TransientAttr
case _ =>
}
- category match {
- case nme.BITMAP_NORMAL if field.isLazy => sym setFlag PROTECTED
- case _ => sym setFlag PrivateLocal
+ val init = bitmapKind match {
+ case BooleanClass => VAL(sym) === FALSE
+ case _ => VAL(sym) === ZERO
}
-
+
+ sym setFlag PrivateLocal
clazz0.info.decls.enter(sym)
- if (clazz0 == clazz)
- addDef(clazz.pos, VAL(sym) === ZERO)
- else {
- //FIXME: the assertion below will not work because of the way bitmaps are added.
- // They should be added during infoTransform, so that in separate compilation, bitmap
- // is a member of clazz and doesn't fail the condition couple lines below.
- // This works, as long as we assume that the previous classes were compiled correctly.
- //assert(clazz0.sourceFile != null)
- addDeferredBitmap(clazz0, VAL(sym) === ZERO)
- }
+ addDef(clazz0.pos, init)
sym
}
if (sym ne NoSymbol)
sym
- else if (searchParents && !isLocalBitmapField(field))
- bitmapForParents(clazz0, offset, field) getOrElse createBitmap
else
createBitmap
}
-
- def bitmapForParents(clazz0: Symbol, offset: Int, valSym: Symbol): Option[Symbol] = {
- def requiredBitmaps(fs: Int): Int = if (fs == 0) -1 else (fs - 1) / FLAGS_PER_WORD
- val bitmapNum = offset / FLAGS_PER_WORD
-
- // filter private and transient
- // since we do not inherit normal values (in checkinit mode) also filter them out
- // !!! Not sure how that comment relates to this code...
- superClassesToCheck(clazz0) foreach { cl =>
- val fields0 = usedBits(cl)
-
- if (requiredBitmaps(fields0) < bitmapNum) {
- val fields1 = cl.info.decls filter isNonLocalFieldWithBitmap size;
- return {
- if (requiredBitmaps(fields0 + fields1) >= bitmapNum)
- Some(bitmapFor(cl, offset, valSym, false))
- else None // Don't waste time, since we won't find bitmap anyway
- }
- }
- }
- None
+
+ def maskForOffset(offset: Int, sym: Symbol, kind: ClassSymbol): Tree = {
+ def realOffset = offset % flagsPerBitmap(sym)
+ if (kind == LongClass ) LIT(1L << realOffset) else LIT(1 << realOffset)
}
/** Return an (untyped) tree of the form 'Clazz.this.bmp = Clazz.this.bmp | mask'. */
- def mkSetFlag(clazz: Symbol, offset: Int, valSym: Symbol): Tree = {
- val bmp = bitmapFor(clazz, offset, valSym)
- val mask = LIT(1 << (offset % FLAGS_PER_WORD))
- def x = This(clazz) DOT bmp
+ def mkSetFlag(clazz: Symbol, offset: Int, valSym: Symbol, kind: ClassSymbol): Tree = {
+ val bmp = bitmapFor(clazz, offset, valSym)
+ def mask = maskForOffset(offset, valSym, kind)
+ def x = This(clazz) DOT bmp
+ def newValue = if (kind == BooleanClass) TRUE else (x GEN_| (mask, kind))
- x === (x INT_| mask)
+ x === newValue
}
/** Return an (untyped) tree of the form 'clazz.this.bitmapSym & mask (==|!=) 0', the
* precise comparison operator depending on the value of 'equalToZero'.
*/
- def mkTest(clazz: Symbol, mask: Tree, bitmapSym: Symbol, equalToZero: Boolean): Tree = {
- def lhs = (This(clazz) DOT bitmapSym) INT_& mask
- if (equalToZero) lhs INT_== ZERO
- else lhs INT_!= ZERO
+ def mkTest(clazz: Symbol, mask: Tree, bitmapSym: Symbol, equalToZero: Boolean, kind: ClassSymbol): Tree = {
+ val bitmapTree = (This(clazz) DOT bitmapSym)
+ def lhs = bitmapTree GEN_& (mask, kind)
+ kind match {
+ case BooleanClass =>
+ if (equalToZero) NOT(bitmapTree)
+ else bitmapTree
+ case _ =>
+ if (equalToZero) lhs GEN_== (ZERO, kind)
+ else lhs GEN_!= (ZERO, kind)
+ }
+ }
+
+ def mkSlowPathDef(clazz: Symbol, lzyVal: Symbol, cond: Tree, syncBody: List[Tree],
+ stats: List[Tree], retVal: Tree, attrThis: Tree, args: List[Tree]): Symbol = {
+ val defSym = clazz.newMethod(nme.newLazyValSlowComputeName(lzyVal.name), lzyVal.pos, PRIVATE)
+ val params = defSym newSyntheticValueParams args.map(_.symbol.tpe)
+ defSym setInfoAndEnter MethodType(params, lzyVal.tpe.resultType)
+ val rhs: Tree = (gen.mkSynchronizedCheck(attrThis, cond, syncBody, stats)).changeOwner(currentOwner -> defSym)
+ val strictSubst = new TreeSymSubstituterWithCopying(args.map(_.symbol), params)
+ addDef(position(defSym), DEF(defSym).mkTree(strictSubst(BLOCK(rhs, retVal))) setSymbol defSym)
+ defSym
+ }
+
+ def mkFastPathLazyBody(clazz: Symbol, lzyVal: Symbol, cond: Tree, syncBody: List[Tree],
+ stats: List[Tree], retVal: Tree): Tree = {
+ mkFastPathBody(clazz, lzyVal, cond, syncBody, stats, retVal, gen.mkAttributedThis(clazz), List())
+ }
+
+ def mkFastPathBody(clazz: Symbol, lzyVal: Symbol, cond: Tree, syncBody: List[Tree],
+ stats: List[Tree], retVal: Tree, attrThis: Tree, args: List[Tree]): Tree = {
+ val slowPathSym: Symbol = mkSlowPathDef(clazz, lzyVal, cond, syncBody, stats, retVal, attrThis, args)
+ If(cond, fn (This(clazz), slowPathSym, args.map(arg => Ident(arg.symbol)): _*), retVal)
}
+
+
+ /** Always copy the tree if we are going to perform sym substitution,
+ * otherwise we will side-effect on the tree that is used in the fast path
+ */
+ class TreeSymSubstituterWithCopying(from: List[Symbol], to: List[Symbol]) extends TreeSymSubstituter(from, to) {
+ override def transform(tree: Tree): Tree =
+ if (tree.hasSymbol && from.contains(tree.symbol))
+ super.transform(tree.duplicate)
+ else super.transform(tree.duplicate)
+
+ override def apply[T <: Tree](tree: T): T = if (from.isEmpty) tree else super.apply(tree)
+ }
/** return a 'lazified' version of rhs. It uses double-checked locking to ensure
- * initialization is performed at most once. Private fields used only in this
- * initializer are subsequently set to null.
+ * initialization is performed at most once. For performance reasons the double-checked
+ * locking is split into two parts, the first (fast) path checks the bitmap without
+ * synchronizing, and if that fails it initializes the lazy val within the
+ * synchronization block (slow path). This way the inliner should optimize
+ * the fast path because the method body is small enough.
+ * Private fields used only in this initializer are subsequently set to null.
*
* @param clazz The class symbol
* @param init The tree which initializes the field ( f = <rhs> )
@@ -809,56 +825,64 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* @param offset The offset of this field in the flags bitmap
*
* The result will be a tree of the form
- * {
- * if ((bitmap$n & MASK) == 0) {
- * synchronized(this) {
- * if ((bitmap$n & MASK) == 0) {
- * init // l$ = <rhs>
- * bitmap$n = bimap$n | MASK
- * }
- * }
- * this.f1 = null
- * ... this.fn = null
+ * { if ((bitmap&n & MASK) == 0) this.l$compute()
+ * else l$
+ *
+ * ...
+ * def l$compute() = { synchronized(this) {
+ * if ((bitmap$n & MASK) == 0) {
+ * init // l$ = <rhs>
+ * bitmap$n = bimap$n | MASK
+ * }}
+ * l$
* }
- * l$
+ *
+ * ...
+ * this.f1 = null
+ * ... this.fn = null
* }
- * where bitmap$n is an int value acting as a bitmap of initialized values. It is
- * the 'n' is (offset / 32), the MASK is (1 << (offset % 32)).
+ * where bitmap$n is a byte, int or long value acting as a bitmap of initialized values.
+ * The kind of the bitmap determines how many bit indicators for lazy vals are stored in it.
+ * For Int bitmap it is 32 and then 'n' in the above code is: (offset / 32),
+ * the MASK is (1 << (offset % 32)).
+ * If the class contains only a single lazy val then the bitmap is represented
+ * as a Boolean and the condition checking is a simple bool test.
*/
def mkLazyDef(clazz: Symbol, lzyVal: Symbol, init: List[Tree], retVal: Tree, offset: Int): Tree = {
def nullify(sym: Symbol) = Select(This(clazz), sym.accessedOrSelf) === LIT(null)
val bitmapSym = bitmapFor(clazz, offset, lzyVal)
- val mask = LIT(1 << (offset % FLAGS_PER_WORD))
- def cond = mkTest(clazz, mask, bitmapSym, true)
+ val kind = bitmapKind(lzyVal)
+ val mask = maskForOffset(offset, lzyVal, kind)
+ def cond = mkTest(clazz, mask, bitmapSym, true, kind)
val nulls = lazyValNullables(lzyVal).toList sortBy (_.id) map nullify
- def syncBody = init ::: List(mkSetFlag(clazz, offset, lzyVal), UNIT)
+ def syncBody = init ::: List(mkSetFlag(clazz, offset, lzyVal, kind), UNIT)
if (nulls.nonEmpty)
log("nulling fields inside " + lzyVal + ": " + nulls)
- val result = gen.mkDoubleCheckedLocking(clazz, cond, syncBody, nulls)
- typedPos(init.head.pos)(BLOCK(result, retVal))
+ typedPos(init.head.pos)(mkFastPathLazyBody(clazz, lzyVal, cond, syncBody, nulls, retVal))
}
- def mkInnerClassAccessorDoubleChecked(attrThis: Tree, rhs: Tree): Tree =
+ def mkInnerClassAccessorDoubleChecked(attrThis: Tree, rhs: Tree, moduleSym: Symbol, args: List[Tree]): Tree =
rhs match {
case Block(List(assign), returnTree) =>
val Assign(moduleVarRef, _) = assign
val cond = Apply(Select(moduleVarRef, nme.eq), List(NULL))
- val doubleSynchrTree = gen.mkDoubleCheckedLocking(attrThis, cond, List(assign), Nil)
- Block(List(doubleSynchrTree), returnTree)
+ mkFastPathBody(clazz, moduleSym, cond, List(assign), List(NULL), returnTree, attrThis, args)
case _ =>
assert(false, "Invalid getter " + rhs + " for module in class " + clazz)
EmptyTree
}
def mkCheckedAccessor(clazz: Symbol, retVal: Tree, offset: Int, pos: Position, fieldSym: Symbol): Tree = {
- val bitmapSym = bitmapFor(clazz, offset, fieldSym.getter(fieldSym.owner))
- val mask = LIT(1 << (offset % FLAGS_PER_WORD))
+ val sym = fieldSym.getter(fieldSym.owner)
+ val bitmapSym = bitmapFor(clazz, offset, sym)
+ val kind = bitmapKind(sym)
+ val mask = maskForOffset(offset, sym, kind)
val msg = "Uninitialized field: " + unit.source + ": " + pos.line
val result =
- IF (mkTest(clazz, mask, bitmapSym, false)) .
+ IF (mkTest(clazz, mask, bitmapSym, false, kind)) .
THEN (retVal) .
ELSE (THROW(UninitializedErrorClass, LIT(msg)))
@@ -903,7 +927,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
else if (settings.checkInit.value && !clazz.isTrait && sym.isSetter) {
val getter = sym.getter(clazz)
if (needsInitFlag(getter) && fieldOffset.isDefinedAt(getter))
- deriveDefDef(stat)(rhs => Block(List(rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter))), UNIT))
+ deriveDefDef(stat)(rhs => Block(List(rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter)))), UNIT))
else stat
}
else if (sym.isModule && (!clazz.isTrait || clazz.isImplClass) && !sym.isBridge) {
@@ -913,7 +937,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// Martin to Hubert: I think this can be replaced by selfRef(tree.pos)
// @PP: It does not seem so, it crashes for me trying to bootstrap.
if (clazz.isImplClass) gen.mkAttributedIdent(stat.vparamss.head.head.symbol) else gen.mkAttributedThis(clazz),
- rhs
+ rhs, sym, stat.vparamss.head
)
)
)
@@ -930,8 +954,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
private def checkedGetter(lhs: Tree) = {
val sym = clazz.info decl lhs.symbol.getterName suchThat (_.isGetter)
if (needsInitAndHasOffset(sym)) {
- debuglog("adding checked getter for: " + sym + " " + lhs.symbol.defaultFlagString)
- List(localTyper typed mkSetFlag(clazz, fieldOffset(sym), sym))
+ debuglog("adding checked getter for: " + sym + " " + lhs.symbol.flagString)
+ List(localTyper typed mkSetFlag(clazz, fieldOffset(sym), sym, bitmapKind(sym)))
}
else Nil
}
@@ -956,23 +980,12 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
def addInitBits(clazz: Symbol, rhs: Tree): Tree =
new AddInitBitsTransformer(clazz) transform rhs
- def isNonLocalFieldWithBitmap(field: Symbol) =
- isFieldWithBitmap(field) && !isLocalBitmapField(field)
-
def isCheckInitField(field: Symbol) =
needsInitFlag(field) && !field.isDeferred
def superClassesToCheck(clazz: Symbol) =
clazz.ancestors filterNot (_ hasFlag TRAIT | JAVA)
- /**
- * Return the number of bits used by superclass fields.
- */
- def usedBits(clazz0: Symbol): Int =
- superClassesToCheck(clazz0) flatMap (_.info.decls) count { f =>
- f.owner != clazz0 && isNonLocalFieldWithBitmap(f)
- }
-
// begin addNewDefs
/** Fill the map from fields to offset numbers.
@@ -980,25 +993,27 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
* code generation easier later.
*/
def buildBitmapOffsets() {
- def fold(zero: Int, fields: List[Symbol]) = {
- var idx = zero
+ def fold(fields: List[Symbol], category: Name) = {
+ var idx = 0
fields foreach { f =>
- idx += 1
fieldOffset(f) = idx
+ idx += 1
}
+
+ if (idx == 0) ()
+ else if (idx == 1) bitmapKindForCategory(category) = BooleanClass
+ else if (idx < 9) bitmapKindForCategory(category) = ByteClass
+ else if (idx < 33) bitmapKindForCategory(category) = IntClass
+ else bitmapKindForCategory(category) = LongClass
}
clazz.info.decls.toList groupBy bitmapCategory foreach {
case (nme.NO_NAME, _) => ()
- case (nme.BITMAP_NORMAL, fields) => fold(usedBits(clazz), fields)
- case (_, fields) => fold(0, fields)
+ case (category, fields) => fold(fields, category)
}
}
buildBitmapOffsets()
var stats1 = addCheckedGetters(clazz, stats)
- // add deferred bitmaps
- deferredBitmaps remove clazz foreach { d => stats1 = add(stats1, d) }
-
def accessedReference(sym: Symbol) = sym.tpe match {
case MethodType(Nil, ConstantType(c)) => Literal(c)
case _ =>
@@ -1044,7 +1059,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
val getter = sym.getter(clazz)
if (!needsInitFlag(getter)) init
- else Block(init, mkSetFlag(clazz, fieldOffset(getter), getter), UNIT)
+ else Block(init, mkSetFlag(clazz, fieldOffset(getter), getter, bitmapKind(getter)), UNIT)
}
}
else if (needsInitFlag(sym))
@@ -1061,7 +1076,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
val rhs = gen.newModule(sym, vdef.symbol.tpe)
val assignAndRet = gen.mkAssignAndReturn(vdef.symbol, rhs)
val attrThis = gen.mkAttributedThis(clazz)
- val rhs1 = mkInnerClassAccessorDoubleChecked(attrThis, assignAndRet)
+ val rhs1 = mkInnerClassAccessorDoubleChecked(attrThis, assignAndRet, sym, List())
addDefDef(sym, rhs1)
}
@@ -1077,7 +1092,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL {
// add forwarders
assert(sym.alias != NoSymbol, sym)
// debuglog("New forwarder: " + sym.defString + " => " + sym.alias.defString)
- addDefDef(sym, Apply(staticRef(sym.alias), gen.mkAttributedThis(clazz) :: sym.paramss.head.map(Ident)))
+ if (!sym.isTermMacro) addDefDef(sym, Apply(staticRef(sym.alias), gen.mkAttributedThis(clazz) :: sym.paramss.head.map(Ident)))
}
}
}
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 1afa1dbf58..aea29a27dd 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -8,6 +8,7 @@ package transform
import scala.tools.nsc.symtab.Flags
import scala.collection.{ mutable, immutable }
+import language.postfixOps
/** Specialize code on types.
*
@@ -67,8 +68,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
import definitions.{
RootClass, BooleanClass, UnitClass, ArrayClass,
ScalaValueClasses, isPrimitiveValueClass, isScalaValueType,
- SpecializedClass, RepeatedParamClass, JavaRepeatedParamClass,
- AnyRefClass, ObjectClass, AnyRefModule,
+ SpecializedClass, UnspecializedClass, AnyRefClass, ObjectClass, AnyRefModule,
GroupOfSpecializable, uncheckedVarianceClass, ScalaInlineClass
}
@@ -99,9 +99,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Concrete methods that use a specialized type, or override such methods. */
private val concreteSpecMethods = perRunCaches.newWeakSet[Symbol]()
- private def isSpecialized(sym: Symbol) = sym hasAnnotation SpecializedClass
- private def hasSpecializedFlag(sym: Symbol) = sym hasFlag SPECIALIZED
- private def specializedTypes(tps: List[Symbol]) = tps filter isSpecialized
+ private def specializedTypes(tps: List[Symbol]) = tps filter (_.isSpecialized)
private def specializedOn(sym: Symbol): List[Symbol] = {
sym getAnnotation SpecializedClass match {
case Some(AnnotationInfo(_, Nil, _)) => specializableTypes.map(_.typeSymbol)
@@ -128,11 +126,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
isBoundedGeneric(tp)
//(tp <:< AnyRefClass.tpe)
}
- private def isBoundedGeneric(tp: Type) = tp match {
- case TypeRef(_, sym, _) if sym.isAbstractType => (tp <:< AnyRefClass.tpe)
- case TypeRef(_, sym, _) => !isPrimitiveValueClass(sym)
- case _ => false
- }
object TypeEnv {
/** Return a new type environment binding specialized type parameters of sym to
@@ -141,7 +134,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def fromSpecialization(sym: Symbol, args: List[Type]): TypeEnv = {
ifDebug(assert(sym.info.typeParams.length == args.length, sym + " args: " + args))
- emptyEnv ++ collectMap2(sym.info.typeParams, args)((k, v) => isSpecialized(k))
+ emptyEnv ++ collectMap2(sym.info.typeParams, args)((k, v) => k.isSpecialized)
}
/** Does typeenv `t1` include `t2`? All type variables in `t1`
@@ -166,7 +159,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
def isValid(env: TypeEnv, sym: Symbol): Boolean = {
env forall { case (tvar, tpe) =>
- isSpecialized(tvar) && (concreteTypes(tvar) contains tpe) && {
+ tvar.isSpecialized && (concreteTypes(tvar) contains tpe) && {
(sym.typeParams contains tvar) ||
(sym.owner != RootClass && (sym.owner.typeParams contains tvar))
}
@@ -178,7 +171,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* 'sClass' itself if sClass is not a specialized subclass.
*/
def genericClass(sClass: Symbol): Symbol =
- if (hasSpecializedFlag(sClass)) sClass.superClass
+ if (sClass.isSpecialized) sClass.superClass
else sClass
case class Overload(sym: Symbol, env: TypeEnv) {
@@ -243,7 +236,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Type bounds of a @specialized type var are now in the environment. */
override def typeBoundsIn(env: TypeEnv): Boolean = {
target.info.typeParams exists { tvar =>
- isSpecialized(tvar) && (specializedTypeVars(tvar.info.bounds) exists env.isDefinedAt)
+ tvar.isSpecialized && (specializedTypeVars(tvar.info.bounds) exists env.isDefinedAt)
}
}
@@ -259,21 +252,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Has `clazz` any type parameters that need be specialized? */
def hasSpecializedParams(clazz: Symbol) =
- clazz.info.typeParams exists isSpecialized
+ clazz.info.typeParams exists (_.isSpecialized)
/** Return specialized type parameters. */
def specializedParams(sym: Symbol): List[Symbol] =
- sym.info.typeParams filter isSpecialized
+ sym.info.typeParams filter (_.isSpecialized)
def splitParams(tps: List[Symbol]) =
- tps partition isSpecialized
+ tps partition (_.isSpecialized)
/** Given an original class symbol and a list of types its type parameters are instantiated at
* returns a list of type parameters that should remain in the TypeRef when instantiating a
* specialized type.
*/
def survivingArgs(sym: Symbol, args: List[Type]): List[Type] =
- for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !isSpecialized(tvar) || !isScalaValueType(tpe))
+ for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !tvar.isSpecialized || !isScalaValueType(tpe))
yield tpe
val specializedType = new TypeMap {
@@ -347,7 +340,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* These are in a meaningful order for stability purposes.
*/
def concreteTypes(sym: Symbol): List[Type] = {
- val types = if (!isSpecialized(sym))
+ val types = if (!sym.isSpecialized)
Nil // no @specialized Annotation
else
specializedOn(sym) map (s => specializesClass(s).tpe) sorted
@@ -363,7 +356,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
private def specializations(tps: List[Symbol]): List[TypeEnv] = {
// the keys in each TypeEnv
- val keys: List[Symbol] = tps filter isSpecialized
+ val keys: List[Symbol] = tps filter (_.isSpecialized)
// creating each permutation of concrete types
def loop(ctypes: List[List[Type]]): List[List[Type]] = ctypes match {
case Nil => Nil
@@ -381,14 +374,19 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* - members with specialized type parameters found in the given environment
* - constructors of specialized classes
* - normalized members whose type bounds appear in the environment
+ * But suppressed for:
+ * - any member with the @unspecialized annotation, or which has an
+ * enclosing member with the annotation.
*/
- private def needsSpecialization(env: TypeEnv, sym: Symbol): Boolean = {
- specializedTypeVars(sym).intersect(env.keySet).diff(wasSpecializedForTypeVars(sym)).nonEmpty ||
- (sym.isClassConstructor && (sym.enclClass.typeParams exists isSpecialized)) ||
- (isNormalizedMember(sym) && info(sym).typeBoundsIn(env))
- }
+ private def needsSpecialization(env: TypeEnv, sym: Symbol): Boolean = (
+ !sym.ownerChain.exists(_ hasAnnotation UnspecializedClass) && (
+ specializedTypeVars(sym).intersect(env.keySet).diff(wasSpecializedForTypeVars(sym)).nonEmpty
+ || sym.isClassConstructor && (sym.enclClass.typeParams exists (_.isSpecialized))
+ || isNormalizedMember(sym) && info(sym).typeBoundsIn(env)
+ )
+ )
- def isNormalizedMember(m: Symbol) = hasSpecializedFlag(m) && (info get m exists {
+ def isNormalizedMember(m: Symbol) = m.isSpecialized && (info get m exists {
case NormalizedMember(_) => true
case _ => false
})
@@ -409,14 +407,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case TypeRef(pre, sym, args) =>
if (sym.isAliasType)
specializedTypeVars(tpe.normalize)
- else if (sym.isTypeParameter && isSpecialized(sym) || (sym.isTypeSkolem && isSpecialized(sym.deSkolemize)))
+ else if (sym.isTypeParameter && sym.isSpecialized || (sym.isTypeSkolem && sym.deSkolemize.isSpecialized))
Set(sym)
else if (sym == ArrayClass)
specializedTypeVars(args)
else if (args.isEmpty)
Set()
else
- specializedTypeVars(sym.typeParams zip args collect { case (tp, arg) if isSpecialized(tp) => arg })
+ specializedTypeVars(sym.typeParams zip args collect { case (tp, arg) if tp.isSpecialized => arg })
case PolyType(tparams, resTpe) => specializedTypeVars(resTpe :: tparams.map(_.info))
// since this method may be run at phase typer (before uncurry, where NMTs are eliminated)
@@ -450,7 +448,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Type parameters that survive when specializing in the specified environment. */
def survivingParams(params: List[Symbol], env: TypeEnv) =
- params.filter(p => !isSpecialized(p) || !isScalaValueType(env(p)))
+ params.filter(p => !p.isSpecialized || !isScalaValueType(env(p)))
/** Produces the symbols from type parameters `syms` of the original owner,
* in the given type environment `env`. The new owner is `nowner`.
@@ -513,8 +511,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
- def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long) =
- member.cloneSymbol(sClass, flagFn(member.flags | SPECIALIZED))
+ def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long, newName: Name = null) =
+ member.cloneSymbol(sClass, flagFn(member.flags | SPECIALIZED), newName)
sClass.sourceFile = clazz.sourceFile
currentRun.symSource(sClass) = clazz.sourceFile // needed later on by mixin
@@ -726,7 +724,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else if (m.isClass) {
val specClass: Symbol = cloneInSpecializedClass(m, x => x)
typeEnv(specClass) = fullEnv
- specClass.name = specializedName(specClass, fullEnv).toTypeName
+ specClass setName specializedName(specClass, fullEnv).toTypeName
enterMember(specClass)
debuglog("entered specialized class " + specClass.fullName)
info(specClass) = SpecializedInnerClass(m, fullEnv)
@@ -754,9 +752,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
val subclasses = specializations(clazz.info.typeParams) filter satisfiable
- subclasses foreach { env =>
+ subclasses foreach {
+ env =>
val spc = specializedClass(env, decls1)
val existing = clazz.owner.info.decl(spc.name)
@@ -804,7 +803,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val env = mapAnyRefsInSpecSym(env0, sym, specMember)
val (keys, vals) = env.toList.unzip
- specMember.name = specializedName(sym, env)
+ specMember setName specializedName(sym, env)
// debuglog("%s normalizes to %s%s".format(sym, specMember,
// if (tps.isEmpty) "" else " with params " + tps.mkString(", ")))
@@ -827,7 +826,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// concise printing of type env
private def pp(env: TypeEnv): String = {
- env.toList.sortBy(_._1.name.toString) map {
+ env.toList.sortBy(_._1.name) map {
case (k, v) =>
val vsym = v.typeSymbol
if (k == vsym) "" + k.name
@@ -882,10 +881,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Return the specialized overload of `m`, in the given environment. */
private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv): Symbol = {
+ val newFlags = (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | ACCESSOR | LAZY)
// this method properly duplicates the symbol's info
- val specMember = sym.cloneSymbol(owner, (sym.flags | SPECIALIZED) & ~(DEFERRED | CASEACCESSOR | ACCESSOR | LAZY))
- specMember.name = specializedName(sym, env)
- specMember modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner)))
+ ( sym.cloneSymbol(owner, newFlags, specializedName(sym, env))
+ modifyInfo (info => subst(env, info.asSeenFrom(owner.thisType, sym.owner)))
+ )
}
/** For each method m that overrides an inherited method m', add a special
@@ -929,7 +929,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (currentRun compiles overriding)
checkOverriddenTParams(overridden)
- val env = unify(overridden.info, overriding.info, emptyEnv, false)
+ val env = unify(overridden.info, overriding.info, emptyEnv, false, true)
def atNext = afterSpecialize(overridden.owner.info.decl(specializedName(overridden, env)))
if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol) {
@@ -991,9 +991,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* Fails if such an environment cannot be found.
*
* If `strict` is true, a UnifyError is thrown if unification is impossible.
+ *
+ * If `tparams` is true, then the methods tries to unify over type params in polytypes as well.
*/
- private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match {
- case (TypeRef(_, sym1, _), _) if isSpecialized(sym1) =>
+ private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean, tparams: Boolean = false): TypeEnv = (tp1, tp2) match {
+ case (TypeRef(_, sym1, _), _) if sym1.isSpecialized =>
debuglog("Unify " + tp1 + ", " + tp2)
if (isPrimitiveValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1))
env + ((sym1, tp2))
@@ -1021,17 +1023,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("Unify polytypes " + tp1 + " and " + tp2)
if (strict && tparams1.length != tparams2.length)
unifyError(tp1, tp2)
+ else if (tparams && tparams1.length == tparams2.length)
+ unify(res1 :: tparams1.map(_.info), res2 :: tparams2.map(_.info), env, strict)
else
unify(res1, res2, env, strict)
- case (PolyType(_, res), other) => unify(res, other, env, strict)
- case (ThisType(_), ThisType(_)) => env
- case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict)
- case (SingleType(_, _), _) => unify(tp1.underlying, tp2, env, strict)
- case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict)
- case (_, ThisType(_)) => unify(tp1, tp2.widen, env, strict)
- case (RefinedType(_, _), RefinedType(_, _)) => env
- case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict)
- case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
+ case (PolyType(_, res), other) => unify(res, other, env, strict)
+ case (ThisType(_), ThisType(_)) => env
+ case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict)
+ case (SingleType(_, _), _) => unify(tp1.underlying, tp2, env, strict)
+ case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict)
+ case (_, ThisType(_)) => unify(tp1, tp2.widen, env, strict)
+ case (RefinedType(_, _), RefinedType(_, _)) => env
+ case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict)
+ case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
+ case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) => unify(List(lo1, hi1), List(lo2, hi2), env, strict)
case _ =>
debuglog("don't know how to unify %s [%s] with %s [%s]".format(tp1, tp1.getClass, tp2, tp2.getClass))
env
@@ -1234,13 +1239,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Return the generic class corresponding to this specialized class. */
def originalClass(clazz: Symbol): Symbol =
- if (hasSpecializedFlag(clazz)) {
+ if (clazz.isSpecialized) {
val (originalName, _, _) = nme.splitSpecializedName(clazz.name)
clazz.owner.info.decl(originalName).suchThat(_.isClass)
} else NoSymbol
def illegalSpecializedInheritance(clazz: Symbol): Boolean = (
- hasSpecializedFlag(clazz)
+ clazz.isSpecialized
&& originalClass(clazz).parentSymbols.exists(p => hasSpecializedParams(p) && !p.isTrait)
)
@@ -1317,7 +1322,15 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else None
} else None
}
-
+
+ def reportError[T](body: =>T)(handler: TypeError => T): T =
+ try body
+ catch {
+ case te: TypeError =>
+ reporter.error(tree.pos, te.msg)
+ handler(te)
+ }
+
curTree = tree
tree match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
@@ -1326,15 +1339,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (found.typeSymbol ne tpt.tpe.typeSymbol) {
// the ctor can be specialized
debuglog("** instantiated specialized type: " + found)
- try localTyper.typedPos(tree.pos)(New(found, transformTrees(args): _*))
- catch {
- case te: TypeError =>
- reporter.error(tree.pos, te.msg)
- super.transform(tree)
+ reportError {
+ localTyper.typedPos(tree.pos)(New(found, transformTrees(args): _*))
+ } {
+ _ => super.transform(tree)
}
} else super.transform(tree)
- case TypeApply(Select(qual, name), targs)
+ case TypeApply(sel @ Select(qual, name), targs)
if (!specializedTypeVars(symbol.info).isEmpty && name != nme.CONSTRUCTOR) =>
debuglog("checking typeapp for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe)
val qual1 = transform(qual)
@@ -1348,14 +1360,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val residualTargs = symbol.info.typeParams zip targs collect {
case (tvar, targ) if !env.contains(tvar) || !isPrimitiveValueClass(env(tvar).typeSymbol) => targ
}
+ // See SI-5583. Don't know why it happens now if it didn't before.
+ if (specMember.info.typeParams.isEmpty && residualTargs.nonEmpty) {
+ log("!!! Type args to be applied, but symbol says no parameters: " + ((specMember.defString, residualTargs)))
+ localTyper.typed(sel)
+ }
+ else {
+ ifDebug(assert(residualTargs.length == specMember.info.typeParams.length,
+ "residual: %s, tparams: %s, env: %s".format(residualTargs, specMember.info.typeParams, env))
+ )
- ifDebug(assert(residualTargs.length == specMember.info.typeParams.length,
- "residual: %s, tparams: %s, env: %s".format(residualTargs, symbol.info.typeParams, env))
- )
-
- val tree1 = gen.mkTypeApply(Select(qual1, specMember), residualTargs)
- debuglog("rewrote " + tree + " to " + tree1)
- localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method
+ val tree1 = gen.mkTypeApply(Select(qual1, specMember), residualTargs)
+ debuglog("rewrote " + tree + " to " + tree1)
+ localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method
+ }
case None => super.transform(tree)
}
@@ -1482,13 +1500,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
})
debuglog("created special overload tree " + t)
debuglog("created " + t)
- localTyper.typed(t)
+ reportError {
+ localTyper.typed(t)
+ } {
+ _ => super.transform(tree)
+ }
case fwd @ Forward(_) =>
debuglog("forward: " + fwd + ", " + ddef)
val rhs1 = forwardCall(tree.pos, gen.mkAttributedRef(symbol.owner.thisType, fwd.target), vparamss)
debuglog("-->d completed forwarder to specialized overload: " + fwd.target + ": " + rhs1)
- localTyper.typed(deriveDefDef(tree)(_ => rhs1))
+ reportError {
+ localTyper.typed(deriveDefDef(tree)(_ => rhs1))
+ } {
+ _ => super.transform(tree)
+ }
case SpecializedAccessor(target) =>
val rhs1 = if (symbol.isGetter)
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 0efdd9ab9f..7f220992a3 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -8,6 +8,7 @@ package transform
import symtab.Flags._
import scala.collection.{ mutable, immutable }
+import language.postfixOps
/*<export> */
/** - uncurry all symbol and tree types (@see UnCurryPhase) -- this includes normalizing all proper types.
@@ -71,14 +72,13 @@ abstract class UnCurry extends InfoTransform
}
class UnCurryTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
-
- private var needTryLift = false
- private var inPattern = false
+ private var needTryLift = false
+ private var inPattern = false
private var inConstructorFlag = 0L
- private val byNameArgs = new mutable.HashSet[Tree]
- private val noApply = new mutable.HashSet[Tree]
- private val newMembers = mutable.ArrayBuffer[Tree]()
- private val repeatedParams = mutable.Map[Symbol, List[ValDef]]()
+ private val byNameArgs = mutable.HashSet[Tree]()
+ private val noApply = mutable.HashSet[Tree]()
+ private val newMembers = mutable.ArrayBuffer[Tree]()
+ private val repeatedParams = mutable.Map[Symbol, List[ValDef]]()
@inline private def withInPattern[T](value: Boolean)(body: => T): T = {
inPattern = value
@@ -86,30 +86,40 @@ abstract class UnCurry extends InfoTransform
finally inPattern = !value
}
+ private def newFunction0(body: Tree): Tree = {
+ val result = localTyper.typedPos(body.pos)(Function(Nil, body)).asInstanceOf[Function]
+ log("Change owner from %s to %s in %s".format(currentOwner, result.symbol, result.body))
+ result.body changeOwner (currentOwner -> result.symbol)
+ transformFunction(result)
+ }
+
private lazy val serialVersionUIDAnnotation =
AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
private var nprinted = 0
- override def transform(tree: Tree): Tree = try { //debug
- postTransform(mainTransform(tree))
- } catch {
- case ex: Throwable =>
- if (nprinted < 10) {
- Console.println("exception when traversing " + tree)
- nprinted += 1
- }
- throw ex
- }
+ // I don't have a clue why I'm catching TypeErrors here, but it's better
+ // than spewing stack traces at end users for internal errors. Examples
+ // which hit at this point should not be hard to come by, but the immediate
+ // motivation can be seen in continuations-neg/t3718.
+ override def transform(tree: Tree): Tree = (
+ try postTransform(mainTransform(tree))
+ catch { case ex: TypeError =>
+ unit.error(ex.pos, ex.msg)
+ debugStack(ex)
+ EmptyTree
+ }
+ )
/* Is tree a reference `x` to a call by name parameter that needs to be converted to
* x.apply()? Note that this is not the case if `x` is used as an argument to another
* call by name parameter.
*/
- def isByNameRef(tree: Tree): Boolean =
- tree.isTerm && tree.hasSymbol &&
- isByNameParamType(tree.symbol.tpe) &&
- !byNameArgs(tree)
+ def isByNameRef(tree: Tree) = (
+ tree.isTerm
+ && !byNameArgs(tree)
+ && tree.hasSymbolWhich(s => isByNameParamType(s.tpe))
+ )
/** Uncurry a type of a tree node.
* This function is sensitive to whether or not we are in a pattern -- when in a pattern
@@ -126,7 +136,7 @@ abstract class UnCurry extends InfoTransform
/** The type of a non-local return expression with given argument type */
private def nonLocalReturnExceptionType(argtype: Type) =
- appliedType(NonLocalReturnControlClass.typeConstructor, List(argtype))
+ appliedType(NonLocalReturnControlClass, argtype)
/** A hashmap from method symbols to non-local return keys */
private val nonLocalReturnKeys = perRunCaches.newMap[Symbol, Symbol]()
@@ -236,23 +246,21 @@ abstract class UnCurry extends InfoTransform
deEta(fun) match {
// nullary or parameterless
case fun1 if fun1 ne fun => fun1
+ case _ if fun.tpe.typeSymbol == PartialFunctionClass =>
+ // only get here when running under -Xoldpatmat
+ synthPartialFunction(fun)
case _ =>
- def owner = fun.symbol.owner
- def targs = fun.tpe.typeArgs
- def isPartial = fun.tpe.typeSymbol == PartialFunctionClass
- assert(!(opt.virtPatmat && isPartial)) // empty-selector matches have already been translated into instantiations of anonymous (partial) functions
-
- def parents =
- if (isFunctionType(fun.tpe)) List(abstractFunctionForFunctionType(fun.tpe), SerializableClass.tpe)
- else if (isPartial) List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
- else List(ObjectClass.tpe, fun.tpe, SerializableClass.tpe)
-
- val anonClass = owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation serialVersionUIDAnnotation
+ val parents = (
+ if (isFunctionType(fun.tpe)) addSerializable(abstractFunctionForFunctionType(fun.tpe))
+ else addSerializable(ObjectClass.tpe, fun.tpe)
+ )
+ val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation serialVersionUIDAnnotation
anonClass setInfo ClassInfoType(parents, newScope, anonClass)
+ val targs = fun.tpe.typeArgs
val (formals, restpe) = (targs.init, targs.last)
- def applyMethodDef = {
+ val applyMethodDef = {
val methSym = anonClass.newMethod(nme.apply, fun.pos, FINAL)
methSym setInfoAndEnter MethodType(methSym newSyntheticValueParams formals, restpe)
@@ -268,71 +276,115 @@ abstract class UnCurry extends InfoTransform
methDef
}
- // def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
- def applyOrElseMethodDef = {
- val methSym = anonClass.newMethod(fun.pos, nme.applyOrElse) setFlag (FINAL | OVERRIDE)
+ localTyper.typedPos(fun.pos) {
+ Block(
+ List(ClassDef(anonClass, NoMods, List(List()), List(List()), List(applyMethodDef), fun.pos)),
+ Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
+ }
- val List(argtpe) = formals
- val A1 = methSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argtpe)
- val B1 = methSym newTypeParameter(newTypeName("B1")) setInfo TypeBounds.lower(restpe)
- val methFormals = List(A1.tpe, functionType(List(A1.tpe), B1.tpe))
- val params@List(x, default) = methSym newSyntheticValueParams methFormals
- methSym setInfoAndEnter polyType(List(A1, B1), MethodType(params, B1.tpe))
+ }
- val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), List(x))
- val body = localTyper.typedPos(fun.pos) { import CODE._
- gen.mkUncheckedMatch(gen.withDefaultCase(substParam(fun.body), scrut => REF(default) APPLY (REF(x))))
- }
- body.changeOwner(fun.symbol -> methSym)
+ def synthPartialFunction(fun: Function) = {
+ if (!settings.XoldPatmat.value) debugwarn("Under the new pattern matching scheme, PartialFunction should have been synthesized during typers.")
+
+ val targs = fun.tpe.typeArgs
+ val (formals, restpe) = (targs.init, targs.last)
+
+ val anonClass = fun.symbol.owner newAnonymousFunctionClass(fun.pos, inConstructorFlag) addAnnotation serialVersionUIDAnnotation
+ val parents = addSerializable(appliedType(AbstractPartialFunctionClass, targs: _*))
+ anonClass setInfo ClassInfoType(parents, newScope, anonClass)
+
+ // duplicate before applyOrElseMethodDef is run so that it does not mess up our trees and label symbols (we have a fresh set)
+ // otherwise `TreeSymSubstituter(fun.vparams map (_.symbol), params)` won't work as the subst has been run already
+ val bodyForIDA = {
+ val duped = fun.body.duplicate
+ val oldParams = new mutable.ListBuffer[Symbol]()
+ val newParams = new mutable.ListBuffer[Symbol]()
+
+ val oldSyms0 =
+ duped filter {
+ case l@LabelDef(_, params, _) =>
+ params foreach {p =>
+ val oldSym = p.symbol
+ p.symbol = oldSym.cloneSymbol
+ oldParams += oldSym
+ newParams += p.symbol
+ }
+ true
+ case _ => false
+ } map (_.symbol)
+ val oldSyms = oldParams.toList ++ oldSyms0
+ val newSyms = newParams.toList ++ (oldSyms0 map (_.cloneSymbol))
+ // println("duping "+ oldSyms +" --> "+ (newSyms map (_.ownerChain)))
- val methDef = DefDef(methSym, body)
+ val substLabels = new TreeSymSubstituter(oldSyms, newSyms)
- // Have to repack the type to avoid mismatches when existentials
- // appear in the result - see SI-4869.
- methDef.tpt setType localTyper.packedType(body, methSym)
- methDef
- }
+ substLabels(duped)
+ }
- // duplicate before applyOrElseMethodDef is run so we start with the same symbols as applyOrElseMethodDef
- // otherwise `TreeSymSubstituter(fun.vparams map (_.symbol), params)` won't work as the subst has been run already
- val bodyForIDA = fun.body.duplicate
- def isDefinedAtMethodDef = {
- val methSym = anonClass.newMethod(nme.isDefinedAt, fun.pos, FINAL)
- val params = methSym newSyntheticValueParams formals
- methSym setInfoAndEnter MethodType(params, BooleanClass.tpe)
-
- val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), params)
- def doSubst(x: Tree) = substParam(resetLocalAttrs(x)) // see pos/t1761 for why `resetLocalAttrs`
- object isDefinedAtTransformer extends gen.MatchMatcher {
- // TODO: optimize duplication, but make sure ValDef's introduced by wrap are treated correctly
- override def caseMatch(orig: Tree, selector: Tree, cases: List[CaseDef], wrap: Tree => Tree): Tree = { import CODE._
- gen.mkUncheckedMatch(
- if (cases exists treeInfo.isDefaultCase) TRUE_typed
- else
- doSubst(wrap(
- Match(selector,
- (cases map (c => deriveCaseDef(c)(x => TRUE_typed))) :+ (
- DEFAULT ==> FALSE_typed)
- )))
- )
+ // def applyOrElse[A1 <: A, B1 >: B](x: A1, default: A1 => B1): B1 =
+ val applyOrElseMethodDef = {
+ val methSym = anonClass.newMethod(fun.pos, nme.applyOrElse) setFlag (FINAL | OVERRIDE)
+
+ val List(argtpe) = formals
+ val A1 = methSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argtpe)
+ val B1 = methSym newTypeParameter(newTypeName("B1")) setInfo TypeBounds.lower(restpe)
+ val methFormals = List(A1.tpe, functionType(List(A1.tpe), B1.tpe))
+ val params@List(x, default) = methSym newSyntheticValueParams methFormals
+ methSym setInfoAndEnter polyType(List(A1, B1), MethodType(params, B1.tpe))
+
+ val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), List(x))
+ val body = localTyper.typedPos(fun.pos) { import CODE._
+ def defaultAction(scrut: Tree) = REF(default) APPLY (REF(x))
+
+ substParam(fun.body) match {
+ case orig@Match(selector, cases) =>
+ if (cases exists treeInfo.isDefaultCase) orig
+ else {
+ val defaultCase = CaseDef(Ident(nme.WILDCARD), EmptyTree, defaultAction(selector.duplicate))
+ Match(/*gen.mkUnchecked*/(selector), cases :+ defaultCase)
}
- }
- val body = isDefinedAtTransformer(bodyForIDA)
- body.changeOwner(fun.symbol -> methSym)
- DefDef(methSym, body)
}
+ }
+ body.changeOwner(fun.symbol -> methSym)
- val members =
- if (isPartial) List(applyOrElseMethodDef, isDefinedAtMethodDef)
- else List(applyMethodDef)
+ val methDef = DefDef(methSym, body)
+
+ // Have to repack the type to avoid mismatches when existentials
+ // appear in the result - see SI-4869.
+ methDef.tpt setType localTyper.packedType(body, methSym)
+ methDef
+ }
+
+ val isDefinedAtMethodDef = {
+ val methSym = anonClass.newMethod(nme.isDefinedAt, fun.pos, FINAL)
+ val params = methSym newSyntheticValueParams formals
+ methSym setInfoAndEnter MethodType(params, BooleanClass.tpe)
+
+ val substParam = new TreeSymSubstituter(fun.vparams map (_.symbol), params)
+ def doSubst(x: Tree) = substParam(resetLocalAttrsKeepLabels(x)) // see pos/t1761 for why `resetLocalAttrs`, but must keep label symbols around
+
+ val body = bodyForIDA match {
+ case Match(selector, cases) =>
+ if (cases exists treeInfo.isDefaultCase) TRUE_typed
+ else
+ doSubst(Match(/*gen.mkUnchecked*/(selector),
+ (cases map (c => deriveCaseDef(c)(x => TRUE_typed))) :+ (
+ DEFAULT ==> FALSE_typed)))
- localTyper.typedPos(fun.pos) {
- Block(
- List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, fun.pos)),
- Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
- }
}
+ body.changeOwner(fun.symbol -> methSym)
+
+ DefDef(methSym, body)
+ }
+
+ localTyper.typedPos(fun.pos) {
+ Block(
+ List(ClassDef(anonClass, NoMods, List(List()), List(List()), List(applyOrElseMethodDef, isDefinedAtMethodDef), fun.pos)),
+ Typed(New(anonClass.tpe), TypeTree(fun.tpe)))
+ }
+ }
def transformArgs(pos: Position, fun: Symbol, args: List[Tree], formals: List[Type]) = {
val isJava = fun.isJavaDefined
@@ -358,30 +410,35 @@ abstract class UnCurry extends InfoTransform
def sequenceToArray(tree: Tree) = {
val toArraySym = tree.tpe member nme.toArray
assert(toArraySym != NoSymbol)
- def getManifest(tp: Type): Tree = {
- val manifestOpt = localTyper.findManifest(tp, false)
+ def getArrayTag(tp: Type): Tree = {
+ val tag = localTyper.resolveArrayTag(tp, tree.pos)
// Don't want bottom types getting any further than this (SI-4024)
- if (tp.typeSymbol.isBottomClass) getManifest(AnyClass.tpe)
- else if (!manifestOpt.tree.isEmpty) manifestOpt.tree
- else if (tp.bounds.hi ne tp) getManifest(tp.bounds.hi)
- else localTyper.getManifestTree(tree, tp, false)
+ if (tp.typeSymbol.isBottomClass) getArrayTag(AnyClass.tpe)
+ else if (!tag.isEmpty) tag
+ else if (tp.bounds.hi ne tp) getArrayTag(tp.bounds.hi)
+ else localTyper.TyperErrorGen.MissingArrayTagError(tree, tp)
+ }
+ def traversableArrayTag(tpe: Type): Tree = {
+ (tpe baseType TraversableClass).typeArgs match {
+ case targ :: _ => getArrayTag(targ)
+ case _ => EmptyTree
+ }
}
afterUncurry {
localTyper.typedPos(pos) {
- Apply(gen.mkAttributedSelect(tree, toArraySym),
- List(getManifest(tree.tpe.baseType(TraversableClass).typeArgs.head)))
+ gen.mkMethodCall(tree, toArraySym, Nil, List(traversableArrayTag(tree.tpe)))
}
}
}
var suffix: Tree =
if (treeInfo isWildcardStarArgList args) {
- val Typed(tree, _) = args.last;
+ val Typed(tree, _) = args.last
if (isJava)
if (tree.tpe.typeSymbol == ArrayClass) tree
else sequenceToArray(tree)
else
- if (tree.tpe.typeSymbol isSubClass TraversableClass) tree // @PP: I suspect this should be SeqClass
+ if (tree.tpe.typeSymbol isSubClass SeqClass) tree
else arrayToSequence(tree, varargsElemType)
}
else {
@@ -392,7 +449,8 @@ abstract class UnCurry extends InfoTransform
}
afterUncurry {
- if (isJava && isPrimitiveArray(suffix.tpe) && isArrayOfSymbol(fun.tpe.params.last.tpe, ObjectClass)) {
+ if (isJava && !isReferenceArray(suffix.tpe) && isArrayOfSymbol(fun.tpe.params.last.tpe, ObjectClass)) {
+ // The array isn't statically known to be a reference array, so call ScalaRuntime.toObjectArray.
suffix = localTyper.typedPos(pos) {
gen.mkRuntimeCall(nme.toObjectArray, List(suffix))
}
@@ -404,22 +462,26 @@ abstract class UnCurry extends InfoTransform
val args1 = if (isVarArgTypes(formals)) transformVarargs(formals.last.typeArgs.head) else args
map2(formals, args1) { (formal, arg) =>
- if (!isByNameParamType(formal)) {
+ if (!isByNameParamType(formal))
arg
- } else if (isByNameRef(arg)) {
+ else if (isByNameRef(arg)) {
byNameArgs += arg
- arg setType functionType(List(), arg.tpe)
- } else {
- if (opt.verboseDebug) {
- val posstr = arg.pos.source.path + ":" + arg.pos.line
- val permstr = if (fun.isPrivate) "private" else "notprivate"
- log("byname | %s | %s | %s".format(posstr, fun.fullName, permstr))
- }
+ arg setType functionType(Nil, arg.tpe)
+ }
+ else {
+ log("byname | %s | %s | %s".format(
+ arg.pos.source.path + ":" + arg.pos.line, fun.fullName,
+ if (fun.isPrivate) "private" else "")
+ )
- val result = localTyper.typed(
- Function(Nil, arg) setPos arg.pos).asInstanceOf[Function]
- new ChangeOwnerTraverser(currentOwner, result.symbol).traverse(arg)
- transformFunction(result)
+ arg match {
+ // don't add a thunk for by-name argument if argument already is an application of
+ // a Function0. We can then remove the application and use the existing Function0.
+ case Apply(Select(recv, nme.apply), Nil) if recv.tpe.typeSymbol isSubClass FunctionClass(0) =>
+ recv
+ case _ =>
+ newFunction0(arg)
+ }
}
}
}
@@ -494,6 +556,12 @@ abstract class UnCurry extends InfoTransform
}
val sym = tree.symbol
+ // Take a pass looking for @specialize annotations and set all
+ // their SPECIALIZE flags for cheaper recognition.
+ if ((sym ne null) && (sym.isClass || sym.isMethod)) {
+ for (tp <- sym.typeParams ; if tp hasAnnotation SpecializedClass)
+ tp setFlag SPECIALIZED
+ }
val result = (
// TODO - settings.noassertions.value temporarily retained to avoid
// breakage until a reasonable interface is settled upon.
@@ -660,12 +728,12 @@ abstract class UnCurry extends InfoTransform
case Apply(Apply(fn, args), args1) =>
treeCopy.Apply(tree, fn, args ::: args1)
case Ident(name) =>
- assert(name != tpnme.WILDCARD_STAR)
+ assert(name != tpnme.WILDCARD_STAR, tree)
applyUnary()
case Select(_, _) | TypeApply(_, _) =>
applyUnary()
- case ret @ Return(expr) if (isNonLocalReturn(ret)) =>
- debuglog("non local return in "+ret.symbol+" from "+currentOwner.enclMethod)
+ case ret @ Return(expr) if isNonLocalReturn(ret) =>
+ log("non-local return from %s to %s".format(currentOwner.enclMethod, ret.symbol))
atPos(ret.pos)(nonLocalReturnThrow(expr, ret.symbol))
case TypeTree() =>
tree
@@ -713,10 +781,10 @@ abstract class UnCurry extends InfoTransform
)
}
- val reps = repeatedParams(dd.symbol)
- val rpsymbols = reps.map(_.symbol).toSet
- val theTyper = typer.atOwner(dd, currentClass)
- val flatparams = flatdd.vparamss.head
+ val reps = repeatedParams(dd.symbol)
+ val rpsymbols = reps.map(_.symbol).toSet
+ val theTyper = typer.atOwner(dd, currentClass)
+ val flatparams = flatdd.vparamss.head
// create the type
val forwformals = flatparams map {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 18c7635b1e..a77df71312 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -24,6 +24,7 @@ trait Analyzer extends AnyRef
with NamesDefaults
with TypeDiagnostics
with ContextErrors
+ with StdAttachments
{
val global : Global
import global._
diff --git a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
index 49ddb985dc..08bf581256 100644
--- a/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/ContextErrors.scala
@@ -129,11 +129,11 @@ trait ContextErrors {
val retyped = typed (tree.duplicate setType null)
val foundDecls = retyped.tpe.decls filter (sym => !sym.isConstructor && !sym.isSynthetic)
- if (foundDecls.isEmpty) found
+ if (foundDecls.isEmpty || (found.typeSymbol eq NoSymbol)) found
else {
// The members arrive marked private, presumably because there was no
// expected type and so they're considered members of an anon class.
- foundDecls foreach (_ resetFlag (PRIVATE | PROTECTED))
+ foundDecls foreach (_.makePublic)
// TODO: if any of the found parents match up with required parents after normalization,
// print the error so that they match. The major beneficiary there would be
// java.lang.Object vs. AnyRef.
@@ -277,11 +277,6 @@ trait ContextErrors {
setError(tree)
}
- def MultiDimensionalArrayError(tree: Tree) = {
- issueNormalTypeError(tree, "cannot create a generic multi-dimensional array of more than "+ definitions.MaxArrayDims+" dimensions")
- setError(tree)
- }
-
//typedSuper
def MixinMissingParentClassNameError(tree: Tree, mix: Name, clazz: Symbol) =
issueNormalTypeError(tree, mix+" does not name a parent class of "+clazz)
@@ -344,6 +339,16 @@ trait ContextErrors {
setError(tree)
}
+ def MacroEtaError(tree: Tree) = {
+ issueNormalTypeError(tree, "macros cannot be eta-expanded")
+ setError(tree)
+ }
+
+ def MacroPartialApplicationError(tree: Tree) = {
+ issueNormalTypeError(tree, "macros cannot be partially applied")
+ setError(tree)
+ }
+
//typedReturn
def ReturnOutsideOfDefError(tree: Tree) = {
issueNormalTypeError(tree, "return outside method definition")
@@ -453,6 +458,9 @@ trait ContextErrors {
// doTypeApply
//tryNamesDefaults
+ def NamedAndDefaultArgumentsNotSupportedForMacros(tree: Tree, fun: Tree) =
+ NormalTypeError(tree, "macros application do not support named and/or default arguments")
+
def WrongNumberOfArgsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, "wrong number of arguments for "+ treeSymTypeMsg(fun))
@@ -480,7 +488,7 @@ trait ContextErrors {
val keep = missing take 3 map (_.name)
".\nUnspecified value parameter%s %s".format(
if (missing.tail.isEmpty) "" else "s",
- if (missing drop 3 nonEmpty) (keep :+ "...").mkString(", ")
+ if ((missing drop 3).nonEmpty) (keep :+ "...").mkString(", ")
else keep.mkString("", ", ", ".")
)
}
@@ -501,6 +509,9 @@ trait ContextErrors {
def ApplyWithoutArgsError(tree: Tree, fun: Tree) =
NormalTypeError(tree, fun.tpe+" does not take parameters")
+ def DynamicVarArgUnsupported(tree: Tree, name: String) =
+ issueNormalTypeError(tree, name+ " does not support passing a vararg parameter")
+
//checkClassType
def TypeNotAStablePrefixError(tpt: Tree, pre: Type) = {
issueNormalTypeError(tpt, "type "+pre+" is not a stable prefix")
@@ -581,9 +592,9 @@ trait ContextErrors {
def AbstractExistentiallyOverParamerizedTpeError(tree: Tree, tp: Type) =
issueNormalTypeError(tree, "can't existentially abstract over parameterized type " + tp)
- //manifestTreee
- def MissingManifestError(tree: Tree, full: Boolean, tp: Type) = {
- issueNormalTypeError(tree, "cannot find "+(if (full) "" else "class ")+"manifest for element type "+tp)
+ // resolveArrayTag
+ def MissingArrayTagError(tree: Tree, tp: Type) = {
+ issueNormalTypeError(tree, "cannot find array tag for element type "+tp)
setError(tree)
}
@@ -611,20 +622,23 @@ trait ContextErrors {
setError(tree)
}
- // checkNoDoubleDefs...
- // @PP: I hacked the filename in (context0.unit) to work around SI-4893. It would be
- // much better if every symbol could offer some idea of where it came from, else
- // the obviously untrue claim that something has been defined twice can only frustrate.
- // There's no direct test because partest doesn't work, but to reproduce, separately
- // compile the next two lines:
- // package object foo { val x: Class[_] = null }
- // package foo
def DefDefinedTwiceError(sym0: Symbol, sym1: Symbol) = {
+ // Most of this hard work is associated with SI-4893.
val isBug = sym0.isAbstractType && sym1.isAbstractType && (sym0.name startsWith "_$")
- issueSymbolTypeError(sym0, sym1+" is defined twice in " + context0.unit
- + ( if (sym0.isMacro && sym1.isMacro) "\n(note that macros cannot be overloaded)" else "" )
- + ( if (isBug) "\n(this error is likely due to a bug in the scala compiler involving wildcards in package objects)" else "" )
+ val addendums = List(
+ if (sym0.associatedFile eq sym1.associatedFile)
+ Some("conflicting symbols both originated in file '%s'".format(sym0.associatedFile.canonicalPath))
+ else if ((sym0.associatedFile ne null) && (sym1.associatedFile ne null))
+ Some("conflicting symbols originated in files '%s' and '%s'".format(sym0.associatedFile.canonicalPath, sym1.associatedFile.canonicalPath))
+ else None ,
+ if (isBug) Some("Note: this may be due to a bug in the compiler involving wildcards in package objects") else None
)
+ val addendum = addendums.flatten match {
+ case Nil => ""
+ case xs => xs.mkString("\n ", "\n ", "")
+ }
+
+ issueSymbolTypeError(sym0, sym1+" is defined twice" + addendum)
}
// cyclic errors
@@ -642,7 +656,7 @@ trait ContextErrors {
private def applyErrorMsg(tree: Tree, msg: String, argtpes: List[Type], pt: Type) = {
def asParams(xs: List[Any]) = xs.mkString("(", ", ", ")")
- def resType = if (pt isWildcard) "" else " with expected result type " + pt
+ def resType = if (pt.isWildcard) "" else " with expected result type " + pt
def allTypes = (alternatives(tree) flatMap (_.paramTypes)) ++ argtpes :+ pt
def locals = alternatives(tree) flatMap (_.typeParams)
@@ -661,7 +675,7 @@ trait ContextErrors {
}
private def ambiguousErrorMsgPos(pos: Position, pre: Type, sym1: Symbol, sym2: Symbol, rest: String) =
- if (sym1.hasDefaultFlag && sym2.hasDefaultFlag && sym1.enclClass == sym2.enclClass) {
+ if (sym1.hasDefault && sym2.hasDefault && sym1.enclClass == sym2.enclClass) {
val methodName = nme.defaultGetterToMethod(sym1.name)
(sym1.enclClass.pos,
"in "+ sym1.enclClass +", multiple overloaded alternatives of " + methodName +
@@ -832,7 +846,7 @@ trait ContextErrors {
implicit val context0 = context
object SymValidateErrors extends Enumeration {
- val ImplicitConstr, ImplicitNotTerm, ImplicitTopObject,
+ val ImplicitConstr, ImplicitNotTermOrClass, ImplicitAtToplevel,
OverrideClass, SealedNonClass, AbstractNonClass,
OverrideConstr, AbstractOverride, LazyAndEarlyInit,
ByNameParameter, AbstractVar = Value
@@ -848,6 +862,19 @@ trait ContextErrors {
def TypeSigError(tree: Tree, ex: TypeError) = {
ex match {
+ case CyclicReference(_, _) if tree.symbol.isTermMacro =>
+ // say, we have a macro def `foo` and its macro impl `impl`
+ // if impl: 1) omits return type, 2) has anything implicit in its body, 3) sees foo
+ //
+ // then implicit search will trigger an error
+ // (note that this is not a compilation error, it's an artifact of implicit search algorithm)
+ // normally, such "errors" are discarded by `isCyclicOrErroneous` in Implicits.scala
+ // but in our case this won't work, because isCyclicOrErroneous catches CyclicReference exceptions
+ // while our error will present itself as a "recursive method needs a return type"
+ //
+ // hence we (together with reportTypeError in TypeDiagnostics) make sure that this CyclicReference
+ // evades all the handlers on its way and successfully reaches `isCyclicOrErroneous` in Implicits
+ throw ex
case CyclicReference(sym, info: TypeCompleter) =>
issueNormalTypeError(tree, typer.cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
case _ =>
@@ -898,10 +925,10 @@ trait ContextErrors {
case ImplicitConstr =>
"`implicit' modifier not allowed for constructors"
- case ImplicitNotTerm =>
- "`implicit' modifier can be used only for values, variables and methods"
+ case ImplicitNotTermOrClass =>
+ "`implicit' modifier can be used only for values, variables, methods and classes"
- case ImplicitTopObject =>
+ case ImplicitAtToplevel =>
"`implicit' modifier cannot be used for top-level objects"
case OverrideClass =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index a1ba8a2982..0924789948 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -67,6 +67,7 @@ trait Contexts { self: Analyzer =>
val c = sc.make(unit, tree, sc.owner, sc.scope, sc.imports)
if (erasedTypes) c.setThrowErrors() else c.setReportErrors()
c.implicitsEnabled = !erasedTypes
+ c.enrichmentEnabled = c.implicitsEnabled
c
}
@@ -105,7 +106,7 @@ trait Contexts { self: Analyzer =>
// not inherited to child contexts
var depth: Int = 0
var imports: List[ImportInfo] = List() // currently visible imports
- var openImplicits: List[(Type,Symbol)] = List() // types for which implicit arguments
+ var openImplicits: List[(Type,Tree)] = List() // types for which implicit arguments
// are currently searched
// for a named application block (Tree) the corresponding NamedApplyInfo
var namedApplyBlockInfo: Option[(Tree, NamedApplyInfo)] = None
@@ -119,6 +120,8 @@ trait Contexts { self: Analyzer =>
var diagnostic: List[String] = Nil // these messages are printed when issuing an error
var implicitsEnabled = false
+ var macrosEnabled = true
+ var enrichmentEnabled = false // to selectively allow enrichment in patterns, where other kinds of implicit conversions are not allowed
var checking = false
var retyping = false
@@ -181,11 +184,49 @@ trait Contexts { self: Analyzer =>
def logError(err: AbsTypeError) = buffer += err
+ def withImplicitsEnabled[T](op: => T): T = {
+ val saved = implicitsEnabled
+ implicitsEnabled = true
+ try op
+ finally implicitsEnabled = saved
+ }
+
def withImplicitsDisabled[T](op: => T): T = {
val saved = implicitsEnabled
implicitsEnabled = false
+ val savedP = enrichmentEnabled
+ enrichmentEnabled = false
try op
- finally implicitsEnabled = saved
+ finally {
+ implicitsEnabled = saved
+ enrichmentEnabled = savedP
+ }
+ }
+
+ def withImplicitsDisabledAllowEnrichment[T](op: => T): T = {
+ val saved = implicitsEnabled
+ implicitsEnabled = false
+ val savedP = enrichmentEnabled
+ enrichmentEnabled = true
+ try op
+ finally {
+ implicitsEnabled = saved
+ enrichmentEnabled = savedP
+ }
+ }
+
+ def withMacrosEnabled[T](op: => T): T = {
+ val saved = macrosEnabled
+ macrosEnabled = true
+ try op
+ finally macrosEnabled = saved
+ }
+
+ def withMacrosDisabled[T](op: => T): T = {
+ val saved = macrosEnabled
+ macrosEnabled = false
+ try op
+ finally macrosEnabled = saved
}
def make(unit: CompilationUnit, tree: Tree, owner: Symbol,
@@ -223,6 +264,8 @@ trait Contexts { self: Analyzer =>
c.diagnostic = this.diagnostic
c.typingIndentLevel = typingIndentLevel
c.implicitsEnabled = this.implicitsEnabled
+ c.macrosEnabled = this.macrosEnabled
+ c.enrichmentEnabled = this.enrichmentEnabled
c.checking = this.checking
c.retyping = this.retyping
c.openImplicits = this.openImplicits
@@ -237,6 +280,7 @@ trait Contexts { self: Analyzer =>
val c = make(unit, EmptyTree, owner, scope, imports)
c.setReportErrors()
c.implicitsEnabled = true
+ c.macrosEnabled = true
c
}
@@ -274,6 +318,7 @@ trait Contexts { self: Analyzer =>
def makeImplicit(reportAmbiguousErrors: Boolean) = {
val c = makeSilent(reportAmbiguousErrors)
c.implicitsEnabled = false
+ c.enrichmentEnabled = false
c
}
@@ -309,29 +354,30 @@ trait Contexts { self: Analyzer =>
private def unitError(pos: Position, msg: String) =
unit.error(pos, if (checking) "\n**** ERROR DURING INTERNAL CHECKING ****\n" + msg else msg)
-
- def issue(err: AbsTypeError) {
+
+ @inline private def issueCommon(err: AbsTypeError)(pf: PartialFunction[AbsTypeError, Unit]) {
debugwarn("issue error: " + err.errMsg)
- if (reportErrors) unitError(err.errPos, addDiagString(err.errMsg))
+ if (settings.Yissuedebug.value) (new Exception).printStackTrace()
+ if (pf isDefinedAt err) pf(err)
else if (bufferErrors) { buffer += err }
else throw new TypeError(err.errPos, err.errMsg)
}
+ def issue(err: AbsTypeError) {
+ issueCommon(err) { case _ if reportErrors =>
+ unitError(err.errPos, addDiagString(err.errMsg))
+ }
+ }
+
def issueAmbiguousError(pre: Type, sym1: Symbol, sym2: Symbol, err: AbsTypeError) {
- debugwarn("issue ambiguous error: " + err.errMsg)
- if (ambiguousErrors) {
+ issueCommon(err) { case _ if ambiguousErrors =>
if (!pre.isErroneous && !sym1.isErroneous && !sym2.isErroneous)
unitError(err.errPos, err.errMsg)
- } else if (bufferErrors) { buffer += err }
- else throw new TypeError(err.errPos, err.errMsg)
+ }
}
def issueAmbiguousError(err: AbsTypeError) {
- debugwarn("issue ambiguous error: " + err.errMsg)
- if (ambiguousErrors)
- unitError(err.errPos, addDiagString(err.errMsg))
- else if (bufferErrors) { buffer += err }
- else throw new TypeError(err.errPos, err.errMsg)
+ issueCommon(err) { case _ if ambiguousErrors => unitError(err.errPos, addDiagString(err.errMsg)) }
}
// TODO remove
@@ -357,6 +403,17 @@ trait Contexts { self: Analyzer =>
case _ => outer.isLocal()
}
+ /** Fast path for some slow checks (ambiguous assignment in Refchecks, and
+ * existence of __match for MatchTranslation in virtpatmat.) This logic probably
+ * needs improvement.
+ */
+ def isNameInScope(name: Name) = (
+ enclosingContextChain exists (ctx =>
+ (ctx.scope.lookupEntry(name) != null)
+ || (ctx.owner.rawInfo.member(name) != NoSymbol)
+ )
+ )
+
// nextOuter determines which context is searched next for implicits
// (after `this`, which contributes `newImplicits` below.) In
// most cases, it is simply the outer context: if we're owned by
@@ -664,7 +721,7 @@ trait Contexts { self: Analyzer =>
case List(ImportSelector(nme.WILDCARD, _, _, _)) => List(sym)
case ImportSelector(from, _, to, _) :: _ if from == sym.name =>
if (to == nme.WILDCARD) List()
- else { val sym1 = sym.cloneSymbol; sym1.name = to; List(sym1) }
+ else List(sym.cloneSymbol(sym.owner, sym.rawflags, to))
case _ :: rest => transformImport(rest, sym)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
new file mode 100644
index 0000000000..0b414801d6
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/typechecker/DestructureTypes.scala
@@ -0,0 +1,206 @@
+/* NSC -- new Scala compiler
+* Copyright 2005-2012 LAMP/EPFL
+* @author Paul Phillips
+*/
+
+package scala.tools.nsc
+package typechecker
+
+/** A generic means of breaking down types into their subcomponents.
+ * Types are decomposed top down, and recognizable substructure is
+ * dispatched via self-apparently named methods. Those methods can
+ * be overridden for custom behavior, but only the abstract methods
+ * require implementations, each of which must create some unknown
+ * "Node" type from its inputs.
+ *
+ * - wrapProduct create Node from a product of Nodes
+ * - wrapSequence create Node from a sequence of Nodes
+ * - wrapAtom create Node from an arbitrary value
+ *
+ * This is a work in progress.
+ */
+trait DestructureTypes {
+ val global: Global
+ import global._
+ import definitions.{ NothingClass, AnyClass }
+
+ trait DestructureType[Node] extends (Type => Node) {
+ def withLabel(node: Node, label: String): Node
+ def withType(node: Node, typeName: String): Node
+
+ def wrapEmpty: Node
+ def wrapPoly(in: Node, out: Node): Node
+ def wrapMono(in: Node, out: Node): Node
+ def wrapProduct(nodes: List[Node]): Node
+ def wrapSequence(nodes: List[Node]): Node
+ def wrapAtom[U](value: U): Node
+
+ private implicit def liftToTerm(name: String): TermName = newTermName(name)
+
+ private val openSymbols = collection.mutable.Set[Symbol]()
+
+ private def nodeList[T](elems: List[T], mkNode: T => Node): Node =
+ if (elems.isEmpty) wrapEmpty else list(elems map mkNode)
+
+ private def scopeMemberList(elems: List[Symbol]): Node = nodeList(elems, wrapAtom)
+ private def typeList(elems: List[Type]): Node = nodeList(elems, this)
+ private def symbolList(elems: List[Symbol]): Node = nodeList(elems, wrapSymbolInfo)
+ private def treeList(elems: List[Tree]): Node = nodeList(elems, wrapTree)
+ private def annotationList(annots: List[AnnotationInfo]): Node = nodeList(annots, annotation)
+
+ private def assocsNode(ann: AnnotationInfo): Node = {
+ val (names, args) = ann.assocs.toIndexedSeq.unzip
+ if (names.isEmpty) wrapEmpty
+ else node("assocs", nodeList(names.indices.toList, (i: Int) => atom(names(i).toString, args(i))))
+ }
+ private def typeTypeName(tp: Type) = tp match {
+ case mt @ MethodType(_, _) if mt.isImplicit => "ImplicitMethodType"
+ case TypeRef(_, sym, _) => typeRefType(sym)
+ case _ => tp.kind
+ }
+
+ def wrapTree(tree: Tree): Node = withType(
+ tree match {
+ case x: NameTree => atom(x.name.toString, x)
+ case _ => wrapAtom(tree)
+ },
+ tree.printingPrefix
+ )
+ def wrapSymbol(label: String, sym: Symbol): Node = {
+ if (sym eq NoSymbol) wrapEmpty
+ else atom(label, sym)
+ }
+ def wrapInfo(sym: Symbol) = sym.info match {
+ case TypeBounds(lo, hi) => typeBounds(lo, hi)
+ case PolyType(tparams, restpe) => polyFunction(tparams, restpe)
+ case _ => wrapEmpty
+ }
+ def wrapSymbolInfo(sym: Symbol): Node = {
+ if ((sym eq NoSymbol) || openSymbols(sym)) wrapEmpty
+ else {
+ openSymbols += sym
+ try product(symbolType(sym), wrapAtom(sym.defString))
+ finally openSymbols -= sym
+ }
+ }
+
+ def list(nodes: List[Node]): Node = wrapSequence(nodes)
+ def product(tp: Type, nodes: Node*): Node = product(typeTypeName(tp), nodes: _*)
+ def product(typeName: String, nodes: Node*): Node = (
+ nodes.toList filterNot (_ == wrapEmpty) match {
+ case Nil => wrapEmpty
+ case xs => withType(wrapProduct(xs), typeName)
+ }
+ )
+
+ def atom[U](label: String, value: U): Node = node(label, wrapAtom(value))
+ def constant(label: String, const: Constant): Node = atom(label, const)
+
+ def scope(decls: Scope): Node = node("decls", scopeMemberList(decls.toList))
+ def const[T](named: (String, T)): Node = constant(named._1, Constant(named._2))
+
+ def resultType(restpe: Type): Node = this("resultType", restpe)
+ def typeParams(tps: List[Symbol]): Node = node("typeParams", symbolList(tps))
+ def valueParams(params: List[Symbol]): Node = node("params", symbolList(params))
+ def typeArgs(tps: List[Type]): Node = node("args", typeList(tps))
+ def parentList(tps: List[Type]): Node = node("parents", typeList(tps))
+
+ def polyFunction(tparams: List[Symbol], restpe: Type): Node = wrapPoly(typeParams(tparams), resultType(restpe))
+ def monoFunction(params: List[Symbol], restpe: Type): Node = wrapMono(valueParams(params), resultType(restpe))
+ def nullaryFunction(restpe: Type): Node = wrapMono(wrapEmpty, this(restpe))
+
+ def prefix(pre: Type): Node = pre match {
+ case NoPrefix => wrapEmpty
+ case _ => this("pre", pre)
+ }
+ def typeBounds(lo0: Type, hi0: Type): Node = {
+ val lo = if ((lo0 eq WildcardType) || (lo0.typeSymbol eq NothingClass)) wrapEmpty else this("lo", lo0)
+ val hi = if ((hi0 eq WildcardType) || (hi0.typeSymbol eq AnyClass)) wrapEmpty else this("hi", hi0)
+
+ product("TypeBounds", lo, hi)
+ }
+
+ def annotation(ann: AnnotationInfo): Node = product(
+ "AnnotationInfo",
+ this("atp", ann.atp),
+ node("args", treeList(ann.args)),
+ assocsNode(ann)
+ )
+ def typeConstraint(constr: TypeConstraint): Node = product(
+ "TypeConstraint",
+ node("lo", typeList(constr.loBounds)),
+ node("hi", typeList(constr.hiBounds)),
+ this("inst", constr.inst)
+ )
+ def annotatedType(annotations: List[AnnotationInfo], underlying: Type) = product(
+ "AnnotatedType",
+ node("annotations", annotationList(annotations)),
+ this("underlying", underlying)
+ )
+
+ /** This imposes additional structure beyond that which is visible in
+ * the case class hierarchy. In particular, (too) many different constructs
+ * are encoded in TypeRefs; here they are partitioned somewhat before
+ * being dispatched.
+ *
+ * For example, a typical type parameter is encoded as TypeRef(NoPrefix, sym, Nil)
+ * with its upper and lower bounds stored in the info of the symbol. Viewing the
+ * TypeRef naively we are treated to both too much information (useless prefix, usually
+ * empty args) and too little (bounds hidden behind indirection.) So drop the prefix
+ * and promote the bounds.
+ */
+ def typeRef(tp: TypeRef) = {
+ val TypeRef(pre, sym, args) = tp
+ // Filtered down to elements with "interesting" content
+ product(
+ tp,
+ if (sym.isDefinedInPackage) wrapEmpty else prefix(pre),
+ wrapSymbolInfo(sym),
+ typeArgs(args),
+ if (tp ne tp.normalize) this("normalize", tp.normalize) else wrapEmpty
+ )
+ }
+
+ def symbolType(sym: Symbol) = (
+ if (sym.isRefinementClass) "Refinement"
+ else if (sym.isAliasType) "Alias"
+ else if (sym.isTypeSkolem) "TypeSkolem"
+ else if (sym.isTypeParameter) "TypeParam"
+ else if (sym.isAbstractType) "AbstractType"
+ else if (sym.isType) "TypeSymbol"
+ else "TermSymbol"
+ )
+ def typeRefType(sym: Symbol) = (
+ if (sym.isRefinementClass) "RefinementTypeRef"
+ else if (sym.isAliasType) "AliasTypeRef"
+ else if (sym.isTypeSkolem) "SkolemTypeRef"
+ else if (sym.isTypeParameter) "TypeParamTypeRef"
+ else if (sym.isAbstractType) "AbstractTypeRef"
+ else "TypeRef"
+ ) + ( if (sym.isFBounded) "(F-Bounded)" else "" )
+
+ def node(label: String, node: Node): Node = withLabel(node, label)
+ def apply(label: String, tp: Type): Node = withLabel(this(tp), label)
+
+ def apply(tp: Type): Node = tp match {
+ case AntiPolyType(pre, targs) => product(tp, prefix(pre), typeArgs(targs))
+ case ClassInfoType(parents, decls, clazz) => product(tp, parentList(parents), scope(decls), wrapAtom(clazz))
+ case ConstantType(const) => product(tp, constant("value", const))
+ case DeBruijnIndex(level, index, args) => product(tp, const("level" -> level), const("index" -> index), typeArgs(args))
+ case OverloadedType(pre, alts) => product(tp, prefix(pre), node("alts", typeList(alts map pre.memberType)))
+ case RefinedType(parents, decls) => product(tp, parentList(parents), scope(decls))
+ case SingleType(pre, sym) => product(tp, prefix(pre), wrapAtom(sym))
+ case SuperType(thistp, supertp) => product(tp, this("this", thistp), this("super", supertp))
+ case ThisType(clazz) => product(tp, wrapAtom(clazz))
+ case TypeVar(inst, constr) => product(tp, this("inst", inst), typeConstraint(constr))
+ case AnnotatedType(annotations, underlying, _) => annotatedType(annotations, underlying)
+ case ExistentialType(tparams, underlying) => polyFunction(tparams, underlying)
+ case PolyType(tparams, restpe) => polyFunction(tparams, restpe)
+ case MethodType(params, restpe) => monoFunction(params, restpe)
+ case NullaryMethodType(restpe) => nullaryFunction(restpe)
+ case TypeBounds(lo, hi) => typeBounds(lo, hi)
+ case tr @ TypeRef(pre, sym, args) => typeRef(tr)
+ case _ => wrapAtom(tp) // XXX see what this is
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index f6d1e42c32..2574a1d241 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -186,7 +186,7 @@ abstract class Duplicators extends Analyzer {
oldClassOwner = oldThis
newClassOwner = newThis
invalidate(ddef.tparams)
- for (vdef <- ddef.vparamss.flatten) {
+ mforeach(ddef.vparamss) { vdef =>
invalidate(vdef)
vdef.tpe = null
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 7d1198a4a2..722440349a 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -32,7 +32,10 @@ trait Implicits {
import global.typer.{ printTyping, deindentTyping, indentTyping, printInference }
def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context): SearchResult =
- inferImplicit(tree, pt, reportAmbiguous, isView, context, true)
+ inferImplicit(tree, pt, reportAmbiguous, isView, context, true, tree.pos)
+
+ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context, saveAmbiguousDivergent: Boolean): SearchResult =
+ inferImplicit(tree, pt, reportAmbiguous, isView, context, saveAmbiguousDivergent, tree.pos)
/** Search for an implicit value. See the comment on `result` at the end of class `ImplicitSearch`
* for more info how the search is conducted.
@@ -48,9 +51,12 @@ trait Implicits {
* @param saveAmbiguousDivergent False if any divergent/ambiguous errors should be ignored after
* implicits search,
* true if they should be reported (used in further typechecking).
+ * @param pos Position that is should be used for tracing and error reporting
+ * (useful when we infer synthetic stuff and pass EmptyTree in the `tree` argument)
+ * If it's set NoPosition, then position-based services will use `tree.pos`
* @return A search result
*/
- def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context, saveAmbiguousDivergent: Boolean): SearchResult = {
+ def inferImplicit(tree: Tree, pt: Type, reportAmbiguous: Boolean, isView: Boolean, context: Context, saveAmbiguousDivergent: Boolean, pos: Position): SearchResult = {
printInference("[infer %s] %s with pt=%s in %s".format(
if (isView) "view" else "implicit",
tree, pt, context.owner.enclClass)
@@ -71,9 +77,11 @@ trait Implicits {
if (printInfers && !tree.isEmpty && !context.undetparams.isEmpty)
printTyping("typing implicit: %s %s".format(tree, context.undetparamsString))
val implicitSearchContext = context.makeImplicit(reportAmbiguous)
- val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext).bestImplicit
- if (saveAmbiguousDivergent && implicitSearchContext.hasErrors)
+ val result = new ImplicitSearch(tree, pt, isView, implicitSearchContext, pos).bestImplicit
+ if (saveAmbiguousDivergent && implicitSearchContext.hasErrors) {
context.updateBuffer(implicitSearchContext.errBuffer.filter(err => err.kind == ErrorKinds.Ambiguous || err.kind == ErrorKinds.Divergent))
+ debugwarn("update buffer: " + implicitSearchContext.errBuffer)
+ }
printInference("[infer implicit] inferred " + result)
context.undetparams = context.undetparams filterNot result.subst.from.contains
@@ -86,6 +94,27 @@ trait Implicits {
result
}
+ /** Find all views from type `tp` (in which `tpars` are free)
+ *
+ * Note that the trees in the search results in the returned list share the same type variables.
+ * Ignore their constr field! The list of type constraints returned along with each tree specifies the constraints that
+ * must be met by the corresponding type parameter in `tpars` (for the returned implicit view to be valid).
+ *
+ * @arg tp from-type for the implicit conversion
+ * @arg context search implicits here
+ * @arg tpars symbols that should be considered free type variables
+ * (implicit search should not try to solve them, just track their constraints)
+ */
+ def allViewsFrom(tp: Type, context: Context, tpars: List[Symbol]): List[(SearchResult, List[TypeConstraint])] = {
+ // my untouchable typevars are better than yours (they can't be constrained by them)
+ val tvars = tpars map (TypeVar untouchable _)
+ val tpSubsted = tp.subst(tpars, tvars)
+
+ val search = new ImplicitSearch(EmptyTree, functionType(List(tpSubsted), AnyClass.tpe), true, context.makeImplicit(false))
+
+ search.allImplicitsPoly(tvars)
+ }
+
private final val sizeLimit = 50000
private type Infos = List[ImplicitInfo]
private type Infoss = List[List[ImplicitInfo]]
@@ -100,8 +129,6 @@ trait Implicits {
improvesCache.clear()
}
- private val ManifestSymbols = Set(PartialManifestClass, FullManifestClass, OptManifestClass)
-
/* Map a polytype to one in which all type parameters and argument-dependent types are replaced by wildcards.
* Consider `implicit def b(implicit x: A): x.T = error("")`. We need to approximate DebruijnIndex types
* when checking whether `b` is a valid implicit, as we haven't even searched a value for the implicit arg `x`,
@@ -139,7 +166,7 @@ trait Implicits {
}
def isCyclicOrErroneous =
- try containsError(tpe)
+ try sym.hasFlag(LOCKED) || containsError(tpe)
catch { case _: CyclicReference => true }
var useCountArg: Int = 0
@@ -187,13 +214,13 @@ trait Implicits {
override def hashCode = 1
}
- /** A constructor for types ?{ name: tp }, used in infer view to member
+ /** A constructor for types ?{ def/type name: tp }, used in infer view to member
* searches.
*/
def memberWildcardType(name: Name, tp: Type) = {
val result = refinedType(List(WildcardType), NoSymbol)
name match {
- case x: TermName => result.typeSymbol.newValue(x) setInfoAndEnter tp
+ case x: TermName => result.typeSymbol.newMethod(x) setInfoAndEnter tp
case x: TypeName => result.typeSymbol.newAbstractType(x) setInfoAndEnter tp
}
result
@@ -251,8 +278,11 @@ trait Implicits {
* @param pt The original expected type of the implicit.
* @param isView We are looking for a view
* @param context0 The context used for the implicit search
+ * @param pos0 Position that is preferable for use in tracing and error reporting
+ * (useful when we infer synthetic stuff and pass EmptyTree in the `tree` argument)
+ * If it's set to NoPosition, then position-based services will use `tree.pos`
*/
- class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context)
+ class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context, pos0: Position = NoPosition)
extends Typer(context0) with ImplicitsContextErrors {
printTyping(
ptBlock("new ImplicitSearch",
@@ -264,6 +294,13 @@ trait Implicits {
)
)
// assert(tree.isEmpty || tree.pos.isDefined, tree)
+ def pos = if (pos0 != NoPosition) pos0 else tree.pos
+
+ def failure(what: Any, reason: String, pos: Position = this.pos): SearchResult = {
+ if (settings.XlogImplicits.value)
+ reporter.echo(pos, what+" is not a valid implicit value for "+pt+" because:\n"+reason)
+ SearchFailure
+ }
import infer._
/** Is implicit info `info1` better than implicit info `info2`?
@@ -351,18 +388,18 @@ trait Implicits {
* @pre `info.tpe` does not contain an error
*/
private def typedImplicit(info: ImplicitInfo, ptChecked: Boolean): SearchResult = {
- (context.openImplicits find { case (tp, sym) => sym == tree.symbol && dominates(pt, tp)}) match {
+ (context.openImplicits find { case (tp, tree1) => tree1.symbol == tree.symbol && dominates(pt, tp)}) match {
case Some(pending) =>
- // println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams) //@MDEBUG
+ //println("Pending implicit "+pending+" dominates "+pt+"/"+undetParams) //@MDEBUG
throw DivergentImplicit
case None =>
try {
- context.openImplicits = (pt, tree.symbol) :: context.openImplicits
+ context.openImplicits = (pt, tree) :: context.openImplicits
// println(" "*context.openImplicits.length+"typed implicit "+info+" for "+pt) //@MDEBUG
typedImplicit0(info, ptChecked)
} catch {
case ex: DivergentImplicit =>
- // println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG
+ //println("DivergentImplicit for pt:"+ pt +", open implicits:"+context.openImplicits) //@MDEBUG
if (context.openImplicits.tail.isEmpty) {
if (!(pt.isErroneous))
DivergingImplicitExpansionError(tree, pt, info.sym)(context)
@@ -494,7 +531,7 @@ trait Implicits {
private def typedImplicit0(info: ImplicitInfo, ptChecked: Boolean): SearchResult = {
incCounter(plausiblyCompatibleImplicits)
- printTyping(
+ printTyping (
ptBlock("typedImplicit0",
"info.name" -> info.name,
"ptChecked" -> ptChecked,
@@ -515,7 +552,7 @@ trait Implicits {
private def typedImplicit1(info: ImplicitInfo): SearchResult = {
incCounter(matchingImplicits)
- val itree = atPos(tree.pos.focus) {
+ val itree = atPos(pos.focus) {
if (info.pre == NoPrefix) Ident(info.name)
else Select(gen.mkAttributedQualifier(info.pre), info.name)
}
@@ -523,11 +560,7 @@ trait Implicits {
typeDebug.ptTree(itree), wildPt, info.name, info.tpe)
)
- def fail(reason: String): SearchResult = {
- if (settings.XlogImplicits.value)
- inform(itree+" is not a valid implicit value for "+pt+" because:\n"+reason)
- SearchFailure
- }
+ def fail(reason: String): SearchResult = failure(itree, reason)
try {
val itree1 =
if (isView) {
@@ -600,6 +633,7 @@ trait Implicits {
else {
val subst = new TreeTypeSubstituter(okParams, okArgs)
subst traverse itree2
+ notifyUndetparamsInferred(okParams, okArgs)
subst
}
@@ -677,7 +711,7 @@ trait Implicits {
def comesBefore(sym: Symbol, owner: Symbol) = {
val ownerPos = owner.pos.pointOrElse(Int.MaxValue)
sym.pos.pointOrElse(0) < ownerPos && (
- if (sym hasAccessorFlag) {
+ if (sym.hasAccessorFlag) {
val symAcc = sym.accessed // #3373
symAcc.pos.pointOrElse(0) < ownerPos &&
!(owner.ownerChain exists (o => (o eq sym) || (o eq symAcc))) // probably faster to iterate only once, don't feel like duplicating hasTransOwner for this case
@@ -707,6 +741,7 @@ trait Implicits {
info.isCyclicOrErroneous
|| isView && isPredefMemberNamed(info.sym, nme.conforms)
|| isShadowed(info.name)
+ || (!context.macrosEnabled && info.sym.isTermMacro)
)
/** True if a given ImplicitInfo (already known isValid) is eligible.
@@ -796,7 +831,7 @@ trait Implicits {
/** Returns all eligible ImplicitInfos and their SearchResults in a map.
*/
- def findAll() = eligible map (info => (info, typedImplicit(info, false))) toMap
+ def findAll() = mapFrom(eligible)(typedImplicit(_, false))
/** Returns the SearchResult of the best match.
*/
@@ -825,7 +860,7 @@ trait Implicits {
throw DivergentImplicit
if (invalidImplicits.nonEmpty)
- setAddendum(tree.pos, () =>
+ setAddendum(pos, () =>
"\n Note: implicit "+invalidImplicits.head+" is not applicable here"+
" because it comes after the application point and it lacks an explicit result type")
}
@@ -1085,6 +1120,62 @@ trait Implicits {
implicitInfoss1
}
+ private def TagSymbols = TagMaterializers.keySet
+ private val TagMaterializers = Map[Symbol, Symbol](
+ ArrayTagClass -> MacroInternal_materializeArrayTag,
+ ErasureTagClass -> MacroInternal_materializeErasureTag,
+ ClassTagClass -> MacroInternal_materializeClassTag,
+ TypeTagClass -> MacroInternal_materializeTypeTag,
+ ConcreteTypeTagClass -> MacroInternal_materializeConcreteTypeTag
+ )
+
+ /** Creates a tree will produce a tag of the requested flavor.
+ * An EmptyTree is returned if materialization fails.
+ */
+ private def tagOfType(pre: Type, tp: Type, tagClass: Symbol): SearchResult = {
+ def success(arg: Tree) =
+ try {
+ val tree1 = typed(atPos(pos.focus)(arg))
+ def isErroneous = tree exists (_.isErroneous)
+ if (context.hasErrors) failure(tp, "failed to typecheck the materialized typetag: %n%s".format(context.errBuffer.head.errMsg), context.errBuffer.head.errPos)
+ else new SearchResult(tree1, EmptyTreeTypeSubstituter)
+ } catch {
+ case ex: TypeError =>
+ failure(arg, "failed to typecheck the materialized typetag: %n%s".format(ex.msg), ex.pos)
+ }
+
+ val prefix = (
+ // ClassTags only exist for scala.reflect.mirror, so their materializer
+ // doesn't care about prefixes
+ if ((tagClass eq ArrayTagClass) || (tagClass eq ErasureTagClass) || (tagClass eq ClassTagClass)) ReflectMirrorPrefix
+ else pre match {
+ // [Eugene to Martin] this is the crux of the interaction between
+ // implicits and reifiers here we need to turn a (supposedly
+ // path-dependent) type into a tree that will be used as a prefix I'm
+ // not sure if I've done this right - please, review
+ case SingleType(prePre, preSym) =>
+ gen.mkAttributedRef(prePre, preSym) setType pre
+ // necessary only to compile typetags used inside the Universe cake
+ case ThisType(thisSym) =>
+ gen.mkAttributedThis(thisSym)
+ case _ =>
+ // if ``pre'' is not a PDT, e.g. if someone wrote
+ // implicitly[scala.reflect.makro.Context#TypeTag[Int]]
+ // then we need to fail, because we don't know the prefix to use during type reification
+ return failure(tp, "tag error: unsupported prefix type %s (%s)".format(pre, pre.kind))
+ }
+ )
+ // todo. migrate hardcoded materialization in Implicits to corresponding implicit macros
+ var materializer = atPos(pos.focus)(
+ gen.mkMethodCall(TagMaterializers(tagClass), List(tp), List(prefix))
+ )
+ if (settings.XlogImplicits.value) println("materializing requested %s.%s[%s] using %s".format(pre, tagClass.name, tp, materializer))
+ if (context.macrosEnabled) success(materializer)
+ else failure(materializer, "macros are disabled")
+ }
+
+ private val ManifestSymbols = Set[Symbol](PartialManifestClass, FullManifestClass, OptManifestClass)
+
/** Creates a tree that calls the relevant factory method in object
* reflect.Manifest for type 'tp'. An EmptyTree is returned if
* no manifest is found. todo: make this instantiate take type params as well?
@@ -1107,7 +1198,7 @@ trait Implicits {
/** Re-wraps a type in a manifest before calling inferImplicit on the result */
def findManifest(tp: Type, manifestClass: Symbol = if (full) FullManifestClass else PartialManifestClass) =
- inferImplicit(tree, appliedType(manifestClass.typeConstructor, List(tp)), true, false, context).tree
+ inferImplicit(tree, appliedType(manifestClass, tp), true, false, context).tree
def findSubManifest(tp: Type) = findManifest(tp, if (full) FullManifestClass else OptManifestClass)
def mot(tp0: Type, from: List[Symbol], to: List[Type]): SearchResult = {
@@ -1174,32 +1265,45 @@ trait Implicits {
}
}
- mot(tp, Nil, Nil)
+ val tagInScope =
+ if (full) context.withMacrosDisabled(resolveTypeTag(ReflectMirrorPrefix.tpe, tp, pos, true))
+ else context.withMacrosDisabled(resolveArrayTag(tp, pos))
+ if (tagInScope.isEmpty) mot(tp, Nil, Nil)
+ else {
+ val interop =
+ if (full) gen.mkMethodCall(ReflectPackage, nme.concreteTypeTagToManifest, List(tp), List(tagInScope))
+ else gen.mkMethodCall(ReflectPackage, nme.arrayTagToClassManifest, List(tp), List(tagInScope))
+ wrapResult(interop)
+ }
}
def wrapResult(tree: Tree): SearchResult =
if (tree == EmptyTree) SearchFailure else new SearchResult(tree, EmptyTreeTypeSubstituter)
- /** The manifest corresponding to type `pt`, provided `pt` is an instance of Manifest.
+ /** The tag corresponding to type `pt`, provided `pt` is a flavor of a tag.
*/
- private def implicitManifestOrOfExpectedType(pt: Type): SearchResult = pt.dealias match {
- case TypeRef(_, sym, args) if ManifestSymbols(sym) =>
- manifestOfType(args.head, sym == FullManifestClass) match {
+ private def implicitTagOrOfExpectedType(pt: Type): SearchResult = pt.dealias match {
+ case TypeRef(pre, sym, arg :: Nil) if ManifestSymbols(sym) =>
+ manifestOfType(arg, sym == FullManifestClass) match {
case SearchFailure if sym == OptManifestClass => wrapResult(gen.mkAttributedRef(NoManifest))
case result => result
}
+ case TypeRef(pre, sym, arg :: Nil) if TagSymbols(sym) =>
+ tagOfType(pre, arg, sym)
case tp@TypeRef(_, sym, _) if sym.isAbstractType =>
- implicitManifestOrOfExpectedType(tp.bounds.lo) // #3977: use tp (==pt.dealias), not pt (if pt is a type alias, pt.bounds.lo == pt)
+ implicitTagOrOfExpectedType(tp.bounds.lo) // #3977: use tp (==pt.dealias), not pt (if pt is a type alias, pt.bounds.lo == pt)
case _ =>
searchImplicit(implicitsOfExpectedType, false)
// shouldn't we pass `pt` to `implicitsOfExpectedType`, or is the recursive case
- // for an abstract type really only meant for manifests?
+ // for an abstract type really only meant for tags?
}
/** The result of the implicit search:
* First search implicits visible in current context.
* If that fails, search implicits in expected type `pt`.
- * If that fails, and `pt` is an instance of Manifest, try to construct a manifest.
+ * // [Eugene] the following two lines should be deleted after we migrate delegate tag materialization to implicit macros
+ * If that fails, and `pt` is an instance of a ClassTag, try to construct a class tag.
+ * If that fails, and `pt` is an instance of a TypeTag, try to construct a type tag.
* If all fails return SearchFailure
*/
def bestImplicit: SearchResult = {
@@ -1219,7 +1323,7 @@ trait Implicits {
val failstart = startTimer(oftypeFailNanos)
val succstart = startTimer(oftypeSucceedNanos)
- result = implicitManifestOrOfExpectedType(pt)
+ result = implicitTagOrOfExpectedType(pt)
if (result == SearchFailure) {
context.updateBuffer(previousErrs)
@@ -1240,6 +1344,26 @@ trait Implicits {
def search(iss: Infoss, isLocal: Boolean) = applicableInfos(iss, isLocal).values
(search(context.implicitss, true) ++ search(implicitsOfExpectedType, false)).toList.filter(_.tree ne EmptyTree)
}
+
+ // find all implicits for some type that contains type variables
+ // collect the constraints that result from typing each implicit
+ def allImplicitsPoly(tvars: List[TypeVar]): List[(SearchResult, List[TypeConstraint])] = {
+ def resetTVars() = tvars foreach { _.constr = new TypeConstraint }
+
+ def eligibleInfos(iss: Infoss, isLocal: Boolean) = new ImplicitComputation(iss, if (isLocal) util.HashSet[Name](512) else null).eligible
+ val allEligibleInfos = (eligibleInfos(context.implicitss, true) ++ eligibleInfos(implicitsOfExpectedType, false)).toList
+
+ allEligibleInfos flatMap { ii =>
+ // each ImplicitInfo contributes a distinct set of constraints (generated indirectly by typedImplicit)
+ // thus, start each type var off with a fresh for every typedImplicit
+ resetTVars()
+ // any previous errors should not affect us now
+ context.flushBuffer()
+ val res = typedImplicit(ii, false)
+ if (res.tree ne EmptyTree) List((res, tvars map (_.constr)))
+ else Nil
+ }
+ }
}
object ImplicitNotFoundMsg {
@@ -1248,7 +1372,7 @@ trait Implicits {
// where `X` refers to a type parameter of `sym`
def check(sym: Symbol): Option[String] =
sym.getAnnotation(ImplicitNotFoundClass).flatMap(_.stringArg(0) match {
- case Some(m) => new Message(sym, m) validate
+ case Some(m) => new Message(sym, m).validate
case None => Some("Missing argument `msg` on implicitNotFound annotation.")
})
@@ -1273,7 +1397,7 @@ trait Implicits {
val decls = typeParamNames.toSet
(refs &~ decls) match {
- case s if s isEmpty => None
+ case s if s.isEmpty => None
case unboundNames =>
val singular = unboundNames.size == 1
Some("The type parameter"+( if(singular) " " else "s " )+ unboundNames.mkString(", ") +
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index a1ca4904f4..fb0616c890 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -67,7 +67,7 @@ trait Infer {
*/
def freshVar(tparam: Symbol): TypeVar = TypeVar(tparam)
- private class NoInstance(msg: String) extends Throwable(msg) with ControlThrowable { }
+ class NoInstance(msg: String) extends Throwable(msg) with ControlThrowable { }
private class DeferredNoInstance(getmsg: () => String) extends NoInstance("") {
override def getMessage(): String = getmsg()
}
@@ -83,7 +83,7 @@ trait Infer {
def apply(tp: Type): Type = tp match {
case WildcardType | BoundedWildcardType(_) | NoType =>
throw new NoInstance("undetermined type")
- case tv @ TypeVar(origin, constr) =>
+ case tv @ TypeVar(origin, constr) if !tv.untouchable =>
if (constr.inst == NoType) {
throw new DeferredNoInstance(() =>
"no unique instantiation of type variable " + origin + " could be found")
@@ -267,6 +267,16 @@ trait Infer {
setError(tree)
}
else {
+ if (context.owner.isTermMacro && (sym1 hasFlag LOCKED)) {
+ // we must not let CyclicReference to be thrown from sym1.info
+ // because that would mark sym1 erroneous, which it is not
+ // but if it's a true CyclicReference then macro def will report it
+ // see comments to TypeSigError for an explanation of this special case
+ // [Eugene] is there a better way?
+ val dummy = new TypeCompleter { val tree = EmptyTree; override def complete(sym: Symbol) {} }
+ throw CyclicReference(sym1, dummy)
+ }
+
if (sym1.isTerm)
sym1.cookJavaRawInfo() // xform java rawtypes into existentials
@@ -310,6 +320,8 @@ trait Infer {
/** Like weakly compatible but don't apply any implicit conversions yet.
* Used when comparing the result type of a method with its prototype.
+ * [Martin] I think Infer is also created by Erasure, with the default
+ * implementation of isCoercible
*/
def isConservativelyCompatible(tp: Type, pt: Type): Boolean =
context.withImplicitsDisabled(isWeaklyCompatible(tp, pt))
@@ -426,12 +438,15 @@ trait Infer {
tvars map (tvar => WildcardType)
}
+ /** [Martin] Can someone comment this please? I have no idea what it's for
+ * and the code is not exactly readable.
+ */
object AdjustedTypeArgs {
val Result = collection.mutable.LinkedHashMap
type Result = collection.mutable.LinkedHashMap[Symbol, Option[Type]]
def unapply(m: Result): Some[(List[Symbol], List[Type])] = Some(toLists(
- m collect {case (p, Some(a)) => (p, a)} unzip ))
+ (m collect {case (p, Some(a)) => (p, a)}).unzip ))
object Undets {
def unapply(m: Result): Some[(List[Symbol], List[Type], List[Symbol])] = Some(toLists{
@@ -484,8 +499,7 @@ trait Infer {
else Some(
if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass)
else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass)
- // this infers Foo.type instead of "object Foo" (see also widenIfNecessary)
- else if (targ.typeSymbol.isModuleClass || ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden)) targ
+ else if ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden) targ
else targ.widen
)
))
@@ -700,7 +714,7 @@ trait Infer {
case NamedType(name, _) => Some(name)
case _ => None
})._1
- if (missing forall (_.hasDefaultFlag)) {
+ if (missing forall (_.hasDefault)) {
// add defaults as named arguments
val argtpes1 = argtpes0 ::: (missing map (p => NamedType(p.name, p.tpe)))
isApplicable(undetparams, ftpe, argtpes1, pt)
@@ -752,7 +766,7 @@ trait Infer {
isAsSpecific(res, ftpe2)
case mt: MethodType if mt.isImplicit =>
isAsSpecific(ftpe1.resultType, ftpe2)
- case MethodType(params, _) if params nonEmpty =>
+ case MethodType(params, _) if params.nonEmpty =>
var argtpes = params map (_.tpe)
if (isVarArgsList(params) && isVarArgsList(ftpe2.params))
argtpes = argtpes map (argtpe =>
@@ -762,7 +776,7 @@ trait Infer {
isAsSpecific(PolyType(tparams, res), ftpe2)
case PolyType(tparams, mt: MethodType) if mt.isImplicit =>
isAsSpecific(PolyType(tparams, mt.resultType), ftpe2)
- case PolyType(_, MethodType(params, _)) if params nonEmpty =>
+ case PolyType(_, MethodType(params, _)) if params.nonEmpty =>
isApplicable(List(), ftpe2, params map (_.tpe), WildcardType)
// case NullaryMethodType(res) =>
// isAsSpecific(res, ftpe2)
@@ -993,6 +1007,7 @@ trait Infer {
PolymorphicExpressionInstantiationError(tree, undetparams, pt)
} else {
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
+ notifyUndetparamsInferred(undetparams, targs)
}
}
@@ -1029,6 +1044,7 @@ trait Infer {
if (checkBounds(fn, NoPrefix, NoSymbol, undetparams, allargs, "inferred ")) {
val treeSubst = new TreeTypeSubstituter(okparams, okargs)
treeSubst traverseTrees fn :: args
+ notifyUndetparamsInferred(okparams, okargs)
leftUndet match {
case Nil => Nil
@@ -1117,6 +1133,7 @@ trait Infer {
(inferFor(pt) orElse inferForApproxPt) map { targs =>
new TreeTypeSubstituter(undetparams, targs).traverse(tree)
+ notifyUndetparamsInferred(undetparams, targs)
} getOrElse {
debugwarn("failed inferConstructorInstance for "+ tree +" : "+ tree.tpe +" under "+ undetparams +" pt = "+ pt +(if(isFullyDefined(pt)) " (fully defined)" else " (not fully defined)"))
// if (settings.explaintypes.value) explainTypes(resTp.instantiateTypeParams(undetparams, tvars), pt)
@@ -1172,6 +1189,50 @@ trait Infer {
}
}
+ /** Does `tp` contain any types that cannot be checked at run-time (i.e., after erasure, will isInstanceOf[erased(tp)] imply conceptualIsInstanceOf[tp]?)
+ * we should find a way to ask erasure: hey, is `tp` going to make it through you with all of its isInstanceOf resolving powers intact?
+ * TODO: at the very least, reduce duplication wrt checkCheckable
+ */
+ def containsUnchecked(tp: Type): Boolean = {
+ def check(tp: Type, bound: List[Symbol]): Boolean = {
+ def isSurroundingTypeParam(sym: Symbol) = {
+ val e = context.scope.lookupEntry(sym.name)
+ ( (e ne null)
+ && (e.sym == sym )
+ && !e.sym.isTypeParameterOrSkolem
+ && (e.owner == context.scope)
+ )
+ }
+ def isLocalBinding(sym: Symbol) = (
+ sym.isAbstractType && (
+ (bound contains sym)
+ || (sym.name == tpnme.WILDCARD)
+ || isSurroundingTypeParam(sym)
+ )
+ )
+ tp.normalize match {
+ case SingleType(pre, _) =>
+ check(pre, bound)
+ case TypeRef(_, ArrayClass, arg :: _) =>
+ check(arg, bound)
+ case tp @ TypeRef(pre, sym, args) =>
+ ( (sym.isAbstractType && !isLocalBinding(sym))
+ || (args exists (x => !isLocalBinding(x.typeSymbol)))
+ || check(pre, bound)
+ )
+ // case RefinedType(_, decls) if decls.nonEmpty =>
+ // patternWarning(tp, "refinement ")
+ case RefinedType(parents, _) =>
+ parents exists (p => check(p, bound))
+ case ExistentialType(quantified, tp1) =>
+ check(tp1, bound ::: quantified)
+ case _ =>
+ false
+ }
+ }
+ check(tp, Nil)
+ }
+
def checkCheckable(tree: Tree, tp: Type, kind: String) {
def patternWarning(tp0: Type, prefix: String) = {
context.unit.uncheckedWarning(tree.pos, prefix+tp0+" in type "+kind+tp+" is unchecked since it is eliminated by erasure")
@@ -1569,9 +1630,9 @@ trait Infer {
else infer
}
- /** Assign <code>tree</code> the type of unique polymorphic alternative
+ /** Assign <code>tree</code> the type of all polymorphic alternatives
* with <code>nparams</code> as the number of type parameters, if it exists.
- * If several or none such polymorphic alternatives exist, error.
+ * If no such polymorphic alternative exist, error.
*
* @param tree ...
* @param nparams ...
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index e43b1fab0b..353514c397 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -3,288 +3,1288 @@ package typechecker
import symtab.Flags._
import scala.tools.nsc.util._
+import scala.tools.nsc.util.ClassPath._
import scala.reflect.ReflectionUtils
+import scala.collection.mutable.ListBuffer
+import scala.compat.Platform.EOL
+import scala.reflect.makro.runtime.{Context => MacroContext}
+import scala.reflect.runtime.Mirror
+import util.Statistics._
+import scala.reflect.makro.util._
+
+/**
+ * Code to deal with macros, namely with:
+ * * Compilation of macro definitions
+ * * Expansion of macro applications
+ *
+ * Say we have in a class C:
+ *
+ * def foo[T](xs: List[T]): T = macro fooBar
+ *
+ * Then fooBar needs to point to a static method of the following form:
+ *
+ * def fooBar[T: c.TypeTag]
+ * (c: scala.reflect.makro.Context)
+ * (xs: c.Expr[List[T]])
+ * : c.mirror.Tree = {
+ * ...
+ * }
+ *
+ * Then, if foo is called in qual.foo[Int](elems), where qual: D,
+ * the macro application is expanded to a reflective invocation of fooBar with parameters
+ *
+ * (simpleMacroContext{ type PrefixType = D; val prefix = qual })
+ * (Expr(elems))
+ * (TypeTag(Int))
+ */
+trait Macros extends Traces {
+ self: Analyzer =>
-trait Macros { self: Analyzer =>
import global._
import definitions._
+ def globalSettings = global.settings
+
+ val globalMacroCache = collection.mutable.Map[Any, Any]()
+ val perRunMacroCache = perRunCaches.newMap[Symbol, collection.mutable.Map[Any, Any]]
+
+ /** A list of compatible macro implementation signatures.
+ *
+ * In the example above:
+ * (c: scala.reflect.makro.Context)(xs: c.Expr[List[T]]): c.Expr[T]
+ *
+ * @param macroDef The macro definition symbol
+ * @param tparams The type parameters of the macro definition
+ * @param vparamss The value parameters of the macro definition
+ * @param retTpe The return type of the macro definition
+ */
+ private def macroImplSigs(macroDef: Symbol, tparams: List[TypeDef], vparamss: List[List[ValDef]], retTpe: Type): (List[List[List[Symbol]]], Type) = {
+ // had to move method's body to an object because of the recursive dependencies between sigma and param
+ object SigGenerator {
+ val hasThis = macroDef.owner.isClass
+ val ownerTpe = macroDef.owner match {
+ case owner if owner.isModuleClass => new UniqueThisType(macroDef.owner)
+ case owner if owner.isClass => macroDef.owner.tpe
+ case _ => NoType
+ }
+ val hasTparams = !tparams.isEmpty
+
+ def sigma(tpe: Type): Type = {
+ class SigmaTypeMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ val pre1 = pre match {
+ case ThisType(sym) if sym == macroDef.owner =>
+ SingleType(SingleType(SingleType(NoPrefix, paramsCtx(0)), MacroContextPrefix), ExprValue)
+ case SingleType(NoPrefix, sym) =>
+ mfind(vparamss)(_.symbol == sym) match {
+ case Some(macroDefParam) =>
+ SingleType(SingleType(NoPrefix, param(macroDefParam)), ExprValue)
+ case _ =>
+ pre
+ }
+ case _ =>
+ pre
+ }
+ val args1 = args map mapOver
+ TypeRef(pre1, sym, args1)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ new SigmaTypeMap() apply tpe
+ }
- def macroMeth(mac: Symbol): Symbol = {
- var owner = mac.owner
- if (!owner.isModuleClass) owner = owner.companionModule.moduleClass
- owner.info.decl(nme.macroMethodName(mac.name))
+ def makeParam(name: Name, pos: Position, tpe: Type, flags: Long = 0L) =
+ macroDef.newValueParameter(name, pos, flags) setInfo tpe
+ val ctxParam = makeParam(nme.macroContext, macroDef.pos, MacroContextClass.tpe, SYNTHETIC)
+ def implType(isType: Boolean, origTpe: Type): Type =
+ if (isRepeatedParamType(origTpe))
+ appliedType(
+ RepeatedParamClass.typeConstructor,
+ List(implType(isType, sigma(origTpe.typeArgs.head))))
+ else {
+ val tsym = getMember(MacroContextClass, if (isType) tpnme.TypeTag else tpnme.Expr)
+ typeRef(singleType(NoPrefix, ctxParam), tsym, List(sigma(origTpe)))
+ }
+ val paramCache = collection.mutable.Map[Symbol, Symbol]()
+ def param(tree: Tree): Symbol =
+ paramCache.getOrElseUpdate(tree.symbol, {
+ // [Eugene] deskolemization became necessary once I implemented inference of macro def return type
+ // please, verify this solution, but for now I'll leave it here - cargo cult for the win
+ val sym = tree.symbol.deSkolemize
+ val sigParam = makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe))
+ if (sym.isSynthetic) sigParam.flags |= SYNTHETIC
+ sigParam
+ })
+
+ val paramsCtx = List(ctxParam)
+ val paramsThis = List(makeParam(nme.macroThis, macroDef.pos, implType(false, ownerTpe), SYNTHETIC))
+ val paramsTparams = tparams map param
+ val paramssParams = mmap(vparamss)(param)
+
+ var paramsss = List[List[List[Symbol]]]()
+ // tparams are no longer part of a signature, they get into macro implementations via context bounds
+// if (hasTparams && hasThis) paramsss :+= paramsCtx :: paramsThis :: paramsTparams :: paramssParams
+// if (hasTparams) paramsss :+= paramsCtx :: paramsTparams :: paramssParams
+ // _this params are no longer part of a signature, its gets into macro implementations via Context.prefix
+// if (hasThis) paramsss :+= paramsCtx :: paramsThis :: paramssParams
+ paramsss :+= paramsCtx :: paramssParams
+
+ val tsym = getMember(MacroContextClass, tpnme.Expr)
+ val implRetTpe = typeRef(singleType(NoPrefix, ctxParam), tsym, List(sigma(retTpe)))
+ }
+
+ import SigGenerator._
+ macroTraceVerbose("generating macroImplSigs for: ")(macroDef)
+ macroTraceVerbose("tparams are: ")(tparams)
+ macroTraceVerbose("vparamss are: ")(vparamss)
+ macroTraceVerbose("retTpe is: ")(retTpe)
+ macroTraceVerbose("macroImplSigs are: ")(paramsss, implRetTpe)
}
- def macroArgs(tree: Tree): (List[List[Tree]]) = tree match {
- case Apply(fn, args) =>
- macroArgs(fn) :+ args
- case TypeApply(fn, args) =>
- macroArgs(fn) :+ args
- case Select(qual, name) =>
- List(List(qual))
- case _ =>
- List(List())
+ private def transformTypeTagEvidenceParams(paramss: List[List[Symbol]], transform: (Symbol, Symbol) => Option[Symbol]): List[List[Symbol]] = {
+ if (paramss.length == 0)
+ return paramss
+
+ val wannabe = if (paramss.head.length == 1) paramss.head.head else NoSymbol
+ val contextParam = if (wannabe != NoSymbol && wannabe.tpe <:< definitions.MacroContextClass.tpe) wannabe else NoSymbol
+
+ val lastParamList0 = paramss.lastOption getOrElse Nil
+ val lastParamList = lastParamList0 flatMap (param => param.tpe match {
+ case TypeRef(SingleType(NoPrefix, contextParam), sym, List(tparam)) =>
+ var wannabe = sym
+ while (wannabe.isAliasType) wannabe = wannabe.info.typeSymbol
+ if (wannabe != definitions.TypeTagClass && wannabe != definitions.ConcreteTypeTagClass)
+ List(param)
+ else
+ transform(param, tparam.typeSymbol) map (_ :: Nil) getOrElse Nil
+ case _ =>
+ List(param)
+ })
+
+ var result = paramss.dropRight(1) :+ lastParamList
+ if (lastParamList0.isEmpty ^ lastParamList.isEmpty) {
+ result = result dropRight 1
+ }
+
+ result
}
- /**
- * The definition of the method implementing a macro. Example:
- * Say we have in a class C
- *
- * def macro foo[T](xs: List[T]): T = expr
- *
- * Then the following macro method is generated for `foo`:
- *
- * def defmacro$foo
- * (_context: scala.reflect.macro.Context)
- * (_this: _context.Tree)
- * (T: _context.TypeTree)
- * (xs: _context.Tree): _context.Tree = {
- * import _context._ // this means that all methods of Context can be used unqualified in macro's body
- * expr
- * }
+ /** As specified above, body of a macro definition must reference its implementation.
+ * This function verifies that the body indeed refers to a method, and that
+ * the referenced macro implementation is compatible with the given macro definition.
*
- * If macro has no type arguments, the third parameter list is omitted (it's not empty, but omitted altogether).
+ * This means that macro implementation (fooBar in example above) must:
+ * 1) Refer to a statically accessible, non-overloaded method.
+ * 2) Have the right parameter lists as outlined in the SIP / in the doc comment of this class.
*
- * To find out the desugared representation of your particular macro, compile it with -Ymacro-debug.
+ * @return typechecked rhs of the given macro definition
*/
- def macroMethDef(mdef: DefDef): Tree = {
- def paramDef(name: Name, tpt: Tree) = ValDef(Modifiers(PARAM), name, tpt, EmptyTree)
- val contextType = TypeTree(ReflectMacroContext.tpe)
- val globParamSec = List(paramDef(nme.macroContext, contextType))
- def globSelect(name: Name) = Select(Ident(nme.macroContext), name)
- def globTree = globSelect(tpnme.Tree)
- def globTypeTree = globSelect(tpnme.TypeTree)
- val thisParamSec = List(paramDef(newTermName(nme.macroThis), globTree))
- def tparamInMacro(tdef: TypeDef) = paramDef(tdef.name.toTermName, globTypeTree)
- def vparamInMacro(vdef: ValDef): ValDef = paramDef(vdef.name, vdef.tpt match {
- case tpt @ AppliedTypeTree(hk, _) if treeInfo.isRepeatedParamType(tpt) => AppliedTypeTree(hk, List(globTree))
- case _ => globTree
- })
- def wrapImplicit(tree: Tree) = atPos(tree.pos) {
- // implicit hasn't proven useful so far, so I'm disabling it
- //val implicitDecl = ValDef(Modifiers(IMPLICIT), nme.macroContextImplicit, SingletonTypeTree(Ident(nme.macroContext)), Ident(nme.macroContext))
- val importGlob = Import(Ident(nme.macroContext), List(ImportSelector(nme.WILDCARD, -1, null, -1)))
- Block(List(importGlob), tree)
- }
- var formals = (mdef.vparamss map (_ map vparamInMacro))
- if (mdef.tparams.nonEmpty) formals = (mdef.tparams map tparamInMacro) :: formals
-
- atPos(mdef.pos) {
- new DefDef( // can't call DefDef here; need to find out why
- mods = mdef.mods &~ MACRO &~ OVERRIDE,
- name = nme.macroMethodName(mdef.name),
- tparams = List(),
- vparamss = globParamSec :: thisParamSec :: formals,
- tpt = globTree,
- wrapImplicit(mdef.rhs))
+ def typedMacroBody(typer: Typer, ddef: DefDef): Tree = {
+ import typer.context
+ macroLogVerbose("typechecking macro def %s at %s".format(ddef.symbol, ddef.pos))
+
+ if (!typer.checkFeature(ddef.pos, MacrosFeature, immediate = true)) {
+ ddef.symbol setFlag IS_ERROR
+ return EmptyTree
+ }
+
+ implicit class AugmentedString(s: String) {
+ def abbreviateCoreAliases: String = { // hack!
+ var result = s
+ result = result.replace("c.mirror.TypeTag", "c.TypeTag")
+ result = result.replace("c.mirror.Expr", "c.Expr")
+ result
+ }
}
- }
- def addMacroMethods(templ: Template, namer: Namer): Unit = {
- for (ddef @ DefDef(mods, _, _, _, _, _) <- templ.body if mods hasFlag MACRO) {
- val trace = scala.tools.nsc.util.trace when settings.Ymacrodebug.value
- val sym = namer.enterSyntheticSym(trace("macro def: ")(macroMethDef(ddef)))
- trace("added to "+namer.context.owner.enclClass+": ")(sym)
+ var hasErrors = false
+ def reportError(pos: Position, msg: String) = {
+ hasErrors = true
+ context.error(pos, msg)
}
- }
- lazy val mirror = new scala.reflect.runtime.Mirror {
- lazy val libraryClassLoader = {
- // todo. this is more or less okay, but not completely correct
- // see https://issues.scala-lang.org/browse/SI-5433 for more info
- val classpath = global.classPath.asURLs
- var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
-
- // an heuristic to detect REPL
- if (global.settings.exposeEmptyPackage.value) {
- import scala.tools.nsc.interpreter._
- val virtualDirectory = global.settings.outputDirs.getSingleOutput.get
- loader = new AbstractFileClassLoader(virtualDirectory, loader) {}
+ val macroDef = ddef.symbol
+ val defpos = macroDef.pos
+ val implpos = ddef.rhs.pos
+ assert(macroDef.isTermMacro, ddef)
+
+ def invalidBodyError() =
+ reportError(defpos,
+ "macro body has wrong shape:" +
+ "\n required: macro <reference to implementation object>.<implementation method name>" +
+ "\n or : macro <implementation method name>")
+ def validatePreTyper(rhs: Tree): Unit = rhs match {
+ // we do allow macro invocations inside macro bodies
+ // personally I don't mind if pre-typer tree is a macro invocation
+ // that later resolves to a valid reference to a macro implementation
+ // however, I don't think that invalidBodyError() should hint at that
+ // let this be an Easter Egg :)
+ case Apply(_, _) => ;
+ case TypeApply(_, _) => ;
+ case Super(_, _) => ;
+ case This(_) => ;
+ case Ident(_) => ;
+ case Select(_, _) => ;
+ case _ => invalidBodyError()
+ }
+ def validatePostTyper(rhs1: Tree): Unit = {
+ def loop(tree: Tree): Unit = {
+ def errorNotStatic() =
+ reportError(implpos, "macro implementation must be in statically accessible object")
+
+ def ensureRoot(sym: Symbol) =
+ if (!sym.isModule && !sym.isModuleClass) errorNotStatic()
+
+ def ensureModule(sym: Symbol) =
+ if (!sym.isModule) errorNotStatic()
+
+ tree match {
+ case TypeApply(fun, _) =>
+ loop(fun)
+ case Super(qual, _) =>
+ ensureRoot(macroDef.owner)
+ loop(qual)
+ case This(_) =>
+ ensureRoot(tree.symbol)
+ case Select(qual, name) if name.isTypeName =>
+ loop(qual)
+ case Select(qual, name) if name.isTermName =>
+ if (tree.symbol != rhs1.symbol) ensureModule(tree.symbol)
+ loop(qual)
+ case Ident(name) if name.isTypeName =>
+ ;
+ case Ident(name) if name.isTermName =>
+ if (tree.symbol != rhs1.symbol) ensureModule(tree.symbol)
+ case _ =>
+ invalidBodyError()
+ }
}
- loader
+ loop(rhs1)
}
- override def defaultReflectiveClassLoader() = libraryClassLoader
- }
+ val rhs = ddef.rhs
+ validatePreTyper(rhs)
+ if (hasErrors) macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
- /** Return optionally address of companion object and implementation method symbol
- * of given macro; or None if implementation classfile cannot be loaded or does
- * not contain the macro implementation.
- */
- def macroImpl(mac: Symbol): Option[(AnyRef, mirror.Symbol)] = {
- val debug = settings.Ymacrodebug.value
- val trace = scala.tools.nsc.util.trace when debug
- trace("looking for macro implementation: ")(mac.fullNameString)
+ // we use typed1 instead of typed, because otherwise adapt is going to mess us up
+ // if adapt sees <qualifier>.<method>, it will want to perform eta-expansion and will fail
+ // unfortunately, this means that we have to manually trigger macro expansion
+ // because it's adapt which is responsible for automatic expansion during typechecking
+ def typecheckRhs(rhs: Tree): Tree = {
+ try {
+ val prevNumErrors = reporter.ERROR.count // [Eugene] funnily enough, the isErroneous check is not enough
+ var rhs1 = if (hasErrors) EmptyTree else typer.typed1(rhs, EXPRmode, WildcardType)
+ def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors
+ def rhsNeedsMacroExpansion = rhs1.symbol != null && rhs1.symbol.isTermMacro && !rhs1.symbol.isErroneous
+ while (!typecheckedWithErrors && rhsNeedsMacroExpansion) {
+ rhs1 = macroExpand1(typer, rhs1) match {
+ case Success(expanded) =>
+ try {
+ val typechecked = typer.typed1(expanded, EXPRmode, WildcardType)
+ macroLogVerbose("typechecked1:%n%s%n%s".format(typechecked, showRaw(typechecked)))
+ typechecked
+ } finally {
+ openMacros = openMacros.tail
+ }
+ case Fallback(fallback) =>
+ typer.typed1(fallback, EXPRmode, WildcardType)
+ case Other(result) =>
+ result
+ }
+ }
+ rhs1
+ } catch {
+ case ex: TypeError =>
+ typer.reportTypeError(context, rhs.pos, ex)
+ typer.infer.setError(rhs)
+ }
+ }
- try {
- val mmeth = macroMeth(mac)
- trace("found implementation at: ")(mmeth.fullNameString)
+ val prevNumErrors = reporter.ERROR.count // funnily enough, the isErroneous check is not enough
+ var rhs1 = typecheckRhs(rhs)
+ def typecheckedWithErrors = (rhs1 exists (_.isErroneous)) || reporter.ERROR.count != prevNumErrors
+ hasErrors = hasErrors || typecheckedWithErrors
+ if (typecheckedWithErrors) macroTraceVerbose("body of a macro def failed to typecheck: ")(ddef)
- if (mmeth == NoSymbol) None
- else {
- trace("loading implementation class: ")(mmeth.owner.fullName)
- trace("classloader is: ")("%s of type %s".format(mirror.libraryClassLoader, mirror.libraryClassLoader.getClass))
- def inferClasspath(cl: ClassLoader) = cl match {
- case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
- case _ => "<unknown>"
+ val macroImpl = rhs1.symbol
+ macroDef withAnnotation AnnotationInfo(MacroImplAnnotation.tpe, List(rhs1), Nil)
+ if (!hasErrors) {
+ if (macroImpl == null) {
+ invalidBodyError()
+ } else {
+ if (!macroImpl.isMethod)
+ invalidBodyError()
+ if (macroImpl.isOverloaded)
+ reportError(implpos, "macro implementation cannot be overloaded")
+ if (!macroImpl.typeParams.isEmpty && (!rhs1.isInstanceOf[TypeApply]))
+ reportError(implpos, "macro implementation reference needs type arguments")
+ if (!hasErrors)
+ validatePostTyper(rhs1)
+ }
+ if (hasErrors)
+ macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
+ }
+
+ if (!hasErrors) {
+ def checkCompatibility(reqparamss: List[List[Symbol]], actparamss: List[List[Symbol]], reqres: Type, actres: Type): List[String] = {
+ var hasErrors = false
+ var errors = List[String]()
+ def compatibilityError(msg: String) {
+ hasErrors = true
+ errors :+= msg
}
- trace("classpath is: ")(inferClasspath(mirror.libraryClassLoader))
-
- // @xeno.by: relies on the fact that macros can only be defined in static classes
- def classfile(sym: Symbol): String = {
- def recur(sym: Symbol): String = sym match {
- case sym if sym.owner.isPackageClass =>
- val suffix = if (sym.isModuleClass) "$" else ""
- sym.fullName + suffix
- case sym =>
- val separator = if (sym.owner.isModuleClass) "" else "$"
- recur(sym.owner) + separator + sym.javaSimpleName.toString
+
+ val flatreqparams = reqparamss.flatten
+ val flatactparams = actparamss.flatten
+ val tparams = macroImpl.typeParams
+ val tvars = tparams map freshVar
+ def lengthMsg(which: String, extra: Symbol) =
+ "parameter lists have different length, "+which+" extra parameter "+extra.defString
+ if (actparamss.length != reqparamss.length)
+ compatibilityError("number of parameter sections differ")
+
+ def checkSubType(slot: String, reqtpe: Type, acttpe: Type): Unit = {
+ val ok = if (macroDebugVerbose) {
+ if (reqtpe eq acttpe) println(reqtpe + " <: " + acttpe + "?" + EOL + "true")
+ withTypesExplained(reqtpe <:< acttpe)
+ } else reqtpe <:< acttpe
+ if (!ok) {
+ compatibilityError("type mismatch for %s: %s does not conform to %s".format(slot, reqtpe.toString.abbreviateCoreAliases, acttpe.toString.abbreviateCoreAliases))
}
+ }
- if (sym.isClass || sym.isModule) recur(sym)
- else recur(sym.enclClass)
+ if (!hasErrors) {
+ try {
+ for ((rparams, aparams) <- reqparamss zip actparamss) {
+ if (rparams.length < aparams.length)
+ compatibilityError(lengthMsg("found", aparams(rparams.length)))
+ if (aparams.length < rparams.length)
+ compatibilityError(lengthMsg("required", rparams(aparams.length)).abbreviateCoreAliases)
+ }
+ // if the implementation signature is already deemed to be incompatible, we bail out
+ // otherwise, high-order type magic employed below might crash in weird ways
+ if (!hasErrors) {
+ for ((rparams, aparams) <- reqparamss zip actparamss) {
+ for ((rparam, aparam) <- rparams zip aparams) {
+ def isRepeated(param: Symbol) = param.tpe.typeSymbol == RepeatedParamClass
+ if (rparam.name != aparam.name && !rparam.isSynthetic) {
+ val rparam1 = rparam
+ val aparam1 = aparam
+ compatibilityError("parameter names differ: "+rparam.name+" != "+aparam.name)
+ }
+ if (isRepeated(rparam) && !isRepeated(aparam))
+ compatibilityError("types incompatible for parameter "+rparam.name+": corresponding is not a vararg parameter")
+ if (!isRepeated(rparam) && isRepeated(aparam))
+ compatibilityError("types incompatible for parameter "+aparam.name+": corresponding is not a vararg parameter")
+ if (!hasErrors) {
+ var atpe = aparam.tpe.substSym(flatactparams, flatreqparams).instantiateTypeParams(tparams, tvars)
+ atpe = atpe.dealias // SI-5706
+ // strip the { type PrefixType = ... } refinement off the Context or otherwise we get compatibility errors
+ atpe = atpe match {
+ case RefinedType(List(tpe), Scope(sym)) if tpe == MacroContextClass.tpe && sym.allOverriddenSymbols.contains(MacroContextPrefixType) => tpe
+ case _ => atpe
+ }
+ checkSubType("parameter " + rparam.name, rparam.tpe, atpe)
+ }
+ }
+ }
+ }
+ if (!hasErrors) {
+ val atpe = actres.substSym(flatactparams, flatreqparams).instantiateTypeParams(tparams, tvars)
+ checkSubType("return type", atpe, reqres)
+ }
+ if (!hasErrors) {
+ val targs = solvedTypes(tvars, tparams, tparams map varianceInType(actres), false,
+ lubDepth(flatactparams map (_.tpe)) max lubDepth(flatreqparams map (_.tpe)))
+ val boundsOk = typer.silent(_.infer.checkBounds(ddef, NoPrefix, NoSymbol, tparams, targs, ""))
+ boundsOk match {
+ case SilentResultValue(true) => ;
+ case SilentResultValue(false) | SilentTypeError(_) =>
+ val bounds = tparams map (tp => tp.info.instantiateTypeParams(tparams, targs).bounds)
+ compatibilityError("type arguments " + targs.mkString("[", ",", "]") +
+ " do not conform to " + tparams.head.owner + "'s type parameter bounds " +
+ (tparams map (_.defString)).mkString("[", ",", "]"))
+ }
+ }
+ } catch {
+ case ex: NoInstance =>
+ compatibilityError(
+ "type parameters "+(tparams map (_.defString) mkString ", ")+" cannot be instantiated\n"+
+ ex.getMessage)
+ }
}
- // @xeno.by: this doesn't work for inner classes
- // neither does mmeth.owner.javaClassName, so I had to roll my own implementation
- //val receiverName = mmeth.owner.fullName
- val receiverName = classfile(mmeth.owner)
- val receiverClass: mirror.Symbol = mirror.symbolForName(receiverName)
+ errors.toList
+ }
+
+ var actparamss = macroImpl.paramss
+ actparamss = transformTypeTagEvidenceParams(actparamss, (param, tparam) => None)
+
+ val rettpe = if (!ddef.tpt.isEmpty) typer.typedType(ddef.tpt).tpe else computeMacroDefTypeFromMacroImpl(ddef, macroDef, macroImpl)
+ val (reqparamsss0, reqres0) = macroImplSigs(macroDef, ddef.tparams, ddef.vparamss, rettpe)
+ var reqparamsss = reqparamsss0
- if (debug) {
- println("receiverClass is: " + receiverClass.fullNameString)
+ // prohibit implicit params on macro implementations
+ // we don't have to do this, but it appears to be more clear than allowing them
+ val implicitParams = actparamss.flatten filter (_.isImplicit)
+ if (implicitParams.length > 0) {
+ reportError(implicitParams.head.pos, "macro implementations cannot have implicit parameters other than TypeTag evidences")
+ macroTraceVerbose("macro def failed to satisfy trivial preconditions: ")(macroDef)
+ }
- val jreceiverClass = mirror.classToJava(receiverClass)
- val jreceiverSource = jreceiverClass.getProtectionDomain.getCodeSource
- println("jreceiverClass is %s from %s".format(jreceiverClass, jreceiverSource))
- println("jreceiverClassLoader is %s with classpath %s".format(jreceiverClass.getClassLoader, inferClasspath(jreceiverClass.getClassLoader)))
+ if (!hasErrors) {
+ val reqres = reqres0
+ val actres = macroImpl.tpe.finalResultType
+ def showMeth(pss: List[List[Symbol]], restpe: Type, abbreviate: Boolean) = {
+ var argsPart = (pss map (ps => ps map (_.defString) mkString ("(", ", ", ")"))).mkString
+ if (abbreviate) argsPart = argsPart.abbreviateCoreAliases
+ var retPart = restpe.toString
+ if (abbreviate || ddef.tpt.tpe == null) retPart = retPart.abbreviateCoreAliases
+ argsPart + ": " + retPart
}
+ def compatibilityError(addendum: String) =
+ reportError(implpos,
+ "macro implementation has wrong shape:"+
+ "\n required: "+showMeth(reqparamsss.head, reqres, true) +
+ (reqparamsss.tail map (paramss => "\n or : "+showMeth(paramss, reqres, true)) mkString "")+
+ "\n found : "+showMeth(actparamss, actres, false)+
+ "\n"+addendum)
- val receiverObj = receiverClass.companionModule
- trace("receiverObj is: ")(receiverObj.fullNameString)
+ macroTraceVerbose("considering " + reqparamsss.length + " possibilities of compatible macro impl signatures for macro def: ")(ddef.name)
+ val results = reqparamsss map (checkCompatibility(_, actparamss, reqres, actres))
+ if (macroDebugVerbose) (reqparamsss zip results) foreach { case (reqparamss, result) =>
+ println("%s %s".format(if (result.isEmpty) "[ OK ]" else "[FAILED]", reqparamss))
+ result foreach (errorMsg => println(" " + errorMsg))
+ }
- if (receiverObj == mirror.NoSymbol) None
- else {
- // @xeno.by: yet another reflection method that doesn't work for inner classes
- //val receiver = mirror.companionInstance(receiverClass)
- val clazz = java.lang.Class.forName(receiverName, true, mirror.libraryClassLoader)
- val receiver = clazz getField "MODULE$" get null
-
- val rmeth = receiverObj.info.member(mirror.newTermName(mmeth.name.toString))
- if (debug) {
- println("rmeth is: " + rmeth.fullNameString)
- println("jrmeth is: " + mirror.methodToJava(rmeth))
+ if (results forall (!_.isEmpty)) {
+ var index = reqparamsss indexWhere (_.length == actparamss.length)
+ if (index == -1) index = 0
+ val mostRelevantMessage = results(index).head
+ compatibilityError(mostRelevantMessage)
+ } else {
+ assert((results filter (_.isEmpty)).length == 1, results)
+ if (macroDebugVerbose) (reqparamsss zip results) filter (_._2.isEmpty) foreach { case (reqparamss, result) =>
+ println("typechecked macro impl as: " + reqparamss)
}
+ }
+ }
+ }
+
+ // if this macro definition is erroneous, then there's no sense in expanding its usages
+ // in the previous prototype macro implementations were magically generated from macro definitions
+ // so macro definitions and its usages couldn't be compiled in the same compilation run
+ // however, now definitions and implementations are decoupled, so it's everything is possible
+ // hence, we now use IS_ERROR flag to serve as an indicator that given macro definition is broken
+ if (hasErrors) {
+ macroDef setFlag IS_ERROR
+ }
- if (rmeth == mirror.NoSymbol) None
- else {
- Some((receiver, rmeth))
+ rhs1
+ }
+
+ def computeMacroDefTypeFromMacroImpl(macroDdef: DefDef, macroDef: Symbol, macroImpl: Symbol): Type = {
+ // get return type from method type
+ def unwrapRet(tpe: Type): Type = {
+ def loop(tpe: Type) = tpe match {
+ case NullaryMethodType(ret) => ret
+ case mtpe @ MethodType(_, ret) => unwrapRet(ret)
+ case _ => tpe
+ }
+
+ tpe match {
+ case PolyType(_, tpe) => loop(tpe)
+ case _ => loop(tpe)
+ }
+ }
+ var metaType = unwrapRet(macroImpl.tpe)
+
+ // downgrade from metalevel-0 to metalevel-1
+ def inferRuntimeType(metaType: Type): Type = metaType match {
+ case TypeRef(pre, sym, args) if sym.name == tpnme.Expr && args.length == 1 =>
+ args.head
+ case _ =>
+ AnyClass.tpe
+ }
+ var runtimeType = inferRuntimeType(metaType)
+
+ // transform type parameters of a macro implementation into type parameters of a macro definition
+ runtimeType = runtimeType map {
+ case TypeRef(pre, sym, args) =>
+ // [Eugene] not sure which of these deSkolemizes are necessary
+ // sym.paramPos is unreliable (see another case below)
+ val tparams = macroImpl.typeParams map (_.deSkolemize)
+ val paramPos = tparams indexOf sym.deSkolemize
+ val sym1 = if (paramPos == -1) sym else {
+ val ann = macroDef.getAnnotation(MacroImplAnnotation)
+ ann match {
+ case Some(ann) =>
+ val TypeApply(_, implRefTargs) = ann.args(0)
+ val implRefTarg = implRefTargs(paramPos).tpe.typeSymbol
+ implRefTarg
+ case None =>
+ sym
}
}
+ TypeRef(pre, sym1, args)
+ case tpe =>
+ tpe
+ }
+
+ // as stated in the spec, before being matched to macroimpl, type and value parameters of macrodef
+ // undergo a special transformation, sigma, that adapts them to the different metalevel macroimpl lives in
+ // as a result, we need to reverse this transformation when inferring macrodef ret from macroimpl ret
+ def unsigma(tpe: Type): Type = {
+ // unfortunately, we cannot dereference ``paramss'', because we're in the middle of inferring a type for ``macroDef''
+// val defParamss = macroDef.paramss
+ val defParamss = mmap(macroDdef.vparamss)(_.symbol)
+ var implParamss = macroImpl.paramss
+ implParamss = transformTypeTagEvidenceParams(implParamss, (param, tparam) => None)
+
+ val implCtxParam = if (implParamss.length > 0 && implParamss(0).length > 0) implParamss(0)(0) else null
+ def implParamToDefParam(implParam: Symbol): Symbol = {
+ val indices = (((implParamss drop 1).zipWithIndex) map { case (implParams, index) => (index, implParams indexOf implParam) } filter (_._2 != -1)).headOption
+ val defParam = indices flatMap {
+ case (plistIndex, pIndex) =>
+ if (defParamss.length <= plistIndex) None
+ else if (defParamss(plistIndex).length <= pIndex) None
+ else Some(defParamss(plistIndex)(pIndex))
+ }
+ defParam.orNull
}
- } catch {
- case ex: ClassNotFoundException =>
- trace("implementation class failed to load: ")(ex.toString)
- None
+
+ class UnsigmaTypeMap extends TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(pre, sym, args) =>
+ val pre1 = pre match {
+ case SingleType(SingleType(SingleType(NoPrefix, param), prefix), value) if param == implCtxParam && prefix == MacroContextPrefix && value == ExprValue =>
+ ThisType(macroDef.owner)
+ case SingleType(SingleType(NoPrefix, param), value) if implParamToDefParam(param) != null && value == ExprValue =>
+ val macroDefParam = implParamToDefParam(param)
+ SingleType(NoPrefix, macroDefParam)
+ case _ =>
+ pre
+ }
+ val args1 = args map mapOver
+ TypeRef(pre1, sym, args1)
+ case _ =>
+ mapOver(tp)
+ }
+ }
+
+ new UnsigmaTypeMap() apply tpe
}
+ runtimeType = unsigma(runtimeType)
+
+ runtimeType
}
- /** Return result of macro expansion.
- * Or, if that fails, and the macro overrides a method return
- * tree that calls this method instead of the macro.
+ /** Primary mirror that is used to resolve and run macro implementations.
+ * Loads classes from -Xmacro-primary-classpath, or from -cp if the option is not specified.
*/
- def macroExpand(tree: Tree, typer: Typer): Option[Any] = {
- val trace = scala.tools.nsc.util.trace when settings.Ymacrodebug.value
- trace("macroExpand: ")(tree)
-
- val macroDef = tree.symbol
- macroImpl(macroDef) match {
- case Some((receiver, rmeth)) =>
- val argss = List(global) :: macroArgs(tree)
- val paramss = macroMeth(macroDef).paramss
- trace("paramss: ")(paramss)
- val rawArgss = for ((as, ps) <- argss zip paramss) yield {
- if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1)
- else as
+ private lazy val primaryMirror: Mirror = {
+ if (global.forMSIL)
+ throw new UnsupportedOperationException("Scala reflection not available on this platform")
+
+ val libraryClassLoader = {
+ if (settings.XmacroPrimaryClasspath.value != "") {
+ macroLogVerbose("primary macro mirror: initializing from -Xmacro-primary-classpath: %s".format(settings.XmacroPrimaryClasspath.value))
+ val classpath = toURLs(settings.XmacroFallbackClasspath.value)
+ ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
+ } else {
+ macroLogVerbose("primary macro mirror: initializing from -cp: %s".format(global.classPath.asURLs))
+ val classpath = global.classPath.asURLs
+ var loader: ClassLoader = ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
+
+ // [Eugene] a heuristic to detect REPL
+ if (global.settings.exposeEmptyPackage.value) {
+ import scala.tools.nsc.interpreter._
+ val virtualDirectory = global.settings.outputDirs.getSingleOutput.get
+ loader = new AbstractFileClassLoader(virtualDirectory, loader) {}
}
- val rawArgs: Seq[Any] = rawArgss.flatten
- trace("rawArgs: ")(rawArgs)
- val savedInfolevel = nodePrinters.infolevel
- try {
- // @xeno.by: InfoLevel.Verbose examines and prints out infos of symbols
- // by the means of this'es these symbols can climb up the lexical scope
- // when these symbols will be examined by a node printer
- // they will enumerate and analyze their children (ask for infos and tpes)
- // if one of those children involves macro expansion, things might get nasty
- // that's why I'm temporarily turning this behavior off
- nodePrinters.infolevel = nodePrinters.InfoLevel.Quiet
- val expanded = mirror.invoke(receiver, rmeth)(rawArgs: _*)
- expanded match {
- case expanded: Tree =>
- val expectedTpe = tree.tpe
- val typed = typer.typed(expanded, EXPRmode, expectedTpe)
- Some(typed)
- case expanded if expanded.isInstanceOf[Tree] =>
- typer.context.unit.error(tree.pos, "macro must return a compiler-specific tree; returned value is Tree, but it doesn't belong to this compiler's universe")
- None
- case expanded =>
- typer.context.unit.error(tree.pos, "macro must return a compiler-specific tree; returned value is of class: " + expanded.getClass)
+
+ loader
+ }
+ }
+
+ new Mirror(libraryClassLoader) { override def toString = "<primary macro mirror>" }
+ }
+
+ /** Fallback mirror that is used to resolve and run macro implementations.
+ * Loads classes from -Xmacro-fallback-classpath aka "macro fallback classpath".
+ */
+ private lazy val fallbackMirror: Mirror = {
+ if (global.forMSIL)
+ throw new UnsupportedOperationException("Scala reflection not available on this platform")
+
+ val fallbackClassLoader = {
+ macroLogVerbose("fallback macro mirror: initializing from -Xmacro-fallback-classpath: %s".format(settings.XmacroFallbackClasspath.value))
+ val classpath = toURLs(settings.XmacroFallbackClasspath.value)
+ ScalaClassLoader.fromURLs(classpath, self.getClass.getClassLoader)
+ }
+
+ new Mirror(fallbackClassLoader) { override def toString = "<fallback macro mirror>" }
+ }
+
+ /** Produces a function that can be used to invoke macro implementation for a given macro definition:
+ * 1) Looks up macro implementation symbol in this universe.
+ * 2) Loads its enclosing class from the primary mirror.
+ * 3) Loads the companion of that enclosing class from the primary mirror.
+ * 4) Resolves macro implementation within the loaded companion.
+ * 5) If 2-4 fails, repeats them for the fallback mirror.
+ *
+ * @return Some(runtime) if macro implementation can be loaded successfully from either of the mirrors,
+ * None otherwise.
+ */
+ private type MacroRuntime = List[Any] => Any
+ private val macroRuntimesCache = perRunCaches.newWeakMap[Symbol, Option[MacroRuntime]]
+ private def macroRuntime(macroDef: Symbol): Option[MacroRuntime] =
+ macroRuntimesCache.getOrElseUpdate(macroDef, {
+ val runtime = {
+ macroTraceVerbose("looking for macro implementation: ")(macroDef)
+ macroTraceVerbose("macroDef is annotated with: ")(macroDef.annotations)
+
+ val ann = macroDef.getAnnotation(MacroImplAnnotation)
+ if (ann == None) {
+ macroTraceVerbose("@macroImpl annotation is missing (this means that macro definition failed to typecheck)")(macroDef)
+ return None
+ }
+
+ val macroImpl = ann.get.args(0).symbol
+ if (macroImpl == NoSymbol) {
+ macroTraceVerbose("@macroImpl annotation is malformed (this means that macro definition failed to typecheck)")(macroDef)
+ return None
+ }
+
+ macroLogVerbose("resolved implementation %s at %s".format(macroImpl, macroImpl.pos))
+ if (macroImpl.isErroneous) {
+ macroTraceVerbose("macro implementation is erroneous (this means that either macro body or macro implementation signature failed to typecheck)")(macroDef)
+ return None
+ }
+
+ def loadMacroImpl(macroMirror: Mirror): Option[(Object, macroMirror.Symbol)] = {
+ try {
+ // this logic relies on the assumptions that were valid for the old macro prototype
+ // namely that macro implementations can only be defined in top-level classes and modules
+ // with the new prototype that materialized in a SIP, macros need to be statically accessible, which is different
+ // for example, a macro def could be defined in a trait that is implemented by an object
+ // there are some more clever cases when seemingly non-static method ends up being statically accessible
+ // however, the code below doesn't account for these guys, because it'd take a look of time to get it right
+ // for now I leave it as a todo and move along to more the important stuff
+
+ macroTraceVerbose("loading implementation class from %s: ".format(macroMirror))(macroImpl.owner.fullName)
+ macroTraceVerbose("classloader is: ")("%s of type %s".format(macroMirror.classLoader, if (macroMirror.classLoader != null) macroMirror.classLoader.getClass.toString else "primordial classloader"))
+ def inferClasspath(cl: ClassLoader) = cl match {
+ case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
+ case null => "[" + scala.tools.util.PathResolver.Environment.javaBootClassPath + "]"
+ case _ => "<unknown>"
+ }
+ macroTraceVerbose("classpath is: ")(inferClasspath(macroMirror.classLoader))
+
+ // [Eugene] relies on the fact that macro implementations can only be defined in static classes
+ // [Martin to Eugene] There's similar logic buried in Symbol#flatname. Maybe we can refactor?
+ def classfile(sym: Symbol): String = {
+ def recur(sym: Symbol): String = sym match {
+ case sym if sym.owner.isPackageClass =>
+ val suffix = if (sym.isModuleClass) "$" else ""
+ sym.fullName + suffix
+ case sym =>
+ val separator = if (sym.owner.isModuleClass) "" else "$"
+ recur(sym.owner) + separator + sym.javaSimpleName.toString
+ }
+
+ if (sym.isClass || sym.isModule) recur(sym)
+ else recur(sym.enclClass)
+ }
+
+ // [Eugene] this doesn't work for inner classes
+ // neither does macroImpl.owner.javaClassName, so I had to roll my own implementation
+ //val receiverName = macroImpl.owner.fullName
+ val implClassName = classfile(macroImpl.owner)
+ val implClassSymbol: macroMirror.Symbol = macroMirror.symbolForName(implClassName)
+
+ if (macroDebugVerbose) {
+ println("implClassSymbol is: " + implClassSymbol.fullNameString)
+
+ if (implClassSymbol != macroMirror.NoSymbol) {
+ val implClass = macroMirror.classToJava(implClassSymbol)
+ val implSource = implClass.getProtectionDomain.getCodeSource
+ println("implClass is %s from %s".format(implClass, implSource))
+ println("implClassLoader is %s with classpath %s".format(implClass.getClassLoader, inferClasspath(implClass.getClassLoader)))
+ }
+ }
+
+ val implObjSymbol = implClassSymbol.companionModule
+ macroTraceVerbose("implObjSymbol is: ")(implObjSymbol.fullNameString)
+
+ if (implObjSymbol == macroMirror.NoSymbol) None
+ else {
+ // yet another reflection method that doesn't work for inner classes
+ //val receiver = macroMirror.companionInstance(receiverClass)
+ val implObj = try {
+ val implObjClass = java.lang.Class.forName(implClassName, true, macroMirror.classLoader)
+ implObjClass getField "MODULE$" get null
+ } catch {
+ case ex: NoSuchFieldException => macroTraceVerbose("exception when loading implObj: ")(ex); null
+ case ex: NoClassDefFoundError => macroTraceVerbose("exception when loading implObj: ")(ex); null
+ case ex: ClassNotFoundException => macroTraceVerbose("exception when loading implObj: ")(ex); null
+ }
+
+ if (implObj == null) None
+ else {
+ val implMethSymbol = implObjSymbol.info.member(macroMirror.newTermName(macroImpl.name.toString))
+ macroLogVerbose("implMethSymbol is: " + implMethSymbol.fullNameString)
+ macroLogVerbose("jimplMethSymbol is: " + macroMirror.methodToJava(implMethSymbol))
+
+ if (implMethSymbol == macroMirror.NoSymbol) None
+ else {
+ macroLogVerbose("successfully loaded macro impl as (%s, %s)".format(implObj, implMethSymbol))
+ Some((implObj, implMethSymbol))
+ }
+ }
+ }
+ } catch {
+ case ex: ClassNotFoundException =>
+ macroTraceVerbose("implementation class failed to load: ")(ex.toString)
None
}
- } catch {
- case ex =>
- val realex = ReflectionUtils.unwrapThrowable(ex)
- val msg = if (settings.Ymacrodebug.value) {
- val stacktrace = new java.io.StringWriter()
- realex.printStackTrace(new java.io.PrintWriter(stacktrace))
- System.getProperty("line.separator") + stacktrace
+ }
+
+ val primary = loadMacroImpl(primaryMirror)
+ primary match {
+ case Some((implObj, implMethSymbol)) =>
+ def runtime(args: List[Any]) = primaryMirror.invoke(implObj, implMethSymbol)(args: _*).asInstanceOf[Any]
+ Some(runtime _)
+ case None =>
+ if (settings.XmacroFallbackClasspath.value != "") {
+ macroLogVerbose("trying to load macro implementation from the fallback mirror: %s".format(settings.XmacroFallbackClasspath.value))
+ val fallback = loadMacroImpl(fallbackMirror)
+ fallback match {
+ case Some((implObj, implMethSymbol)) =>
+ def runtime(args: List[Any]) = fallbackMirror.invoke(implObj, implMethSymbol)(args: _*).asInstanceOf[Any]
+ Some(runtime _)
+ case None =>
+ None
+ }
} else {
- realex.getMessage
+ None
}
- typer.context.unit.error(tree.pos, "exception during macro expansion: " + msg)
- None
- } finally {
- nodePrinters.infolevel = savedInfolevel
}
- case None =>
- def notFound() = {
- typer.context.unit.error(tree.pos, "macro implementation not found: " + macroDef.name)
- None
+ }
+
+ if (runtime == None) macroDef setFlag IS_ERROR
+ runtime
+ })
+
+ /** Should become private again once we're done with migrating typetag generation from implicits */
+ def macroContext(typer: Typer, prefixTree: Tree, expandeeTree: Tree): MacroContext { val mirror: global.type } =
+ new {
+ val mirror: global.type = global
+ val callsiteTyper: mirror.analyzer.Typer = typer.asInstanceOf[global.analyzer.Typer]
+ // todo. infer precise typetag for this Expr, namely the PrefixType member of the Context refinement
+ val prefix = Expr(prefixTree)(TypeTag.Nothing)
+ val expandee = expandeeTree
+ } with MacroContext {
+ override def toString = "MacroContext(%s@%s +%d)".format(expandee.symbol.name, expandee.pos, enclosingMacros.length - 1 /* exclude myself */)
+ }
+
+ /** Calculate the arguments to pass to a macro implementation when expanding the provided tree.
+ *
+ * This includes inferring the exact type and instance of the macro context to pass, and also
+ * allowing for missing parameter sections in macro implementation (see ``macroImplParamsss'' for more info).
+ *
+ * @return list of runtime objects to pass to the implementation obtained by ``macroRuntime''
+ */
+ private def macroArgs(typer: Typer, expandee: Tree): Option[List[Any]] = {
+ val macroDef = expandee.symbol
+ val runtime = macroRuntime(macroDef) orElse { return None }
+ var prefixTree: Tree = EmptyTree
+ var typeArgs = List[Tree]()
+ val exprArgs = ListBuffer[List[Expr[_]]]()
+
+ def collectMacroArgs(tree: Tree): Unit = tree match {
+ case Apply(fn, args) =>
+ // todo. infer precise typetag for this Expr, namely the declared type of the corresponding macro impl argument
+ exprArgs.prepend(args map (Expr(_)(TypeTag.Nothing)))
+ collectMacroArgs(fn)
+ case TypeApply(fn, args) =>
+ typeArgs = args
+ collectMacroArgs(fn)
+ case Select(qual, name) =>
+ prefixTree = qual
+ case _ =>
+ }
+ collectMacroArgs(expandee)
+ val context = expandee.attachmentOpt[MacroAttachment].flatMap(_.macroContext).getOrElse(macroContext(typer, prefixTree, expandee))
+ var argss: List[List[Any]] = List(context) :: exprArgs.toList
+ macroTraceVerbose("argss: ")(argss)
+
+ val ann = macroDef.getAnnotation(MacroImplAnnotation).getOrElse(throw new Error("assertion failed. %s: %s".format(macroDef, macroDef.annotations)))
+ val macroImpl = ann.args(0).symbol
+ var paramss = macroImpl.paramss
+ val tparams = macroImpl.typeParams
+ macroTraceVerbose("paramss: ")(paramss)
+
+ // we need to take care of all possible combos of nullary/empty-paramlist macro defs vs nullary/empty-arglist invocations
+ // nullary def + nullary invocation => paramss and argss match, everything is okay
+ // nullary def + empty-arglist invocation => illegal Scala code, impossible, everything is okay
+ // empty-paramlist def + nullary invocation => uh-oh, we need to append a List() to argss
+ // empty-paramlist def + empty-arglist invocation => paramss and argss match, everything is okay
+ // that's almost it, but we need to account for the fact that paramss might have context bounds that mask the empty last paramlist
+ val paramss_without_evidences = transformTypeTagEvidenceParams(paramss, (param, tparam) => None)
+ val isEmptyParamlistDef = paramss_without_evidences.nonEmpty && paramss_without_evidences.last.isEmpty
+ val isEmptyArglistInvocation = argss.nonEmpty && argss.last.isEmpty
+ if (isEmptyParamlistDef && !isEmptyArglistInvocation) {
+ macroLogVerbose("isEmptyParamlistDef && !isEmptyArglistInvocation: appending a List() to argss")
+ argss = argss :+ Nil
+ }
+
+ // nb! check partial application against paramss without evidences
+ val numParamLists = paramss_without_evidences.length
+ val numArgLists = argss.length
+ if (numParamLists != numArgLists) {
+ typer.TyperErrorGen.MacroPartialApplicationError(expandee)
+ return None
+ }
+
+ // if paramss have typetag context bounds, add an arglist to argss if necessary and instantiate the corresponding evidences
+ // consider the following example:
+ //
+ // class D[T] {
+ // class C[U] {
+ // def foo[V] = macro Impls.foo[T, U, V]
+ // }
+ // }
+ //
+ // val outer1 = new D[Int]
+ // val outer2 = new outer1.C[String]
+ // outer2.foo[Boolean]
+ //
+ // then T and U need to be inferred from the lexical scope of the call using ``asSeenFrom''
+ // whereas V won't be resolved by asSeenFrom and need to be loaded directly from ``expandee'' which needs to contain a TypeApply node
+ // also, macro implementation reference may contain a regular type as a type argument, then we pass it verbatim
+ val resolved = collection.mutable.Map[Symbol, Type]()
+ paramss = transformTypeTagEvidenceParams(paramss, (param, tparam) => {
+ val TypeApply(_, implRefTargs) = ann.args(0)
+ var implRefTarg = implRefTargs(tparam.paramPos).tpe.typeSymbol
+ val tpe = if (implRefTarg.isTypeParameterOrSkolem) {
+ if (implRefTarg.owner == macroDef) {
+ // [Eugene] doesn't work when macro def is compiled separately from its usages
+ // then implRefTarg is not a skolem and isn't equal to any of macroDef.typeParams
+// val paramPos = implRefTarg.deSkolemize.paramPos
+ val paramPos = macroDef.typeParams.indexWhere(_.name == implRefTarg.name)
+ typeArgs(paramPos).tpe
+ } else
+ implRefTarg.tpe.asSeenFrom(
+ if (prefixTree == EmptyTree) macroDef.owner.tpe else prefixTree.tpe,
+ macroDef.owner)
+ } else
+ implRefTarg.tpe
+ macroLogVerbose("resolved tparam %s as %s".format(tparam, tpe))
+ resolved(tparam) = tpe
+ param.tpe.typeSymbol match {
+ case definitions.TypeTagClass =>
+ // do nothing
+ case definitions.ConcreteTypeTagClass =>
+ if (!tpe.isConcrete) context.abort(context.enclosingPosition, "cannot create ConcreteTypeTag from a type %s having unresolved type parameters".format(tpe))
+ // otherwise do nothing
+ case _ =>
+ throw new Error("unsupported tpe: " + tpe)
+ }
+ Some(tparam)
+ })
+ val tags = paramss.last takeWhile (_.isType) map (resolved(_)) map (tpe => {
+ // generally speaking, it's impossible to calculate erasure from a tpe here
+ // the tpe might be compiled by this run, so its jClass might not exist yet
+ // hence I just pass `null` instead and leave this puzzle to macro programmers
+ val ttag = TypeTag(tpe, null)
+ if (ttag.isConcrete) ttag.toConcrete else ttag
+ })
+ if (paramss.lastOption map (params => !params.isEmpty && params.forall(_.isType)) getOrElse false) argss = argss :+ Nil
+ argss = argss.dropRight(1) :+ (tags ++ argss.last) // todo. add support for context bounds in argss
+
+ assert(argss.length == paramss.length, "argss: %s, paramss: %s".format(argss, paramss))
+ val rawArgss = for ((as, ps) <- argss zip paramss) yield {
+ if (isVarArgsList(ps)) as.take(ps.length - 1) :+ as.drop(ps.length - 1)
+ else as
+ }
+ val rawArgs = rawArgss.flatten
+ macroTraceVerbose("rawArgs: ")(rawArgs)
+ Some(rawArgs)
+ }
+
+ /** Keeps track of macros in-flight.
+ * See more informations in comments to ``openMacros'' in ``scala.reflect.makro.Context''.
+ */
+ var openMacros = List[MacroContext]()
+ def enclosingMacroPosition = openMacros map (_.macroApplication.pos) find (_ ne NoPosition) getOrElse NoPosition
+
+ /** Performs macro expansion:
+ * 1) Checks whether the expansion needs to be delayed (see ``mustDelayMacroExpansion'')
+ * 2) Loads macro implementation using ``macroMirror''
+ * 3) Synthesizes invocation arguments for the macro implementation
+ * 4) Checks that the result is a tree bound to this universe
+ * 5) Typechecks the result against the return type of the macro definition
+ *
+ * If -Ymacro-debug-lite is enabled, you will get basic notifications about macro expansion
+ * along with macro expansions logged in the form that can be copy/pasted verbatim into REPL.
+ *
+ * If -Ymacro-debug-verbose is enabled, you will get detailed log of how exactly this function
+ * performs class loading and method resolution in order to load the macro implementation.
+ * The log will also include other non-trivial steps of macro expansion.
+ *
+ * @return
+ * the expansion result if the expansion has been successful,
+ * the fallback method invocation if the expansion has been unsuccessful, but there is a fallback,
+ * the expandee unchanged if the expansion has been delayed,
+ * the expandee fully expanded if the expansion has been delayed before and has been expanded now,
+ * the expandee with an error marker set if the expansion has been cancelled due malformed arguments or implementation
+ * the expandee with an error marker set if there has been an error
+ */
+ def macroExpand(typer: Typer, expandee: Tree, mode: Int = EXPRmode, pt: Type = WildcardType): Tree = {
+ def fail(what: String, tree: Tree): Tree = {
+ val err = typer.context.errBuffer.head
+ this.fail(typer, tree, "failed to %s: %s at %s".format(what, err.errMsg, err.errPos))
+ return expandee
+ }
+ val start = startTimer(macroExpandNanos)
+ incCounter(macroExpandCount)
+ try {
+ macroExpand1(typer, expandee) match {
+ case Success(expanded) =>
+ try {
+ var expectedTpe = expandee.tpe
+
+ // [Eugene] weird situation. what's the conventional way to deal with it?
+ val isNullaryInvocation = expandee match {
+ case TypeApply(Select(_, _), _) => true
+ case TypeApply(Ident(_), _) => true
+ case Select(_, _) => true
+ case Ident(_) => true
+ case _ => false
+ }
+ if (isNullaryInvocation) expectedTpe match {
+ case NullaryMethodType(restpe) =>
+ macroTraceVerbose("nullary invocation of a nullary method. unwrapping expectedTpe from " + expectedTpe + " to: ")(restpe)
+ expectedTpe = restpe
+ case MethodType(Nil, restpe) =>
+ macroTraceVerbose("nullary invocation of a method with an empty parameter list. unwrapping expectedTpe from " + expectedTpe + " to: ")(restpe)
+ expectedTpe = restpe
+ case _ => ;
+ }
+
+ macroLogVerbose("typechecking1 against %s: %s".format(expectedTpe, expanded))
+ var typechecked = typer.context.withImplicitsEnabled(typer.typed(expanded, EXPRmode, expectedTpe))
+ if (typer.context.hasErrors) fail("typecheck against macro def return type", expanded)
+ macroLogVerbose("typechecked1:%n%s%n%s".format(typechecked, showRaw(typechecked)))
+
+ macroLogVerbose("typechecking2 against %s: %s".format(pt, expanded))
+ typechecked = typer.context.withImplicitsEnabled(typer.typed(typechecked, EXPRmode, pt))
+ if (typer.context.hasErrors) fail("typecheck against expected type", expanded)
+ macroLogVerbose("typechecked2:%n%s%n%s".format(typechecked, showRaw(typechecked)))
+
+ typechecked
+ } finally {
+ openMacros = openMacros.tail
+ }
+ case Fallback(fallback) =>
+ typer.context.withImplicitsEnabled(typer.typed(fallback, EXPRmode, pt))
+ case Other(result) =>
+ result
+ }
+ } finally {
+ stopTimer(macroExpandNanos, start)
+ }
+ }
+
+ private sealed abstract class MacroExpansionResult extends Product with Serializable
+ private case class Success(expanded: Tree) extends MacroExpansionResult
+ private case class Fallback(fallback: Tree) extends MacroExpansionResult
+ private case class Other(result: Tree) extends MacroExpansionResult
+ private def Delay(expanded: Tree) = Other(expanded)
+ private def Skip(expanded: Tree) = Other(expanded)
+ private def Cancel(expandee: Tree) = Other(expandee)
+ private def Failure(expandee: Tree) = Other(expandee)
+ private def fail(typer: Typer, expandee: Tree, msg: String = null) = {
+ def msgForLog = if (msg != null && (msg contains "exception during macro expansion")) msg.split(EOL).drop(1).headOption.getOrElse("?") else msg
+ macroLogLite("macro expansion has failed: %s".format(msgForLog))
+ val pos = if (expandee.pos != NoPosition) expandee.pos else enclosingMacroPosition
+ if (msg != null) typer.context.error(pos, msg)
+ typer.infer.setError(expandee)
+ Failure(expandee)
+ }
+
+ /** Does the same as ``macroExpand'', but without typechecking the expansion
+ * Meant for internal use within the macro infrastructure, don't use it elsewhere.
+ */
+ private def macroExpand1(typer: Typer, expandee: Tree): MacroExpansionResult =
+ // InfoLevel.Verbose examines and prints out infos of symbols
+ // by the means of this'es these symbols can climb up the lexical scope
+ // when these symbols will be examined by a node printer
+ // they will enumerate and analyze their children (ask for infos and tpes)
+ // if one of those children involves macro expansion, things might get nasty
+ // that's why I'm temporarily turning this behavior off
+ withInfoLevel(nodePrinters.InfoLevel.Quiet) {
+ // if a macro implementation is incompatible or any of the arguments are erroneous
+ // there is no sense to expand the macro itself => it will only make matters worse
+ if (expandee.symbol.isErroneous || (expandee exists (_.isErroneous))) {
+ val reason = if (expandee.symbol.isErroneous) "incompatible macro implementation" else "erroneous arguments"
+ macroTraceVerbose("cancelled macro expansion because of %s: ".format(reason))(expandee)
+ return Cancel(typer.infer.setError(expandee))
+ }
+
+ macroRuntime(expandee.symbol) match {
+ case Some(runtime) =>
+ macroExpandWithRuntime(typer, expandee, runtime)
+ case None =>
+ macroExpandWithoutRuntime(typer, expandee)
+ }
+ }
+
+ /** Expands a macro when a runtime (i.e. the macro implementation) can be successfully loaded
+ * Meant for internal use within the macro infrastructure, don't use it elsewhere.
+ */
+ private def macroExpandWithRuntime(typer: Typer, expandee: Tree, runtime: MacroRuntime): MacroExpansionResult = {
+ def issueFreeError(sym: FreeSymbol) = {
+ val template = (
+ "Macro expansion contains free @kind@ variable %s. Have you forgotten to use %s? "
+ + "If you have troubles tracking free @kind@ variables, consider using -Xlog-free-@kind@s"
+ )
+ val forgotten = (
+ if (sym.isTerm) "eval when splicing this variable into a reifee"
+ else "c.TypeTag annotation for this type parameter"
+ )
+ typer.context.error(expandee.pos,
+ template.replaceAllLiterally("@kind@", sym.name.nameKind).format(
+ sym.name + " " + sym.origin, forgotten)
+ )
+ }
+ def macroExpandInternal = {
+ val wasDelayed = isDelayed(expandee)
+ val undetparams = calculateUndetparams(expandee)
+ val nowDelayed = !typer.context.macrosEnabled || undetparams.nonEmpty
+
+ def failExpansion(msg: String = null) = fail(typer, expandee, msg)
+ def performExpansion(args: List[Any]): MacroExpansionResult = {
+ val numErrors = reporter.ERROR.count
+ def hasNewErrors = reporter.ERROR.count > numErrors
+
+ val expanded = runtime(args)
+
+ if (hasNewErrors)
+ failExpansion() // errors have been reported by the macro itself
+ else expanded match {
+ case expanded: Expr[_] =>
+ macroLogVerbose("original:")
+ macroLogLite("" + expanded.tree + "\n" + showRaw(expanded.tree))
+
+ freeTerms(expanded.tree) foreach issueFreeError
+ freeTypes(expanded.tree) foreach issueFreeError
+ if (hasNewErrors) failExpansion()
+
+ // inherit the position from the first position-ful expandee in macro callstack
+ // this is essential for sane error messages
+ // now macro expansion gets typechecked against the macro definition return type
+ // however, this happens in macroExpand, not here in macroExpand1
+ else Success(atPos(enclosingMacroPosition.focus)(expanded.tree))
+ case _ =>
+ failExpansion(
+ "macro must return a compiler-specific expr; returned value is " + (
+ if (expanded.isInstanceOf[Expr[_]]) " Expr, but it doesn't belong to this compiler's universe"
+ else " of " + expanded.getClass
+ )
+ )
}
- def fallBackToOverridden(tree: Tree): Option[Tree] = {
- tree match {
- case Select(qual, name) if (macroDef.isMacro) =>
- macroDef.allOverriddenSymbols match {
- case first :: _ =>
- Some(Select(qual, name) setPos tree.pos setSymbol first)
- case _ =>
- trace("macro is not overridden: ")(tree)
- notFound()
- }
- case Apply(fn, args) =>
- fallBackToOverridden(fn) match {
- case Some(fn1) => Some(Apply(fn1, args) setPos tree.pos)
- case _ => None
+ }
+
+ if (wasDelayed) {
+ if (nowDelayed) Delay(expandee)
+ else Skip(macroExpandAll(typer, expandee))
+ }
+ else {
+ macroLogLite("typechecking macro expansion %s at %s".format(expandee, expandee.pos))
+ macroArgs(typer, expandee).fold(failExpansion(): MacroExpansionResult) {
+ case args @ ((context: MacroContext) :: _) =>
+ if (nowDelayed) {
+ macroLogLite("macro expansion is delayed: %s".format(expandee))
+ delayed += expandee -> undetparams
+ // need to save typer context for `macroExpandAll`
+ // need to save macro context to preserve enclosures
+ expandee attach MacroAttachment(delayed = true, typerContext = typer.context, macroContext = Some(context))
+ Delay(expandee)
+ }
+ else {
+ // adding stuff to openMacros is easy, but removing it is a nightmare
+ // it needs to be sprinkled over several different code locations
+ // why? https://github.com/scala/scala/commit/bd3eacbae21f39b1ac7fe8ade4ed71fa98e1a28d#L2R1137
+ // todo. will be improved
+ openMacros ::= context
+ var isSuccess = false
+ try performExpansion(args) match {
+ case x: Success => isSuccess = true ; x
+ case x => x
}
- case TypeApply(fn, args) =>
- fallBackToOverridden(fn) match {
- case Some(fn1) => Some(TypeApply(fn1, args) setPos tree.pos)
- case _ => None
+ finally {
+ expandee.detach(classOf[MacroAttachment])
+ if (!isSuccess) openMacros = openMacros.tail
}
+ }
+ }
+ }
+ }
+
+ try macroExpandInternal
+ catch { case ex => handleMacroExpansionException(typer, expandee, ex) }
+ }
+
+ private def macroExpandWithoutRuntime(typer: Typer, expandee: Tree): MacroExpansionResult = {
+ val macroDef = expandee.symbol
+ def notFound() = {
+ typer.context.error(expandee.pos, "macro implementation not found: " + macroDef.name + " " +
+ "(the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)\n" +
+ "if you do need to define macro implementations along with the rest of your program, consider two-phase compilation with -Xmacro-fallback-classpath " +
+ "in the second phase pointing to the output of the first phase")
+ None
+ }
+ def fallBackToOverridden(tree: Tree): Option[Tree] = {
+ tree match {
+ case Select(qual, name) if (macroDef.isTermMacro) =>
+ macroDef.allOverriddenSymbols match {
+ case first :: _ =>
+ Some(Select(qual, name) setPos tree.pos setSymbol first)
case _ =>
- trace("unexpected tree in fallback: ")(tree)
+ macroTraceVerbose("macro is not overridden: ")(tree)
notFound()
}
- }
- fallBackToOverridden(tree) match {
- case Some(tree1) =>
- trace("falling back to ")(tree1)
- currentRun.macroExpansionFailed = true
- Some(tree1)
- case None =>
- None
- }
+ case Apply(fn, args) =>
+ fallBackToOverridden(fn) match {
+ case Some(fn1) => Some(Apply(fn1, args) setPos tree.pos)
+ case _ => None
+ }
+ case TypeApply(fn, args) =>
+ fallBackToOverridden(fn) match {
+ case Some(fn1) => Some(TypeApply(fn1, args) setPos tree.pos)
+ case _ => None
+ }
+ case _ =>
+ macroTraceVerbose("unexpected tree in fallback: ")(tree)
+ notFound()
+ }
+ }
+ fallBackToOverridden(expandee) match {
+ case Some(tree1) =>
+ macroTraceLite("falling back to: ")(tree1)
+ currentRun.macroExpansionFailed = true
+ Fallback(tree1)
+ case None =>
+ fail(typer, expandee)
+ }
+ }
+
+ private def handleMacroExpansionException(typer: Typer, expandee: Tree, ex: Throwable): MacroExpansionResult = {
+ // [Eugene] any ideas about how to improve this one?
+ val realex = ReflectionUtils.unwrapThrowable(ex)
+ realex match {
+ case realex: reflect.makro.runtime.AbortMacroException =>
+ macroLogVerbose("macro expansion has failed: %s".format(realex.msg))
+ fail(typer, expandee) // error has been reported by abort
+ case err: TypeError =>
+ macroLogLite("macro expansion has failed: %s at %s".format(err.msg, err.pos))
+ throw err // error should be propagated, don't report
+ case _ =>
+ val message = {
+ try {
+ // [Eugene] is there a better way?
+ // [Paul] See Exceptional.scala and Origins.scala.
+ val relevancyThreshold = realex.getStackTrace().indexWhere(este => este.getMethodName == "macroExpand1")
+ if (relevancyThreshold == -1) None
+ else {
+ var relevantElements = realex.getStackTrace().take(relevancyThreshold + 1)
+ var framesTillReflectiveInvocationOfMacroImpl = relevantElements.reverse.indexWhere(_.isNativeMethod) + 1
+ relevantElements = relevantElements dropRight framesTillReflectiveInvocationOfMacroImpl
+
+ realex.setStackTrace(relevantElements)
+ val message = new java.io.StringWriter()
+ realex.printStackTrace(new java.io.PrintWriter(message))
+ Some(EOL + message)
+ }
+ } catch {
+ // if the magic above goes boom, just fall back to uninformative, but better than nothing, getMessage
+ case ex: Throwable =>
+ None
+ }
+ } getOrElse realex.getMessage
+ fail(typer, expandee, "exception during macro expansion: " + message)
}
}
+
+ /** Without any restrictions on macro expansion, macro applications will expand at will,
+ * and when type inference is involved, expansions will end up using yet uninferred type params.
+ *
+ * For some macros this might be ok (thanks to TreeTypeSubstituter that replaces
+ * the occurrences of undetparams with their inferred values), but in general case this won't work.
+ * E.g. for reification simple substitution is not enough - we actually need to re-reify inferred types.
+ *
+ * Luckily, there exists a very simple way to fix the problem: delay macro expansion until everything is inferred.
+ * Here are the exact rules. Macro application gets delayed if any of its subtrees contain:
+ * 1) type vars (tpe.isInstanceOf[TypeVar]) // [Eugene] this check is disabled right now, because TypeVars seem to be created from undetparams anyways
+ * 2) undetparams (sym.isTypeParameter && !sym.isSkolem)
+ */
+ var hasPendingMacroExpansions = false
+ private val delayed = perRunCaches.newWeakMap[Tree, collection.mutable.Set[Int]]
+ private def isDelayed(expandee: Tree) = delayed contains expandee
+ private def calculateUndetparams(expandee: Tree): collection.mutable.Set[Int] =
+ delayed.get(expandee).getOrElse {
+ val calculated = collection.mutable.Set[Symbol]()
+ expandee foreach (sub => {
+ def traverse(sym: Symbol) = if (sym != null && (undetparams contains sym.id)) calculated += sym
+ if (sub.symbol != null) traverse(sub.symbol)
+ if (sub.tpe != null) sub.tpe foreach (sub => traverse(sub.typeSymbol))
+ })
+ macroLogVerbose("calculateUndetparams: %s".format(calculated))
+ calculated map (_.id)
+ }
+ private val undetparams = perRunCaches.newSet[Int]
+ def notifyUndetparamsAdded(newUndets: List[Symbol]): Unit = {
+ undetparams ++= newUndets map (_.id)
+ if (macroDebugVerbose) newUndets foreach (sym => println("undetParam added: %s".format(sym)))
+ }
+ def notifyUndetparamsInferred(undetNoMore: List[Symbol], inferreds: List[Type]): Unit = {
+ undetparams --= undetNoMore map (_.id)
+ if (macroDebugVerbose) (undetNoMore zip inferreds) foreach { case (sym, tpe) => println("undetParam inferred: %s as %s".format(sym, tpe))}
+ if (!delayed.isEmpty)
+ delayed.toList foreach {
+ case (expandee, undetparams) if !undetparams.isEmpty =>
+ undetparams --= undetNoMore map (_.id)
+ if (undetparams.isEmpty) {
+ hasPendingMacroExpansions = true
+ macroTraceVerbose("macro expansion is pending: ")(expandee)
+ }
+ case _ =>
+ // do nothing
+ }
+ }
+
+ /** Performs macro expansion on all subtrees of a given tree.
+ * Innermost macros are expanded first, outermost macros are expanded last.
+ * See the documentation for ``macroExpand'' for more information.
+ */
+ def macroExpandAll(typer: Typer, expandee: Tree): Tree =
+ new Transformer {
+ override def transform(tree: Tree) = super.transform(tree match {
+ // todo. expansion should work from the inside out
+ case wannabe if (delayed contains wannabe) && calculateUndetparams(wannabe).isEmpty =>
+ val context = wannabe.attachment[MacroAttachment].typerContext
+ delayed -= wannabe
+ context.implicitsEnabled = typer.context.implicitsEnabled
+ context.enrichmentEnabled = typer.context.enrichmentEnabled
+ context.macrosEnabled = typer.context.macrosEnabled
+ macroExpand(newTyper(context), wannabe, EXPRmode, WildcardType)
+ case _ =>
+ tree
+ })
+ }.transform(expandee)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
index b57f139074..cf94f7d4d6 100644
--- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala
@@ -8,6 +8,8 @@ package typechecker
import symtab.Flags._
import scala.collection.{ mutable, immutable }
import scala.tools.util.StringOps.{ ojoin }
+import scala.reflect.{ mirror => rm }
+import language.higherKinds
/** Logic related to method synthesis which involves cooperation between
* Namer and Typer.
@@ -20,52 +22,72 @@ trait MethodSynthesis {
import CODE._
object synthesisUtil {
- type M[T] = Manifest[T]
- type CM[T] = ClassManifest[T]
+ type CTT[T] = rm.ConcreteTypeTag[T]
+ type CT[T] = ClassTag[T]
def ValOrDefDef(sym: Symbol, body: Tree) =
if (sym.isLazy) ValDef(sym, body)
else DefDef(sym, body)
- def applyTypeInternal(manifests: List[M[_]]): Type = {
- val symbols = manifests map manifestToSymbol
+ def applyTypeInternal(tags: List[CTT[_]]): Type = {
+ // [Eugene to Paul] needs review!!
+ val symbols = tags map compilerSymbolFromTag
val container :: args = symbols
val tparams = container.typeConstructor.typeParams
// Conservative at present - if manifests were more usable this could do a lot more.
- require(symbols forall (_ ne NoSymbol), "Must find all manifests: " + symbols)
+ // [Eugene to Paul] all right, they are now. what do you have in mind?
+ require(symbols forall (_ ne NoSymbol), "Must find all tags: " + symbols)
require(container.owner.isPackageClass, "Container must be a top-level class in a package: " + container)
require(tparams.size == args.size, "Arguments must match type constructor arity: " + tparams + ", " + args)
- typeRef(container.typeConstructor.prefix, container, args map (_.tpe))
+ appliedType(container, args map (_.tpe): _*)
}
- def companionType[T](implicit m: M[T]) =
+ def companionType[T](implicit m: CTT[T]) =
getRequiredModule(m.erasure.getName).tpe
// Use these like `applyType[List, Int]` or `applyType[Map, Int, String]`
- def applyType[CC](implicit m1: M[CC]): Type =
+ def applyType[CC](implicit m1: CTT[CC]): Type =
applyTypeInternal(List(m1))
- def applyType[CC[X1], X1](implicit m1: M[CC[_]], m2: M[X1]): Type =
+ def applyType[CC[X1], X1](implicit m1: CTT[CC[_]], m2: CTT[X1]): Type =
applyTypeInternal(List(m1, m2))
- def applyType[CC[X1, X2], X1, X2](implicit m1: M[CC[_,_]], m2: M[X1], m3: M[X2]): Type =
+ def applyType[CC[X1, X2], X1, X2](implicit m1: CTT[CC[_,_]], m2: CTT[X1], m3: CTT[X2]): Type =
applyTypeInternal(List(m1, m2, m3))
- def applyType[CC[X1, X2, X3], X1, X2, X3](implicit m1: M[CC[_,_,_]], m2: M[X1], m3: M[X2], m4: M[X3]): Type =
+ def applyType[CC[X1, X2, X3], X1, X2, X3](implicit m1: CTT[CC[_,_,_]], m2: CTT[X1], m3: CTT[X2], m4: CTT[X3]): Type =
applyTypeInternal(List(m1, m2, m3, m4))
- def newMethodType[F](owner: Symbol)(implicit m: Manifest[F]): Type = {
- val fnSymbol = manifestToSymbol(m)
- assert(fnSymbol isSubClass FunctionClass(m.typeArguments.size - 1), (owner, m))
- val symbols = m.typeArguments map (m => manifestToSymbol(m))
- val formals = symbols.init map (_.typeConstructor)
+ def newMethodType[F](owner: Symbol)(implicit t: CTT[F]): Type = {
+ val fnSymbol = compilerSymbolFromTag(t)
+ assert(fnSymbol isSubClass FunctionClass(t.tpe.typeArguments.size - 1), (owner, t))
+ // [Eugene to Paul] needs review!!
+ // val symbols = m.typeArguments map (m => manifestToSymbol(m))
+ // val formals = symbols.init map (_.typeConstructor)
+ val formals = compilerTypeFromTag(t).typeArguments
val params = owner newSyntheticValueParams formals
-
- MethodType(params, symbols.last.typeConstructor)
+ MethodType(params, formals.last)
}
- }
+
+ /** The annotations amongst those found on the original symbol which
+ * should be propagated to this kind of accessor.
+ */
+ def deriveAnnotations(initial: List[AnnotationInfo], category: Symbol, keepClean: Boolean): List[AnnotationInfo] = {
+ initial filter { ann =>
+ // There are no meta-annotation arguments attached to `ann`
+ if (ann.metaAnnotations.isEmpty) {
+ // A meta-annotation matching `annotKind` exists on `ann`'s definition.
+ (ann.defaultTargets contains category) ||
+ // `ann`'s definition has no meta-annotations, and `keepClean` is true.
+ (ann.defaultTargets.isEmpty && keepClean)
+ }
+ // There are meta-annotation arguments, and one of them matches `annotKind`
+ else ann.metaAnnotations exists (_ matches category)
+ }
+ }
+ }
import synthesisUtil._
class ClassMethodSynthesis(val clazz: Symbol, localTyper: Typer) {
@@ -96,8 +118,7 @@ trait MethodSynthesis {
finishMethod(m setInfoAndEnter infoFn(m), f)
}
private def cloneInternal(original: Symbol, f: Symbol => Tree, name: Name): Tree = {
- val m = original.cloneSymbol(clazz, newMethodFlags(original)) setPos clazz.pos.focus
- m.name = name
+ val m = original.cloneSymbol(clazz, newMethodFlags(original), name) setPos clazz.pos.focus
finishMethod(clazz.info.decls enter m, f)
}
@@ -156,28 +177,23 @@ trait MethodSynthesis {
/** There are two key methods in here.
*
- * 1) enterGetterSetter is called from Namer with a ValDef which
- * may need accessors. Some setup is performed. In general this
- * creates symbols and enters them into the scope of the owner.
+ * 1) Enter methods such as enterGetterSetterare called
+ * from Namer with a tree which may generate further trees such as accessors or
+ * implicit wrappers. Some setup is performed. In general this creates symbols
+ * and enters them into the scope of the owner.
*
- * 2) finishGetterSetter is called from Typer when a Template is typed.
+ * 2) addDerivedTrees is called from Typer when a Template is typed.
* It completes the job, returning a list of trees with their symbols
- * set to those created in enterGetterSetter. Those trees then become
+ * set to those created in the enter methods. Those trees then become
* part of the typed template.
*/
trait MethodSynth {
self: Namer =>
import NamerErrorGen._
-
- /** TODO - synthesize method.
- */
- def enterImplicitClass(tree: ClassDef) {
- /** e.g.
- val ClassDef(mods, name, tparams, impl) = tree
- val converter = ImplicitClassConverter(tree).createAndEnterSymbol()
- ...
- */
+
+ def enterImplicitWrapper(tree: ClassDef) {
+ ImplicitClassWrapper(tree).createAndEnterSymbol()
}
def enterGetterSetter(tree: ValDef) {
@@ -204,7 +220,8 @@ trait MethodSynthesis {
enterBeans(tree)
}
- def finishGetterSetter(typer: Typer, stat: Tree): List[Tree] = stat match {
+
+ def addDerivedTrees(typer: Typer, stat: Tree): List[Tree] = stat match {
case vd @ ValDef(mods, name, tpt, rhs) if !noFinishGetterSetter(vd) && !vd.symbol.isLazy =>
// If we don't save the annotations, they seem to wander off.
val annotations = stat.symbol.initialize.annotations
@@ -212,22 +229,36 @@ trait MethodSynthesis {
map (acc => atPos(vd.pos.focus)(acc derive annotations))
filterNot (_ eq EmptyTree)
)
+ case cd @ ClassDef(mods, _, _, _) if mods.isImplicit =>
+ val annotations = stat.symbol.initialize.annotations
+ // TODO: need to shuffle annotations between wrapper and class.
+ val wrapper = ImplicitClassWrapper(cd)
+ val meth = wrapper.derivedSym
+ context.unit.synthetics get meth match {
+ case Some(mdef) =>
+ context.unit.synthetics -= meth
+ meth setAnnotations deriveAnnotations(annotations, MethodTargetClass, false)
+ cd.symbol setAnnotations deriveAnnotations(annotations, ClassTargetClass, true)
+ List(cd, mdef)
+ case _ =>
+ // Shouldn't happen, but let's give ourselves a reasonable error when it does
+ abort("No synthetics for " + meth + ": synthetics contains " + context.unit.synthetics.keys.mkString(", "))
+ }
case _ =>
List(stat)
- }
+ }
def standardAccessors(vd: ValDef): List[DerivedFromValDef] = (
if (vd.mods.isMutable && !vd.mods.isLazy) List(Getter(vd), Setter(vd))
else List(Getter(vd))
)
def beanAccessors(vd: ValDef): List[DerivedFromValDef] = {
+ val setter = if (vd.mods.isMutable) List(BeanSetter(vd)) else Nil
if (forMSIL) Nil
- else if (vd.symbol hasAnnotation BeanPropertyAttr) {
- if (vd.mods.isMutable) List(BeanGetter(vd), BeanSetter(vd))
- else List(BeanGetter(vd))
- }
+ else if (vd.symbol hasAnnotation BeanPropertyAttr)
+ BeanGetter(vd) :: setter
else if (vd.symbol hasAnnotation BooleanBeanPropertyAttr)
- List(BooleanBeanGetter(vd))
+ BooleanBeanGetter(vd) :: setter
else Nil
}
def allValDefDerived(vd: ValDef) = {
@@ -235,35 +266,59 @@ trait MethodSynthesis {
field ::: standardAccessors(vd) ::: beanAccessors(vd)
}
+ /** This trait assembles what's needed for synthesizing derived methods.
+ * Important: Typically, instances of this trait are created TWICE for each derived
+ * symbol; once form Namers in an enter method, and once from Typers in addDerivedTrees.
+ * So it's important that creating an instance of Derived does not have a side effect,
+ * or if it has a side effect, control that it is done only once.
+ */
trait Derived {
- /** The tree from which we are deriving a synthetic member. */
+
+ /** The tree from which we are deriving a synthetic member. Typically, that's
+ * given as an argument of the instance. */
def tree: Tree
+
+ /** The name of the method */
def name: TermName
+
+ /** The flags that are retained from the original symbol */
+
def flagsMask: Long
+
+ /** The flags that the derived symbol has in addition to those retained from
+ * the original symbol*/
def flagsExtra: Long
-
- /** The tree, symbol, and type completer for the synthetic member. */
+
+ /** type completer for the synthetic member.
+ */
def completer(sym: Symbol): Type
+
+ /** The derived symbol. It is assumed that this symbol already exists and has been
+ * entered in the parent scope when derivedSym is called */
def derivedSym: Symbol
+
+ /** The definition tree of the derived symbol. */
def derivedTree: Tree
}
-
+
trait DerivedFromMemberDef extends Derived {
def tree: MemberDef
-
+ def enclClass: Symbol
+
// Final methods to make the rest easier to reason about.
final def mods = tree.mods
final def basisSym = tree.symbol
- final def enclClass = basisSym.enclClass
final def derivedFlags: Long = basisSym.flags & flagsMask | flagsExtra
}
-
+
trait DerivedFromClassDef extends DerivedFromMemberDef {
def tree: ClassDef
+ final def enclClass = basisSym.owner.enclClass
}
trait DerivedFromValDef extends DerivedFromMemberDef {
def tree: ValDef
+ final def enclClass = basisSym.enclClass
/** Which meta-annotation is associated with this kind of entity.
* Presently one of: field, getter, setter, beanGetter, beanSetter, param.
@@ -287,31 +342,15 @@ trait MethodSynthesis {
enterInScope(sym)
sym setInfo completer(sym)
}
- /** The annotations amongst those found on the original symbol which
- * should be propagated to this kind of accessor.
- */
- private def deriveAnnotations(initial: List[AnnotationInfo]): List[AnnotationInfo] = {
- initial filter { ann =>
- // There are no meta-annotation arguments attached to `ann`
- if (ann.metaAnnotations.isEmpty) {
- // A meta-annotation matching `annotKind` exists on `ann`'s definition.
- (ann.defaultTargets contains category) ||
- // `ann`'s definition has no meta-annotations, and `keepClean` is true.
- (ann.defaultTargets.isEmpty && keepClean)
- }
- // There are meta-annotation arguments, and one of them matches `annotKind`
- else ann.metaAnnotations exists (_ matches category)
- }
- }
private def logDerived(result: Tree): Tree = {
- debuglog("[+derived] " + ojoin(mods.defaultFlagString, basisSym.accurateKindString, basisSym.getterName.decode)
+ debuglog("[+derived] " + ojoin(mods.flagString, basisSym.accurateKindString, basisSym.getterName.decode)
+ " (" + derivedSym + ")\n " + result)
result
}
final def derive(initial: List[AnnotationInfo]): Tree = {
validate()
- derivedSym setAnnotations deriveAnnotations(initial)
+ derivedSym setAnnotations deriveAnnotations(initial, category, keepClean)
logDerived(derivedTree)
}
}
@@ -335,15 +374,23 @@ trait MethodSynthesis {
/** A synthetic method which performs the implicit conversion implied by
* the declaration of an implicit class. Yet to be written.
*/
- case class ImplicitClassConverter(tree: ClassDef) extends DerivedFromClassDef {
- def completer(sym: Symbol): Type = ???
- def derivedSym: Symbol = ???
- def derivedTree: DefDef = ???
- def flagsExtra: Long = ???
- def flagsMask: Long = ???
- def name: TermName = ???
- }
-
+ case class ImplicitClassWrapper(tree: ClassDef) extends DerivedFromClassDef {
+ def completer(sym: Symbol): Type = ??? // not needed
+ def createAndEnterSymbol(): Symbol = enterSyntheticSym(derivedTree)
+ def derivedSym: Symbol = {
+ // Only methods will do! Don't want to pick up any stray
+ // companion objects of the same name.
+ val result = enclClass.info decl name suchThat (_.isMethod)
+ assert(result != NoSymbol, "not found: "+name+" in "+enclClass+" "+enclClass.info.decls)
+ result
+ }
+ def derivedTree: DefDef =
+ factoryMeth(mods & flagsMask | flagsExtra, name, tree, symbolic = false)
+ def flagsExtra: Long = METHOD | IMPLICIT | SYNTHETIC
+ def flagsMask: Long = AccessFlags
+ def name: TermName = tree.name.toTermName
+ }
+
case class Getter(tree: ValDef) extends DerivedGetter {
def name = tree.name
def category = GetterTargetClass
@@ -374,7 +421,7 @@ trait MethodSynthesis {
case ExistentialType(_, _) => TypeTree()
case tp => TypeTree(tp)
}
- tpt setPos focusPos(derivedSym.pos)
+ tpt setPos derivedSym.pos.focus
// keep type tree of original abstract field
if (mods.isDeferred)
tpt setOriginal tree.tpt
diff --git a/src/compiler/scala/tools/nsc/typechecker/Modes.scala b/src/compiler/scala/tools/nsc/typechecker/Modes.scala
index 48068b58d4..3eff5ef024 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Modes.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Modes.scala
@@ -105,7 +105,7 @@ trait Modes {
final def inFunMode(mode: Int) = (mode & FUNmode) != 0
final def inPolyMode(mode: Int) = (mode & POLYmode) != 0
final def inPatternMode(mode: Int) = (mode & PATTERNmode) != 0
-
+ final def inExprModeOr(mode: Int, others: Int) = (mode & (EXPRmode | others)) != 0
final def inExprModeButNot(mode: Int, prohibited: Int) =
(mode & (EXPRmode | prohibited)) == EXPRmode
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 8604366bf2..6620ef7347 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -99,7 +99,7 @@ trait Namers extends MethodSynthesis {
owner.unsafeTypeParams foreach (paramContext.scope enter _)
newNamer(paramContext)
}
-
+
def enclosingNamerWithScope(scope: Scope) = {
var cx = context
while (cx != NoContext && cx.scope != scope) cx = cx.outer
@@ -139,16 +139,9 @@ trait Namers extends MethodSynthesis {
|| vd.symbol.isLazy
)
- def setPrivateWithin[Sym <: Symbol](tree: Tree, sym: Sym, mods: Modifiers): Sym =
+ def setPrivateWithin[T <: Symbol](tree: Tree, sym: T, mods: Modifiers): T =
if (sym.isPrivateLocal || !mods.hasAccessBoundary) sym
- else sym setPrivateWithin (
- typer.qualifyingClass(tree, mods.privateWithin, true) match {
- case None =>
- NoSymbol
- case Some(sym) =>
- sym
- }
- )
+ else sym setPrivateWithin typer.qualifyingClass(tree, mods.privateWithin, packageOK = true)
def setPrivateWithin(tree: MemberDef, sym: Symbol): Symbol =
setPrivateWithin(tree, sym, tree.mods)
@@ -160,24 +153,14 @@ trait Namers extends MethodSynthesis {
def moduleClassFlags(moduleFlags: Long) =
(moduleFlags & ModuleToClassFlags) | inConstructorFlag
- private def resetKeepingFlags(sym: Symbol, keeping: Long): Symbol = {
- val keep = sym.flags & keeping
- sym reset NoType
- sym setFlag keep
- }
-
def updatePosFlags(sym: Symbol, pos: Position, flags: Long): Symbol = {
debuglog("[overwrite] " + sym)
- resetKeepingFlags(sym, LOCKED)
- sym setFlag flags
- sym setPos pos
-
- if (sym.isModule && sym.moduleClass != NoSymbol)
- updatePosFlags(sym.moduleClass, pos, moduleClassFlags(flags))
+ val newFlags = (sym.flags & LOCKED) | flags
+ sym reset NoType setFlag newFlags setPos pos
+ sym.moduleClass andAlso (updatePosFlags(_, pos, moduleClassFlags(flags)))
if (sym.owner.isPackageClass) {
- val companion = companionSymbolOf(sym, context)
- if (companion != NoSymbol) {
+ companionSymbolOf(sym, context) andAlso { companion =>
val assignNoType = companion.rawInfo match {
case _: SymLoader => true
case tp => tp.isComplete && (runId(sym.validTo) != currentRunId)
@@ -400,9 +383,7 @@ trait Namers extends MethodSynthesis {
if (m.isModule && !m.isPackage && inCurrentScope(m) && (currentRun.canRedefine(m) || m.isSynthetic)) {
updatePosFlags(m, tree.pos, moduleFlags)
setPrivateWithin(tree, m)
- if (m.moduleClass != NoSymbol)
- setPrivateWithin(tree, m.moduleClass)
-
+ m.moduleClass andAlso (setPrivateWithin(tree, _))
context.unit.synthetics -= m
tree.symbol = m
}
@@ -475,8 +456,7 @@ trait Namers extends MethodSynthesis {
val defSym = context.prefix.member(to) filter (
sym => sym.exists && context.isAccessible(sym, context.prefix, false))
- if (defSym != NoSymbol)
- typer.permanentlyHiddenWarning(pos, to0, defSym)
+ defSym andAlso (typer.permanentlyHiddenWarning(pos, to0, _))
}
}
if (!tree.symbol.isSynthetic && expr.symbol != null && !expr.symbol.isInterpreterWrapper) {
@@ -529,7 +509,7 @@ trait Namers extends MethodSynthesis {
def enterCopyMethodOrGetter(tree: Tree, tparams: List[TypeDef]): Symbol = {
val sym = tree.symbol
val lazyType = completerOf(tree, tparams)
- def completeCopyFirst = sym.isSynthetic && (!sym.hasDefaultFlag || sym.owner.info.member(nme.copy).isSynthetic)
+ def completeCopyFirst = sym.isSynthetic && (!sym.hasDefault || sym.owner.info.member(nme.copy).isSynthetic)
def completeCopyMethod(clazz: Symbol) {
// the 'copy' method of case classes needs a special type completer to make
// bug0054.scala (and others) work. the copy method has to take exactly the same
@@ -624,20 +604,16 @@ trait Namers extends MethodSynthesis {
enterCopyMethodOrGetter(tree, tparams)
else
sym setInfo completerOf(tree, tparams)
-
- if (mods hasFlag MACRO) {
- if (!(sym.owner.isClass && sym.owner.isStatic))
- context.error(tree.pos, "macro definition must appear in globally accessible class")
- }
}
def enterClassDef(tree: ClassDef) {
val ClassDef(mods, name, tparams, impl) = tree
+ val primaryConstructorArity = treeInfo.firstConstructorArgs(impl.body).size
tree.symbol = enterClassSymbol(tree)
tree.symbol setInfo completerOf(tree)
if (mods.isCase) {
- if (treeInfo.firstConstructorArgs(impl.body).size > MaxFunctionArity)
+ if (primaryConstructorArity > MaxFunctionArity)
MaxParametersCaseClassError(tree)
val m = ensureCompanionObject(tree, caseModuleDef)
@@ -651,25 +627,22 @@ trait Namers extends MethodSynthesis {
val m = ensureCompanionObject(tree)
classAndNamerOfModule(m) = (tree, null)
}
- val hasMacro = impl.body exists {
- case DefDef(mods, _, _, _, _, _) => mods hasFlag MACRO
- case _ => false
- }
- if (hasMacro) {
- val m = ensureCompanionObject(tree)
- classOfModuleClass(m.moduleClass) = new WeakReference(tree)
- }
val owner = tree.symbol.owner
- if (owner.isPackageObjectClass) {
+ if (settings.lint.value && owner.isPackageObjectClass) {
context.unit.warning(tree.pos,
"it is not recommended to define classes/objects inside of package objects.\n" +
"If possible, define " + tree.symbol + " in " + owner.skipPackageObject + " instead."
)
}
-
+
// Suggested location only.
- if (mods.isImplicit)
- enterImplicitClass(tree)
+ if (mods.isImplicit) {
+ if (primaryConstructorArity == 1) {
+ log("enter implicit wrapper "+tree+", owner = "+owner)
+ enterImplicitWrapper(tree)
+ }
+ else context.unit.error(tree.pos, "implicit classes must accept exactly one primary constructor parameter")
+ }
}
// this logic is needed in case typer was interrupted half
@@ -680,11 +653,10 @@ trait Namers extends MethodSynthesis {
protected def enterExistingSym(sym: Symbol): Context = {
if (forInteractive && sym != null && sym.owner.isTerm) {
enterIfNotThere(sym)
- if (sym.isLazy) {
- val acc = sym.lazyAccessor
- if (acc != NoSymbol) enterIfNotThere(acc)
- }
- defaultParametersOfMethod(sym) foreach enterIfNotThere
+ if (sym.isLazy)
+ sym.lazyAccessor andAlso enterIfNotThere
+
+ defaultParametersOfMethod(sym) foreach { symRef => enterIfNotThere(symRef()) }
}
this.context
}
@@ -793,10 +765,7 @@ trait Namers extends MethodSynthesis {
val tpe1 = dropRepeatedParamType(tpe.deconst)
val tpe2 = tpe1.widen
- // This infers Foo.type instead of "object Foo"
- // See Infer#adjustTypeArgs for the polymorphic case.
- if (tpe.typeSymbolDirect.isModuleClass) tpe1
- else if (sym.isVariable || sym.isMethod && !sym.hasAccessorFlag)
+ if (sym.isVariable || sym.isMethod && !sym.hasAccessorFlag)
if (tpe2 <:< pt) tpe2 else tpe1
else if (isHidden(tpe)) tpe2
// In an attempt to make pattern matches involving method local vals
@@ -812,7 +781,9 @@ trait Namers extends MethodSynthesis {
*/
private def assignTypeToTree(tree: ValOrDefDef, defnTyper: Typer, pt: Type): Type = {
// compute result type from rhs
- val typedBody = defnTyper.computeType(tree.rhs, pt)
+ val typedBody =
+ if (tree.symbol.isTermMacro) defnTyper.computeMacroDefType(tree, pt)
+ else defnTyper.computeType(tree.rhs, pt)
val sym = if (owner.isMethod) owner else tree.symbol
val typedDefn = widenIfNecessary(sym, typedBody, pt)
assignTypeToTree(tree, typedDefn)
@@ -834,19 +805,17 @@ trait Namers extends MethodSynthesis {
if (!hasType)
tpt defineType NoType
- if (hasType || hasName) {
- owner.typeOfThis =
- if (hasType) selfTypeCompleter(tpt)
- else owner.tpe
- }
val sym = (
- if (hasType) owner.thisSym setPos self.pos
- else if (hasName) owner.thisSym
- else owner.newThisSym(self.pos) setInfo owner.tpe
+ if (hasType || hasName) {
+ owner.typeOfThis = if (hasType) selfTypeCompleter(tpt) else owner.tpe
+ val selfSym = owner.thisSym setPos self.pos
+ if (hasName) selfSym setName name else selfSym
+ }
+ else {
+ val symName = if (name != nme.WILDCARD) name else nme.this_
+ owner.newThisSym(symName, owner.pos) setInfo owner.tpe
+ }
)
- if (hasName)
- sym.name = name
-
self.symbol = context.scope enter sym
}
@@ -876,10 +845,8 @@ trait Namers extends MethodSynthesis {
Namers.this.classOfModuleClass get clazz foreach { cdefRef =>
val cdef = cdefRef()
if (cdef.mods.isCase) addApplyUnapply(cdef, templateNamer)
- if (settings.Xmacros.value) addMacroMethods(cdef.impl, templateNamer)
classOfModuleClass -= clazz
}
- if (settings.Xmacros.value) addMacroMethods(templ, templateNamer)
}
// add the copy method to case classes; this needs to be done here, not in SyntheticMethods, because
@@ -1034,12 +1001,20 @@ trait Namers extends MethodSynthesis {
}
addDefaultGetters(meth, vparamss, tparams, overriddenSymbol)
+ // macro defs need to be typechecked in advance
+ // because @macroImpl annotation only gets assigned during typechecking
+ // otherwise we might find ourselves in the situation when we specified -Xmacro-fallback-classpath
+ // but macros still don't expand
+ // that might happen because macro def doesn't have its link a macro impl yet
+ if (ddef.symbol.isTermMacro) {
+ val pt = resultPt.substSym(tparamSyms, tparams map (_.symbol))
+ typer.computeMacroDefType(ddef, pt)
+ }
+
thisMethodType({
val rt = (
if (!tpt.isEmpty) {
typer.typedType(tpt).tpe
- } else if (meth.isMacro) {
- assignTypeToTree(ddef, AnyClass.tpe)
} else {
// replace deSkolemized symbols with skolemized ones
// (for resultPt computed by looking at overridden symbol, right?)
@@ -1048,7 +1023,7 @@ trait Namers extends MethodSynthesis {
}
)
// #2382: return type of default getters are always @uncheckedVariance
- if (meth.hasDefaultFlag)
+ if (meth.hasDefault)
rt.withAnnotation(AnnotationInfo(uncheckedVarianceClass.tpe, List(), List()))
else rt
})
@@ -1098,8 +1073,8 @@ trait Namers extends MethodSynthesis {
for (vparam <- vparams) {
val sym = vparam.symbol
// true if the corresponding parameter of the base class has a default argument
- val baseHasDefault = overrides && baseParams.head.hasDefaultFlag
- if (sym.hasDefaultFlag) {
+ val baseHasDefault = overrides && baseParams.head.hasDefault
+ if (sym.hasDefault) {
// generate a default getter for that argument
val oflag = if (baseHasDefault) OVERRIDE else 0
val name = nme.defaultGetterName(meth.name, posCounter)
@@ -1166,7 +1141,7 @@ trait Namers extends MethodSynthesis {
// if compiling the same local block several times (which can happen in interactive mode)
// we might otherwise not find the default symbol, because the second time it the
// method symbol will be re-entered in the scope but the default parameter will not.
- defaultParametersOfMethod(meth) += default
+ defaultParametersOfMethod(meth) += new WeakReference(default)
}
} else if (baseHasDefault) {
// the parameter does not have a default itself, but the
@@ -1365,7 +1340,7 @@ trait Namers extends MethodSynthesis {
}
}
private val logDefinition = new LogTransitions[Symbol](
- sym => "[define] >> " + sym.defaultFlagString + " " + sym.fullLocationString,
+ sym => "[define] >> " + sym.flagString + " " + sym.fullLocationString,
sym => "[define] << " + sym
)
private def logAndValidate(sym: Symbol)(body: => Unit) {
@@ -1376,6 +1351,11 @@ trait Namers extends MethodSynthesis {
/** Convert Java generic array type T[] to (T with Object)[]
* (this is necessary because such arrays have a representation which is incompatible
* with arrays of primitive types.)
+ *
+ * @note the comparison to Object only works for abstract types bounded by classes that are strict subclasses of Object
+ * if the bound is exactly Object, it will have been converted to Any, and the comparison will fail
+ *
+ * see also sigToType
*/
private object RestrictJavaArraysMap extends TypeMap {
def apply(tp: Type): Type = tp match {
@@ -1409,10 +1389,10 @@ trait Namers extends MethodSynthesis {
if (sym.isImplicit) {
if (sym.isConstructor)
fail(ImplicitConstr)
- if (!sym.isTerm)
- fail(ImplicitNotTerm)
+ if (!(sym.isTerm || (sym.isClass && !sym.isTrait)))
+ fail(ImplicitNotTermOrClass)
if (sym.owner.isPackageClass)
- fail(ImplicitTopObject)
+ fail(ImplicitAtToplevel)
}
if (sym.isClass) {
if (sym.isAnyOverride && !sym.hasFlag(TRAIT))
@@ -1555,13 +1535,13 @@ trait Namers extends MethodSynthesis {
* call this method?
*/
def companionSymbolOf(original: Symbol, ctx: Context): Symbol = {
- try original.companionSymbol match {
- case NoSymbol =>
+ try {
+ original.companionSymbol orElse {
ctx.lookup(original.name.companionName, original.owner).suchThat(sym =>
(original.isTerm || sym.hasModuleFlag) &&
(sym isCoDefinedWith original)
)
- case sym => sym
+ }
}
catch {
case e: InvalidCompanions =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
index c621497618..bef6f13bc3 100644
--- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala
@@ -8,6 +8,7 @@ package typechecker
import symtab.Flags._
import scala.collection.mutable
+import scala.ref.WeakReference
/**
* @author Lukas Rytz
@@ -20,7 +21,7 @@ trait NamesDefaults { self: Analyzer =>
import NamesDefaultsErrorsGen._
val defaultParametersOfMethod =
- perRunCaches.newWeakMap[Symbol, Set[Symbol]]() withDefaultValue Set()
+ perRunCaches.newWeakMap[Symbol, Set[WeakReference[Symbol]]]() withDefaultValue Set()
case class NamedApplyInfo(
qual: Option[Tree],
@@ -38,16 +39,16 @@ trait NamesDefaults { self: Analyzer =>
def isNamed(arg: Tree) = nameOf(arg).isDefined
/** @param pos maps indices from old to new */
- def reorderArgs[T: ClassManifest](args: List[T], pos: Int => Int): List[T] = {
+ def reorderArgs[T: ArrayTag](args: List[T], pos: Int => Int): List[T] = {
val res = new Array[T](args.length)
foreachWithIndex(args)((arg, index) => res(pos(index)) = arg)
res.toList
}
/** @param pos maps indices from new to old (!) */
- def reorderArgsInv[T: ClassManifest](args: List[T], pos: Int => Int): List[T] = {
+ def reorderArgsInv[T: ArrayTag](args: List[T], pos: Int => Int): List[T] = {
val argsArray = args.toArray
- argsArray.indices map (i => argsArray(pos(i))) toList
+ (argsArray.indices map (i => argsArray(pos(i)))).toList
}
/** returns `true` if every element is equal to its index */
@@ -154,6 +155,8 @@ trait NamesDefaults { self: Analyzer =>
val sym = blockTyper.context.owner.newValue(unit.freshTermName("qual$"), qual.pos) setInfo qual.tpe
blockTyper.context.scope enter sym
val vd = atPos(sym.pos)(ValDef(sym, qual) setType NoType)
+ // it stays in Vegas: SI-5720, SI-5727
+ qual changeOwner (blockTyper.context.owner -> sym)
var baseFunTransformed = atPos(baseFun.pos.makeTransparent) {
// don't use treeCopy: it would assign opaque position.
@@ -335,7 +338,7 @@ trait NamesDefaults { self: Analyzer =>
// cannot call blockTyper.typedBlock here, because the method expr might be partially applied only
val res = blockTyper.doTypedApply(tree, expr, refArgs, mode, pt)
res.setPos(res.pos.makeTransparent)
- val block = Block(stats ::: valDefs, res).setType(res.tpe).setPos(tree.pos)
+ val block = Block(stats ::: valDefs, res).setType(res.tpe).setPos(tree.pos.makeTransparent)
context.namedApplyBlockInfo =
Some((block, NamedApplyInfo(qual, targs, vargss :+ refArgs, blockTyper)))
block
@@ -377,7 +380,7 @@ trait NamesDefaults { self: Analyzer =>
pos: util.Position, context: Context): (List[Tree], List[Symbol]) = {
if (givenArgs.length < params.length) {
val (missing, positional) = missingParams(givenArgs, params)
- if (missing forall (_.hasDefaultFlag)) {
+ if (missing forall (_.hasDefault)) {
val defaultArgs = missing flatMap (p => {
val defGetter = defaultGetter(p, context)
// TODO #3649 can create spurious errors when companion object is gone (because it becomes unlinked from scope)
@@ -399,7 +402,7 @@ trait NamesDefaults { self: Analyzer =>
}
})
(givenArgs ::: defaultArgs, Nil)
- } else (givenArgs, missing filterNot (_.hasDefaultFlag))
+ } else (givenArgs, missing filterNot (_.hasDefault))
} else (givenArgs, Nil)
}
@@ -443,21 +446,12 @@ trait NamesDefaults { self: Analyzer =>
}
}
- /** Fast path for ambiguous assignment check.
- */
- private def isNameInScope(context: Context, name: Name) = (
- context.enclosingContextChain exists (ctx =>
- (ctx.scope.lookupEntry(name) != null)
- || (ctx.owner.rawInfo.member(name) != NoSymbol)
- )
- )
-
/** A full type check is very expensive; let's make sure there's a name
* somewhere which could potentially be ambiguous before we go that route.
*/
private def isAmbiguousAssignment(typer: Typer, param: Symbol, arg: Tree) = {
import typer.context
- isNameInScope(context, param.name) && {
+ (context isNameInScope param.name) && {
// for named arguments, check whether the assignment expression would
// typecheck. if it does, report an ambiguous error.
val paramtpe = param.tpe.cloneInfo(param)
diff --git a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
index aff8368f75..61e02edaff 100644
--- a/src/compiler/scala/tools/nsc/typechecker/PatMatVirtualiser.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/PatternMatching.scala
@@ -1,5 +1,6 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
+ *
+ * Copyright 2012 LAMP/EPFL
* @author Adriaan Moors
*/
@@ -8,32 +9,76 @@ package typechecker
import symtab._
import Flags.{MUTABLE, METHOD, LABEL, SYNTHETIC}
+import language.postfixOps
+import scala.tools.nsc.transform.TypingTransformers
+import scala.tools.nsc.transform.Transform
-/** Translate pattern matching into method calls (these methods form a zero-plus monad), similar in spirit to how for-comprehensions are compiled.
+/** Translate pattern matching.
+ *
+ * Either into optimized if/then/else's,
+ * or virtualized as method calls (these methods form a zero-plus monad), similar in spirit to how for-comprehensions are compiled.
*
* For each case, express all patterns as extractor calls, guards as 0-ary extractors, and sequence them using `flatMap`
* (lifting the body of the case into the monad using `one`).
*
* Cases are combined into a pattern match using the `orElse` combinator (the implicit failure case is expressed using the monad's `zero`).
-
+ *
* TODO:
- * - interaction with CPS
+ * - exhaustivity
+ * - DCE (unreachability/refutability/optimization)
+ * - use TypeTags for type testing
* - Array patterns
* - implement spec more closely (see TODO's)
- * - DCE
- * - use manifests for type testing
*
* (longer-term) TODO:
* - user-defined unapplyProd
* - recover GADT typing by locally inserting implicit witnesses to type equalities derived from the current case, and considering these witnesses during subtyping (?)
* - recover exhaustivity and unreachability checking using a variation on the type-safe builder pattern
*/
-trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
- import global._
+trait PatternMatching extends Transform with TypingTransformers with ast.TreeDSL { // self: Analyzer =>
+ val global: Global // need to repeat here because otherwise last mixin defines global as
+ // SymbolTable. If we had DOT this would not be an issue
+ import global._ // the global environment
+ import definitions._ // standard classes and methods
+
+ val phaseName: String = "patmat"
+
+ def newTransformer(unit: CompilationUnit): Transformer =
+ if (opt.virtPatmat) new MatchTransformer(unit)
+ else noopTransformer
+
+ // duplicated from CPSUtils (avoid dependency from compiler -> cps plugin...)
+ private lazy val MarkerCPSAdaptPlus = definitions.getClassIfDefined("scala.util.continuations.cpsPlus")
+ private lazy val MarkerCPSAdaptMinus = definitions.getClassIfDefined("scala.util.continuations.cpsMinus")
+ private lazy val MarkerCPSSynth = definitions.getClassIfDefined("scala.util.continuations.cpsSynth")
+ private lazy val stripTriggerCPSAnns = List(MarkerCPSSynth, MarkerCPSAdaptMinus, MarkerCPSAdaptPlus)
+ private lazy val MarkerCPSTypes = definitions.getClassIfDefined("scala.util.continuations.cpsParam")
+ private lazy val strippedCPSAnns = MarkerCPSTypes :: stripTriggerCPSAnns
+ private def removeCPSAdaptAnnotations(tp: Type) = tp filterAnnotations (ann => !(strippedCPSAnns exists (ann matches _)))
+
+ class MatchTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
+ override def transform(tree: Tree): Tree = tree match {
+ case Match(sel, cases) =>
+ val origTp = tree.tpe
+ // setType origTp intended for CPS -- TODO: is it necessary?
+ localTyper.typed(translator.translateMatch(treeCopy.Match(tree, transform(sel), transformTrees(cases).asInstanceOf[List[CaseDef]]))) setType origTp
+ case Try(block, catches, finalizer) =>
+ treeCopy.Try(tree, transform(block), translator.translateTry(transformTrees(catches).asInstanceOf[List[CaseDef]], tree.tpe, tree.pos), transform(finalizer))
+ case _ => super.transform(tree)
+ }
+
+ def translator: MatchTranslation with CodegenCore = {
+ new OptimizingMatchTranslator(localTyper)
+ }
+ }
+
import definitions._
+ import analyzer._ //Typer
val SYNTH_CASE = Flags.CASE | SYNTHETIC
+ case class DefaultOverrideMatchAttachment(default: Tree)
+
object vpmName {
val one = newTermName("one")
val drop = newTermName("drop")
@@ -45,22 +90,11 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
val outer = newTermName("<outer>")
val runOrElse = newTermName("runOrElse")
val zero = newTermName("zero")
- val _match = newTermName("__match") // don't call it __match, since that will trigger virtual pattern matching...
+ val _match = newTermName("__match") // don't call the val __match, since that will trigger virtual pattern matching...
def counted(str: String, i: Int) = newTermName(str+i)
}
- object MatchTranslator {
- def apply(typer: Typer): MatchTranslation with CodegenCore = {
- import typer._
- // typing `_match` to decide which MatchTranslator to create adds 4% to quick.comp.timer
- newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) match {
- case SilentResultValue(ms) => new PureMatchTranslator(typer, ms)
- case _ => new OptimizingMatchTranslator(typer)
- }
- }
- }
-
class PureMatchTranslator(val typer: Typer, val matchStrategy: Tree) extends MatchTranslation with TreeMakers with PureCodegen
class OptimizingMatchTranslator(val typer: Typer) extends MatchTranslation with TreeMakers with MatchOptimizations
@@ -118,6 +152,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
trait MatchTranslation extends MatchMonadInterface { self: TreeMakers with CodegenCore =>
import typer.{typed, context, silent, reallyExists}
+ // import typer.infer.containsUnchecked
/** Implement a pattern match by turning its cases (including the implicit failure case)
* into the corresponding (monadic) extractors, and combining them with the `orElse` combinator.
@@ -129,15 +164,44 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
* thus, you must typecheck the result (and that will in turn translate nested matches)
* this could probably optimized... (but note that the matchStrategy must be solved for each nested patternmatch)
*/
- def translateMatch(scrut: Tree, cases: List[CaseDef], pt: Type, scrutType: Type, matchFailGenOverride: Option[Tree => Tree] = None): Tree = {
- // we don't transform after typers
- // (that would require much more sophistication when generating trees,
+ def translateMatch(match_ : Match): Tree = {
+ val Match(selector, cases) = match_
+
+ // we don't transform after uncurry
+ // (that would require more sophistication when generating trees,
// and the only place that emits Matches after typers is for exception handling anyway)
- assert(phase.id <= currentRun.typerPhase.id, phase)
+ if(phase.id >= currentRun.uncurryPhase.id) debugwarn("running translateMatch at "+ phase +" on "+ selector +" match "+ cases)
+ // println("translating "+ cases.mkString("{", "\n", "}"))
+
+ def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match {
+ case TypeRef(_, RepeatedParamClass, arg :: Nil) => seqType(arg)
+ case _ => tp
+ }
+
+ val selectorTp = repeatedToSeq(elimAnonymousClass(selector.tpe.widen.withoutAnnotations))
+
+ val origPt = match_.tpe
+ // when one of the internal cps-type-state annotations is present, strip all CPS annotations
+ // a cps-type-state-annotated type makes no sense as an expected type (matchX.tpe is used as pt in translateMatch)
+ // (only test availability of MarkerCPSAdaptPlus assuming they are either all available or none of them are)
+ val ptUnCPS =
+ if (MarkerCPSAdaptPlus != NoSymbol && (stripTriggerCPSAnns exists origPt.hasAnnotation))
+ removeCPSAdaptAnnotations(origPt)
+ else origPt
+
+ // we've packed the type for each case in typedMatch so that if all cases have the same existential case, we get a clean lub
+ // here, we should open up the existential again
+ // relevant test cases: pos/existentials-harmful.scala, pos/gadt-gilles.scala, pos/t2683.scala, pos/virtpatmat_exist4.scala
+ // TODO: fix skolemizeExistential (it should preserve annotations, right?)
+ val pt = repeatedToSeq(ptUnCPS.skolemizeExistential(context.owner, context.tree) withAnnotations ptUnCPS.annotations)
- val scrutSym = freshSym(scrut.pos, pureType(scrutType)) setFlag SYNTH_CASE
+ // the alternative to attaching the default case override would be to simply
+ // append the default to the list of cases and suppress the unreachable case error that may arise (once we detect that...)
+ val matchFailGenOverride = match_ firstAttachment {case DefaultOverrideMatchAttachment(default) => ((scrut: Tree) => default)}
+
+ val selectorSym = freshSym(selector.pos, pureType(selectorTp)) setFlag SYNTH_CASE
// pt = Any* occurs when compiling test/files/pos/annotDepMethType.scala with -Xexperimental
- combineCases(scrut, scrutSym, cases map translateCase(scrutSym, pt), pt, matchOwner, matchFailGenOverride)
+ combineCases(selector, selectorSym, cases map translateCase(selectorSym, pt), pt, matchOwner, matchFailGenOverride)
}
// return list of typed CaseDefs that are supported by the backend (typed/bind/wildcard)
@@ -157,12 +221,12 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
(caseScrutSym, propagateSubstitution(translateCase(caseScrutSym, pt)(caseDef), EmptySubstitution))
}
- for(cases <- emitTypeSwitch(bindersAndCases, pt) toList;
+ for(cases <- emitTypeSwitch(bindersAndCases, pt).toList;
if cases forall treeInfo.isCatchCase; // must check again, since it's not guaranteed -- TODO: can we eliminate this? e.g., a type test could test for a trait or a non-trivial prefix, which are not handled by the back-end
cse <- cases) yield fixerUpper(matchOwner, pos)(cse).asInstanceOf[CaseDef]
}
- val catches = if (swatches nonEmpty) swatches else {
+ val catches = if (swatches.nonEmpty) swatches else {
val scrutSym = freshSym(pos, pureType(ThrowableClass.tpe))
val casesNoSubstOnly = caseDefs map { caseDef => (propagateSubstitution(translateCase(scrutSym, pt)(caseDef), EmptySubstitution))}
@@ -224,7 +288,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
val pos = patTree.pos
def translateExtractorPattern(extractor: ExtractorCall): TranslationStep = {
- if (!extractor.isTyped) throw new TypeError(pos, "Could not typecheck extractor call: "+ extractor)
+ if (!extractor.isTyped) ErrorUtils.issueNormalTypeError(patTree, "Could not typecheck extractor call: "+ extractor)(context)
// if (extractor.resultInMonad == ErrorType) throw new TypeError(pos, "Unsupported extractor type: "+ extractor.tpe)
// must use type `tp`, which is provided by extractor's result, not the type expected by binder,
@@ -258,10 +322,11 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
* @arg patBinder symbol used to refer to the result of the previous pattern's extractor (will later be replaced by the outer tree with the correct tree to refer to that patterns result)
*/
def unapply(tree: Tree): Option[(Symbol, Type)] = tree match {
- case Bound(subpatBinder, typed@Typed(expr, tpt)) if typed.tpe ne null => Some((subpatBinder, typed.tpe))
- case Bind(_, typed@Typed(expr, tpt)) if typed.tpe ne null => Some((patBinder, typed.tpe))
- case Typed(expr, tpt) if tree.tpe ne null => Some((patBinder, tree.tpe))
- case _ => None
+ // the Ident subpattern can be ignored, subpatBinder or patBinder tell us all we need to know about it
+ case Bound(subpatBinder, typed@Typed(Ident(_), tpt)) if typed.tpe ne null => Some((subpatBinder, typed.tpe))
+ case Bind(_, typed@Typed(Ident(_), tpt)) if typed.tpe ne null => Some((patBinder, typed.tpe))
+ case Typed(Ident(_), tpt) if tree.tpe ne null => Some((patBinder, tree.tpe))
+ case _ => None
}
}
@@ -288,7 +353,7 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
**/
case Apply(fun, args) =>
ExtractorCall.fromCaseClass(fun, args) map translateExtractorPattern getOrElse {
- error("cannot find unapply member for "+ fun +" with args "+ args)
+ ErrorUtils.issueNormalTypeError(patTree, "Could not find unapply member for "+ fun +" with args "+ args)(context)
noFurtherSubPats()
}
@@ -544,18 +609,29 @@ trait PatMatVirtualiser extends ast.TreeDSL { self: Analyzer =>
ProductExtractorTreeMaker(binder, lengthGuard(binder), Substitution(subPatBinders, subPatRefs(binder)))
}
-/* TODO: remove special case when the following bug is fixed
-class Foo(x: Other) { x._1 } // BUG: can't refer to _1 if its defining class has not been type checked yet
-case class Other(y: String)
--- this is ok:
-case class Other(y: String)
-class Foo(x: Other) { x._1 } // no error in this order
-*/
+ // reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component
override protected def tupleSel(binder: Symbol)(i: Int): Tree = { import CODE._
- // reference the (i-1)th case accessor if it exists, otherwise the (i-1)th tuple component
- val caseAccs = binder.info.typeSymbol.caseFieldAccessors
- if (caseAccs isDefinedAt (i-1)) REF(binder) DOT caseAccs(i-1)
- else codegen.tupleSel(binder)(i)
+ // caseFieldAccessors is messed up after typers (reversed, names mangled for non-public fields)
+ // TODO: figure out why...
+ val accessors = binder.caseFieldAccessors
+ // luckily, the constrParamAccessors are still sorted properly, so sort the field-accessors using them
+ // (need to undo name-mangling, including the sneaky trailing whitespace)
+ val constrParamAccessors = binder.constrParamAccessors
+
+ def indexInCPA(acc: Symbol) =
+ constrParamAccessors indexWhere { orig =>
+ // println("compare: "+ (orig, acc, orig.name, acc.name, (acc.name == orig.name), (acc.name startsWith (orig.name append "$"))))
+ val origName = orig.name.toString.trim
+ val accName = acc.name.toString.trim
+ (accName == origName) || (accName startsWith (origName + "$"))
+ }
+
+ // println("caseFieldAccessors: "+ (accessors, binder.caseFieldAccessors map indexInCPA))
+ // println("constrParamAccessors: "+ constrParamAccessors)
+
+ val accessorsSorted = accessors sortBy indexInCPA
+ if (accessorsSorted isDefinedAt (i-1)) REF(binder) DOT accessorsSorted(i-1)
+ else codegen.tupleSel(binder)(i) // this won't type check for case classes, as they do not inherit ProductN
}
override def toString(): String = "case class "+ (if (constructorTp eq null) fun else paramType.typeSymbol) +" with arguments "+ args
@@ -819,13 +895,35 @@ class Foo(x: Other) { x._1 } // no error in this order
cond
}
- // TODO: also need to test when erasing pt loses crucial information (and if we can recover it using a manifest)
- def needsTypeTest(tp: Type, pt: Type) = !(tp <:< pt)
- private def typeTest(binder: Symbol, pt: Type) = maybeWithOuterCheck(binder, pt)(codegen._isInstanceOf(binder, pt))
+ // containsUnchecked: also need to test when erasing pt loses crucial information (maybe we can recover it using a TypeTag)
+ def needsTypeTest(tp: Type, pt: Type): Boolean = !(tp <:< pt) // || containsUnchecked(pt)
+ // TODO: try to find the TypeTag for the binder's type and the expected type, and if they exists,
+ // check that the TypeTag of the binder's type conforms to the TypeTag of the expected type
+ private def typeTest(binderToTest: Symbol, expectedTp: Type, disableOuterCheck: Boolean = false, dynamic: Boolean = false): Tree = { import CODE._
+ // def coreTest =
+ if (disableOuterCheck) codegen._isInstanceOf(binderToTest, expectedTp) else maybeWithOuterCheck(binderToTest, expectedTp)(codegen._isInstanceOf(binderToTest, expectedTp))
+ // [Eugene to Adriaan] use `resolveErasureTag` instead of `findManifest`. please, provide a meaningful position
+ // if (opt.experimental && containsUnchecked(expectedTp)) {
+ // if (dynamic) {
+ // val expectedTpTagTree = findManifest(expectedTp, true)
+ // if (!expectedTpTagTree.isEmpty)
+ // ((expectedTpTagTree DOT "erasure".toTermName) DOT "isAssignableFrom".toTermName)(REF(binderToTest) DOT nme.getClass_)
+ // else
+ // coreTest
+ // } else {
+ // val expectedTpTagTree = findManifest(expectedTp, true)
+ // val binderTpTagTree = findManifest(binderToTest.info, true)
+ // if(!(expectedTpTagTree.isEmpty || binderTpTagTree.isEmpty))
+ // coreTest AND (binderTpTagTree DOT nme.CONFORMS)(expectedTpTagTree)
+ // else
+ // coreTest
+ // }
+ // } else coreTest
+ }
// need to substitute since binder may be used outside of the next extractor call (say, in the body of the case)
case class TypeTestTreeMaker(prevBinder: Symbol, nextBinderTp: Type, pos: Position) extends CondTreeMaker {
- val cond = typeTest(prevBinder, nextBinderTp)
+ val cond = typeTest(prevBinder, nextBinderTp, dynamic = true)
val res = codegen._asInstanceOf(prevBinder, nextBinderTp)
override def toString = "TT"+(prevBinder, nextBinderTp)
}
@@ -833,7 +931,7 @@ class Foo(x: Other) { x._1 } // no error in this order
// implements the run-time aspects of (§8.2) (typedPattern has already done the necessary type transformations)
// TODO: normalize construction, which yields a combination of a EqualityTestTreeMaker (when necessary) and a TypeTestTreeMaker
case class TypeAndEqualityTestTreeMaker(prevBinder: Symbol, patBinder: Symbol, pt: Type, pos: Position) extends CondTreeMaker {
- val nextBinderTp = glb(List(patBinder.info.widen, pt))
+ val nextBinderTp = glb(List(patBinder.info.widen, pt)).normalize
/** Type patterns consist of types, type variables, and wildcards. A type pattern T is of one of the following forms:
- A reference to a class C, p.C, or T#C.
@@ -865,7 +963,7 @@ class Foo(x: Other) { x._1 } // no error in this order
// TODO: `null match { x : T }` will yield a check that (indirectly) tests whether `null ne null`
// don't bother (so that we don't end up with the warning "comparing values of types Null and Null using `ne' will always yield false")
def genEqualsAndInstanceOf(sym: Symbol): Tree
- = codegen._equals(REF(sym), patBinder) AND codegen._isInstanceOf(patBinder, pt.widen)
+ = codegen._equals(REF(sym), patBinder) AND typeTest(patBinder, pt.widen, disableOuterCheck = true)
def isRefTp(tp: Type) = tp <:< AnyRefClass.tpe
@@ -873,7 +971,7 @@ class Foo(x: Other) { x._1 } // no error in this order
def isMatchUnlessNull = isRefTp(pt) && !needsTypeTest(patBinderTp, pt)
// TODO: [SPEC] type test for Array
- // TODO: use manifests to improve tests (for erased types we can do better when we have a manifest)
+ // TODO: use TypeTags to improve tests (for erased types we can do better when we have a TypeTag)
pt match {
case SingleType(_, sym) /*this implies sym.isStable*/ => genEqualsAndInstanceOf(sym) // TODO: [SPEC] the spec requires `eq` instead of `==` here
case ThisType(sym) if sym.isModule => genEqualsAndInstanceOf(sym) // must use == to support e.g. List() == Nil
@@ -962,6 +1060,7 @@ class Foo(x: Other) { x._1 } // no error in this order
fixerUpper(owner, scrut.pos){
val ptDefined = if (isFullyDefined(pt)) pt else NoType
def matchFailGen = (matchFailGenOverride orElse Some(CODE.MATCHERROR(_: Tree)))
+ // println("combining cases: "+ (casesNoSubstOnly.map(_.mkString(" >> ")).mkString("{", "\n", "}")))
emitSwitch(scrut, scrutSym, casesNoSubstOnly, pt, matchFailGenOverride).getOrElse{
if (casesNoSubstOnly nonEmpty) {
@@ -1041,7 +1140,7 @@ class Foo(x: Other) { x._1 } // no error in this order
// assert(owner ne null); assert(owner ne NoSymbol)
def freshSym(pos: Position, tp: Type = NoType, prefix: String = "x") =
- NoSymbol.newTermSymbol(freshName(prefix), pos) setInfo /*repackExistential*/(tp)
+ NoSymbol.newTermSymbol(freshName(prefix), pos) setInfo tp
// codegen relevant to the structure of the translation (how extractors are combined)
trait AbsCodegen {
@@ -1082,22 +1181,16 @@ class Foo(x: Other) { x._1 } // no error in this order
def _equals(checker: Tree, binder: Symbol): Tree = checker MEMBER_== REF(binder) // NOTE: checker must be the target of the ==, that's the patmat semantics for ya
def and(a: Tree, b: Tree): Tree = a AND b
- // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly)
- def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree = { val tpX = /*repackExistential*/(tp)
- if (!force && (t.tpe ne NoType) && t.isTyped && typesConform(t.tpe, tpX)) t //{ println("warning: emitted redundant asInstanceOf: "+(t, t.tpe, tp)); t } //.setType(tpX)
- else gen.mkAsInstanceOf(t, tpX, true, false)
- }
+ // drop annotations generated by CPS plugin etc, since its annotationchecker rejects T @cps[U] <: Any
+ // let's assume for now annotations don't affect casts, drop them there, and bring them back using the outer Typed tree
+ private def mkCast(t: Tree, tp: Type) =
+ Typed(gen.mkAsInstanceOf(t, tp.withoutAnnotations, true, false), TypeTree() setType tp)
- def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), /*repackExistential*/(tp), true, false)
- // { val tpX = /*repackExistential*/(tp)
+ // the force is needed mainly to deal with the GADT typing hack (we can't detect it otherwise as tp nor pt need contain an abstract type, we're just casting wildly)
+ def _asInstanceOf(t: Tree, tp: Type, force: Boolean = false): Tree = if (!force && (t.tpe ne NoType) && t.isTyped && typesConform(t.tpe, tp)) t else mkCast(t, tp)
+ def _asInstanceOf(b: Symbol, tp: Type): Tree = if (typesConform(b.info, tp)) REF(b) else mkCast(REF(b), tp)
+ def _isInstanceOf(b: Symbol, tp: Type): Tree = gen.mkIsInstanceOf(REF(b), tp.withoutAnnotations, true, false)
// if (typesConform(b.info, tpX)) { println("warning: emitted spurious isInstanceOf: "+(b, tp)); TRUE }
- // else gen.mkIsInstanceOf(REF(b), tpX, true, false)
- // }
-
- def _asInstanceOf(b: Symbol, tp: Type): Tree = { val tpX = /*repackExistential*/(tp)
- if (typesConform(b.info, tpX)) REF(b) //{ println("warning: emitted redundant asInstanceOf: "+(b, b.info, tp)); REF(b) } //.setType(tpX)
- else gen.mkAsInstanceOf(REF(b), tpX, true, false)
- }
// duplicated out of frustration with cast generation
def mkZero(tp: Type): Tree = {
@@ -1121,7 +1214,7 @@ class Foo(x: Other) { x._1 } // no error in this order
val matchStrategy: Tree
def inMatchMonad(tp: Type): Type = appliedType(oneSig, List(tp)).finalResultType
- def pureType(tp: Type): Type = appliedType(oneSig, List(tp)).paramTypes.head
+ def pureType(tp: Type): Type = appliedType(oneSig, List(tp)).paramTypes.headOption getOrElse NoType // fail gracefully (otherwise we get crashes)
protected def matchMonadSym = oneSig.finalResultType.typeSymbol
import CODE._
@@ -1553,7 +1646,7 @@ class Foo(x: Other) { x._1 } // no error in this order
// TODO: if patterns allow switch but the type of the scrutinee doesn't, cast (type-test) the scrutinee to the corresponding switchable type and switch on the result
if (regularSwitchMaker.switchableTpe(scrutSym.tpe)) {
val caseDefsWithDefault = regularSwitchMaker(cases map {c => (scrutSym, c)}, pt)
- if (caseDefsWithDefault isEmpty) None
+ if (caseDefsWithDefault.length <= 2) None // not worth emitting a switch... also, the optimizer has trouble digesting tiny switches, apparently, so let's be nice and not generate them
else {
// match on scrutSym -- converted to an int if necessary -- not on scrut directly (to avoid duplicating scrut)
val scrutToInt: Tree =
@@ -1561,7 +1654,7 @@ class Foo(x: Other) { x._1 } // no error in this order
else (REF(scrutSym) DOT (nme.toInt))
Some(BLOCK(
VAL(scrutSym) === scrut,
- Match(gen.mkSynthSwitchSelector(scrutToInt), caseDefsWithDefault) // add switch annotation
+ Match(scrutToInt, caseDefsWithDefault) // a switch
))
}
} else None
@@ -1635,7 +1728,7 @@ class Foo(x: Other) { x._1 } // no error in this order
*/
def matcher(scrut: Tree, scrutSym: Symbol, restpe: Type)(cases: List[Casegen => Tree], matchFailGen: Option[Tree => Tree]): Tree = {
val matchEnd = NoSymbol.newLabel(freshName("matchEnd"), NoPosition) setFlag SYNTH_CASE
- val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe
+ val matchRes = NoSymbol.newValueParameter(newTermName("x"), NoPosition, SYNTHETIC) setInfo restpe.withoutAnnotations //
matchEnd setInfo MethodType(List(matchRes), restpe)
def newCaseSym = NoSymbol.newLabel(freshName("case"), NoPosition) setInfo MethodType(Nil, restpe) setFlag SYNTH_CASE
@@ -1649,7 +1742,11 @@ class Foo(x: Other) { x._1 } // no error in this order
def catchAll = matchFailGen map { matchFailGen =>
val scrutRef = if(scrutSym ne NoSymbol) REF(scrutSym) else EmptyTree // for alternatives
- LabelDef(nextCase, Nil, matchEnd APPLY (_asInstanceOf(matchFailGen(scrutRef), restpe))) // need to jump to matchEnd with result generated by matchFailGen (could be `FALSE` for isDefinedAt)
+ // must jump to matchEnd, use result generated by matchFailGen (could be `FALSE` for isDefinedAt)
+ LabelDef(nextCase, Nil, matchEnd APPLY (matchFailGen(scrutRef)))
+ // don't cast the arg to matchEnd when using PartialFun synth in uncurry, since it won't detect the throw (see gen.withDefaultCase)
+ // the cast is necessary when using typedMatchAnonFun-style PartialFun synth:
+ // (_asInstanceOf(matchFailGen(scrutRef), restpe))
} toList
// catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default)
// if the last user-defined case is a default, it will never jump to the next case; it will go immediately to matchEnd
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 54b711cebc..e60cda6af7 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -10,6 +10,7 @@ import symtab.Flags._
import collection.{ mutable, immutable }
import transform.InfoTransform
import scala.collection.mutable.ListBuffer
+import language.postfixOps
/** <p>
* Post-attribution checking and transformation.
@@ -123,7 +124,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
defaultMethodNames.distinct foreach { name =>
val methods = clazz.info.findMember(name, 0L, METHOD, false).alternatives
- val haveDefaults = methods filter (sym => sym.hasParamWhich(_.hasDefaultFlag) && !nme.isProtectedAccessorName(sym.name))
+ val haveDefaults = methods filter (sym => sym.hasParamWhich(_.hasDefault) && !nme.isProtectedAccessorName(sym.name))
if (haveDefaults.lengthCompare(1) > 0) {
val owners = haveDefaults map (_.owner)
@@ -227,6 +228,8 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
* 1.8.1 M's type is a subtype of O's type, or
* 1.8.2 M is of type []S, O is of type ()T and S <: T, or
* 1.8.3 M is of type ()S, O is of type []T and S <: T, or
+ * 1.9. If M is a macro def, O cannot be deferred.
+ * 1.10. If M is not a macro def, O cannot be a macro def.
* 2. Check that only abstract classes have deferred members
* 3. Check that concrete classes do not have deferred definitions
* that are not implemented in a subclass.
@@ -356,7 +359,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
/** Is the intersection between given two lists of overridden symbols empty?
*/
def intersectionIsEmpty(syms1: List[Symbol], syms2: List[Symbol]) =
- !(syms1 exists (syms2 contains))
+ !(syms1 exists (syms2 contains _))
if (typesOnly) checkOverrideTypes()
else {
@@ -381,7 +384,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
overrideError("cannot be used here - class definitions cannot be overridden");
} else if (!other.isDeferred && member.isClass) {
overrideError("cannot be used here - classes can only override abstract types");
- } else if (other.isFinal) { // (1.2)
+ } else if (other.isEffectivelyFinal) { // (1.2)
overrideError("cannot override final member");
// synthetic exclusion needed for (at least) default getters.
} else if (!other.isDeferred && !member.isAnyOverride && !member.isSynthetic) {
@@ -416,6 +419,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
} else if (other.isValue && other.isLazy && !other.isSourceMethod && !other.isDeferred &&
member.isValue && !member.isLazy) {
overrideError("must be declared lazy to override a concrete lazy value")
+ } else if (other.isDeferred && member.isTermMacro) { // (1.9)
+ overrideError("cannot override an abstract method")
+ } else if (other.isTermMacro && !member.isTermMacro) { // (1.10)
+ overrideError("cannot override a macro")
} else {
checkOverrideTypes()
if (settings.warnNullaryOverride.value) {
@@ -662,7 +669,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
}
// Check the remainder for invalid absoverride.
- for (member <- rest ; if ((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz))) {
+ for (member <- rest ; if (member.isAbstractOverride && member.isIncompleteIn(clazz))) {
val other = member.superSymbol(clazz)
val explanation =
if (other != NoSymbol) " and overrides incomplete superclass member " + infoString(other)
@@ -756,11 +763,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
// 4. Check that every defined member with an `override` modifier overrides some other member.
for (member <- clazz.info.decls)
- if ((member hasFlag (OVERRIDE | ABSOVERRIDE)) &&
- !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) {
+ if (member.isAnyOverride && !(clazz.thisType.baseClasses exists (hasMatchingSym(_, member)))) {
// for (bc <- clazz.info.baseClasses.tail) Console.println("" + bc + " has " + bc.info.decl(member.name) + ":" + bc.info.decl(member.name).tpe);//DEBUG
unit.error(member.pos, member.toString() + " overrides nothing");
- member resetFlag OVERRIDE
+ member resetFlag (OVERRIDE | ABSOVERRIDE) // Any Override
}
}
@@ -1052,13 +1058,18 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
def typesString = normalizeAll(qual.tpe.widen)+" and "+normalizeAll(args.head.tpe.widen)
/** Symbols which limit the warnings we can issue since they may be value types */
- val isMaybeValue = Set(AnyClass, AnyRefClass, AnyValClass, ObjectClass, ComparableClass, JavaSerializableClass)
+ val isMaybeValue = Set[Symbol](AnyClass, AnyRefClass, AnyValClass, ObjectClass, ComparableClass, JavaSerializableClass)
- // Whether def equals(other: Any) is overridden or synthetic
+ // Whether def equals(other: Any) has known behavior: it is the default
+ // inherited from java.lang.Object, or it is a synthetically generated
+ // case equals. TODO - more cases are warnable if the target is a synthetic
+ // equals.
def isUsingWarnableEquals = {
val m = receiver.info.member(nme.equals_)
- (m == Object_equals) || (m == Any_equals) || (m.isSynthetic && m.owner.isCase)
+ ((m == Object_equals) || (m == Any_equals) || isMethodCaseEquals(m))
}
+ def isMethodCaseEquals(m: Symbol) = m.isSynthetic && m.owner.isCase
+ def isCaseEquals = isMethodCaseEquals(receiver.info.member(nme.equals_))
// Whether this == or != is one of those defined in Any/AnyRef or an overload from elsewhere.
def isUsingDefaultScalaOp = {
val s = fn.symbol
@@ -1081,9 +1092,11 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
val msg = alwaysEqual == (name == nme.EQ || name == nme.eq)
unit.warning(pos, "comparing "+what+" using `"+name.decode+"' will always yield " + msg)
}
-
def nonSensible(pre: String, alwaysEqual: Boolean) =
nonSensibleWarning(pre+"values of types "+typesString, alwaysEqual)
+ def nonSensiblyEq() = nonSensible("", true)
+ def nonSensiblyNeq() = nonSensible("", false)
+ def nonSensiblyNew() = nonSensibleWarning("a fresh object", false)
def unrelatedTypes() = {
val msg = if (name == nme.EQ || name == nme.eq)
@@ -1091,52 +1104,73 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
unit.warning(pos, typesString + " are unrelated: they will most likely " + msg)
}
- if (nullCount == 2)
- nonSensible("", true) // null == null
+ if (nullCount == 2) // null == null
+ nonSensiblyEq()
else if (nullCount == 1) {
if (onSyms(_ exists isPrimitiveValueClass)) // null == 5
- nonSensible("", false)
+ nonSensiblyNeq()
else if (onTrees( _ exists isNew)) // null == new AnyRef
- nonSensibleWarning("a fresh object", false)
+ nonSensiblyNew()
}
else if (isBoolean(receiver)) {
if (!isBoolean(actual) && !isMaybeValue(actual)) // true == 5
- nonSensible("", false)
+ nonSensiblyNeq()
}
else if (isUnit(receiver)) {
if (isUnit(actual)) // () == ()
- nonSensible("", true)
+ nonSensiblyEq()
else if (!isUnit(actual) && !isMaybeValue(actual)) // () == "abc"
- nonSensible("", false)
+ nonSensiblyNeq()
}
else if (isNumeric(receiver)) {
if (!isNumeric(actual) && !forMSIL)
if (isUnit(actual) || isBoolean(actual) || !isMaybeValue(actual)) // 5 == "abc"
- nonSensible("", false)
+ nonSensiblyNeq()
}
- else if (isWarnable) {
+ else if (isWarnable && !isCaseEquals) {
if (isNew(qual)) // new X == y
- nonSensibleWarning("a fresh object", false)
+ nonSensiblyNew()
else if (isNew(args.head) && (receiver.isEffectivelyFinal || isReferenceOp)) // object X ; X == new Y
- nonSensibleWarning("a fresh object", false)
+ nonSensiblyNew()
else if (receiver.isEffectivelyFinal && !(receiver isSubClass actual)) { // object X, Y; X == Y
if (isEitherNullable)
nonSensible("non-null ", false)
else
- nonSensible("", false)
+ nonSensiblyNeq()
}
}
// possibleNumericCount is insufficient or this will warn on e.g. Boolean == j.l.Boolean
if (isWarnable && nullCount == 0 && !(isSpecial(receiver) && isSpecial(actual))) {
- if (actual isSubClass receiver) ()
- else if (receiver isSubClass actual) ()
- // warn only if they have no common supertype below Object
- else {
+ // better to have lubbed and lost
+ def warnIfLubless(): Unit = {
val common = global.lub(List(actual.tpe, receiver.tpe))
if (ObjectClass.tpe <:< common)
unrelatedTypes()
}
+ def eitherSubclasses = (actual isSubClass receiver) || (receiver isSubClass actual)
+ // warn if actual has a case parent that is not same as receiver's;
+ // if actual is not a case, then warn if no common supertype, as below
+ if (isCaseEquals) {
+ def thisCase = receiver.info.member(nme.equals_).owner
+ actual.info.baseClasses.find(_.isCase) match {
+ case Some(p) if (p != thisCase) => nonSensible("case class ", false)
+ case None =>
+ // stronger message on (Some(1) == None)
+ //if (receiver.isCase && receiver.isEffectivelyFinal && !(receiver isSubClass actual)) nonSensiblyNeq()
+ //else
+ // if a class, it must be super to thisCase (and receiver) since not <: thisCase
+ if (!actual.isTrait && !(receiver isSubClass actual)) nonSensiblyNeq()
+ else if (!eitherSubclasses) warnIfLubless()
+ case _ =>
+ }
+ }
+ else if (actual isSubClass receiver) ()
+ else if (receiver isSubClass actual) ()
+ // warn only if they have no common supertype below Object
+ else {
+ warnIfLubless()
+ }
}
case _ =>
}
@@ -1424,6 +1458,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
analyzer.ImplicitNotFoundMsg.check(sym) foreach { warn =>
unit.warning(tree.pos, "Invalid implicitNotFound message for %s%s:\n%s".format(sym, sym.locationString, warn))
}
+
case tpt@TypeTree() =>
if(tpt.original != null) {
tpt.original foreach {
@@ -1642,9 +1677,10 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
inPattern = false
treeCopy.CaseDef(tree, pat1, transform(guard), transform(body))
case LabelDef(_, _, _) if gen.hasSynthCaseSymbol(result) =>
+ val old = inPattern
inPattern = true
val res = deriveLabelDef(result)(transform)
- inPattern = false
+ inPattern = old
res
case _ =>
super.transform(result)
diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
new file mode 100644
index 0000000000..329a247106
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala
@@ -0,0 +1,10 @@
+package scala.tools.nsc
+package typechecker
+
+import scala.reflect.makro.runtime.{Context => MacroContext}
+
+trait StdAttachments {
+ self: Analyzer =>
+
+ case class MacroAttachment(delayed: Boolean, typerContext: Context, macroContext: Option[MacroContext])
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 94733369a8..d327d9c397 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -121,7 +121,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
if (sym.isDeferred) {
val member = sym.overridingSymbol(clazz);
if (mix != tpnme.EMPTY || member == NoSymbol ||
- !((member hasFlag ABSOVERRIDE) && member.isIncompleteIn(clazz)))
+ !(member.isAbstractOverride && member.isIncompleteIn(clazz)))
unit.error(sel.pos, ""+sym.fullLocationString+" is accessed from super. It may not be abstract "+
"unless it is overridden by a member declared `abstract' and `override'");
}
@@ -134,7 +134,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
// otherwise lead to either a compiler crash or runtime failure.
private lazy val isDisallowed = {
import definitions._
- Set(Any_isInstanceOf, Object_isInstanceOf, Any_asInstanceOf, Object_asInstanceOf, Object_==, Object_!=, Object_##)
+ Set[Symbol](Any_isInstanceOf, Object_isInstanceOf, Any_asInstanceOf, Object_asInstanceOf, Object_==, Object_!=, Object_##)
}
override def transform(tree: Tree): Tree = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
index da87d38ab0..57e82ed706 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala
@@ -50,7 +50,7 @@ trait SyntheticMethods extends ast.TreeDSL {
import synthesizer._
if (clazz0 == AnyValClass || isPrimitiveValueClass(clazz0)) return {
- if (clazz0.info member nme.getClass_ isDeferred) {
+ if ((clazz0.info member nme.getClass_).isDeferred) {
// XXX dummy implementation for now
val getClassMethod = createMethod(nme.getClass_, getClassReturnType(clazz.tpe))(_ => NULL)
deriveTemplate(templ)(_ :+ getClassMethod)
@@ -74,7 +74,7 @@ trait SyntheticMethods extends ast.TreeDSL {
// Option[Int] { def productIterator: Iterator[String] }
//
// appearing legitimately, but this breaks invariant places
- // like Manifests and Arrays which are not robust and infer things
+ // like Tags and Arrays which are not robust and infer things
// which they shouldn't.
val accessorLub = (
if (opt.experimental) {
@@ -299,11 +299,12 @@ trait SyntheticMethods extends ast.TreeDSL {
newAcc resetFlag (ACCESSOR | PARAMACCESSOR)
ddef.rhs.duplicate
}
+ // TODO: shouldn't the next line be: `original resetFlag CASEACCESSOR`?
ddef.symbol resetFlag CASEACCESSOR
lb += logResult("case accessor new")(newAcc)
}
- lb ++= templ.body ++= synthesize() toList
+ (lb ++= templ.body ++= synthesize()).toList
}
if (phase.id > currentRun.typerPhase.id) templ
diff --git a/src/compiler/scala/tools/nsc/typechecker/Taggings.scala b/src/compiler/scala/tools/nsc/typechecker/Taggings.scala
new file mode 100644
index 0000000000..fb0d6fb3c5
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/typechecker/Taggings.scala
@@ -0,0 +1,71 @@
+package scala.tools.nsc
+package typechecker
+
+trait Taggings {
+ self: Analyzer =>
+
+ import global._
+ import definitions._
+
+ trait Tagging {
+ self: Typer =>
+
+ private def resolveTag(taggedTp: Type, pos: Position) = beforeTyper {
+ inferImplicit(
+ EmptyTree,
+ taggedTp,
+ /*reportAmbiguous =*/ true,
+ /*isView =*/ false,
+ /*context =*/ context,
+ /*saveAmbiguousDivergent =*/ true,
+ /*pos =*/ pos
+ ).tree
+ }
+
+ /** Finds in scope or materializes an ArrayTag.
+ * Should be used instead of ClassTag or ClassManifest every time compiler needs to create an array.
+ *
+ * @param tp Type we're looking an ArrayTag for, e.g. resolveArrayTag(IntClass.tpe, pos) will look for ArrayTag[Int].
+ * @param pos Position for error reporting. Please, provide meaningful value.
+ *
+ * @returns Tree that represents an `scala.reflect.ArrayTag` for `tp` if everything is okay.
+ * EmptyTree if the result contains unresolved (i.e. not spliced) type parameters and abstract type members.
+ */
+ def resolveArrayTag(tp: Type, pos: Position): Tree = {
+ val taggedTp = appliedType(ArrayTagClass.typeConstructor, List(tp))
+ resolveTag(taggedTp, pos)
+ }
+
+ /** Finds in scope or materializes an ErasureTag (if `concrete` is false) or a ClassTag (if `concrete` is true).
+ * Should be used instead of ClassTag or ClassManifest every time compiler needs to persist an erasure.
+ *
+ * @param tp Type we're looking an ErasureTag for, e.g. resolveErasureTag(IntClass.tpe, pos, true) will look for ClassTag[Int].
+ * @param pos Position for error reporting. Please, provide meaningful value.
+ * @param concrete If true then the result must not contain unresolved (i.e. not spliced) type parameters and abstract type members.
+ * If false then the function will always succeed (abstract types will be erased to their upper bounds).
+ *
+ * @returns Tree that represents an `scala.reflect.ErasureTag` for `tp` if everything is okay.
+ * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members.
+ */
+ def resolveErasureTag(tp: Type, pos: Position, concrete: Boolean): Tree = {
+ val taggedTp = appliedType(if (concrete) ClassTagClass.typeConstructor else ErasureTagClass.typeConstructor, List(tp))
+ resolveTag(taggedTp, pos)
+ }
+
+ /** Finds in scope or materializes a TypeTag (if `concrete` is false) or a ConcreteTypeTag (if `concrete` is true).
+ *
+ * @param pre Prefix that represents a universe this type tag will be bound to.
+ * @param tp Type we're looking a TypeTag for, e.g. resolveTypeTag(reflectMirrorPrefix, IntClass.tpe, pos, false) will look for scala.reflect.mirror.TypeTag[Int].
+ * @param pos Position for error reporting. Please, provide meaningful value.
+ * @param concrete If true then the result must not contain unresolved (i.e. not spliced) type parameters and abstract type members.
+ * If false then the function will always succeed (abstract types will be reified as free types).
+ *
+ * @returns Tree that represents a `scala.reflect.TypeTag` for `tp` if everything is okay.
+ * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members.
+ */
+ def resolveTypeTag(pre: Type, tp: Type, pos: Position, concrete: Boolean): Tree = {
+ val taggedTp = appliedType(singleType(pre, pre member (if (concrete) ConcreteTypeTagClass else TypeTagClass).name), List(tp))
+ resolveTag(taggedTp, pos)
+ }
+ }
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
index 105c2c0b98..a6a8d6009f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala
@@ -14,7 +14,22 @@ import util.returning
abstract class TreeCheckers extends Analyzer {
import global._
- private def classstr(x: AnyRef) = x.getClass.getName split """\\.|\\$""" last;
+ private val everything = ListBuffer[(Phase, Map[Tree, (Symbol, Type)])]()
+ private val currentTrees = mutable.Map[Tree, (Symbol, Type)]()
+ private val tpeOfTree = mutable.HashMap[Tree, Type]()
+
+ if (settings.debug.value) {
+ sys addShutdownHook {
+ for ((ph, map) <- everything.toList) {
+ println("\n>>>> " + ph + "\n")
+ for ((tree, (sym, tpe)) <- map.toList.sortBy(_._1.summaryString)) {
+ println("%20s %20s %s".format(sym, tpe, ("" + tree) take 50))
+ }
+ }
+ }
+ }
+
+ private def classstr(x: AnyRef) = (x.getClass.getName split """\\.|\\$""").last
private def typestr(x: Type) = " (tpe = " + x + ")"
private def treestr(t: Tree) = t + " [" + classstr(t) + "]" + typestr(t.tpe)
private def ownerstr(s: Symbol) = "'" + s + "'" + s.locationString
@@ -35,13 +50,14 @@ abstract class TreeCheckers extends Analyzer {
object SymbolTracker extends Traverser {
type PhaseMap = mutable.HashMap[Symbol, List[Tree]]
+ val defSyms = mutable.HashMap[Symbol, List[DefTree]]() withDefaultValue Nil
+ val newSyms = mutable.HashSet[Symbol]()
val maps = ListBuffer[(Phase, PhaseMap)]()
+ val movedMsgs = ListBuffer[String]()
+
def prev = maps.init.last._2
def latest = maps.last._2
- val defSyms = mutable.HashMap[Symbol, List[DefTree]]()
- val newSyms = mutable.HashSet[Symbol]()
- val movedMsgs = new ListBuffer[String]
- def sortedNewSyms = newSyms.toList.distinct sortBy (_.name.toString)
+ def sortedNewSyms = newSyms.toList.distinct sortBy (_.name)
def inPrev(sym: Symbol) = {
(maps.size >= 2) && (prev contains sym)
@@ -92,18 +108,21 @@ abstract class TreeCheckers extends Analyzer {
if (maps.isEmpty || maps.last._1 != ph)
maps += ((ph, new PhaseMap))
+ currentTrees.clear()
traverse(unit.body)
+ everything += ((ph, currentTrees.toMap))
+
reportChanges()
}
override def traverse(tree: Tree): Unit = {
val sym = tree.symbol
+ currentTrees(tree) = ((sym, tree.tpe))
+
if (sym != null && sym != NoSymbol) {
record(sym, tree)
tree match {
- case x: DefTree =>
- if (defSyms contains sym) defSyms(sym) = defSyms(sym) :+ x
- else defSyms(sym) = List(x)
- case _ => ()
+ case x: DefTree => defSyms(sym) :+= x
+ case _ => ()
}
}
@@ -111,8 +130,6 @@ abstract class TreeCheckers extends Analyzer {
}
}
- lazy val tpeOfTree = mutable.HashMap[Tree, Type]()
-
def posstr(p: Position) =
try p.source.path + ":" + p.line
catch { case _: UnsupportedOperationException => p.toString }
@@ -128,9 +145,7 @@ abstract class TreeCheckers extends Analyzer {
if (!cond) errorFn(msg)
def checkTrees() {
- if (settings.verbose.value)
- Console.println("[consistency check at the beginning of phase " + phase + "]")
-
+ informFn("[consistency check at the beginning of phase " + phase + "]")
currentRun.units foreach check
}
@@ -153,7 +168,7 @@ abstract class TreeCheckers extends Analyzer {
informProgress("checking "+unit)
val context = rootContext(unit)
context.checking = true
- tpeOfTree.clear
+ tpeOfTree.clear()
SymbolTracker.check(phase, unit)
val checker = new TreeChecker(context)
runWithUnit(unit) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index 6efa595d99..38c2c5f719 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -270,8 +270,7 @@ trait TypeDiagnostics {
private val savedName = sym.name
def restoreName() = sym.name = savedName
def isAltered = sym.name != savedName
- def modifyName(f: String => String) =
- sym.name = newTypeName(f(sym.name.toString))
+ def modifyName(f: String => String) = sym setName newTypeName(f(sym.name.toString))
/** Prepend java.lang, scala., or Predef. if this type originated
* in one of those.
@@ -457,14 +456,20 @@ trait TypeDiagnostics {
ex match {
case CyclicReference(sym, info: TypeCompleter) =>
- val pos = info.tree match {
- case Import(expr, _) => expr.pos
- case _ => ex.pos
+ if (context0.owner.isTermMacro) {
+ // see comments to TypeSigError for an explanation of this special case
+ // [Eugene] is there a better way?
+ throw ex
+ } else {
+ val pos = info.tree match {
+ case Import(expr, _) => expr.pos
+ case _ => ex.pos
+ }
+ contextError(context0, pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
+
+ if (sym == ObjectClass)
+ throw new FatalError("cannot redefine root "+sym)
}
- contextError(context0, pos, cyclicReferenceMessage(sym, info.tree) getOrElse ex.getMessage())
-
- if (sym == ObjectClass)
- throw new FatalError("cannot redefine root "+sym)
case _ =>
contextError(context0, ex.pos, ex)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 2aff00f6a5..08d6bd7226 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -26,12 +26,14 @@ import util.Statistics._
* @author Martin Odersky
* @version 1.0
*/
-trait Typers extends Modes with Adaptations with PatMatVirtualiser {
+trait Typers extends Modes with Adaptations with Taggings {
self: Analyzer =>
import global._
import definitions._
+ import patmat.DefaultOverrideMatchAttachment
+
final def forArgMode(fun: Tree, mode: Int) =
if (treeInfo.isSelfOrSuperConstrCall(fun)) mode | SCCmode
else mode
@@ -51,6 +53,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
transformed.clear()
}
+ // [Eugene] shouldn't this be converted to resetAllAttrs?
object UnTyper extends Traverser {
override def traverse(tree: Tree) = {
if (tree != EmptyTree) tree.tpe = null
@@ -82,7 +85,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
private def isPastTyper = phase.id > currentRun.typerPhase.id
- abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with TyperContextErrors {
+ // when true:
+ // - we may virtualize matches (if -Xexperimental and there's a suitable __match in scope)
+ // - we synthesize PartialFunction implementations for `x => x match {...}` and `match {...}` when the expected type is PartialFunction
+ // this is disabled by: -Xoldpatmat, scaladoc or interactive compilation
+ @inline private def newPatternMatching = opt.virtPatmat && !forScaladoc && !forInteractive // && (phase.id < currentRun.uncurryPhase.id)
+
+ abstract class Typer(context0: Context) extends TyperDiagnostics with Adaptation with Tagging with TyperContextErrors {
import context0.unit
import typeDebug.{ ptTree, ptBlock, ptLine }
import TyperErrorGen._
@@ -181,12 +190,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case _ =>
def wrapImplicit(from: Type): Tree = {
val result = inferImplicit(tree, functionType(List(from), to), reportAmbiguous, true, context, saveErrors)
- if (result.subst != EmptyTreeTypeSubstituter) result.subst traverse tree
+ if (result.subst != EmptyTreeTypeSubstituter) {
+ result.subst traverse tree
+ notifyUndetparamsInferred(result.subst.from, result.subst.to)
+ }
result.tree
}
val result = wrapImplicit(from)
if (result != EmptyTree) result
- else wrapImplicit(appliedType(ByNameParamClass.typeConstructor, List(from)))
+ else wrapImplicit(byNameType(from))
}
}
@@ -451,13 +463,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* of a this or super with prefix <code>qual</code>.
* packageOk is equal false when qualifying class symbol
*/
- def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean = false): Option[Symbol] =
+ def qualifyingClass(tree: Tree, qual: Name, packageOK: Boolean) =
context.enclClass.owner.ownerChain.find(o => qual.isEmpty || o.isClass && o.name == qual) match {
- case Some(c) if packageOK || !c.isPackageClass =>
- Some(c)
- case _ =>
- QualifyingClassError(tree, qual)
- None
+ case Some(c) if packageOK || !c.isPackageClass => c
+ case _ => QualifyingClassError(tree, qual) ; NoSymbol
}
/** The typer for an expression, depending on where we are. If we are before a superclass
@@ -508,7 +517,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
res
}
-
/** The typer for a label definition. If this is part of a template we
* first have to enter the label definition.
*/
@@ -671,7 +679,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
if (tree.tpe.isInstanceOf[MethodType] && pre.isStable && sym.tpe.params.isEmpty &&
(isStableContext(tree, mode, pt) || sym.isModule))
- tree.setType(MethodType(List(), singleType(pre, sym)))
+ tree.setType(MethodType(List(), singleType(pre, sym))) // TODO: should this be a NullaryMethodType?
else tree
}
@@ -730,6 +738,58 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
+ /** Check whether feature given by `featureTrait` is enabled.
+ * If it is not, issue an error or a warning depending on whether the feature is required.
+ * @param construct A string expression that is substituted for "#" in the feature description string
+ * @param immediate When set, feature check is run immediately, otherwise it is run
+ * at the end of the typechecking run for the enclosing unit. This
+ * is done to avoid potential cyclic reference errors by implicits
+ * that are forced too early.
+ * @return if feature check is run immediately: true if feature is enabled, false otherwise
+ * if feature check is delayed or suppressed because we are past typer: true
+ */
+ def checkFeature(pos: Position, featureTrait: Symbol, construct: => String = "", immediate: Boolean = false): Boolean =
+ if (isPastTyper) true
+ else {
+ val nestedOwners =
+ featureTrait.owner.ownerChain.takeWhile(_ != languageFeatureModule.moduleClass).reverse
+ val featureName = (nestedOwners map (_.name + ".")).mkString + featureTrait.name
+ def action(): Boolean = {
+ def hasImport = inferImplicit(EmptyTree: Tree, featureTrait.tpe, true, false, context) != SearchFailure
+ def hasOption = settings.language.value contains featureName
+ val OK = hasImport || hasOption
+ if (!OK) {
+ val Some(AnnotationInfo(_, List(Literal(Constant(featureDesc: String)), Literal(Constant(required: Boolean))), _)) =
+ featureTrait getAnnotation LanguageFeatureAnnot
+ val req = if (required) "needs to" else "should"
+ var raw = featureDesc + " " + req + " be enabled\n" +
+ "by making the implicit value language." + featureName + " visible."
+ if (!(currentRun.reportedFeature contains featureTrait))
+ raw += "\nThis can be achieved by adding the import clause 'import language." + featureName + "'\n" +
+ "or by setting the compiler option -language:" + featureName + ".\n" +
+ "See the Scala docs for value scala.language." + featureName + " for a discussion\n" +
+ "why the feature " + req + " be explicitly enabled."
+ currentRun.reportedFeature += featureTrait
+ val msg = raw replace ("#", construct)
+ if (required) unit.error(pos, msg)
+ else currentRun.featureWarnings.warn(pos, msg)
+ }
+ OK
+ }
+ if (immediate) {
+ action()
+ } else {
+ unit.toCheck += action
+ true
+ }
+ }
+
+ def checkExistentialsFeature(pos: Position, tpe: Type, prefix: String) = tpe match {
+ case extp: ExistentialType if !extp.isRepresentableWithWildcards =>
+ checkFeature(pos, ExistentialsFeature, prefix+" "+tpe)
+ case _ =>
+ }
+
/** Perform the following adaptations of expression, pattern or type `tree` wrt to
* given mode `mode` and given prototype `pt`:
* (-1) For expressions with annotated types, let AnnotationCheckers decide what to do
@@ -769,17 +829,13 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
protected def adapt(tree: Tree, mode: Int, pt: Type, original: Tree = EmptyTree): Tree = {
def adaptToImplicitMethod(mt: MethodType): Tree = {
- if (context.undetparams nonEmpty) { // (9) -- should revisit dropped condition `(mode & POLYmode) == 0`
+ if (context.undetparams.nonEmpty) { // (9) -- should revisit dropped condition `(mode & POLYmode) == 0`
// dropped so that type args of implicit method are inferred even if polymorphic expressions are allowed
// needed for implicits in 2.8 collection library -- maybe once #3346 is fixed, we can reinstate the condition?
context.undetparams = inferExprInstance(tree, context.extractUndetparams(), pt,
// approximate types that depend on arguments since dependency on implicit argument is like dependency on type parameter
mt.approximate,
- // if we are looking for a manifest, instantiate type to Nothing anyway,
- // as we would get ambiguity errors otherwise. Example
- // Looking for a manifest of Nil: This has many potential types,
- // so we need to instantiate to minimal type List[Nothing].
- keepNothings = false, // retract Nothing's that indicate failure, ambiguities in manifests are dealt with in manifestOfType
+ keepNothings = false,
useWeaklyCompatible = true) // #3808
}
@@ -813,7 +869,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case Block(_, tree1) => tree1.symbol
case _ => tree.symbol
}
- if (!meth.isConstructor && !meth.isMacro && isFunctionType(pt)) { // (4.2)
+ if (!meth.isConstructor && !meth.isTermMacro && isFunctionType(pt)) { // (4.2)
debuglog("eta-expanding " + tree + ":" + tree.tpe + " to " + pt)
checkParamsConvertible(tree, tree.tpe)
val tree0 = etaExpand(context.unit, tree)
@@ -865,7 +921,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
KindArityMismatchError(tree, pt)
} else tree match { // (6)
case TypeTree() => tree
- case _ => TypeTree(tree.tpe) setOriginal (tree) setPos (tree.pos)
+ case _ => TypeTree(tree.tpe) setOriginal tree
}
}
@@ -1006,14 +1062,15 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val tparams1 = cloneSymbols(tparams)
val tree1 = if (tree.isType) tree
else TypeApply(tree, tparams1 map (tparam =>
- TypeTree(tparam.tpeHK) setPos tree.pos.focus)) setPos tree.pos //@M/tcpolyinfer: changed tparam.tpe to tparam.tpeHK
+ TypeTree(tparam.tpeHK) setPos tree.pos.focus)) setPos tree.pos
context.undetparams ++= tparams1
+ notifyUndetparamsAdded(tparams1)
adapt(tree1 setType restpe.substSym(tparams, tparams1), mode, pt, original)
case mt: MethodType if mt.isImplicit && ((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) => // (4.1)
adaptToImplicitMethod(mt)
case mt: MethodType if (((mode & (EXPRmode | FUNmode | LHSmode)) == EXPRmode) &&
- (context.undetparams.isEmpty || inPolyMode(mode))) =>
+ (context.undetparams.isEmpty || inPolyMode(mode))) && !(tree.symbol != null && tree.symbol.isTermMacro) =>
instantiateToMethodType(mt)
case _ =>
@@ -1026,13 +1083,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
if (tree.isType)
adaptType()
- else if (inExprModeButNot(mode, FUNmode) && tree.symbol != null && tree.symbol.isMacro && !tree.isDef && !(tree exists (_.isErroneous)))
- macroExpand(tree, this) match {
- case Some(expanded: Tree) =>
- typed(expanded, mode, pt)
- case None =>
- setError(tree) // error already reported
- }
+ else if (
+ inExprModeButNot(mode, FUNmode) && !tree.isDef && // typechecking application
+ tree.symbol != null && tree.symbol.isTermMacro) // of a macro
+ macroExpand(this, tree, mode, pt)
else if ((mode & (PATTERNmode | FUNmode)) == (PATTERNmode | FUNmode))
adaptConstrPattern()
else if (inAllModes(mode, EXPRmode | FUNmode) &&
@@ -1169,7 +1223,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
&& !qtpe.typeSymbol.isBottomClass
&& qtpe != WildcardType
&& !qual.isInstanceOf[ApplyImplicitView] // don't chain views
- && context.implicitsEnabled
+ && (context.implicitsEnabled || context.enrichmentEnabled)
// Elaborating `context.implicitsEnabled`:
// don't try to adapt a top-level type that's the subject of an implicit search
// this happens because, if isView, typedImplicit tries to apply the "current" implicit value to
@@ -1562,10 +1616,16 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val clazz = mdef.symbol.moduleClass
val typedMods = typedModifiers(mdef.mods)
assert(clazz != NoSymbol, mdef)
+ val noSerializable = (
+ (linkedClass eq NoSymbol)
+ || linkedClass.isErroneous
+ || !linkedClass.isSerializable
+ || clazz.isSerializable
+ )
val impl1 = typerReportAnyContextErrors(context.make(mdef.impl, clazz, newScope)) {
_.typedTemplate(mdef.impl, {
parentTypes(mdef.impl) ++ (
- if (linkedClass == NoSymbol || !linkedClass.isSerializable || clazz.isSerializable) Nil
+ if (noSerializable) Nil
else {
clazz.makeSerializable()
List(TypeTree(SerializableClass.tpe) setPos clazz.pos.focus)
@@ -1653,7 +1713,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val body =
if (isPastTyper || reporter.hasErrors) templ.body
- else templ.body flatMap rewrappingWrapperTrees(namer.finishGetterSetter(Typer.this, _))
+ else templ.body flatMap rewrappingWrapperTrees(namer.addDerivedTrees(Typer.this, _))
val body1 = typedStats(body, templ.symbol)
@@ -1906,8 +1966,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
meth.owner.isAnonOrRefinementClass))
InvalidConstructorDefError(ddef)
typed(ddef.rhs)
- } else if (meth.isMacro) {
- EmptyTree
+ } else if (meth.isTermMacro) {
+ // typechecking macro bodies is sort of unconventional
+ // that's why we employ our custom typing scheme orchestrated outside of the typer
+ transformedOr(ddef.rhs, typedMacroBody(this, ddef))
} else {
transformedOrTyped(ddef.rhs, EXPRmode, tpt1.tpe)
}
@@ -1922,7 +1984,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
rhs1 = checkDead(rhs1)
if (!isPastTyper && meth.owner.isClass &&
- meth.paramss.exists(ps => ps.exists(_.hasDefaultFlag) && isRepeatedParamType(ps.last.tpe)))
+ meth.paramss.exists(ps => ps.exists(_.hasDefault) && isRepeatedParamType(ps.last.tpe)))
StarWithDefaultError(meth)
if (!isPastTyper) {
@@ -1937,6 +1999,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (meth.isStructuralRefinementMember)
checkMethodStructuralCompatible(meth)
+ if (meth.isImplicit && !meth.isSynthetic) meth.info.paramss match {
+ case List(param) :: _ if !param.isImplicit =>
+ checkFeature(ddef.pos, ImplicitConversionsFeature, meth.toString)
+ case _ =>
+ }
+
treeCopy.DefDef(ddef, typedMods, ddef.name, tparams1, vparamss1, tpt1, rhs1) setType NoType
}
@@ -1968,6 +2036,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case TypeBounds(lo1, hi1) if (!(lo1 <:< hi1)) => LowerBoundError(tdef, lo1, hi1)
case _ => ()
}
+
+ if (tdef.symbol.isDeferred && tdef.symbol.info.isHigherKinded)
+ checkFeature(tdef.pos, HigherKindsFeature)
+
treeCopy.TypeDef(tdef, typedMods, tdef.name, tparams1, rhs1) setType NoType
}
@@ -2089,7 +2161,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
for (Apply(_, xs) <- cdef.pat ; x <- xs dropRight 1 ; if treeInfo isStar x)
StarPositionInPatternError(x)
- val pat1 = typedPattern(cdef.pat, pattpe)
+ // withoutAnnotations - see continuations-run/z1673.scala
+ // This adjustment is awfully specific to continuations, but AFAICS the
+ // whole AnnotationChecker framework is.
+ val pat1 = typedPattern(cdef.pat, pattpe.withoutAnnotations)
// When case classes have more than two parameter lists, the pattern ends
// up typed as a method. We only pattern match on the first parameter
// list, so substitute the final result type of the method, i.e. the type
@@ -2108,7 +2183,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
var body1: Tree = typed(cdef.body, pt)
val contextWithTypeBounds = context.nextEnclosing(_.tree.isInstanceOf[CaseDef])
- if (contextWithTypeBounds.savedTypeBounds nonEmpty) {
+ if (contextWithTypeBounds.savedTypeBounds.nonEmpty) {
body1.tpe = contextWithTypeBounds restoreTypeBounds body1.tpe
// insert a cast if something typechecked under the GADT constraints,
@@ -2144,88 +2219,94 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def adaptCase(cdef: CaseDef, mode: Int, tpe: Type): CaseDef = deriveCaseDef(cdef)(adapt(_, mode, tpe))
- def prepareTranslateMatch(selector0: Tree, cases: List[CaseDef], mode: Int, resTp: Type) = {
- val (selector, doTranslation) = selector0 match {
- case Annotated(Ident(nme.synthSwitch), selector) => (selector, false)
- case s => (s, true)
- }
- val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType))
- val selectorTp = packCaptured(selector1.tpe.widen)
+ def ptOrLub(tps: List[Type], pt: Type ) = if (isFullyDefined(pt)) (pt, false) else weakLub(tps map (_.deconst))
+ def ptOrLubPacked(trees: List[Tree], pt: Type) = if (isFullyDefined(pt)) (pt, false) else weakLub(trees map (c => packedType(c, context.owner).deconst))
+
+ // takes untyped sub-trees of a match and type checks them
+ def typedMatch(selector: Tree, cases: List[CaseDef], mode: Int, pt: Type, tree: Tree = EmptyTree): Match = {
+ val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType))
+ val selectorTp = packCaptured(selector1.tpe.widen)
+ val casesTyped = typedCases(cases, selectorTp, pt)
- val casesTyped = typedCases(cases, selectorTp, resTp)
- val caseTypes = casesTyped map (c => packedType(c, context.owner).deconst)
- val (ownType, needAdapt) = if (isFullyDefined(resTp)) (resTp, false) else weakLub(caseTypes)
+ val (resTp, needAdapt) =
+ if (opt.virtPatmat) ptOrLubPacked(casesTyped, pt)
+ else ptOrLub(casesTyped map (_.tpe), pt)
- val casesAdapted = if (!needAdapt) casesTyped else casesTyped map (adaptCase(_, mode, ownType))
+ val casesAdapted = if (!needAdapt) casesTyped else casesTyped map (adaptCase(_, mode, resTp))
- (selector1, selectorTp, casesAdapted, ownType, doTranslation)
+ treeCopy.Match(tree, selector1, casesAdapted) setType resTp
}
- def translateMatch(selector1: Tree, selectorTp: Type, casesAdapted: List[CaseDef], ownType: Type, doTranslation: Boolean, matchFailGen: Option[Tree => Tree] = None) = {
- def repeatedToSeq(tp: Type): Type = (tp baseType RepeatedParamClass) match {
- case TypeRef(_, RepeatedParamClass, args) => appliedType(SeqClass.typeConstructor, args)
- case _ => tp
- }
+ // match has been typed -- virtualize it if we're feeling experimental
+ // (virtualized matches are expanded during type checking so they have the full context available)
+ // otherwise, do nothing: matches are translated during phase `patmat` (unless -Xoldpatmat)
+ def virtualizedMatch(match_ : Match, mode: Int, pt: Type) = {
+ import patmat.{vpmName, PureMatchTranslator, OptimizingMatchTranslator}
+
+ // TODO: add fallback __match sentinel to predef
+ val matchStrategy: Tree =
+ if (!(newPatternMatching && opt.experimental && context.isNameInScope(vpmName._match))) null // fast path, avoiding the next line if there's no __match to be seen
+ else newTyper(context.makeImplicit(reportAmbiguousErrors = false)).silent(_.typed(Ident(vpmName._match), EXPRmode, WildcardType), reportAmbiguousErrors = false) match {
+ case SilentResultValue(ms) => ms
+ case _ => null
+ }
- if (!doTranslation) { // a switch
- Match(selector1, casesAdapted) setType ownType // setType of the Match to avoid recursing endlessly
- } else {
- val scrutType = repeatedToSeq(elimAnonymousClass(selectorTp))
- // we've packed the type for each case in prepareTranslateMatch so that if all cases have the same existential case, we get a clean lub
- // here, we should open up the existential again
- // relevant test cases: pos/existentials-harmful.scala, pos/gadt-gilles.scala, pos/t2683.scala, pos/virtpatmat_exist4.scala
- MatchTranslator(this).translateMatch(selector1, casesAdapted, repeatedToSeq(ownType.skolemizeExistential(context.owner, context.tree)), scrutType, matchFailGen)
- }
+ if (matchStrategy ne null) // virtualize
+ typed((new PureMatchTranslator(this.asInstanceOf[patmat.global.analyzer.Typer] /*TODO*/, matchStrategy)).translateMatch(match_), mode, pt)
+ else
+ match_ // will be translated in phase `patmat`
}
- def typedMatchAnonFun(tree: Tree, cases: List[CaseDef], mode: Int, pt0: Type, selOverride: Option[(List[ValDef], Tree)] = None) = {
- val pt = deskolemizeGADTSkolems(pt0)
- val targs = pt.normalize.typeArgs
- val arity = if (isFunctionType(pt)) targs.length - 1 else 1 // TODO pt should always be a (Partial)Function, right?
- val ptRes = if (targs.isEmpty) WildcardType else targs.last // may not be fully defined
+ // synthesize and type check a PartialFunction implementation based on a match specified by `cases`
+ // Match(EmptyTree, cases) ==> new PartialFunction { def apply<OrElse>(params) = `translateMatch('`(param1,...,paramN)` match { cases }')` }
+ // for fresh params, the selector of the match we'll translated simply gathers those in a tuple
+ // NOTE: restricted to PartialFunction -- leave Function trees if the expected type does not demand a partial function
+ class MatchFunTyper(tree: Tree, cases: List[CaseDef], mode: Int, pt0: Type) {
+ // TODO: remove FunctionN support -- this is currently designed so that it can emit FunctionN and PartialFunction subclasses
+ // however, we should leave Function nodes until Uncurry so phases after typer can still detect normal Function trees
+ // we need to synthesize PartialFunction impls, though, to avoid nastiness in Uncurry in transforming&duplicating generated pattern matcher trees
+ // TODO: remove PartialFunction support from UnCurry
+ private val pt = deskolemizeGADTSkolems(pt0)
+ private val targs = pt.normalize.typeArgs
+ private val arity = if (isFunctionType(pt)) targs.length - 1 else 1 // TODO pt should always be a (Partial)Function, right?
+ private val ptRes = if (targs.isEmpty) WildcardType else targs.last // may not be fully defined
+
+ private val isPartial = pt.typeSymbol == PartialFunctionClass
+ assert(isPartial)
- val isPartial = pt.typeSymbol == PartialFunctionClass
- val anonClass = context.owner.newAnonymousFunctionClass(tree.pos)
- val funThis = This(anonClass)
- val serialVersionUIDAnnotation = AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
+ private val anonClass = context.owner.newAnonymousFunctionClass(tree.pos)
+ private val funThis = This(anonClass)
- anonClass addAnnotation serialVersionUIDAnnotation
+ anonClass addAnnotation AnnotationInfo(SerialVersionUIDAttr.tpe, List(Literal(Constant(0))), List())
def deriveFormals =
- selOverride match {
- case None if targs.isEmpty => Nil
- case None => targs.init // is there anything we can do if targs.isEmpty??
- case Some((vparams, _)) =>
- vparams map {p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe}
- }
+ if (targs.isEmpty) Nil
+ else targs.init
- def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) = {
- selOverride match {
- case None if targs.isEmpty => MissingParameterTypeAnonMatchError(tree, pt); (Nil, EmptyTree)
- case None =>
- val ps = methodSym newSyntheticValueParams formals // is there anything we can do if targs.isEmpty??
- val ids = ps map (p => Ident(p.name))
- val sel = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
- (ps, sel)
- case Some((vparams, sel)) =>
- val newParamSyms = (vparams, formals).zipped map {(p, tp) =>
- methodSym.newValueParameter(p.name, focusPos(p.pos), SYNTHETIC) setInfo tp
- }
+ def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) =
+ if (formals.isEmpty) { MissingParameterTypeAnonMatchError(tree, pt); Nil }
+ else methodSym newSyntheticValueParams formals
- (newParamSyms, sel.duplicate)
+ def mkSel(params: List[Symbol]) =
+ if (params.isEmpty) EmptyTree
+ else {
+ val ids = params map (p => Ident(p.name))
+ atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
}
- }
import CODE._
// need to duplicate the cases before typing them to generate the apply method, or the symbols will be all messed up
val casesTrue = if (isPartial) cases map (c => deriveCaseDef(c)(x => TRUE_typed).duplicate) else Nil
+ // println("casesTrue "+ casesTrue)
+ def parentsPartial(targs: List[Type]) = addSerializable(appliedType(AbstractPartialFunctionClass.typeConstructor, targs))
def applyMethod = {
// rig the show so we can get started typing the method body -- later we'll correct the infos...
- anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass)
- val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ anonClass setInfo ClassInfoType(addSerializable(ObjectClass.tpe, pt), newScope, anonClass)
+ val methodSym = anonClass.newMethod(nme.apply, tree.pos, if(isPartial) (FINAL | OVERRIDE) else FINAL)
+ val paramSyms = mkParams(methodSym)
+ val selector = mkSel(paramSyms)
if (selector eq EmptyTree) EmptyTree
else {
@@ -2234,15 +2315,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)
paramSyms foreach (methodBodyTyper.context.scope enter _)
- val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, cases, mode, ptRes)
+ val match_ = methodBodyTyper.typedMatch(selector, cases, mode, ptRes)
+ val resTp = match_.tpe
val methFormals = paramSyms map (_.tpe)
- val parents = List(appliedType(AbstractFunctionClass(arity).typeConstructor, methFormals :+ resTp), SerializableClass.tpe)
-
+ val parents = (
+ if (isPartial) parentsPartial(List(methFormals.head, resTp))
+ else addSerializable(abstractFunctionType(methFormals, resTp))
+ )
anonClass setInfo ClassInfoType(parents, newScope, anonClass)
methodSym setInfoAndEnter MethodType(paramSyms, resTp)
- DefDef(methodSym, methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation))
+ DefDef(methodSym, methodBodyTyper.virtualizedMatch(match_, mode, resTp))
}
}
@@ -2250,21 +2334,20 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def applyOrElseMethodDef = {
// rig the show so we can get started typing the method body -- later we'll correct the infos...
// targs were type arguments for PartialFunction, so we know they will work for AbstractPartialFunction as well
- def parents(targs: List[Type]) = List(appliedType(AbstractPartialFunctionClass.typeConstructor, targs), SerializableClass.tpe)
-
- anonClass setInfo ClassInfoType(parents(targs), newScope, anonClass)
+ anonClass setInfo ClassInfoType(parentsPartial(targs), newScope, anonClass)
val methodSym = anonClass.newMethod(nme.applyOrElse, tree.pos, FINAL | OVERRIDE)
// create the parameter that corresponds to the function's parameter
- val List(argTp) = deriveFormals
- val A1 = methodSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argTp)
- val (List(x), selector) = mkParams(methodSym, List(A1.tpe))
+ val List(argTp) = deriveFormals
+ val A1 = methodSym newTypeParameter(newTypeName("A1")) setInfo TypeBounds.upper(argTp)
+ val paramSyms@List(x) = mkParams(methodSym, List(A1.tpe))
+ val selector = mkSel(paramSyms)
if (selector eq EmptyTree) EmptyTree
else {
// applyOrElse's default parameter:
val B1 = methodSym newTypeParameter(newTypeName("B1")) setInfo TypeBounds.empty //lower(resTp)
- val default = methodSym newValueParameter(newTermName("default"), focusPos(tree.pos), SYNTHETIC) setInfo functionType(List(A1.tpe), B1.tpe)
+ val default = methodSym newValueParameter(newTermName("default"), tree.pos.focus, SYNTHETIC) setInfo functionType(List(A1.tpe), B1.tpe)
val paramSyms = List(x, default)
methodSym setInfoAndEnter polyType(List(A1, B1), MethodType(paramSyms, B1.tpe))
@@ -2272,16 +2355,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)
paramSyms foreach (methodBodyTyper.context.scope enter _)
- val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, cases, mode, ptRes)
+ val match_ = methodBodyTyper.typedMatch(selector, cases, mode, ptRes)
+ val resTp = match_.tpe
- anonClass setInfo ClassInfoType(parents(List(argTp, resTp)), newScope, anonClass)
+ anonClass setInfo ClassInfoType(parentsPartial(List(argTp, resTp)), newScope, anonClass)
B1 setInfo TypeBounds.lower(resTp)
anonClass.info.decls enter methodSym // methodSym's info need not change (B1's bound has been updated instead)
- // use applyOrElse's first parameter since the scrut's type has been widened
- def doDefault(scrut_ignored: Tree) = REF(default) APPLY (REF(x))
+ match_ setType B1.tpe
- val body = methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, B1.tpe, doTranslation, Some(doDefault))
+ // the default uses applyOrElse's first parameter since the scrut's type has been widened
+ val body = methodBodyTyper.virtualizedMatch(match_ withAttachment DefaultOverrideMatchAttachment(REF(default) APPLY (REF(x))), mode, B1.tpe)
DefDef(methodSym, body)
}
@@ -2289,23 +2373,46 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def isDefinedAtMethod = {
val methodSym = anonClass.newMethod(nme.isDefinedAt, tree.pos, FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ val paramSyms = mkParams(methodSym)
+ val selector = mkSel(paramSyms)
+
if (selector eq EmptyTree) EmptyTree
else {
val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)
paramSyms foreach (methodBodyTyper.context.scope enter _)
methodSym setInfoAndEnter MethodType(paramSyms, BooleanClass.tpe)
- val (selector1, selectorTp, casesAdapted, resTp, doTranslation) = methodBodyTyper.prepareTranslateMatch(selector, casesTrue, mode, BooleanClass.tpe)
- val body = methodBodyTyper.translateMatch(selector1, selectorTp, casesAdapted, resTp, doTranslation, Some(scrutinee => FALSE_typed))
+ val match_ = methodBodyTyper.typedMatch(selector, casesTrue, mode, BooleanClass.tpe)
+ val body = methodBodyTyper.virtualizedMatch(match_ withAttachment DefaultOverrideMatchAttachment(FALSE_typed), mode, BooleanClass.tpe)
DefDef(methodSym, body)
}
}
- val members = if (!isPartial) List(applyMethod) else List(applyOrElseMethodDef, isDefinedAtMethod)
- if (members.head eq EmptyTree) setError(tree)
- else typed(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos)), New(anonClass.tpe)), mode, pt)
+ lazy val members = if (isPartial) {
+ // somehow @cps annotations upset the typer when looking at applyOrElse's signature, but not apply's
+ // TODO: figure out the details (T @cps[U] is not a subtype of Any, but then why does it work for the apply method?)
+ if (targs forall (_ <:< AnyClass.tpe)) List(applyOrElseMethodDef, isDefinedAtMethod)
+ else List(applyMethod, isDefinedAtMethod)
+ } else List(applyMethod)
+
+ def translated =
+ if (members.head eq EmptyTree) setError(tree)
+ else typed(Block(List(ClassDef(anonClass, NoMods, List(List()), List(List()), members, tree.pos)), New(anonClass.tpe)), mode, pt)
+ }
+
+ // Function(params, Match(sel, cases)) ==> new <Partial>Function { def apply<OrElse>(params) = `translateMatch('sel match { cases }')` }
+ class MatchFunTyperBetaReduced(fun: Function, sel: Tree, cases: List[CaseDef], mode: Int, pt: Type) extends MatchFunTyper(fun, cases, mode, pt) {
+ override def deriveFormals =
+ fun.vparams map { p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe }
+
+ // the only difference from the super class is that we must preserve the names of the parameters
+ override def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) =
+ (fun.vparams, formals).zipped map { (p, tp) =>
+ methodSym.newValueParameter(p.name, p.pos.focus, SYNTHETIC) setInfo tp
+ }
+
+ override def mkSel(params: List[Symbol]) = sel.duplicate
}
/**
@@ -2359,11 +2466,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
fun.body match {
- case Match(sel, cases) if opt.virtPatmat =>
+ // later phase indicates scaladoc is calling (where shit is messed up, I tell you)
+ // -- so fall back to old patmat, which is more forgiving
+ case Match(sel, cases) if (sel ne EmptyTree) && newPatternMatching && (pt.typeSymbol == PartialFunctionClass) =>
// go to outer context -- must discard the context that was created for the Function since we're discarding the function
// thus, its symbol, which serves as the current context.owner, is not the right owner
// you won't know you're using the wrong owner until lambda lift crashes (unless you know better than to use the wrong owner)
- newTyper(context.outer).typedMatchAnonFun(fun, cases, mode, pt, Some((fun.vparams, sel)))
+ val outerTyper = newTyper(context.outer)
+ (new outerTyper.MatchFunTyperBetaReduced(fun, sel, cases, mode, pt)).translated
case _ =>
val vparamSyms = fun.vparams map { vparam =>
enterSym(context, vparam)
@@ -2471,54 +2581,53 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
|| (looker.hasAccessorFlag && !accessed.hasAccessorFlag && accessed.isPrivate)
)
- def checkNoDoubleDefsAndAddSynthetics(stats: List[Tree]): List[Tree] = {
+ def checkNoDoubleDefs(stats: List[Tree]): Unit = {
val scope = if (inBlock) context.scope else context.owner.info.decls
- var newStats = new ListBuffer[Tree]
- var needsCheck = true
- var moreToAdd = true
- while (moreToAdd) {
- val initSize = scope.size
- var e = scope.elems
- while ((e ne null) && e.owner == scope) {
-
- // check no double def
- if (needsCheck) {
- var e1 = scope.lookupNextEntry(e)
- while ((e1 ne null) && e1.owner == scope) {
- if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
- (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe) || e.sym.isMacro && e1.sym.isMacro))
- // default getters are defined twice when multiple overloads have defaults. an
- // error for this is issued in RefChecks.checkDefaultsInOverloaded
- if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag &&
- !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) {
- log("Double definition detected:\n " +
- ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " +
- ((e1.sym.getClass, e1.sym.info, e1.sym.ownerChain)))
-
- DefDefinedTwiceError(e.sym, e1.sym)
- scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
- }
- e1 = scope.lookupNextEntry(e1)
+ var e = scope.elems
+ while ((e ne null) && e.owner == scope) {
+ var e1 = scope.lookupNextEntry(e)
+ while ((e1 ne null) && e1.owner == scope) {
+ if (!accesses(e.sym, e1.sym) && !accesses(e1.sym, e.sym) &&
+ (e.sym.isType || inBlock || (e.sym.tpe matches e1.sym.tpe)))
+ // default getters are defined twice when multiple overloads have defaults. an
+ // error for this is issued in RefChecks.checkDefaultsInOverloaded
+ if (!e.sym.isErroneous && !e1.sym.isErroneous && !e.sym.hasDefaultFlag &&
+ !e.sym.hasAnnotation(BridgeClass) && !e1.sym.hasAnnotation(BridgeClass)) {
+ log("Double definition detected:\n " +
+ ((e.sym.getClass, e.sym.info, e.sym.ownerChain)) + "\n " +
+ ((e1.sym.getClass, e1.sym.info, e1.sym.ownerChain)))
+
+ DefDefinedTwiceError(e.sym, e1.sym)
+ scope.unlink(e1) // need to unlink to avoid later problems with lub; see #2779
}
- }
-
- // add synthetics
- context.unit.synthetics get e.sym foreach { tree =>
- newStats += typedStat(tree) // might add even more synthetics to the scope
- context.unit.synthetics -= e.sym
+ e1 = scope.lookupNextEntry(e1)
}
-
e = e.next
}
- needsCheck = false
- // the type completer of a synthetic might add more synthetics. example: if the
- // factory method of a case class (i.e. the constructor) has a default.
- moreToAdd = initSize != scope.size
+ }
+
+ def addSynthetics(stats: List[Tree]): List[Tree] = {
+ val scope = if (inBlock) context.scope else context.owner.info.decls
+ var newStats = new ListBuffer[Tree]
+ var moreToAdd = true
+ while (moreToAdd) {
+ val initElems = scope.elems
+ for (sym <- scope)
+ for (tree <- context.unit.synthetics get sym) {
+ newStats += typedStat(tree) // might add even more synthetics to the scope
+ context.unit.synthetics -= sym
+ }
+ // the type completer of a synthetic might add more synthetics. example: if the
+ // factory method of a case class (i.e. the constructor) has a default.
+ moreToAdd = scope.elems ne initElems
}
if (newStats.isEmpty) stats
else {
// put default getters next to the method they belong to,
// same for companion objects. fixes #2489 and #4036.
+ // [Martin] This is pretty ugly. I think we could avoid
+ // this code by associating defaults and companion objects
+ // with the original tree instead of the new symbol.
def matches(stat: Tree, synt: Tree) = (stat, synt) match {
case (DefDef(_, statName, _, _, _, _), DefDef(mods, syntName, _, _, _, _)) =>
mods.hasDefaultFlag && syntName.toString.startsWith(statName.toString)
@@ -2548,7 +2657,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
context.updateBuffer(statsErrors)
if (phase.erasedTypes) stats1
- else checkNoDoubleDefsAndAddSynthetics(stats1)
+ else {
+ checkNoDoubleDefs(stats1)
+ addSynthetics(stats1)
+ }
}
def typedArg(arg: Tree, mode: Int, newmode: Int, pt: Type): Tree = {
@@ -2572,7 +2684,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
else if (isByNameParamType(formals.head)) 0
else BYVALmode
)
- val tree = typedArg(args.head, mode, typedMode, adapted.head)
+ var tree = typedArg(args.head, mode, typedMode, adapted.head)
+ if (hasPendingMacroExpansions) tree = macroExpandAll(this, tree)
// formals may be empty, so don't call tail
tree :: loop(args.tail, formals drop 1, adapted.tail)
}
@@ -2734,6 +2847,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def tryNamesDefaults: Tree = {
val lencmp = compareLengths(args, formals)
+ def checkNotMacro() = {
+ if (fun.symbol != null && fun.symbol.filter(sym => sym != null && sym.isTermMacro && !sym.isErroneous) != NoSymbol)
+ duplErrorTree(NamedAndDefaultArgumentsNotSupportedForMacros(tree, fun))
+ }
+
if (mt.isErroneous) duplErrTree
else if (inPatternMode(mode)) {
// #2064
@@ -2752,8 +2870,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
else if (isIdentity(argPos) && !isNamedApplyBlock(fun)) {
// if there's no re-ordering, and fun is not transformed, no need to transform
// more than an optimization, e.g. important in "synchronized { x = update-x }"
+ checkNotMacro()
doTypedApply(tree, fun, namelessArgs, mode, pt)
} else {
+ checkNotMacro()
transformNamedApplication(Typer.this, mode, pt)(
treeCopy.Apply(tree, fun, namelessArgs), argPos)
}
@@ -2761,6 +2881,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// defaults are needed. they are added to the argument list in named style as
// calls to the default getters. Example:
// foo[Int](a)() ==> foo[Int](a)(b = foo$qual.foo$default$2[Int](a))
+ checkNotMacro()
val fun1 = transformNamedApplication(Typer.this, mode, pt)(fun, x => x)
if (fun1.isErroneous) duplErrTree
else {
@@ -2799,7 +2920,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
(args exists isNamed) || // uses a named argument
isNamedApplyBlock(fun)) { // fun was transformed to a named apply block =>
// integrate this application into the block
- tryNamesDefaults
+ if (dyna.isApplyDynamicNamed(fun)) dyna.typedNamedApply(tree, fun, args, mode, pt)
+ else tryNamesDefaults
} else {
val tparams = context.extractUndetparams()
if (tparams.isEmpty) { // all type params are defined
@@ -2859,7 +2981,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
assert(!inPatternMode(mode), modeString(mode)) // this case cannot arise for patterns
val lenientTargs = protoTypeArgs(tparams, formals, mt.resultApprox, pt)
val strictTargs = map2(lenientTargs, tparams)((targ, tparam) =>
- if (targ == WildcardType) tparam.tpe else targ) //@M TODO: should probably be .tpeHK
+ if (targ == WildcardType) tparam.tpeHK else targ)
var remainingParams = paramTypes
def typedArgToPoly(arg: Tree, formal: Type): Tree = { //TR TODO: cleanup
val lenientPt = formal.instantiateTypeParams(tparams, lenientTargs)
@@ -3012,7 +3134,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (annInfo.atp.isErroneous) { hasError = true; None }
else Some(NestedAnnotArg(annInfo))
- // use of Array.apply[T: ClassManifest](xs: T*): Array[T]
+ // use of Array.apply[T: ArrayTag](xs: T*): Array[T]
// and Array.apply(x: Int, xs: Int*): Array[Int] (and similar)
case Apply(fun, args) =>
val typedFun = typed(fun, forFunMode(mode), WildcardType)
@@ -3103,12 +3225,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
for (sym <- names) {
// make sure the flags are up to date before erroring (jvm/t3415 fails otherwise)
sym.initialize
- if (!sym.hasAnnotation(AnnotationDefaultAttr) && !sym.hasDefaultFlag)
+ if (!sym.hasAnnotation(AnnotationDefaultAttr) && !sym.hasDefault)
reportAnnotationError(AnnotationMissingArgError(ann, annType, sym))
}
if (hasError) annotationError
- else AnnotationInfo(annType, List(), nvPairs map {p => (p._1, p._2.get)}).setOriginal(ann).setPos(ann.pos)
+ else AnnotationInfo(annType, List(), nvPairs map {p => (p._1.asInstanceOf[Name], p._2.get)}).setOriginal(Apply(typedFun, args).setPos(ann.pos)) // [Eugene+] why do we need this cast?
}
} else if (requireJava) {
reportAnnotationError(NestedAnnotationError(ann, annType))
@@ -3148,7 +3270,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def annInfo(t: Tree): AnnotationInfo = t match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
- AnnotationInfo(annType, args, List()).setOriginal(ann).setPos(t.pos)
+ AnnotationInfo(annType, args, List()).setOriginal(typedAnn).setPos(t.pos)
case Block(stats, expr) =>
context.warning(t.pos, "Usage of named or default arguments transformed this annotation\n"+
@@ -3200,14 +3322,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case tp => tp
}
- (hidden map { s =>
- // Hanging onto lower bound in case anything interesting
- // happens with it.
- (s, s.existentialBound match {
- case TypeBounds(lo, hi) => TypeBounds(lo, hiBound(s))
- case _ => hiBound(s)
- })
- }).toMap
+ // Hanging onto lower bound in case anything interesting
+ // happens with it.
+ mapFrom(hidden)(s => s.existentialBound match {
+ case TypeBounds(lo, hi) => TypeBounds(lo, hiBound(s))
+ case _ => hiBound(s)
+ })
}
/** Given a set `rawSyms` of term- and type-symbols, and a type
@@ -3231,7 +3351,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val typeParams: List[Symbol] = rawSyms map { sym =>
val name = sym.name match {
case x: TypeName => x
- case x => nme.singletonName(x)
+ case x => tpnme.singletonName(x)
}
val bound = allBounds(sym)
val sowner = if (isRawParameter(sym)) context.owner else sym.owner
@@ -3420,7 +3540,108 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case ErrorType =>
setError(treeCopy.TypeApply(tree, fun, args))
case _ =>
- TypedApplyDoesNotTakeTpeParametersError(tree, fun)
+ fun match {
+ // drop the application for an applyDynamic or selectDynamic call since it has been pushed down
+ case treeInfo.DynamicApplication(_, _) => fun
+ case _ => TypedApplyDoesNotTakeTpeParametersError(tree, fun)
+ }
+ }
+
+ object dyna {
+ import treeInfo.{isApplyDynamicName, DynamicUpdate, DynamicApplicationNamed}
+
+ def acceptsApplyDynamic(tp: Type) = tp.typeSymbol isNonBottomSubClass DynamicClass
+
+ /** Returns `Some(t)` if `name` can be selected dynamically on `qual`, `None` if not.
+ * `t` specifies the type to be passed to the applyDynamic/selectDynamic call (unless it is NoType)
+ * NOTE: currently either returns None or Some(NoType) (scala-virtualized extends this to Some(t) for selections on staged Structs)
+ */
+ def acceptsApplyDynamicWithType(qual: Tree, name: Name): Option[Type] =
+ // don't selectDynamic selectDynamic, do select dynamic at unknown type,
+ // in scala-virtualized, we may return a Some(tp) where tp ne NoType
+ if (!isApplyDynamicName(name) && acceptsApplyDynamic(qual.tpe.widen)) Some(NoType)
+ else None
+
+ def isDynamicallyUpdatable(tree: Tree) = tree match {
+ case DynamicUpdate(qual, name) =>
+ // if the qualifier is a Dynamic, that's all we need to know
+ acceptsApplyDynamic(qual.tpe)
+ case _ => false
+ }
+
+ def isApplyDynamicNamed(fun: Tree): Boolean = fun match {
+ case DynamicApplicationNamed(qual, _) if acceptsApplyDynamic(qual.tpe.widen) => true
+ case _ => false
+ // look deeper?
+ // val methPart = treeInfo.methPart(fun)
+ // println("methPart of "+ fun +" is "+ methPart)
+ // if (methPart ne fun) isApplyDynamicNamed(methPart)
+ // else false
+ }
+
+ def typedNamedApply(orig: Tree, fun: Tree, args: List[Tree], mode: Int, pt: Type): Tree = {
+ def argToBinding(arg: Tree): Tree = arg match {
+ case AssignOrNamedArg(Ident(name), rhs) => gen.mkTuple(List(CODE.LIT(name.toString), rhs))
+ case _ => gen.mkTuple(List(CODE.LIT(""), arg))
+ }
+ typed(treeCopy.Apply(orig, fun, args map argToBinding), mode, pt)
+ }
+
+ /** Translate selection that does not typecheck according to the normal rules into a selectDynamic/applyDynamic.
+ *
+ * foo.method("blah") ~~> foo.applyDynamic("method")("blah")
+ * foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah"))
+ * foo.varia = 10 ~~> foo.updateDynamic("varia")(10)
+ * foo.field ~~> foo.selectDynamic("field")
+ * foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13)
+ *
+ * what if we want foo.field == foo.selectDynamic("field") == 1, but `foo.field = 10` == `foo.selectDynamic("field").update(10)` == ()
+ * what would the signature for selectDynamic be? (hint: it needs to depend on whether an update call is coming or not)
+ *
+ * need to distinguish selectDynamic and applyDynamic somehow: the former must return the selected value, the latter must accept an apply or an update
+ * - could have only selectDynamic and pass it a boolean whether more is to come,
+ * so that it can either return the bare value or something that can handle the apply/update
+ * HOWEVER that makes it hard to return unrelated values for the two cases
+ * --> selectDynamic's return type is now dependent on the boolean flag whether more is to come
+ * - simplest solution: have two method calls
+ *
+ */
+ def mkInvoke(cxTree: Tree, tree: Tree, qual: Tree, name: Name): Option[Tree] =
+ acceptsApplyDynamicWithType(qual, name) map { tp =>
+ // tp eq NoType => can call xxxDynamic, but not passing any type args (unless specified explicitly by the user)
+ // in scala-virtualized, when not NoType, tp is passed as type argument (for selection on a staged Struct)
+
+ // strip off type application -- we're not doing much with outer, so don't bother preserving cxTree's attributes etc
+ val (outer, explicitTargs) = cxTree match {
+ case TypeApply(fun, targs) => (fun, targs)
+ case Apply(TypeApply(fun, targs), args) => (Apply(fun, args), targs)
+ case t => (t, Nil)
+ }
+
+ @inline def hasNamedArg(as: List[Tree]) = as collectFirst {case AssignOrNamedArg(lhs, rhs) =>} nonEmpty
+
+ // note: context.tree includes at most one Apply node
+ // thus, we can't use it to detect we're going to receive named args in expressions such as:
+ // qual.sel(a)(a2, arg2 = "a2")
+ val oper = outer match {
+ case Apply(`tree`, as) =>
+ val oper =
+ if (hasNamedArg(as)) nme.applyDynamicNamed
+ else nme.applyDynamic
+ // not supported: foo.bar(a1,..., an: _*)
+ if (treeInfo.isWildcardStarArgList(as)) {
+ DynamicVarArgUnsupported(tree, oper)
+ return Some(setError(tree))
+ } else oper
+ case Assign(`tree`, _) => nme.updateDynamic
+ case _ => nme.selectDynamic
+ }
+
+ val dynSel = Select(qual, oper)
+ val tappSel = if (explicitTargs nonEmpty) TypeApply(dynSel, explicitTargs) else dynSel
+
+ atPos(qual.pos)(Apply(tappSel, List(Literal(Constant(name.decode)))))
+ }
}
@inline final def deindentTyping() = context.typingIndentLevel -= 2
@@ -3434,12 +3655,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
println(s)
}
- protected def typed1(tree: Tree, mode: Int, pt: Type): Tree = {
+ def typed1(tree: Tree, mode: Int, pt: Type): Tree = {
def isPatternMode = inPatternMode(mode)
//Console.println("typed1("+tree.getClass()+","+Integer.toHexString(mode)+","+pt+")")
- def ptOrLub(tps: List[Type]) = if (isFullyDefined(pt)) (pt, false) else weakLub(tps map (_.deconst))
-
//@M! get the type of the qualifier in a Select tree, otherwise: NoType
def prefixType(fun: Tree): Type = fun match {
case Select(qualifier, _) => qualifier.tpe
@@ -3448,10 +3667,26 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
def typedAnnotated(ann: Tree, arg1: Tree): Tree = {
- def mkTypeTree(tpe: Type) = TypeTree(tpe) setOriginal tree setPos tree.pos.focus
/** mode for typing the annotation itself */
val annotMode = mode & ~TYPEmode | EXPRmode
+ def resultingTypeTree(tpe: Type) = {
+ // we need symbol-ful originals for reification
+ // hence we go the extra mile to hand-craft tis guy
+ val original =
+ if (arg1.isType)
+ (tree, arg1) match {
+ case (Annotated(annot, arg), tt @ TypeTree()) => Annotated(annot, tt.original)
+ // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)"
+ case (Annotated(annot, arg), _) => Annotated(annot, arg1)
+ case _ => throw new Error("unexpected trees in typedAnnotated: tree = %s, arg1 = %s".format(showRaw(tree), showRaw(arg1)))
+ }
+ else
+ tree
+ original setType ann.tpe
+ TypeTree(tpe) setOriginal original setPos tree.pos.focus
+ }
+
if (arg1.isType) {
// make sure the annotation is only typechecked once
if (ann.tpe == null) {
@@ -3494,11 +3729,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
arg1 // simply drop erroneous annotations
else {
ann.tpe = atype
- mkTypeTree(atype)
+ resultingTypeTree(atype)
}
} else {
// the annotation was typechecked before
- mkTypeTree(ann.tpe)
+ resultingTypeTree(ann.tpe)
}
}
else {
@@ -3507,7 +3742,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
ann.tpe = arg1.tpe.withAnnotation(annotInfo)
}
val atype = ann.tpe
- Typed(arg1, mkTypeTree(atype)) setPos tree.pos setType atype
+ Typed(arg1, resultingTypeTree(atype)) setPos tree.pos setType atype
}
}
@@ -3552,7 +3787,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
treeCopy.ArrayValue(tree, elemtpt1, elems1)
.setType(
(if (isFullyDefined(pt) && !phase.erasedTypes) pt
- else appliedType(ArrayClass.typeConstructor, List(elemtpt1.tpe))).notNull)
+ else arrayType(elemtpt1.tpe)).notNull)
}
def typedAssign(lhs: Tree, rhs: Tree): Tree = {
@@ -3577,10 +3812,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case _ =>
}
}
+// if (varsym.isVariable ||
+// // setter-rewrite has been done above, so rule out methods here, but, wait a minute, why are we assigning to non-variables after erasure?!
+// (phase.erasedTypes && varsym.isValue && !varsym.isMethod)) {
if (varsym.isVariable || varsym.isValue && phase.erasedTypes) {
val rhs1 = typed(rhs, EXPRmode | BYVALmode, lhs1.tpe)
treeCopy.Assign(tree, lhs1, checkDead(rhs1)) setType UnitClass.tpe
}
+ else if(dyna.isDynamicallyUpdatable(lhs1)) {
+ val rhs1 = typed(rhs, EXPRmode | BYVALmode, WildcardType)
+ typed1(Apply(lhs1, List(rhs1)), mode, pt)
+ }
else fail()
}
@@ -3595,14 +3837,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
lazy val thenTp = packedType(thenp1, context.owner)
lazy val elseTp = packedType(elsep1, context.owner)
+ // println("typedIf: "+(thenp1.tpe, elsep1.tpe, ptOrLub(List(thenp1.tpe, elsep1.tpe)),"\n", thenTp, elseTp, thenTp =:= elseTp))
val (owntype, needAdapt) =
// in principle we should pack the types of each branch before lubbing, but lub doesn't really work for existentials anyway
// in the special (though common) case where the types are equal, it pays to pack before comparing
// especially virtpatmat needs more aggressive unification of skolemized types
// this breaks src/library/scala/collection/immutable/TrieIterator.scala
- if (opt.virtPatmat && !isPastTyper && thenTp =:= elseTp) (thenp1.tpe, false) // use unpacked type
+ if ( opt.virtPatmat && !isPastTyper
+ && thenp1.tpe.annotations.isEmpty && elsep1.tpe.annotations.isEmpty // annotated types need to be lubbed regardless (at least, continations break if you by pass them like this)
+ && thenTp =:= elseTp
+ ) (thenp1.tpe, false) // use unpacked type
// TODO: skolemize (lub of packed types) when that no longer crashes on files/pos/t4070b.scala
- else ptOrLub(List(thenp1.tpe, elsep1.tpe))
+ else ptOrLub(List(thenp1.tpe, elsep1.tpe), pt)
if (needAdapt) { //isNumericValueType(owntype)) {
thenp1 = adapt(thenp1, mode, owntype)
@@ -3612,33 +3858,26 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
}
- def typedMatch(tree: Tree, selector: Tree, cases: List[CaseDef]): Tree = {
- if (opt.virtPatmat && !isPastTyper) {
- if (selector ne EmptyTree) {
- val (selector1, selectorTp, casesAdapted, ownType, doTranslation) = prepareTranslateMatch(selector, cases, mode, pt)
- typed(translateMatch(selector1, selectorTp, casesAdapted, ownType, doTranslation), mode, pt)
- } else typedMatchAnonFun(tree, cases, mode, pt)
- } else if (selector == EmptyTree) {
- val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1
- val params = for (i <- List.range(0, arity)) yield
- atPos(tree.pos.focusStart) {
- ValDef(Modifiers(PARAM | SYNTHETIC),
- unit.freshTermName("x" + i + "$"), TypeTree(), EmptyTree)
- }
- val ids = for (p <- params) yield Ident(p.name)
- val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
- val body = treeCopy.Match(tree, selector1, cases)
- typed1(atPos(tree.pos) { Function(params, body) }, mode, pt)
- } else {
- val selector1 = checkDead(typed(selector, EXPRmode | BYVALmode, WildcardType))
- var cases1 = typedCases(cases, packCaptured(selector1.tpe.widen), pt)
- val (owntype, needAdapt) = ptOrLub(cases1 map (_.tpe))
- if (needAdapt) {
- cases1 = cases1 map (adaptCase(_, mode, owntype))
+ // under -Xexperimental (and not -Xoldpatmat), and when there's a suitable __match in scope, virtualize the pattern match
+ // otherwise, type the Match and leave it until phase `patmat` (immediately after typer)
+ // empty-selector matches are transformed into synthetic PartialFunction implementations when the expected type demands it
+ def typedVirtualizedMatch(tree: Tree, selector: Tree, cases: List[CaseDef]): Tree =
+ if (selector == EmptyTree) {
+ if (newPatternMatching && (pt.typeSymbol == PartialFunctionClass)) (new MatchFunTyper(tree, cases, mode, pt)).translated
+ else {
+ val arity = if (isFunctionType(pt)) pt.normalize.typeArgs.length - 1 else 1
+ val params = for (i <- List.range(0, arity)) yield
+ atPos(tree.pos.focusStart) {
+ ValDef(Modifiers(PARAM | SYNTHETIC),
+ unit.freshTermName("x" + i + "$"), TypeTree(), EmptyTree)
+ }
+ val ids = for (p <- params) yield Ident(p.name)
+ val selector1 = atPos(tree.pos.focusStart) { if (arity == 1) ids.head else gen.mkTuple(ids) }
+ val body = treeCopy.Match(tree, selector1, cases)
+ typed1(atPos(tree.pos) { Function(params, body) }, mode, pt)
}
- treeCopy.Match(tree, selector1, cases1) setType owntype
- }
- }
+ } else
+ virtualizedMatch(typedMatch(selector, cases, mode, pt, tree), mode, pt)
def typedReturn(expr: Tree) = {
val enclMethod = context.enclMethod
@@ -3673,6 +3912,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (checkStablePrefixClassType(tpt0))
if (tpt0.hasSymbol && !tpt0.symbol.typeParams.isEmpty) {
context.undetparams = cloneSymbols(tpt0.symbol.typeParams)
+ notifyUndetparamsAdded(context.undetparams)
TypeTree().setOriginal(tpt0)
.setType(appliedType(tpt0.tpe, context.undetparams map (_.tpeHK))) // @PP: tpeHK! #3343, #4018, #4347.
} else tpt0
@@ -3696,6 +3936,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val sym = tp.typeSymbol.initialize
if (sym.isAbstractType || sym.hasAbstractFlag)
IsAbstractError(tree, sym)
+ else if (isPrimitiveValueClass(sym)) {
+ NotAMemberError(tpt, TypeTree(tp), nme.CONSTRUCTOR)
+ setError(tpt)
+ }
else if (!( tp == sym.thisSym.tpe // when there's no explicit self type -- with (#3612) or without self variable
// sym.thisSym.tpe == tp.typeOfThis (except for objects)
|| narrowRhs(tp) <:< tp.typeOfThis
@@ -3901,7 +4145,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
def convertToAssignment(fun: Tree, qual: Tree, name: Name, args: List[Tree]): Tree = {
- val prefix = name.subName(0, name.length - nme.EQL.length)
+ val prefix = name stripSuffix nme.EQL
def mkAssign(vble: Tree): Tree =
Assign(
vble,
@@ -3910,21 +4154,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
) setPos tree.pos
def mkUpdate(table: Tree, indices: List[Tree]) = {
- gen.evalOnceAll(table :: indices, context.owner, context.unit) { ts =>
- val tab = ts.head
- val is = ts.tail
- Apply(
- Select(tab(), nme.update) setPos table.pos,
- ((is map (i => i())) ::: List(
- Apply(
- Select(
- Apply(
- Select(tab(), nme.apply) setPos table.pos,
- is map (i => i())) setPos qual.pos,
- prefix) setPos fun.pos,
- args) setPos tree.pos)
- )
- ) setPos tree.pos
+ gen.evalOnceAll(table :: indices, context.owner, context.unit) {
+ case tab :: is =>
+ def mkCall(name: Name, extraArgs: Tree*) = (
+ Apply(
+ Select(tab(), name) setPos table.pos,
+ is.map(i => i()) ++ extraArgs
+ ) setPos tree.pos
+ )
+ mkCall(
+ nme.update,
+ Apply(Select(mkCall(nme.apply), prefix) setPos fun.pos, args) setPos tree.pos
+ )
}
}
@@ -3991,15 +4232,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
treeCopy.Super(tree, qual1, mix) setType SuperType(clazz.thisType, owntype)
}
- def typedThis(qual: Name) = {
- val qualifyingClassSym = if (tree.symbol != NoSymbol) Some(tree.symbol) else qualifyingClass(tree, qual)
- qualifyingClassSym match {
- case Some(clazz) =>
- tree setSymbol clazz setType clazz.thisType.underlying
- if (isStableContext(tree, mode, pt)) tree setType clazz.thisType
- tree
- case None => tree
- }
+ def typedThis(qual: Name) = tree.symbol orElse qualifyingClass(tree, qual, packageOK = false) match {
+ case NoSymbol => tree
+ case clazz =>
+ tree setSymbol clazz setType clazz.thisType.underlying
+ if (isStableContext(tree, mode, pt)) tree setType clazz.thisType else tree
}
/** Attribute a selection where <code>tree</code> is <code>qual.name</code>.
@@ -4010,31 +4247,22 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
* @return ...
*/
def typedSelect(qual: Tree, name: Name): Tree = {
- val sym =
- if (tree.symbol != NoSymbol) {
- if (phase.erasedTypes && qual.isInstanceOf[Super])
- qual.tpe = tree.symbol.owner.tpe
- if (false && settings.debug.value) { // todo: replace by settings.check.value?
- val alts = qual.tpe.member(tree.symbol.name).alternatives
- if (!(alts exists (alt =>
- alt == tree.symbol || alt.isTerm && (alt.tpe matches tree.symbol.tpe))))
- assert(false, "symbol "+tree.symbol+tree.symbol.locationString+" not in "+alts+" of "+qual.tpe+
- "\n members = "+qual.tpe.members+
- "\n type history = "+qual.tpe.termSymbol.infosString+
- "\n phase = "+phase)
- }
- tree.symbol
- } else {
- member(qual, name)
+ def asDynamicCall = dyna.mkInvoke(context.tree, tree, qual, name) map (typed1(_, mode, pt))
+
+ val sym = tree.symbol orElse member(qual, name) orElse {
+ // symbol not found? --> try to convert implicitly to a type that does have the required
+ // member. Added `| PATTERNmode` to allow enrichment in patterns (so we can add e.g., an
+ // xml member to StringContext, which in turn has an unapply[Seq] method)
+ if (name != nme.CONSTRUCTOR && inExprModeOr(mode, PATTERNmode)) {
+ val qual1 = adaptToMemberWithArgs(tree, qual, name, mode, true, true)
+ if (qual1 ne qual)
+ return typed(treeCopy.Select(tree, qual1, name), mode, pt)
}
- if (sym == NoSymbol && name != nme.CONSTRUCTOR && (mode & EXPRmode) != 0) {
- val qual1 =
- if (member(qual, name) != NoSymbol) qual
- else adaptToMemberWithArgs(tree, qual, name, mode, true, true)
-
- if (qual1 ne qual)
- return typed(treeCopy.Select(tree, qual1, name), mode, pt)
+ NoSymbol
}
+ if (phase.erasedTypes && qual.isInstanceOf[Super] && tree.symbol != NoSymbol)
+ qual.tpe = tree.symbol.owner.tpe
+
if (!reallyExists(sym)) {
if (context.owner.enclosingTopLevelClass.isJavaDefined && name.isTypeName) {
val tree1 = atPos(tree.pos) { gen.convertToSelectFromType(qual, name) }
@@ -4042,26 +4270,14 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
}
// try to expand according to Dynamic rules.
+ asDynamicCall foreach (x => return x)
- if (settings.Xexperimental.value && (qual.tpe.widen.typeSymbol isNonBottomSubClass DynamicClass)) {
- var dynInvoke = Apply(Select(qual, nme.applyDynamic), List(Literal(Constant(name.decode))))
- context.tree match {
- case Apply(tree1, args) if tree1 eq tree =>
- ;
- case _ =>
- dynInvoke = Apply(dynInvoke, List())
- }
- return typed1(util.trace("dynatype: ")(dynInvoke), mode, pt)
- }
-
- if (settings.debug.value) {
- log(
- "qual = "+qual+":"+qual.tpe+
- "\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+
- "\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+
- "\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner
- )
- }
+ debuglog(
+ "qual = "+qual+":"+qual.tpe+
+ "\nSymbol="+qual.tpe.termSymbol+"\nsymbol-info = "+qual.tpe.termSymbol.info+
+ "\nscope-id = "+qual.tpe.termSymbol.info.decls.hashCode()+"\nmembers = "+qual.tpe.members+
+ "\nname = "+name+"\nfound = "+sym+"\nowner = "+context.enclClass.owner
+ )
def makeInteractiveErrorTree = {
val tree1 = tree match {
@@ -4093,7 +4309,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
if (err.kind != ErrorKinds.Access) {
context issue err
return setError(tree)
- } else (tree1, Some(err))
+ }
+ else (tree1, Some(err))
case SilentResultValue(treeAndPre) =>
(stabilize(treeAndPre._1, treeAndPre._2, mode, pt), None)
}
@@ -4110,7 +4327,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
result match {
// could checkAccessible (called by makeAccessible) potentially have skipped checking a type application in qual?
- case SelectFromTypeTree(qual@TypeTree(), name) if qual.tpe.typeArgs nonEmpty => // TODO: somehow the new qual is not checked in refchecks
+ case SelectFromTypeTree(qual@TypeTree(), name) if qual.tpe.typeArgs.nonEmpty => // TODO: somehow the new qual is not checked in refchecks
treeCopy.SelectFromTypeTree(
result,
(TypeTreeWithDeferredRefCheck(){ () => val tp = qual.tpe; val sym = tp.typeSymbolDirect
@@ -4123,10 +4340,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
val qual1 = adaptToMemberWithArgs(tree, qual, name, mode, false, false)
if (!qual1.isErrorTyped && (qual1 ne qual))
typed(Select(qual1, name) setPos tree.pos, mode, pt)
- else {
- issue(accessibleError.get)
- setError(tree)
- }
+ else
+ // before failing due to access, try a dynamic call.
+ asDynamicCall getOrElse {
+ issue(accessibleError.get)
+ setError(tree)
+ }
case _ =>
result
}
@@ -4430,7 +4649,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
typedValDef(vdef)
case ddef @ DefDef(_, _, _, _, _, _) =>
- newTyper(context.makeNewScope(tree, sym)).typedDefDef(ddef)
+ // flag default getters for constructors. An actual flag would be nice. See SI-5543.
+ //val flag = ddef.mods.hasDefaultFlag && ddef.mods.hasFlag(PRESUPER)
+ val flag = ddef.mods.hasDefaultFlag && sym.owner.isModuleClass &&
+ nme.defaultGetterToMethod(sym.name) == nme.CONSTRUCTOR
+ newTyper(context.makeNewScope(tree, sym)).constrTyperIf(flag).typedDefDef(ddef)
case tdef @ TypeDef(_, _, _, _) =>
typedTypeDef(tdef)
@@ -4501,7 +4724,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
typedIf(cond, thenp, elsep)
case tree @ Match(selector, cases) =>
- typedMatch(tree, selector, cases)
+ typedVirtualizedMatch(tree, selector, cases)
case Return(expr) =>
typedReturn(expr)
@@ -4511,16 +4734,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
var catches1 = typedCases(catches, ThrowableClass.tpe, pt)
val finalizer1 = if (finalizer.isEmpty) finalizer
else typed(finalizer, UnitClass.tpe)
- val (owntype, needAdapt) = ptOrLub(block1.tpe :: (catches1 map (_.tpe)))
+ val (owntype, needAdapt) = ptOrLub(block1.tpe :: (catches1 map (_.tpe)), pt)
if (needAdapt) {
block1 = adapt(block1, mode, owntype)
catches1 = catches1 map (adaptCase(_, mode, owntype))
}
- if(!isPastTyper && opt.virtPatmat) {
- catches1 = (MatchTranslator(this)).translateTry(catches1, owntype, tree.pos)
- }
-
treeCopy.Try(tree, block1, catches1, finalizer1) setType owntype
case Throw(expr) =>
@@ -4531,7 +4750,18 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
typedNew(tpt)
case Typed(expr, Function(List(), EmptyTree)) =>
- typedEta(checkDead(typed1(expr, mode, pt)))
+ // find out whether the programmer is trying to eta-expand a macro def
+ // to do that we need to typecheck the tree first (we need a symbol of the eta-expandee)
+ // that typecheck must not trigger macro expansions, so we explicitly prohibit them
+ // Q: "but, " - you may ask - ", `typed1` doesn't call adapt, which does macro expansion, so why explicit check?"
+ // A: solely for robustness reasons. this mechanism might change in the future, which might break unprotected code
+ val expr1 = context.withMacrosDisabled(typed1(expr, mode, pt))
+ expr1 match {
+ case macroDef if macroDef.symbol != null && macroDef.symbol.isTermMacro && !macroDef.symbol.isErroneous =>
+ MacroEtaError(expr1)
+ case _ =>
+ typedEta(checkDead(expr1))
+ }
case Typed(expr0, tpt @ Ident(tpnme.WILDCARD_STAR)) =>
val expr = typed(expr0, onlyStickyModes(mode), WildcardType)
@@ -4605,18 +4835,17 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
tpt.tpe.typeSymbol == ArrayClass &&
args.length == 1 &&
erasure.GenericArray.unapply(tpt.tpe).isDefined) => // !!! todo simplify by using extractor
- // convert new Array[T](len) to evidence[ClassManifest[T]].newArray(len)
- // convert new Array^N[T](len) for N > 1 to evidence[ClassManifest[T]].newArrayN(len)
- val Some((level, manifType)) = erasure.GenericArray.unapply(tpt.tpe)
- if (level > MaxArrayDims)
- MultiDimensionalArrayError(tree)
- else {
- val newArrayApp = atPos(tree.pos) {
- val manif = getManifestTree(tree, manifType, false)
- new ApplyToImplicitArgs(Select(manif, if (level == 1) "newArray" else "newArray"+level), args)
- }
- typed(newArrayApp, mode, pt)
+ // convert new Array[T](len) to evidence[ClassTag[T]].newArray(len)
+ // convert new Array^N[T](len) for N > 1 to evidence[ClassTag[Array[...Array[T]...]]].newArray(len), where Array HK gets applied (N-1) times
+ // [Eugene] no more MaxArrayDims. ClassTags are flexible enough to allow creation of arrays of arbitrary dimensionality (w.r.t JVM restrictions)
+ val Some((level, componentType)) = erasure.GenericArray.unapply(tpt.tpe)
+ val tagType = List.iterate(componentType, level)(tpe => appliedType(ArrayClass.asType, List(tpe))).last
+ val newArrayApp = atPos(tree.pos) {
+ val tag = resolveArrayTag(tagType, tree.pos)
+ if (tag.isEmpty) MissingArrayTagError(tree, tagType)
+ else new ApplyToImplicitArgs(Select(tag, nme.newArray), args)
}
+ typed(newArrayApp, mode, pt)
case tree1 =>
tree1
}
@@ -4663,6 +4892,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
else
typedSelect(qual1, name)
+ if (tree.isInstanceOf[PostfixSelect])
+ checkFeature(tree.pos, PostfixOpsFeature, name.decode)
+ if (tree1.symbol != null && tree1.symbol.isOnlyRefinementMember)
+ checkFeature(tree1.pos, ReflectiveCallsFeature, tree1.symbol.toString)
+
if (qual1.symbol == RootPackage) treeCopy.Ident(tree1, name)
else tree1
@@ -4676,7 +4910,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
case ReferenceToBoxed(idt @ Ident(_)) =>
val id1 = typed1(idt, mode, pt) match { case id: Ident => id }
- treeCopy.ReferenceToBoxed(tree, id1) setType AnyRefClass.tpe
+ // [Eugene] am I doing it right?
+ val erasedTypes = phaseId(currentPeriod) >= currentRun.erasurePhase.id
+ val tpe = capturedVariableType(idt.symbol, erasedTypes = erasedTypes)
+ treeCopy.ReferenceToBoxed(tree, id1) setType tpe
case Literal(value) =>
tree setType (
@@ -4705,9 +4942,11 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
treeCopy.TypeBoundsTree(tree, lo1, hi1) setType TypeBounds(lo1.tpe, hi1.tpe)
case etpt @ ExistentialTypeTree(_, _) =>
- typerWithLocalContext(context.makeNewScope(tree, context.owner)){
+ val tree1 = typerWithLocalContext(context.makeNewScope(tree, context.owner)){
_.typedExistentialTypeTree(etpt, mode)
}
+ checkExistentialsFeature(tree1.pos, tree1.tpe, "the existential type")
+ tree1
case dc@TypeTreeWithDeferredRefCheck() => dc // TODO: should we re-type the wrapped tree? then we need to change TypeTreeWithDeferredRefCheck's representation to include the wrapped tree explicitly (instead of in its closure)
case tpt @ TypeTree() =>
@@ -4757,6 +4996,8 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
ptLine("typing %s: pt = %s".format(ptTree(tree), pt),
"undetparams" -> context.undetparams,
"implicitsEnabled" -> context.implicitsEnabled,
+ "enrichmentEnabled" -> context.enrichmentEnabled,
+ "mode" -> modeString(mode),
"silent" -> context.bufferErrors,
"context.owner" -> context.owner
)
@@ -4860,7 +5101,22 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// We disable implicits because otherwise some constructs will
// type check which should not. The pattern matcher does not
// perform implicit conversions in an attempt to consummate a match.
- context.withImplicitsDisabled(typed(tree, PATTERNmode, pt))
+
+ // on the one hand,
+ // "abc" match { case Seq('a', 'b', 'c') => true }
+ // should be ruled out statically, otherwise this is a runtime
+ // error both because there is an implicit from String to Seq
+ // (even though such implicits are not used by the matcher) and
+ // because the typer is fine with concluding that "abc" might
+ // be of type "String with Seq[T]" and thus eligible for a call
+ // to unapplySeq.
+
+ // on the other hand, we want to be able to use implicits to add members retro-actively (e.g., add xml to StringContext)
+
+ // as a compromise, context.enrichmentEnabled tells adaptToMember to go ahead and enrich,
+ // but arbitrary conversions (in adapt) are disabled
+ // TODO: can we achieve the pattern matching bit of the string interpolation SIP without this?
+ context.withImplicitsDisabledAllowEnrichment(typed(tree, PATTERNmode, pt))
}
/** Types a (fully parameterized) type tree */
@@ -4913,31 +5169,47 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def typedTypeConstructor(tree: Tree): Tree = typedTypeConstructor(tree, NOmode)
def computeType(tree: Tree, pt: Type): Type = {
+ // macros employ different logic of `computeType`
+ assert(!context.owner.isTermMacro, context.owner)
val tree1 = typed(tree, pt)
transformed(tree) = tree1
- packedType(tree1, context.owner)
+ val tpe = packedType(tree1, context.owner)
+ checkExistentialsFeature(tree.pos, tpe, "inferred existential type")
+ tpe
}
- def transformedOrTyped(tree: Tree, mode: Int, pt: Type): Tree = transformed.get(tree) match {
- case Some(tree1) => transformed -= tree; tree1
- case None => typed(tree, mode, pt)
+ def computeMacroDefType(tree: Tree, pt: Type): Type = {
+ assert(context.owner.isTermMacro, context.owner)
+ assert(tree.symbol.isTermMacro, tree.symbol)
+ assert(tree.isInstanceOf[DefDef], tree.getClass)
+ val ddef = tree.asInstanceOf[DefDef]
+
+ val tree1 =
+ if (transformed contains ddef.rhs) {
+ // macro defs are typechecked in `methodSig` (by calling this method) in order to establish their link to macro implementation asap
+ // if a macro def doesn't have explicitly specified return type, this method will be called again by `assignTypeToTree`
+ // here we guard against this case
+ transformed(ddef.rhs)
+ } else {
+ val tree1 = typedMacroBody(this, ddef)
+ transformed(ddef.rhs) = tree1
+ tree1
+ }
+
+ val isMacroBodyOkay = !tree.symbol.isErroneous && !(tree1 exists (_.isErroneous))
+ if (isMacroBodyOkay) computeMacroDefTypeFromMacroImpl(ddef, tree.symbol, tree1.symbol) else AnyClass.tpe
}
- def findManifest(tp: Type, full: Boolean) = beforeTyper {
- inferImplicit(
- EmptyTree,
- appliedType((if (full) FullManifestClass else PartialManifestClass).typeConstructor, List(tp)),
- true, false, context)
+ def transformedOr(tree: Tree, op: => Tree): Tree = transformed.get(tree) match {
+ case Some(tree1) => transformed -= tree; tree1
+ case None => op
}
- def getManifestTree(tree: Tree, tp: Type, full: Boolean): Tree = {
- val manifestOpt = findManifest(tp, full)
- if (manifestOpt.tree.isEmpty) {
- MissingManifestError(tree, full, tp)
- } else {
- manifestOpt.tree
- }
+ def transformedOrTyped(tree: Tree, mode: Int, pt: Type): Tree = transformed.get(tree) match {
+ case Some(tree1) => transformed -= tree; tree1
+ case None => typed(tree, mode, pt)
}
+
/*
def convertToTypeTree(tree: Tree): Tree = tree match {
case TypeTree() => tree
diff --git a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
index 4f5b6868ae..1ebcea4a07 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Unapplies.scala
@@ -112,8 +112,8 @@ trait Unapplies extends ast.TreeDSL
private def toIdent(x: DefTree) = Ident(x.name) setPos x.pos.focus
- private def classType(cdef: ClassDef, tparams: List[TypeDef]): Tree = {
- val tycon = REF(cdef.symbol)
+ private def classType(cdef: ClassDef, tparams: List[TypeDef], symbolic: Boolean = true): Tree = {
+ val tycon = if (symbolic) REF(cdef.symbol) else Ident(cdef.name)
if (tparams.isEmpty) tycon else AppliedTypeTree(tycon, tparams map toIdent)
}
@@ -166,15 +166,20 @@ trait Unapplies extends ast.TreeDSL
/** The apply method corresponding to a case class
*/
- def caseModuleApplyMeth(cdef: ClassDef): DefDef = {
+ def factoryMeth(mods: Modifiers, name: TermName, cdef: ClassDef, symbolic: Boolean): DefDef = {
val tparams = cdef.tparams map copyUntypedInvariant
val cparamss = constrParamss(cdef)
+ def classtpe = classType(cdef, tparams, symbolic)
atPos(cdef.pos.focus)(
- DefDef(caseMods, nme.apply, tparams, cparamss, classType(cdef, tparams),
- New(classType(cdef, tparams), mmap(cparamss)(gen.paramToArg)))
+ DefDef(mods, name, tparams, cparamss, classtpe,
+ New(classtpe, mmap(cparamss)(gen.paramToArg)))
)
}
+ /** The apply method corresponding to a case class
+ */
+ def caseModuleApplyMeth(cdef: ClassDef): DefDef = factoryMeth(caseMods, nme.apply, cdef, symbolic = true)
+
/** The unapply method corresponding to a case class
*/
def caseModuleUnapplyMeth(cdef: ClassDef): DefDef = {
@@ -195,7 +200,7 @@ trait Unapplies extends ast.TreeDSL
def caseClassCopyMeth(cdef: ClassDef): Option[DefDef] = {
def isDisallowed(vd: ValDef) = isRepeatedParamType(vd.tpt) || isByNameParamType(vd.tpt)
val cparamss = constrParamss(cdef)
- val flat = cparamss flatten
+ val flat = cparamss.flatten
if (cdef.symbol.hasAbstractFlag || (flat exists isDisallowed)) None
else {
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index ce10ee34a2..48ec941b50 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -26,12 +26,12 @@ object ClassPath {
def scalaLibrary = locate[Option[_]]
def scalaCompiler = locate[Global]
- def infoFor[T](value: T) = info(value.getClass)
- def info[T](clazz: Class[T]) = new ClassAndJarInfo()(ClassManifest fromClass clazz)
- def info[T: ClassManifest] = new ClassAndJarInfo[T]
- def locate[T: ClassManifest] = info[T] rootClasspath
- def locateJar[T: ClassManifest] = info[T].rootPossibles find (x => isJarOrZip(x)) map (x => File(x))
- def locateDir[T: ClassManifest] = info[T].rootPossibles find (_.isDirectory) map (_.toDirectory)
+ def infoFor[T](value: T) = info(value.getClass)
+ def info[T](clazz: Class[T]) = new ClassAndJarInfo()(ClassTag[T](clazz))
+ def info[T: ClassTag] = new ClassAndJarInfo[T]
+ def locate[T: ClassTag] = info[T].rootClasspath
+ def locateJar[T: ClassTag] = info[T].rootPossibles find (x => isJarOrZip(x)) map (x => File(x))
+ def locateDir[T: ClassTag] = info[T].rootPossibles find (_.isDirectory) map (_.toDirectory)
/** Expand single path entry */
private def expandS(pattern: String): List[String] = {
@@ -373,7 +373,7 @@ extends ClassPath[T] {
this(entries.toIndexedSeq, context)
def name = entries.head.name
- def asURLs = entries flatMap (_.asURLs) toList
+ def asURLs = (entries flatMap (_.asURLs)).toList
lazy val sourcepaths: IndexedSeq[AbstractFile] = entries flatMap (_.sourcepaths)
override def origin = Some(entries map (x => x.origin getOrElse x.name) mkString ("Merged(", ", ", ")"))
diff --git a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
index 00fe49d36a..78bfd5e908 100644
--- a/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
+++ b/src/compiler/scala/tools/nsc/util/CommandLineParser.scala
@@ -20,11 +20,10 @@ import scala.collection.mutable.ListBuffer
*/
trait ParserUtil extends Parsers {
- class ParserPlus[+T](underlying: Parser[T]) {
+ protected implicit class ParserPlus[+T](underlying: Parser[T]) {
def !~>[U](p: => Parser[U]): Parser[U] = (underlying ~! p) ^^ { case a~b => b }
def <~![U](p: => Parser[U]): Parser[T] = (underlying ~! p) ^^ { case a~b => a }
}
- protected implicit def parser2parserPlus[T](p: Parser[T]): ParserPlus[T] = new ParserPlus(p)
}
case class CommandLine(
diff --git a/src/compiler/scala/tools/nsc/util/Exceptional.scala b/src/compiler/scala/tools/nsc/util/Exceptional.scala
index 667b7d15a6..7452aa1b67 100644
--- a/src/compiler/scala/tools/nsc/util/Exceptional.scala
+++ b/src/compiler/scala/tools/nsc/util/Exceptional.scala
@@ -5,6 +5,7 @@ import java.util.concurrent.ExecutionException
import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException }
import io.{ Sources, Fileish }
import scala.tools.util.StringOps._
+import language.implicitConversions
/** A simple throwable wrapper so it looks more like a parade of
* glittering frame-shaped beauties than the other thing.
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index bc74717366..208cd5703a 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -33,62 +33,32 @@ object Position {
}
}
-/**
- * A tree does not directly store a Position. It stores a TreeAnnotation, which /typically/ is a Position.
- *
- * A TreeAnnotion may encompass more than just a Position, though, depending on the exact subclass of TreeAnnotation.
- */
-trait TreeAnnotation {
- def pos: Position
-}
+trait Position extends scala.reflect.api.Position with scala.reflect.api.Attachment {
+ /** Exposes itself as payload of Attachment */
+ // necessary for conformance with Attachment
+ def pos: Position = this
+ /** A bit weird method that is necessary to safely update positions without destroying custom attachments */
+ // necessary for conformance with Attachment
+ def withPos(newPos: scala.reflect.api.Position): scala.reflect.api.Attachment = newPos
-/** The Position class and its subclasses represent positions of ASTs and symbols.
- * Except for NoPosition and FakePos, every position refers to a SourceFile
- * and to an offset in the sourcefile (its `point`). For batch compilation,
- * that's all. For interactive IDE's there are also RangePositions
- * and TransparentPositions. A RangePosition indicates a start and an end
- * in addition to its point. TransparentPositions are a subclass of RangePositions.
- * Range positions that are not transparent are called opaque.
- * Trees with RangePositions need to satisfy the following invariants.
- *
- * INV1: A tree with an offset position never contains a child
- * with a range position
- * INV2: If the child of a tree with a range position also has a range position,
- * then the child's range is contained in the parent's range.
- * INV3: Opaque range positions of children of the same node are non-overlapping
- * (this means their overlap is at most a single point).
- *
- * The following tests are useful on positions:
- *
- * pos.isDefined true if position is not a NoPosition nor a FakePosition
- * pos.isRange true if position is a range
- * pos.isOpaqueRange true if position is an opaque range
- *
- * The following accessor methods are provided:
- *
- * pos.source The source file of the position, which must be defined
- * pos.point The offset of the position's point, which must be defined
- * pos.start The start of the position, which must be a range
- * pos.end The end of the position, which must be a range
- *
- * There are also convenience methods, such as
- *
- * pos.startOrPoint
- * pos.endOrPoint
- * pos.pointOrElse(default)
- *
- * These are less strict about the kind of position on which they can be applied.
- *
- * The following conversion methods are often used:
- *
- * pos.focus converts a range position to an offset position, keeping its point;
- * returns all other positions unchanged.
- * pos.makeTransparent converts an opaque range position into a transparent one.
- * returns all other positions unchanged.
- */
-trait Position extends TreeAnnotation {
- def pos: Position = this
+ /** Exposes itself as payload of Attachment */
+ // necessary for conformance with Attachment
+ def payload: Position = this
+
+ /** A bit weird method that is necessary to safely update positions without destroying custom attachments */
+ // necessary for conformance with Attachment
+ def withPayload(newPos: Any): scala.reflect.api.Attachment = newPos.asInstanceOf[Position]
+
+ /** Java file corresponding to the source file of this position.
+ */
+ // necessary for conformance with scala.reflect.api.Position
+ def fileInfo: java.io.File = source.file.file
+
+ /** Contents of the source file that contains this position.
+ */
+ // necessary for conformance with scala.reflect.api.Position
+ def fileContent: Array[Char] = source.content
/** An optional value containing the source file referred to by this position, or
* None if not defined.
@@ -134,74 +104,74 @@ trait Position extends TreeAnnotation {
def offset: Option[Int] = if (isDefined) Some(point) else None
/** The same position with a different start value (if a range) */
- def withStart(off: Int) = this
+ def withStart(off: Int): Position = this
/** The same position with a different end value (if a range) */
- def withEnd(off: Int) = this
+ def withEnd(off: Int): Position = this
/** The same position with a different point value (if a range or offset) */
- def withPoint(off: Int) = this
+ def withPoint(off: Int): Position = this
/** The same position with a different source value, and its values shifted by given offset */
- def withSource(source: SourceFile, shift: Int) = this
+ def withSource(source: SourceFile, shift: Int): Position = this
/** If this is a range, the union with the other range, with the point of this position.
* Otherwise, this position
*/
- def union(pos: Position) = this
+ def union(pos: scala.reflect.api.Position): Position = this
/** If this is a range position, the offset position of its start.
* Otherwise the position itself
*/
- def focusStart = this
+ def focusStart: Position = this
/** If this is a range position, the offset position of its point.
* Otherwise the position itself
*/
- def focus = this
+ def focus: Position = this
/** If this is a range position, the offset position of its end.
* Otherwise the position itself
*/
- def focusEnd = this
+ def focusEnd: Position = this
/** Does this position include the given position `pos`.
* This holds if `this` is a range position and its range [start..end]
* is the same or covers the range of the given position, which may or may not be a range position.
*/
- def includes(pos: Position) = false
+ def includes(pos: scala.reflect.api.Position): Boolean = false
/** Does this position properly include the given position `pos` ("properly" meaning their
* ranges are not the same)?
*/
- def properlyIncludes(pos: Position) =
+ def properlyIncludes(pos: scala.reflect.api.Position): Boolean =
includes(pos) && (start < pos.startOrPoint || pos.endOrPoint < end)
/** Does this position precede that position?
* This holds if both positions are defined and the end point of this position
* is not larger than the start point of the given position.
*/
- def precedes(pos: Position) =
+ def precedes(pos: scala.reflect.api.Position): Boolean =
isDefined && pos.isDefined && endOrPoint <= pos.startOrPoint
/** Does this position properly precede the given position `pos` ("properly" meaning their ranges
* do not share a common point).
*/
- def properlyPrecedes(pos: Position) =
+ def properlyPrecedes(pos: scala.reflect.api.Position): Boolean =
isDefined && pos.isDefined && endOrPoint < pos.startOrPoint
/** Does this position overlap with that position?
* This holds if both positions are ranges and there is an interval of
* non-zero length that is shared by both position ranges.
*/
- def overlaps(pos: Position) =
+ def overlaps(pos: scala.reflect.api.Position): Boolean =
isRange && pos.isRange &&
((pos.start < end && start < pos.end) || (start < pos.end && pos.start < end))
/** Does this position cover the same range as that position?
* Holds only if both position are ranges
*/
- def sameRange(pos: Position) =
+ def sameRange(pos: scala.reflect.api.Position): Boolean =
isRange && pos.isRange && start == pos.start && end == pos.end
def line: Int = throw new UnsupportedOperationException("Position.line")
@@ -219,11 +189,11 @@ trait Position extends TreeAnnotation {
* file. If the SourceFile is a normal SourceFile, simply
* return this.
*/
- def inUltimateSource(source : SourceFile) =
+ def inUltimateSource(source : SourceFile): Position =
if (source == null) this else source.positionInUltimateSource(this)
- def dbgString = toString
- def safeLine = try line catch { case _: UnsupportedOperationException => -1 }
+ def dbgString: String = toString
+ def safeLine: Int = try line catch { case _: UnsupportedOperationException => -1 }
def show: String = "["+toString+"]"
}
@@ -254,8 +224,10 @@ class OffsetPosition(override val source: SourceFile, override val point: Int) e
col + 1
}
- override def union(pos: Position) =
- if (pos.isRange) pos else this
+ override def union(pos: scala.reflect.api.Position) =
+ // [Eugene] how do I get rid of this cast?
+ // I could introduce a "type PositionType <: scala.reflect.api.Position", but that's also ugly
+ if (pos.isRange) pos.asInstanceOf[Position] else this
override def equals(that : Any) = that match {
case that : OffsetPosition => point == that.point && source.file == that.source.file
@@ -265,7 +237,7 @@ class OffsetPosition(override val source: SourceFile, override val point: Int) e
override def toString = {
val pointmsg = if (point > source.length) "out-of-bounds-" else "offset="
- "source-%s,line-%s,%s%s".format(source.path, line, pointmsg, point)
+ "source-%s,line-%s,%s%s".format(source.file.canonicalPath, line, pointmsg, point)
}
override def show = "["+point+"]"
}
@@ -289,8 +261,8 @@ extends OffsetPosition(source, point) {
}
override def focusEnd = new OffsetPosition(source, end)
override def makeTransparent = new TransparentPosition(source, start, point, end)
- override def includes(pos: Position) = pos.isDefined && start <= pos.startOrPoint && pos.endOrPoint <= end
- override def union(pos: Position) =
+ override def includes(pos: scala.reflect.api.Position) = pos.isDefined && start <= pos.startOrPoint && pos.endOrPoint <= end
+ override def union(pos: scala.reflect.api.Position): Position =
if (pos.isRange) new RangePosition(source, start min pos.start, point, end max pos.end) else this
override def toSingleLine: Position = source match {
@@ -301,7 +273,7 @@ extends OffsetPosition(source, point) {
case _ => this
}
- override def toString = "RangePosition("+source+", "+start+", "+point+", "+end+")"
+ override def toString = "RangePosition("+source.file.canonicalPath+", "+start+", "+point+", "+end+")"
override def show = "["+start+":"+end+"]"
private var focusCache: Position = NoPosition
}
@@ -311,10 +283,4 @@ class TransparentPosition(source: SourceFile, start: Int, point: Int, end: Int)
override def isTransparent = true
override def makeTransparent = this
override def show = "<"+start+":"+end+">"
-}
-
-
-
-
-
-
+} \ No newline at end of file
diff --git a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
index fda713c5c6..120cceb238 100644
--- a/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
+++ b/src/compiler/scala/tools/nsc/util/ScalaClassLoader.scala
@@ -14,6 +14,8 @@ import java.net.URL
import scala.reflect.ReflectionUtils.unwrapHandler
import ScalaClassLoader._
import scala.util.control.Exception.{ catching }
+import language.implicitConversions
+
// import Exceptional.unwrap
trait HasClassPath {
@@ -65,8 +67,8 @@ trait ScalaClassLoader extends JClassLoader {
result
}
- def constructorsOf[T <: AnyRef : Manifest]: List[Constructor[T]] =
- manifest[T].erasure.getConstructors.toList map (_.asInstanceOf[Constructor[T]])
+ def constructorsOf[T <: AnyRef : ClassTag]: List[Constructor[T]] =
+ classTag[T].erasure.getConstructors.toList map (_.asInstanceOf[Constructor[T]])
/** The actual bytes for a class file, or an empty array if it can't be found. */
def classBytes(className: String): Array[Byte] = classAsStream(className) match {
@@ -123,9 +125,9 @@ object ScalaClassLoader {
def bootLoader = apply(null)
def contextChain = loaderChain(contextLoader)
- def pathToErasure[T: ClassManifest] = pathToClass(classManifest[T].erasure)
- def pathToClass(clazz: Class[_]) = clazz.getName.replace('.', JFile.separatorChar) + ".class"
- def locate[T: ClassManifest] = contextLoader getResource pathToErasure[T]
+ def pathToErasure[T: ClassTag] = pathToClass(classTag[T].erasure)
+ def pathToClass(clazz: Class[_]) = clazz.getName.replace('.', JFile.separatorChar) + ".class"
+ def locate[T: ClassTag] = contextLoader getResource pathToErasure[T]
/** Tries to guess the classpath by type matching the context classloader
* and its parents, looking for any classloaders which will reveal their
diff --git a/src/compiler/scala/tools/nsc/util/Statistics.scala b/src/compiler/scala/tools/nsc/util/Statistics.scala
index d1cdd30dd8..61c7695911 100644
--- a/src/compiler/scala/tools/nsc/util/Statistics.scala
+++ b/src/compiler/scala/tools/nsc/util/Statistics.scala
@@ -57,6 +57,9 @@ class Statistics extends scala.reflect.internal.util.Statistics {
val counter2: SubCounter = new SubCounter(subtypeCount)
val timer1: Timer = new Timer
val timer2: Timer = new Timer
+
+ val macroExpandCount = new Counter
+ val macroExpandNanos = new Timer
}
object Statistics extends Statistics
@@ -125,34 +128,36 @@ abstract class StatisticsInfo {
inform("ms type-flow-analysis: " + analysis.timer.millis)
if (phase.name == "typer") {
- inform("time spent typechecking : "+showRelTyper(typerNanos))
- inform("time classfilereading : "+showRelTyper(classReadNanos))
- inform("time spent in implicits : "+showRelTyper(implicitNanos))
- inform(" successful in scope : "+showRelTyper(inscopeSucceedNanos))
- inform(" failed in scope : "+showRelTyper(inscopeFailNanos))
- inform(" successful of type : "+showRelTyper(oftypeSucceedNanos))
- inform(" failed of type : "+showRelTyper(oftypeFailNanos))
- inform(" assembling parts : "+showRelTyper(subtypeETNanos))
- inform(" matchesPT : "+showRelTyper(matchesPtNanos))
- inform("implicit cache hits : "+showRelative(implicitCacheHits.value + implicitCacheMisses.value)(implicitCacheHits.value))
- inform("time spent in failed : "+showRelTyper(failedSilentNanos))
- inform(" failed apply : "+showRelTyper(failedApplyNanos))
- inform(" failed op= : "+showRelTyper(failedOpEqNanos))
- inform("time spent ref scanning : "+showRelTyper(isReferencedNanos))
- inform("micros by tree node : "+showCounts(microsByType))
- inform("#visits by tree node : "+showCounts(visitsByType))
+ inform("time spent typechecking : " + showRelTyper(typerNanos))
+ inform("time classfilereading : " + showRelTyper(classReadNanos))
+ inform("time spent in implicits : " + showRelTyper(implicitNanos))
+ inform(" successful in scope : " + showRelTyper(inscopeSucceedNanos))
+ inform(" failed in scope : " + showRelTyper(inscopeFailNanos))
+ inform(" successful of type : " + showRelTyper(oftypeSucceedNanos))
+ inform(" failed of type : " + showRelTyper(oftypeFailNanos))
+ inform(" assembling parts : " + showRelTyper(subtypeETNanos))
+ inform(" matchesPT : " + showRelTyper(matchesPtNanos))
+ inform("implicit cache hits : " + showRelative(implicitCacheHits.value + implicitCacheMisses.value)(implicitCacheHits.value))
+ inform("time spent in failed : " + showRelTyper(failedSilentNanos))
+ inform(" failed apply : " + showRelTyper(failedApplyNanos))
+ inform(" failed op= : " + showRelTyper(failedOpEqNanos))
+ inform("time spent ref scanning : " + showRelTyper(isReferencedNanos))
+ inform("micros by tree node : " + showCounts(microsByType))
+ inform("#visits by tree node : " + showCounts(visitsByType))
val average = new ClassCounts
for (c <- microsByType.keysIterator) average(c) = microsByType(c)/visitsByType(c)
- inform("avg micros by tree node : "+showCounts(average))
- inform("time spent in <:< : "+showRelTyper(subtypeNanos))
- inform("time spent in findmember : "+showRelTyper(findMemberNanos))
- inform("time spent in asSeenFrom : "+showRelTyper(asSeenFromNanos))
- inform("#implicit searches : " + implicitSearchCount)
+ inform("avg micros by tree node : " + showCounts(average))
+ inform("time spent in <:< : " + showRelTyper(subtypeNanos))
+ inform("time spent in findmember : " + showRelTyper(findMemberNanos))
+ inform("time spent in asSeenFrom : " + showRelTyper(asSeenFromNanos))
+ inform("#implicit searches : " + implicitSearchCount)
inform("#tried, plausible, matching, typed, found implicits: "+triedImplicits+", "+plausiblyCompatibleImplicits+", "+matchingImplicits+", "+typedImplicits+", "+foundImplicits)
- inform("#implicit improves tests : " + improvesCount)
- inform("#implicit improves cached: " + improvesCachedCount)
- inform("#implicit inscope hits : " + inscopeImplicitHits)
- inform("#implicit oftype hits : " + oftypeImplicitHits)
+ inform("#implicit improves tests : " + improvesCount)
+ inform("#implicit improves cached : " + improvesCachedCount)
+ inform("#implicit inscope hits : " + inscopeImplicitHits)
+ inform("#implicit oftype hits : " + oftypeImplicitHits)
+ inform("#macro expansions : " + macroExpandCount)
+ inform("#time spent in macroExpand : " + showRelTyper(macroExpandNanos))
}
if (ctr1 != null) inform("#ctr1 : " + ctr1)
diff --git a/src/compiler/scala/tools/nsc/util/WeakHashSet.scala b/src/compiler/scala/tools/nsc/util/WeakHashSet.scala
index 6a10422b00..5bbb766e21 100644
--- a/src/compiler/scala/tools/nsc/util/WeakHashSet.scala
+++ b/src/compiler/scala/tools/nsc/util/WeakHashSet.scala
@@ -4,6 +4,7 @@ import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.Builder
import scala.collection.mutable.SetBuilder
+import scala.collection.generic.Clearable
import scala.runtime.AbstractFunction1
/** A bare-bones implementation of a mutable `Set` that uses weak references
@@ -12,7 +13,7 @@ import scala.runtime.AbstractFunction1
* This implementation offers only add/remove/test operations,
* therefore it does not fulfill the contract of Scala collection sets.
*/
-class WeakHashSet[T <: AnyRef] extends AbstractFunction1[T, Boolean] {
+class WeakHashSet[T <: AnyRef] extends AbstractFunction1[T, Boolean] with Clearable {
private val underlying = mutable.HashSet[WeakReferenceWithEquals[T]]()
/** Add the given element to this set. */
diff --git a/src/compiler/scala/tools/nsc/util/package.scala b/src/compiler/scala/tools/nsc/util/package.scala
index 88e6c51e9f..1336cca3c5 100644
--- a/src/compiler/scala/tools/nsc/util/package.scala
+++ b/src/compiler/scala/tools/nsc/util/package.scala
@@ -9,6 +9,8 @@ import java.io.{ OutputStream, PrintStream, ByteArrayOutputStream, PrintWriter,
package object util {
+ implicit def postfixOps = language.postfixOps // make all postfix ops in this package compile without warning
+
// forwarder for old code that builds against 2.9 and 2.10
val Chars = scala.reflect.internal.Chars
diff --git a/src/compiler/scala/tools/reflect/Invoked.scala b/src/compiler/scala/tools/reflect/Invoked.scala
index 30c6201a0d..516c6b9bf6 100644
--- a/src/compiler/scala/tools/reflect/Invoked.scala
+++ b/src/compiler/scala/tools/reflect/Invoked.scala
@@ -16,7 +16,7 @@ class Invoked private (val proxy: AnyRef, val m: Method, val args: List[AnyRef])
def name = m.getName
def arity = m.getParameterTypes.size
def returnType = m.getReturnType
- def returns[T: Manifest] = returnType == manifest[T].erasure
+ def returns[T: ClassTag] = returnType == classTag[T].erasure
def invokeOn(target: AnyRef) = m.invoke(target, args: _*)
def isObjectMethod = Set("toString", "equals", "hashCode") contains name
diff --git a/src/compiler/scala/tools/reflect/UniversalFn.scala b/src/compiler/scala/tools/reflect/UniversalFn.scala
index 9ccd580560..b0c2a19021 100644
--- a/src/compiler/scala/tools/reflect/UniversalFn.scala
+++ b/src/compiler/scala/tools/reflect/UniversalFn.scala
@@ -26,8 +26,8 @@ class UniversalFn private (val closure: AnyRef, val method: Method) extends (Seq
* them to this universal function. Will throw an exception in the
* face of any bad data.
*/
- def as[T: Manifest] : T = {
- val clazz = manifest[T].erasure
+ def as[T: ClassTag] : T = {
+ val clazz = classTag[T].erasure
require(clazz.isInterface, "Type argument must be an interface.")
val interfaceMethods = clazz.getDeclaredMethods.toSet
diff --git a/src/compiler/scala/tools/reflect/package.scala b/src/compiler/scala/tools/reflect/package.scala
index 8f5e099fbf..0b0c0905cb 100644
--- a/src/compiler/scala/tools/reflect/package.scala
+++ b/src/compiler/scala/tools/reflect/package.scala
@@ -27,17 +27,17 @@ package object reflect {
}
}
- def zeroOfClass(clazz: Class[_]) = zeroOf(Manifest.classType(clazz))
- def zeroOf[T](implicit m: Manifest[T]): AnyRef = {
- if (m == manifest[Boolean] || m == manifest[jl.Boolean]) false: jl.Boolean
- else if (m == manifest[Unit] || m == manifest[jl.Void] || m == manifest[scala.runtime.BoxedUnit]) scala.runtime.BoxedUnit.UNIT
- else if (m == manifest[Char] || m == manifest[jl.Character]) 0.toChar: jl.Character
- else if (m == manifest[Byte] || m == manifest[jl.Byte]) 0.toByte: jl.Byte
- else if (m == manifest[Short] || m == manifest[jl.Short]) 0.toShort: jl.Short
- else if (m == manifest[Int] || m == manifest[jl.Integer]) 0: jl.Integer
- else if (m == manifest[Long] || m == manifest[jl.Long]) 0l: jl.Long
- else if (m == manifest[Float] || m == manifest[jl.Float]) 0f: jl.Float
- else if (m == manifest[Double] || m == manifest[jl.Double]) 0d: jl.Double
+ def zeroOfClass(clazz: Class[_]) = zeroOf(ClassTag(clazz))
+ def zeroOf[T](implicit t: ClassTag[T]): AnyRef = {
+ if (t == classTag[Boolean] || t == classTag[jl.Boolean]) false: jl.Boolean
+ else if (t == classTag[Unit] || t == classTag[jl.Void] || t == classTag[scala.runtime.BoxedUnit]) scala.runtime.BoxedUnit.UNIT
+ else if (t == classTag[Char] || t == classTag[jl.Character]) 0.toChar: jl.Character
+ else if (t == classTag[Byte] || t == classTag[jl.Byte]) 0.toByte: jl.Byte
+ else if (t == classTag[Short] || t == classTag[jl.Short]) 0.toShort: jl.Short
+ else if (t == classTag[Int] || t == classTag[jl.Integer]) 0: jl.Integer
+ else if (t == classTag[Long] || t == classTag[jl.Long]) 0l: jl.Long
+ else if (t == classTag[Float] || t == classTag[jl.Float]) 0f: jl.Float
+ else if (t == classTag[Double] || t == classTag[jl.Double]) 0d: jl.Double
else null
}
}
diff --git a/src/compiler/scala/tools/util/StringOps.scala b/src/compiler/scala/tools/util/StringOps.scala
index 02eb364abe..725e0afb79 100644
--- a/src/compiler/scala/tools/util/StringOps.scala
+++ b/src/compiler/scala/tools/util/StringOps.scala
@@ -25,6 +25,16 @@ trait StringOps {
val ys = oempty(xs: _*)
if (ys.isEmpty) orElse else ys mkString sep
}
+ def trimTrailingSpace(s: String) = {
+ if (s.length == 0 || !s.charAt(s.length - 1).isWhitespace) s
+ else {
+ var idx = s.length - 1
+ while (idx >= 0 && s.charAt(idx).isWhitespace)
+ idx -= 1
+
+ s.substring(0, idx + 1)
+ }
+ }
def decompose(str: String, sep: Char): List[String] = {
def ws(start: Int): List[String] =
diff --git a/src/continuations/library/scala/util/continuations/ControlContext.scala b/src/continuations/library/scala/util/continuations/ControlContext.scala
index 19c2bc4038..910ca60eb0 100644
--- a/src/continuations/library/scala/util/continuations/ControlContext.scala
+++ b/src/continuations/library/scala/util/continuations/ControlContext.scala
@@ -13,7 +13,7 @@ import annotation.{ Annotation, StaticAnnotation, TypeConstraint }
/** This annotation is used to mark a parameter as part of a continuation
* context.
*
- * The type `A @cps[B,C]` is desugared to `ControlContext[A,B,C]` at compile
+ * The type `A @cpsParam[B,C]` is desugared to `ControlContext[A,B,C]` at compile
* time.
*
* @tparam B The type of computation state after computation has executed, and
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
index af0d768607..862b19d0a4 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSAnnotationChecker.scala
@@ -3,8 +3,9 @@
package scala.tools.selectivecps
import scala.tools.nsc.Global
+import scala.tools.nsc.typechecker.Modes
-abstract class CPSAnnotationChecker extends CPSUtils {
+abstract class CPSAnnotationChecker extends CPSUtils with Modes {
val global: Global
import global._
import definitions._
@@ -94,8 +95,7 @@ abstract class CPSAnnotationChecker extends CPSUtils {
if (!cpsEnabled) return bounds
val anyAtCPS = newCpsParamsMarker(NothingClass.tpe, AnyClass.tpe)
-
- if (isFunctionType(tparams.head.owner.tpe) || tparams.head.owner == PartialFunctionClass) {
+ if (isFunctionType(tparams.head.owner.tpe) || isPartialFunctionType(tparams.head.owner.tpe)) {
vprintln("function bound: " + tparams.head.owner.tpe + "/"+bounds+"/"+targs)
if (hasCpsParamTypes(targs.last))
bounds.reverse match {
@@ -178,59 +178,38 @@ abstract class CPSAnnotationChecker extends CPSUtils {
override def adaptAnnotations(tree: Tree, mode: Int, pt: Type): Tree = {
if (!cpsEnabled) return tree
- vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt)
+ vprintln("adapt annotations " + tree + " / " + tree.tpe + " / " + modeString(mode) + " / " + pt)
- val annots1 = cpsParamAnnotation(tree.tpe)
- val annots2 = cpsParamAnnotation(pt)
+ val patMode = (mode & global.analyzer.PATTERNmode) != 0
+ val exprMode = (mode & global.analyzer.EXPRmode) != 0
+ val byValMode = (mode & global.analyzer.BYVALmode) != 0
- if ((mode & global.analyzer.PATTERNmode) != 0) {
- if (!annots1.isEmpty) {
- return tree modifyType removeAllCPSAnnotations
- }
- }
+ val annotsTree = cpsParamAnnotation(tree.tpe)
+ val annotsExpected = cpsParamAnnotation(pt)
-/*
+ // not sure I rephrased this comment correctly:
+ // replacing `patMode` in the condition below by `patMode || ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode))`
// doesn't work correctly -- still relying on addAnnotations to remove things from ValDef symbols
- if ((mode & global.analyzer.TYPEmode) != 0 && (mode & global.analyzer.BYVALmode) != 0) {
- if (!annots1.isEmpty) {
- println("removing annotation from " + tree + "/" + tree.tpe)
- val s = tree.setType(removeAllCPSAnnotations(tree.tpe))
- println(s)
- s
- }
- }
-*/
-
- if ((mode & global.analyzer.EXPRmode) != 0) {
- if (annots1.isEmpty && !annots2.isEmpty && ((mode & global.analyzer.BYVALmode) == 0)) { // shiftUnit
- // add a marker annotation that will make tree.tpe behave as pt, subtyping wise
- // tree will look like having any possible annotation
- //println("adapt annotations " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt)
- //val same = annots2 forall { case AnnotationInfo(atp: TypeRef, _, _) => atp.typeArgs(0) =:= atp.typeArgs(1) }
- // TBD: use same or not? see infer0.scala/infer1.scala
-
- // CAVEAT:
- // for monomorphic answer types we want to have @plus @cps (for better checking)
- // for answer type modification we want to have only @plus (because actual answer type may differ from pt)
-
- //val known = global.analyzer.isFullyDefined(pt)
-
- if (/*same &&*/ !hasPlusMarker(tree.tpe)) {
- //if (known)
- return tree modifyType (_ withAnnotations newPlusMarker() :: annots2) // needed for #1807
- //else
- // return tree.setType(tree.tpe.withAnnotations(adapt::Nil))
- }
- tree
- } else if (!annots1.isEmpty && ((mode & global.analyzer.BYVALmode) != 0)) { // dropping annotation
- // add a marker annotation that will make tree.tpe behave as pt, subtyping wise
- // tree will look like having no annotation
- if (!hasMinusMarker(tree.tpe)) {
- return tree modifyType addMinusMarker
- }
- }
- }
- tree
+ if (patMode && !annotsTree.isEmpty) tree modifyType removeAllCPSAnnotations
+ else if (exprMode && !byValMode && !hasPlusMarker(tree.tpe) && annotsTree.isEmpty && annotsExpected.nonEmpty) { // shiftUnit
+ // add a marker annotation that will make tree.tpe behave as pt, subtyping wise
+ // tree will look like having any possible annotation
+ //println("adapt annotations " + tree + " / " + tree.tpe + " / " + Integer.toHexString(mode) + " / " + pt)
+
+ // CAVEAT:
+ // for monomorphic answer types we want to have @plus @cps (for better checking)
+ // for answer type modification we want to have only @plus (because actual answer type may differ from pt)
+
+ val res = tree modifyType (_ withAnnotations newPlusMarker() :: annotsExpected) // needed for #1807
+ vprintln("adapted annotations (not by val) of " + tree + " to " + res.tpe)
+ res
+ } else if (exprMode && byValMode && !hasMinusMarker(tree.tpe) && annotsTree.nonEmpty) { // dropping annotation
+ // add a marker annotation that will make tree.tpe behave as pt, subtyping wise
+ // tree will look like having no annotation
+ val res = tree modifyType addMinusMarker
+ vprintln("adapted annotations (by val) of " + tree + " to " + res.tpe)
+ res
+ } else tree
}
def updateAttributesFromChildren(tpe: Type, childAnnots: List[AnnotationInfo], byName: List[Tree]): Type = {
@@ -455,11 +434,10 @@ abstract class CPSAnnotationChecker extends CPSUtils {
transChildrenInOrder(tree, tpe, List(cond), List(thenp, elsep))
case Match(select, cases) =>
- // TODO: can there be cases that are not CaseDefs?? check collect vs map!
- transChildrenInOrder(tree, tpe, List(select), cases:::(cases collect { case CaseDef(_, _, body) => body }))
+ transChildrenInOrder(tree, tpe, List(select), cases:::(cases map { case CaseDef(_, _, body) => body }))
case Try(block, catches, finalizer) =>
- val tpe1 = transChildrenInOrder(tree, tpe, Nil, block::catches:::(catches collect { case CaseDef(_, _, body) => body }))
+ val tpe1 = transChildrenInOrder(tree, tpe, Nil, block::catches:::(catches map { case CaseDef(_, _, body) => body }))
val annots = cpsParamAnnotation(tpe1)
if (annots.nonEmpty) {
diff --git a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
index 075009ce5e..6f5284f75f 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/CPSUtils.scala
@@ -9,7 +9,7 @@ trait CPSUtils {
import global._
import definitions._
- var cpsEnabled = true
+ var cpsEnabled = false
val verbose: Boolean = System.getProperty("cpsVerbose", "false") == "true"
def vprintln(x: =>Any): Unit = if (verbose) println(x)
@@ -24,6 +24,7 @@ trait CPSUtils {
val shift = newTermName("shift")
val shiftR = newTermName("shiftR")
val shiftSuffix = newTermName("$shift")
+ val shiftUnit0 = newTermName("shiftUnit0")
val shiftUnit = newTermName("shiftUnit")
val shiftUnitR = newTermName("shiftUnitR")
}
@@ -38,6 +39,7 @@ trait CPSUtils {
lazy val ModCPS = definitions.getRequiredModule("scala.util.continuations")
lazy val MethShiftUnit = definitions.getMember(ModCPS, cpsNames.shiftUnit)
+ lazy val MethShiftUnit0 = definitions.getMember(ModCPS, cpsNames.shiftUnit0)
lazy val MethShiftUnitR = definitions.getMember(ModCPS, cpsNames.shiftUnitR)
lazy val MethShift = definitions.getMember(ModCPS, cpsNames.shift)
lazy val MethShiftR = definitions.getMember(ModCPS, cpsNames.shiftR)
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
index 1189cc2e38..017c8d24fd 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveANFTransform.scala
@@ -71,25 +71,46 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
// { x => x match { case A => ... }} to
// { x => shiftUnit(x match { case A => ... })}
// which Uncurry cannot handle (see function6.scala)
+ // thus, we push down the shiftUnit to each of the case bodies
val ext = getExternalAnswerTypeAnn(body.tpe)
+ val pureBody = getAnswerTypeAnn(body.tpe).isEmpty
+
+ def transformPureMatch(tree: Tree, selector: Tree, cases: List[CaseDef]) = {
+ val caseVals = cases map { case cd @ CaseDef(pat, guard, body) =>
+ // if (!hasPlusMarker(body.tpe)) body.tpe = body.tpe withAnnotation newPlusMarker() // TODO: to avoid warning
+ val bodyVal = transExpr(body, None, ext) // ??? triggers "cps-transformed unexpectedly" warning in transTailValue
+ treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal)
+ }
+ treeCopy.Match(tree, transform(selector), caseVals)
+ }
+
+ def transformPureVirtMatch(body: Block, selDef: ValDef, cases: List[Tree], matchEnd: Tree) = {
+ val stats = transform(selDef) :: (cases map (transExpr(_, None, ext)))
+ treeCopy.Block(body, stats, transExpr(matchEnd, None, ext))
+ }
val body1 = body match {
- case Match(selector, cases) if (ext.isDefined && getAnswerTypeAnn(body.tpe).isEmpty) =>
- val cases1 = for {
- cd @ CaseDef(pat, guard, caseBody) <- cases
- caseBody1 = transExpr(body, None, ext)
- } yield {
- treeCopy.CaseDef(cd, transform(pat), transform(guard), caseBody1)
- }
- treeCopy.Match(tree, transform(selector), cases1)
+ case Match(selector, cases) if ext.isDefined && pureBody =>
+ transformPureMatch(body, selector, cases)
+
+ // virtpatmat switch
+ case Block(List(selDef: ValDef), mat@Match(selector, cases)) if ext.isDefined && pureBody =>
+ treeCopy.Block(body, List(transform(selDef)), transformPureMatch(mat, selector, cases))
+
+ // virtpatmat
+ case b@Block(matchStats@((selDef: ValDef) :: cases), matchEnd) if ext.isDefined && pureBody && (matchStats forall gen.hasSynthCaseSymbol) =>
+ transformPureVirtMatch(b, selDef, cases, matchEnd)
+
+ // virtpatmat that stores the scrut separately -- TODO: can we eliminate this case??
+ case Block(List(selDef0: ValDef), mat@Block(matchStats@((selDef: ValDef) :: cases), matchEnd)) if ext.isDefined && pureBody && (matchStats forall gen.hasSynthCaseSymbol)=>
+ treeCopy.Block(body, List(transform(selDef0)), transformPureVirtMatch(mat, selDef, cases, matchEnd))
case _ =>
transExpr(body, None, ext)
}
- debuglog("result "+body1)
- debuglog("result is of type "+body1.tpe)
+ debuglog("anf result "+body1+"\nresult is of type "+body1.tpe)
treeCopy.Function(ff, transformValDefs(vparams), body1)
}
@@ -120,7 +141,6 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
transExpr(tree, None, None)
case _ =>
-
if (hasAnswerTypeAnn(tree.tpe)) {
if (!cpsAllowed)
unit.error(tree.pos, "cps code not allowed here / " + tree.getClass + " / " + tree)
@@ -170,63 +190,74 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
tree match {
case Block(stms, expr) =>
val (cpsA2, cpsR2) = (cpsA, linearize(cpsA, getAnswerTypeAnn(tree.tpe))) // tbd
-// val (cpsA2, cpsR2) = (None, getAnswerTypeAnn(tree.tpe))
- val (a, b) = transBlock(stms, expr, cpsA2, cpsR2)
+ // val (cpsA2, cpsR2) = (None, getAnswerTypeAnn(tree.tpe))
- val tree1 = (treeCopy.Block(tree, a, b)) // no updateSynthFlag here!!!
+ val (a, b) = transBlock(stms, expr, cpsA2, cpsR2)
+ val tree1 = (treeCopy.Block(tree, a, b)) // no updateSynthFlag here!!!
(Nil, tree1, cpsA)
- case If(cond, thenp, elsep) =>
- /* possible situations:
- cps before (cpsA)
- cps in condition (spc) <-- synth flag set if *only* here!
- cps in (one or both) branches */
- val (condStats, condVal, spc) = transInlineValue(cond, cpsA)
- val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe))
- (spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else
- (None, getAnswerTypeAnn(tree.tpe)) // if no cps in condition, branches must conform to tree.tpe directly
- val thenVal = transExpr(thenp, cpsA2, cpsR2)
- val elseVal = transExpr(elsep, cpsA2, cpsR2)
-
- // check that then and else parts agree (not necessary any more, but left as sanity check)
- if (cpsR.isDefined) {
- if (elsep == EmptyTree)
- unit.error(tree.pos, "always need else part in cps code")
- }
- if (hasAnswerTypeAnn(thenVal.tpe) != hasAnswerTypeAnn(elseVal.tpe)) {
- unit.error(tree.pos, "then and else parts must both be cps code or neither of them")
- }
-
- (condStats, updateSynthFlag(treeCopy.If(tree, condVal, thenVal, elseVal)), spc)
+ case If(cond, thenp, elsep) =>
+ /* possible situations:
+ cps before (cpsA)
+ cps in condition (spc) <-- synth flag set if *only* here!
+ cps in (one or both) branches */
+ val (condStats, condVal, spc) = transInlineValue(cond, cpsA)
+ val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe))
+ (spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else
+ (None, getAnswerTypeAnn(tree.tpe)) // if no cps in condition, branches must conform to tree.tpe directly
+ val thenVal = transExpr(thenp, cpsA2, cpsR2)
+ val elseVal = transExpr(elsep, cpsA2, cpsR2)
+
+ // check that then and else parts agree (not necessary any more, but left as sanity check)
+ if (cpsR.isDefined) {
+ if (elsep == EmptyTree)
+ unit.error(tree.pos, "always need else part in cps code")
+ }
+ if (hasAnswerTypeAnn(thenVal.tpe) != hasAnswerTypeAnn(elseVal.tpe)) {
+ unit.error(tree.pos, "then and else parts must both be cps code or neither of them")
+ }
- case Match(selector, cases) =>
+ (condStats, updateSynthFlag(treeCopy.If(tree, condVal, thenVal, elseVal)), spc)
- val (selStats, selVal, spc) = transInlineValue(selector, cpsA)
- val (cpsA2, cpsR2) = if (hasSynthMarker(tree.tpe))
- (spc, linearize(spc, getAnswerTypeAnn(tree.tpe))) else
- (None, getAnswerTypeAnn(tree.tpe))
+ case Match(selector, cases) =>
+ val (selStats, selVal, spc) = transInlineValue(selector, cpsA)
+ val (cpsA2, cpsR2) =
+ if (hasSynthMarker(tree.tpe)) (spc, linearize(spc, getAnswerTypeAnn(tree.tpe)))
+ else (None, getAnswerTypeAnn(tree.tpe))
- val caseVals = for {
- cd @ CaseDef(pat, guard, body) <- cases
- bodyVal = transExpr(body, cpsA2, cpsR2)
- } yield {
- treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal)
- }
+ val caseVals = cases map { case cd @ CaseDef(pat, guard, body) =>
+ val bodyVal = transExpr(body, cpsA2, cpsR2)
+ treeCopy.CaseDef(cd, transform(pat), transform(guard), bodyVal)
+ }
- (selStats, updateSynthFlag(treeCopy.Match(tree, selVal, caseVals)), spc)
+ (selStats, updateSynthFlag(treeCopy.Match(tree, selVal, caseVals)), spc)
+ // this is utterly broken: LabelDefs need to be considered together when transforming them to DefDefs:
+ // suppose a Block {L1; ... ; LN}
+ // this should become {D1def ; ... ; DNdef ; D1()}
+ // where D$idef = def L$i(..) = {L$i.body; L${i+1}(..)}
case ldef @ LabelDef(name, params, rhs) =>
+ // println("trans LABELDEF "+(name, params, tree.tpe, hasAnswerTypeAnn(tree.tpe)))
+ // TODO why does the labeldef's type have a cpsMinus annotation, whereas the rhs does not? (BYVALmode missing/too much somewhere?)
if (hasAnswerTypeAnn(tree.tpe)) {
- val sym = currentOwner.newMethod(name, tree.pos, Flags.SYNTHETIC) setInfo ldef.symbol.info
- val rhs1 = new TreeSymSubstituter(List(ldef.symbol), List(sym)).transform(rhs)
+ // currentOwner.newMethod(name, tree.pos, Flags.SYNTHETIC) setInfo ldef.symbol.info
+ val sym = ldef.symbol resetFlag Flags.LABEL
+ val rhs1 = rhs //new TreeSymSubstituter(List(ldef.symbol), List(sym)).transform(rhs)
val rhsVal = transExpr(rhs1, None, getAnswerTypeAnn(tree.tpe)) changeOwner (currentOwner -> sym)
val stm1 = localTyper.typed(DefDef(sym, rhsVal))
- val expr = localTyper.typed(Apply(Ident(sym), List()))
-
- (List(stm1), expr, cpsA)
+ // since virtpatmat does not rely on fall-through, don't call the labels it emits
+ // transBlock will take care of calling the first label
+ // calling each labeldef is wrong, since some labels may be jumped over
+ // we can get away with this for now since the only other labels we emit are for tailcalls/while loops,
+ // which do not have consecutive labeldefs (and thus fall-through is irrelevant)
+ if (gen.hasSynthCaseSymbol(ldef)) (List(stm1), localTyper.typed{Literal(Constant(()))}, cpsA)
+ else {
+ assert(params.isEmpty, "problem in ANF transforming label with non-empty params "+ ldef)
+ (List(stm1), localTyper.typed{Apply(Ident(sym), List())}, cpsA)
+ }
} else {
val rhsVal = transExpr(rhs, None, None)
(Nil, updateSynthFlag(treeCopy.LabelDef(tree, name, params, rhsVal)), cpsA)
@@ -310,15 +341,36 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
try {
val Some((a, b)) = cpsR
-
- val res = localTyper.typed(atPos(tree.pos) {
- Apply(TypeApply(gen.mkAttributedRef(MethShiftUnit),
- List(TypeTree(plainTpe), TypeTree(a), TypeTree(b))),
- List(expr))
- })
- return (stms, res)
-
- } catch {
+ /** Since shiftUnit is bounded [A,B,C>:B] this may not typecheck
+ * if C is overly specific. So if !(B <:< C), call shiftUnit0
+ * instead, which takes only two type arguments.
+ */
+ val conforms = a <:< b
+ val call = localTyper.typedPos(tree.pos)(
+ Apply(
+ TypeApply(
+ gen.mkAttributedRef( if (conforms) MethShiftUnit else MethShiftUnit0 ),
+ List(TypeTree(plainTpe), TypeTree(a)) ++ ( if (conforms) List(TypeTree(b)) else Nil )
+ ),
+ List(expr)
+ )
+ )
+ // This is today's sick/meaningless heuristic for spotting breakdown so
+ // we don't proceed until stack traces start draping themselves over everything.
+ // If there are wildcard types in the tree and B == Nothing, something went wrong.
+ // (I thought WildcardTypes would be enough, but nope. 'reset0 { 0 }' has them.)
+ //
+ // Code as simple as reset((_: String).length)
+ // will crash meaninglessly without this check. See SI-3718.
+ //
+ // TODO - obviously this should be done earlier, differently, or with
+ // a more skilled hand. Most likely, all three.
+ if ((b.typeSymbol eq NothingClass) && call.tpe.exists(_ eq WildcardType))
+ unit.error(tree.pos, "cannot cps-transform malformed (possibly in shift/reset placement) expression")
+ else
+ return ((stms, call))
+ }
+ catch {
case ex:TypeError =>
unit.error(ex.pos, "cannot cps-transform expression " + tree + ": " + ex.msg)
}
@@ -404,18 +456,32 @@ abstract class SelectiveANFTransform extends PluginComponent with Transform with
}
def transBlock(stms: List[Tree], expr: Tree, cpsA: CPSInfo, cpsR: CPSInfo): (List[Tree], Tree) = {
- stms match {
- case Nil =>
- transTailValue(expr, cpsA, cpsR)
-
- case stm::rest =>
- var (rest2, expr2) = (rest, expr)
- val (headStms, headSpc) = transInlineStm(stm, cpsA)
- val (restStms, restExpr) = transBlock(rest2, expr2, headSpc, cpsR)
- (headStms:::restStms, restExpr)
- }
+ def rec(currStats: List[Tree], currAns: CPSInfo, accum: List[Tree]): (List[Tree], Tree) =
+ currStats match {
+ case Nil =>
+ val (anfStats, anfExpr) = transTailValue(expr, currAns, cpsR)
+ (accum ++ anfStats, anfExpr)
+
+ case stat :: rest =>
+ val (stats, nextAns) = transInlineStm(stat, currAns)
+ rec(rest, nextAns, accum ++ stats)
+ }
+
+ val (anfStats, anfExpr) = rec(stms, cpsA, List())
+ // println("\nanf-block:\n"+ ((stms :+ expr) mkString ("{", "\n", "}")) +"\nBECAME\n"+ ((anfStats :+ anfExpr) mkString ("{", "\n", "}")))
+ // println("synth case? "+ (anfStats map (t => (t, t.isDef, gen.hasSynthCaseSymbol(t)))))
+ // SUPER UGLY HACK: handle virtpatmat-style matches, whose labels have already been turned into DefDefs
+ if (anfStats.nonEmpty && (anfStats forall (t => !t.isDef || gen.hasSynthCaseSymbol(t)))) {
+ val (prologue, rest) = (anfStats :+ anfExpr) span (s => !s.isInstanceOf[DefDef]) // find first case
+ // println("rest: "+ rest)
+ // val (defs, calls) = rest partition (_.isInstanceOf[DefDef])
+ if (rest nonEmpty){
+ // the filter drops the ()'s emitted when transValue encountered a LabelDef
+ val stats = prologue ++ (rest filter (_.isInstanceOf[DefDef])).reverse // ++ calls
+ // println("REVERSED "+ (stats mkString ("{", "\n", "}")))
+ (stats, localTyper.typed{Apply(Ident(rest.head.symbol), List())}) // call first label to kick-start the match
+ } else (anfStats, anfExpr)
+ } else (anfStats, anfExpr)
}
-
-
}
}
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
index eb18f03748..8a500d6c4d 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSPlugin.scala
@@ -26,6 +26,7 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin {
override val runsBefore = List("uncurry")
}
+
val components = List[PluginComponent](anfPhase, cpsPhase)
val checker = new CPSAnnotationChecker {
@@ -42,17 +43,19 @@ class SelectiveCPSPlugin(val global: Global) extends Plugin {
}
// TODO: require -enabled command-line flag
+
override def processOptions(options: List[String], error: String => Unit) = {
- var enabled = true
- options foreach {
- case "enable" => enabled = true
- case "disable" => enabled = false
- case option => error("Option not understood: "+option)
+ var enabled = false
+ for (option <- options) {
+ if (option == "enable") {
+ enabled = true
+ } else {
+ error("Option not understood: "+option)
+ }
}
setEnabled(enabled)
}
- override val optionsHelp: Option[String] = {
- Some(" -P:continuations:disable Disable continuations plugin")
- }
+ override val optionsHelp: Option[String] =
+ Some(" -P:continuations:enable Enable continuations")
}
diff --git a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
index 6453671eac..dcb7cd601f 100644
--- a/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
+++ b/src/continuations/plugin/scala/tools/selectivecps/SelectiveCPSTransform.scala
@@ -15,7 +15,7 @@ import scala.tools.nsc.ast._
* In methods marked @cps, CPS-transform assignments introduced by ANF-transform phase.
*/
abstract class SelectiveCPSTransform extends PluginComponent with
- InfoTransform with TypingTransformers with CPSUtils {
+ InfoTransform with TypingTransformers with CPSUtils with TreeDSL {
// inherits abstract value `global` and class `Phase` from Transform
import global._ // the global environment
@@ -65,6 +65,7 @@ abstract class SelectiveCPSTransform extends PluginComponent with
class CPSTransformer(unit: CompilationUnit) extends TypingTransformer(unit) {
+ private val patmatTransformer = patmat.newTransformer(unit)
override def transform(tree: Tree): Tree = {
if (!cpsEnabled) return tree
@@ -190,28 +191,29 @@ abstract class SelectiveCPSTransform extends PluginComponent with
val targettp = transformCPSType(tree.tpe)
-// val expr2 = if (catches.nonEmpty) {
- val pos = catches.head.pos
- val argSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe)
- val rhs = Match(Ident(argSym), catches1)
- val fun = Function(List(ValDef(argSym)), rhs)
- val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp)))
- val funDef = localTyper.typed(atPos(pos) { ValDef(funSym, fun) })
- val expr2 = localTyper.typed(atPos(pos) { Apply(Select(expr1, expr1.tpe.member(cpsNames.flatMapCatch)), List(Ident(funSym))) })
-
- argSym.owner = fun.symbol
- rhs.changeOwner(currentOwner -> fun.symbol)
-
- val exSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe)
- val catch2 = { localTyper.typedCases(List(
- CaseDef(Bind(exSym, Typed(Ident("_"), TypeTree(ThrowableClass.tpe))),
- Apply(Select(Ident(funSym), nme.isDefinedAt), List(Ident(exSym))),
- Apply(Ident(funSym), List(Ident(exSym))))
- ), ThrowableClass.tpe, targettp) }
-
- //typedCases(tree, catches, ThrowableClass.tpe, pt)
-
- localTyper.typed(Block(List(funDef), treeCopy.Try(tree, treeCopy.Block(block1, stms, expr2), catch2, finalizer1)))
+ val pos = catches.head.pos
+ val funSym = currentOwner.newValueParameter(cpsNames.catches, pos).setInfo(appliedType(PartialFunctionClass.tpe, List(ThrowableClass.tpe, targettp)))
+ val funDef = localTyper.typed(atPos(pos) {
+ ValDef(funSym, Match(EmptyTree, catches1))
+ })
+ val expr2 = localTyper.typed(atPos(pos) {
+ Apply(Select(expr1, expr1.tpe.member(cpsNames.flatMapCatch)), List(Ident(funSym)))
+ })
+
+ val exSym = currentOwner.newValueParameter(cpsNames.ex, pos).setInfo(ThrowableClass.tpe)
+
+ import CODE._
+ // generate a case that is supported directly by the back-end
+ val catchIfDefined = CaseDef(
+ Bind(exSym, Ident(nme.WILDCARD)),
+ EmptyTree,
+ IF ((REF(funSym) DOT nme.isDefinedAt)(REF(exSym))) THEN (REF(funSym) APPLY (REF(exSym))) ELSE Throw(REF(exSym))
+ )
+
+ val catch2 = localTyper.typedCases(List(catchIfDefined), ThrowableClass.tpe, targettp)
+ //typedCases(tree, catches, ThrowableClass.tpe, pt)
+
+ patmatTransformer.transform(localTyper.typed(Block(List(funDef), treeCopy.Try(tree, treeCopy.Block(block1, stms, expr2), catch2, finalizer1))))
/*
diff --git a/src/dbc/scala/dbc/DataType.scala b/src/dbc/scala/dbc/DataType.scala
deleted file mode 100644
index 677621e0c0..0000000000
--- a/src/dbc/scala/dbc/DataType.scala
+++ /dev/null
@@ -1,69 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc;
-
-
-/** An ISO-9075:2003 (SQL) data type. Mappings between SQL types and
- * database specific types should be provided by the database driver.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class DataType {
-
- /** Tests whether this datatype is equivalent to another. Usually, two
- * types are defined as equivalent if they are equal. Two types can be
- * equivalent without being equal if values of those types will be
- * encoded in the same native Scala type.
- */
- def isEquivalent(datatype: DataType): Boolean;
-
- /** Tests whether this datatype is equivalent or a subtype of another
- * datatype. Type <code>A</code> is said to be subtype of type
- * <code>B</code> if any value of type <code>A</code> can be
- * represented as a value of type <code>B</code>.
- */
- def isSubtypeOf(datatype: DataType): Boolean;
-
- /** The native Scala type in which values of this SQL type will be
- * encoded.
- */
- type NativeType <: Any;
-
- /** The native Scala type in which values of this SQL type will be
- * encoded. This must point to the same type as <code>NativeType</code>.
- */
- def nativeTypeId: DataType.Id;
-
- /** Whether the value can take the null value, None when this property is
- * unknown.
- */
- def nullable: Option[Boolean] = None;
-
- /** The SQL name of the type */
- def sqlString: String = "UNDEFINED DATA TYPE"
-
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object DataType {
-
- type Id = Int;
-
- val OBJECT : Id = 10;
- val BOOLEAN : Id = 20;
- val BYTE : Id = 30;
- val SHORT : Id = 31;
- val INT : Id = 32;
- val LONG : Id = 33;
- val BIG_INTEGER: Id = 34;
- val BIG_DECIMAL: Id = 35;
- val FLOAT : Id = 40;
- val DOUBLE : Id = 41;
- val STRING : Id = 50;
-
-}
diff --git a/src/dbc/scala/dbc/Database.scala b/src/dbc/scala/dbc/Database.scala
deleted file mode 100644
index 60e16367e8..0000000000
--- a/src/dbc/scala/dbc/Database.scala
+++ /dev/null
@@ -1,187 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-
-
-import java.sql._
-
-/** A link to a database. The <code>Database</code> abstract class must
- * be specialised for every different DBMS.
- *
- * @author Gilles Dubochet
- */
-@deprecated(DbcIsDeprecated, "2.9.0") case class Database(dbms: Vendor) {
-
- class Closed extends Exception {}
-
- /** A lock used for operations that need to be atomic for this database
- * instance. */
- private val lock: scala.concurrent.Lock = new scala.concurrent.Lock()
-
- /** The vendor of the DBMS that contains this database. */
- private val vendor: Vendor = dbms
-
- /** The Database connections available to use. */
- private var availableConnections: List[Connection] = Nil
-
- /** The connections that are currently in use. */
- private var usedConnections: List[Connection] = Nil
-
- /** Whether the database no longer accepts new connections. */
- private var closing: Boolean = false;
-
- /** Retrieves a connection from the available connection pool or creates
- * a new one.
- *
- * @return A connection that can be used to access the database.
- */
- private def getConnection: Connection = {
- if (closing) {
- throw new Closed;
- } else {
- availableConnections match {
- case Nil => {
- lock.acquire;
- val connection = vendor.getConnection;
- usedConnections = connection :: usedConnections;
- lock.release;
- connection
- }
- case connection :: cs => {
- lock.acquire;
- availableConnections = cs;
- usedConnections = connection :: usedConnections;
- lock.release;
- connection;
- }
- }
- }
- }
-
- /** Closes a connection to this database. A closed connection might
- * also return to the available connection pool if the latter is depleted.
- *
- * @param connection The connection that should be closed.
- */
- private def closeConnection(connection: Connection): Unit = {
- if (closing) {
- connection.close()
- } else {
- lock.acquire
- usedConnections = usedConnections.filterNot(e => (e.equals(connection)));
- if (availableConnections.length < vendor.retainedConnections)
- availableConnections = connection :: availableConnections
- else
- connection.close()
- lock.release
- }
- }
-
- /** ..
- */
- def close() {
- closing = true
- for (conn <- availableConnections) conn.close()
- }
-
- /** Executes a statement that returns a relation on this database.
- *
- * @param relationStatement The statement to execute.
- * @return The relation returned by the database for this statement.
- */
- def executeStatement(relationStatement: statement.Relation): result.Relation =
- executeStatement(relationStatement, false);
-
- /** Executes a statement that returns a relation on this database.
- *
- * @param relationStatement The statement to execute.
- * @param debug Whether debugging information should be printed on the console.
- * @return The relation returned by the database for this statement.
- */
- def executeStatement(relationStatement: statement.Relation,
- debug: Boolean): result.Relation =
- new scala.dbc.result.Relation {
- val statement = relationStatement
- if (debug) Console.println("## " + statement.sqlString)
- private val connection = getConnection
- val sqlResult = connection.createStatement().executeQuery(statement.sqlString)
- closeConnection(connection)
- statement.typeCheck(this)
- }
-
- /** Executes a statement that updates the state of the database.
- * @param statusStatement The statement to execute.
- * @return The status of the database after the statement has been executed. */
- def executeStatement(statusStatement: statement.Status): result.Status[Unit] =
- executeStatement(statusStatement, false);
-
- /** Executes a statement that updates the state of the database.
- *
- * @param statusStatement The statement to execute.
- * @param debug Whether debugging information should be printed on the console.
- * @return The status of the database after the statement has been executed.
- */
- def executeStatement(statusStatement: statement.Status,
- debug: Boolean): result.Status[Unit] =
- new scala.dbc.result.Status[Unit] {
- val statement = statusStatement;
- if (debug) Console.println("## " + statement.sqlString);
- def result = ()
- private val connection = getConnection;
- val jdbcStatement: java.sql.Statement = connection.createStatement();
- jdbcStatement.execute(statement.sqlString);
- val touchedCount = Some(jdbcStatement.getUpdateCount());
- closeConnection(connection);
- }
-
- /** Executes a list of statements or other operations inside a transaction.
- * Only statements are protected in a transaction, other Scala code is not.
- *
- * @param transactionStatement The transaction to execute as a closure.
- * @return The status of the database after the transaction has been executed.
- */
- def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType]): result.Status[ResultType] =
- executeStatement(transactionStatement, false);
-
- /** Executes a list of statements or other operations inside a transaction.
- * Only statements are protected in a transaction, other Scala code is not.
- *
- * @param transactionStatement The transaction to execute as a closure.
- * @param debug Whether debugging information should be printed on the console.
- * @return The status of the database after the transaction has been executed.
- */
- def executeStatement[ResultType](transactionStatement: statement.Transaction[ResultType], debug: Boolean): result.Status[ResultType] = {
- new scala.dbc.result.Status[ResultType] {
- val touchedCount = None
- val statement = transactionStatement
- private val connection = getConnection
- connection.setAutoCommit(false)
- val jdbcStatement: java.sql.Statement = connection.createStatement();
- if (debug) Console.println("## " + transactionStatement.sqlStartString);
- jdbcStatement.execute(transactionStatement.sqlStartString);
- val result: ResultType = try {
- val buffer = transactionStatement.transactionBody(Database.this);
- if (debug) Console.println("## " + transactionStatement.sqlCommitString);
- jdbcStatement.execute(transactionStatement.sqlCommitString);
- buffer
- } catch {
- case e: Throwable => {
- if (debug) Console.println("## " + transactionStatement.sqlAbortString);
- jdbcStatement.execute(transactionStatement.sqlAbortString);
- throw e
- }
- }
- connection.setAutoCommit(true)
- closeConnection(connection)
- }
- }
-
-}
diff --git a/src/dbc/scala/dbc/Syntax.scala b/src/dbc/scala/dbc/Syntax.scala
deleted file mode 100644
index 85cd1c1a1d..0000000000
--- a/src/dbc/scala/dbc/Syntax.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc;
-
-
-import java.math.{BigDecimal, BigInteger};
-
-
-/** This class ..
- *
- */
-@deprecated(DbcIsDeprecated, "2.9.0") object Syntax {
-
- import syntax.DataTypeUtil;
-
- /* Data types */
- def boolean = DataTypeUtil.boolean;
- def tinyint = DataTypeUtil.tinyint;
- def smallint = DataTypeUtil.smallint;
- def integer = DataTypeUtil.integer;
- def bigint = DataTypeUtil.bigint;
- def real = DataTypeUtil.real;
-
- def numeric(precision: Int) = DataTypeUtil.numeric(precision);
- def numeric(precision: Int, scale: Int) = DataTypeUtil.numeric(precision, scale);
-
- def doublePrecision = DataTypeUtil.doublePrecision;
- def character(length: Int) = DataTypeUtil.character(length);
- def characterVarying(length: Int) = DataTypeUtil.characterVarying(length);
- def characterLargeObject = DataTypeUtil.characterLargeObject;
-
- /* Statements */
- //def select
-
- /* Other stuff */
- def database (server: String, username: String, password: String): dbc.Database =
- syntax.Database.database(server, username, password);
-
-}
diff --git a/src/dbc/scala/dbc/Utilities.scala b/src/dbc/scala/dbc/Utilities.scala
deleted file mode 100644
index c37b1bb98d..0000000000
--- a/src/dbc/scala/dbc/Utilities.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc;
-
-
-/** An object offering transformation methods (views) on various values.
- * This object's members must be visible in an expression to use value
- * auto-conversion.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") object Utilities {
-
- implicit def constantToValue (obj: statement.expression.Constant): Value =
- obj.constantValue;
-
- implicit def valueToConstant (obj: Value): statement.expression.Constant =
- new statement.expression.Constant {
- val constantValue = obj;
- }
-
-}
diff --git a/src/dbc/scala/dbc/Value.scala b/src/dbc/scala/dbc/Value.scala
deleted file mode 100644
index a502f51cb5..0000000000
--- a/src/dbc/scala/dbc/Value.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc;
-
-
-/** A SQL-99 value of any type. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Value {
-
- /** The SQL-99 type of the value. */
- val dataType: DataType;
-
- type NativeType = dataType.type#NativeType;
-
- val nativeValue: NativeType;
-
- /** A SQL-99 compliant string representation of the value. */
- def sqlString: String;
-
-}
diff --git a/src/dbc/scala/dbc/Vendor.scala b/src/dbc/scala/dbc/Vendor.scala
deleted file mode 100644
index 68f6102526..0000000000
--- a/src/dbc/scala/dbc/Vendor.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc;
-
-
-import java.sql.{Connection, Driver};
-
-
-/** This class ..
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Vendor {
-
- def nativeDriverClass: Class[_];
- def uri: java.net.URI;
- def user: String;
- def pass: String;
- def nativeProperties: java.util.Properties = {
- val properties = new java.util.Properties();
- properties.setProperty("user", user);
- properties.setProperty("password", pass);
- properties
- }
-
- def retainedConnections: Int;
-
- def getConnection: Connection = {
- val driver = nativeDriverClass.newInstance().asInstanceOf[Driver];
- driver.connect(uri.toString(),nativeProperties)
- }
-
- def urlProtocolString: String;
-
-}
diff --git a/src/dbc/scala/dbc/datatype/ApproximateNumeric.scala b/src/dbc/scala/dbc/datatype/ApproximateNumeric.scala
deleted file mode 100644
index 31752e18c7..0000000000
--- a/src/dbc/scala/dbc/datatype/ApproximateNumeric.scala
+++ /dev/null
@@ -1,57 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A type category for all SQL types that store varying-precision
- * numbers.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class ApproximateNumeric[Type] (
- override val nativeTypeId: DataType.Id
-) extends datatype.Numeric[Type](nativeTypeId) {
-
- def isEquivalent(datatype: DataType) = datatype match {
- case dt: ApproximateNumeric[_] =>
- (nativeTypeId == dt.nativeTypeId &&
- precisionRadix == dt.precisionRadix &&
- precision == dt.precision &&
- signed == dt.signed)
- case _ =>
- false
- }
-
- def isSubtypeOf (datatype:DataType) = datatype match {
- case dt:ApproximateNumeric[_] =>
- (nativeTypeId == dt.nativeTypeId &&
- precisionRadix == dt.precisionRadix &&
- precision <= dt.precision &&
- signed == dt.signed)
- case _ =>
- false
- }
-
- /** A SQL-99 compliant string representation of the type.
- * <h3>Compatibility notice</h3> This method assumes that a real
- * uses 32 bits and a double 64. This is not defined in the
- * standard but is usually the case.
- */
- override def sqlString: java.lang.String = Tuple2(precisionRadix,precision) match {
- case Tuple2(2,64) => "REAL"
- case Tuple2(2,128) => "DOUBLE PRECISION"
- case Tuple2(2,p) =>
- throw exception.UnsupportedFeature("SQL-99 does not support an approximate numeric type with a binary defined precision other than 16, 32 and 64 bits");
- case Tuple2(10,p) => "FLOAT (" + p.toString() + ")"
- case Tuple2(pr,_) =>
- throw exception.UnsupportedFeature("SQL-99 does not support the precision of an approximate numeric type to be defined in a radix other than 2 or 10");
- }
-
-}
diff --git a/src/dbc/scala/dbc/datatype/Boolean.scala b/src/dbc/scala/dbc/datatype/Boolean.scala
deleted file mode 100644
index 4a32ce98f1..0000000000
--- a/src/dbc/scala/dbc/datatype/Boolean.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** The SQL type for a truth value. */
-@deprecated(DbcIsDeprecated, "2.9.0") class Boolean extends DataType {
-
- def isEquivalent (datatype:DataType) = datatype match {
- case dt:Boolean => true
- case _ => false
- }
-
- def isSubtypeOf (datatype:DataType) = isEquivalent(datatype);
-
- type NativeType = scala.Boolean;
- val nativeTypeId = DataType.BOOLEAN;
-
- /** A SQL-99 compliant string representation of the type. */
- override def sqlString: java.lang.String = "BOOLEAN";
-
-}
diff --git a/src/dbc/scala/dbc/datatype/Character.scala b/src/dbc/scala/dbc/datatype/Character.scala
deleted file mode 100644
index 02dec06281..0000000000
--- a/src/dbc/scala/dbc/datatype/Character.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A SQL type for a string of characters of arbitrary length with
- * arbitrary character set.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Character extends CharacterString {
-
- def isEquivalent(datatype: DataType) = datatype match {
- case dt: Character =>
- length == dt.length && encoding == dt.encoding
- case _ =>
- false
- }
-
- def isSubtypeOf(datatype: DataType) = datatype match {
- case dt: Character =>
- length >= dt.length && encoding == dt.encoding
- case _ =>
- false
- }
-
- /** The length of the string defined in characters. */
- def length: Int;
-
- /** A SQL-99 compliant string representation of the type. */
- override def sqlString: java.lang.String = "CHARACTER (" + length.toString() + ")";
-
-}
diff --git a/src/dbc/scala/dbc/datatype/CharacterLargeObject.scala b/src/dbc/scala/dbc/datatype/CharacterLargeObject.scala
deleted file mode 100644
index 2c7ef64d66..0000000000
--- a/src/dbc/scala/dbc/datatype/CharacterLargeObject.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A SQL type for an unbounded length string of characters with arbitrary
- * character set. */
-@deprecated(DbcIsDeprecated, "2.9.0") class CharacterLargeObject extends CharacterString {
-
- def isEquivalent (datatype:DataType) = datatype match {
- case dt:CharacterLargeObject => {
- encoding == dt.encoding
- }
- case _ => false
- }
-
- def isSubtypeOf (datatype:DataType) = isEquivalent(datatype);
-
- /** A SQL-99 compliant string representation of the type. */
- override def sqlString: java.lang.String = "CHARACTER LARGE OBJECT";
-
-}
diff --git a/src/dbc/scala/dbc/datatype/CharacterString.scala b/src/dbc/scala/dbc/datatype/CharacterString.scala
deleted file mode 100644
index 54d6e0111f..0000000000
--- a/src/dbc/scala/dbc/datatype/CharacterString.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A type category for all SQL types that store strings of characters. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class CharacterString extends String {
-
- type NativeType = java.lang.String;
- val nativeTypeId = DataType.STRING;
-
- /** The name of the character set in which the string is encoded. */
- def encoding: Option[java.lang.String] = None;
-
-}
diff --git a/src/dbc/scala/dbc/datatype/CharacterVarying.scala b/src/dbc/scala/dbc/datatype/CharacterVarying.scala
deleted file mode 100644
index 9df487579f..0000000000
--- a/src/dbc/scala/dbc/datatype/CharacterVarying.scala
+++ /dev/null
@@ -1,41 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A SQL type for a varying length string of characters with arbitrary
- * maximal length and arbitrary character set.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class CharacterVarying extends CharacterString {
-
- def isEquivalent(datatype: DataType) = datatype match {
- case dt: CharacterVarying =>
- length == dt.length && encoding == dt.encoding
- case _ =>
- false
- }
-
- def isSubtypeOf(datatype: DataType) = datatype match {
- case dt: CharacterVarying =>
- length >= dt.length && encoding == dt.encoding
- case _ =>
- false
- }
-
- /** The maximal length of the string defined in characters. */
- def length: Int;
-
- /** A SQL-99 compliant string representation of the type. */
- override def sqlString: java.lang.String =
- "CHARACTER VARYING (" + length.toString() + ")";
-
-}
diff --git a/src/dbc/scala/dbc/datatype/ExactNumeric.scala b/src/dbc/scala/dbc/datatype/ExactNumeric.scala
deleted file mode 100644
index a578846977..0000000000
--- a/src/dbc/scala/dbc/datatype/ExactNumeric.scala
+++ /dev/null
@@ -1,65 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A type category for all SQL types that store constant-precision
- * numbers.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class ExactNumeric[Type](
- override val nativeTypeId: DataType.Id
-) extends datatype.Numeric[Type](nativeTypeId) {
-
- def isEquivalent(datatype: DataType) = datatype match {
- case dt: ExactNumeric[_] =>
- (nativeTypeId == dt.nativeTypeId &&
- precisionRadix == dt.precisionRadix &&
- precision == dt.precision &&
- scale == dt.scale &&
- signed == dt.signed)
- case _ =>
- false
- }
-
- def isSubtypeOf(datatype: DataType) = datatype match {
- case dt: ExactNumeric[_] =>
- (nativeTypeId == dt.nativeTypeId &&
- precisionRadix == dt.precisionRadix &&
- precision <= dt.precision &&
- scale <= dt.scale &&
- signed == dt.signed)
- case _ =>
- false
- }
-
- /** The number of digits used after the decimal point. */
- def scale: Int;
-
- /** A SQL-99 compliant string representation of the type.
- * <h3>Compatibility notice</h3> This method assumes that an integer
- * uses 32 bits, a small 16 and a big 64. This is not defined in the
- * standard but is usually the case.
- */
- override def sqlString: java.lang.String = Tuple3(precisionRadix,precision,scale) match {
- case Tuple3(2,16,0) => "SMALLINT"
- case Tuple3(2,32,0) => "INTEGER"
- case Tuple3(2,64,0) => "BIGINT"
- case Tuple3(2,java.lang.Integer.MAX_VALUE,0) => "BIGINT"
- case Tuple3(2,p,s) =>
- throw exception.UnsupportedFeature("SQL-99 does not support an exact numeric type with a binary defined precision other than 16, 32 and 64 bits");
- case Tuple3(10,p,0) => "NUMERIC (" + p.toString() + ")"
- case Tuple3(10,p,s) => "NUMERIC (" + p.toString() + ", " + s.toString() + ")"
- case Tuple3(pr,_,_) =>
- throw exception.UnsupportedFeature("SQL-99 does not support the precision of an exact numeric type to be defined in a radix other than 2 or 10");
- }
-
-}
diff --git a/src/dbc/scala/dbc/datatype/Factory.scala b/src/dbc/scala/dbc/datatype/Factory.scala
deleted file mode 100644
index bb9b3f5b61..0000000000
--- a/src/dbc/scala/dbc/datatype/Factory.scala
+++ /dev/null
@@ -1,250 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-import java.sql.Types._;
-import java.math.BigInteger;
-import java.math.BigDecimal;
-
-@deprecated(DbcIsDeprecated, "2.9.0") object Factory {
-
- final val java_lang_Integer_SIZE = 32;
- final val java_lang_Long_SIZE = 64;
-
- /** Returns a nullable property formatted as a boolean option */
- def isNullable (metadata:java.sql.ResultSetMetaData, index:Int): Option[scala.Boolean] =
- metadata.isNullable(index) match {
- case java.sql.ResultSetMetaData.columnNoNulls => Some(false);
- case java.sql.ResultSetMetaData.columnNullable => Some(true);
- case java.sql.ResultSetMetaData.columnNullableUnknown => None;
- }
-
- /** Returns the binary precision for an integer field. This should only be
- * used to find precision for integer numbers. It assumes that
- * bytes cannot be used partially (result % 8 = 0). */
- def bytePrecision (precision:Int, signed:scala.Boolean, safe:scala.Boolean): Int = {
- val decimalPrecision = precision + (if (safe) 1 else 0);
- Pair(signed,decimalPrecision) match {
- case Pair(_,0) => java.lang.Integer.MAX_VALUE // That's a bit of a hack.
- case Pair(_,dp) if (dp <= 3) => 8
- case Pair(_,dp) if (dp <= 5) => 16
- case Pair(true,dp) if (dp <= 7) => 24
- case Pair(false,dp) if (dp <= 8) => 24
- case Pair(_,dp) if (dp <= 10) => 32
- case Pair(true,dp) if (dp <= 12) => 40
- case Pair(false,dp) if (dp <= 13) => 40
- case Pair(_,dp) if (dp <= 15) => 48
- case Pair(_,dp) if (dp <= 17) => 56
- case Pair(true,dp) if (dp <= 19) => 64
- case Pair(false,dp) if (dp <= 20) => 64
- case Pair(_,dp) if (dp <= 22) => 72
- case Pair(true,dp) if (dp <= 24) => 80
- case Pair(false,dp) if (dp <= 25) => 80
- case Pair(_,dp) if (dp <= 27) => 88
- case Pair(_,dp) if (dp <= 29) => 96
- case Pair(_,dp) if (dp <= 32) => 104
- case Pair(_,dp) if (dp <= 34) => 112
- case Pair(true,dp) if (dp <= 36) => 120
- case Pair(false,dp) if (dp <= 37) => 120
- case Pair(_,dp) if (dp <= 39) => 128
- case _ => java.lang.Integer.MAX_VALUE
- }
- }
-
- def create (metadata:java.sql.ResultSetMetaData, index:Int): DataType = {
- metadata.getColumnType(index) match {
- /* Boolean data types. */
- case BOOLEAN => new datatype.Boolean {
- override val nullable = isNullable(metadata,index);
- }
- case BIT => new datatype.Boolean {
- override val nullable = isNullable(metadata,index);
- }
- /* Fixed precision numeric data types. */
- case DECIMAL => {
- Pair(bytePrecision(metadata.getPrecision(index),metadata.isSigned(index),true),metadata.getScale(index) == 0) match {
- case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) =>
- new datatype.ExactNumeric[Int](DataType.INT) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- case Pair(bp,true) if (bp <= java_lang_Long_SIZE) =>
- new datatype.ExactNumeric[Long](DataType.LONG) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- case Pair(_,true) =>
- new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- case Pair(_,false) =>
- new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- }
- }
- case NUMERIC => {
- Pair(bytePrecision(metadata.getPrecision(index),metadata.isSigned(index),true),metadata.getScale(index) == 0) match {
- case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) =>
- new datatype.ExactNumeric[Int](DataType.INT) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- case Pair(bp,true) if (bp <= java_lang_Long_SIZE) =>
- new datatype.ExactNumeric[Long](DataType.LONG) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- case Pair(_,true) =>
- new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- case Pair(_,false) =>
- new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 10;
- val precision = metadata.getPrecision(index);
- val signed = metadata.isSigned(index);
- val scale = metadata.getScale(index);
- }
- }
- }
- /* Fixed precision integer data types. */
- case BIGINT =>
- new datatype.ExactNumeric[Long](DataType.LONG) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 2;
- val precision = 64;
- val signed = metadata.isSigned(index);
- val scale = 0;
- }
- case INTEGER =>
- new datatype.ExactNumeric[Int](DataType.INT) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 2;
- val precision = 32;
- val signed = metadata.isSigned(index);
- val scale = 0;
- }
- case SMALLINT =>
- new datatype.ExactNumeric[Short](DataType.SHORT) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 2;
- val precision = 16;
- val signed = metadata.isSigned(index);
- val scale = 0;
- }
- case TINYINT =>
- new datatype.ExactNumeric[Byte](DataType.BYTE) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 2;
- val precision = 8;
- val signed = metadata.isSigned(index);
- val scale = 0;
- }
- /* Floating point numeric data types. */
- case REAL =>
- new datatype.ApproximateNumeric[Float](DataType.FLOAT) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 2;
- val precision = 64;
- val signed = metadata.isSigned(index);
- }
- case DOUBLE =>
- new datatype.ApproximateNumeric[Double](DataType.DOUBLE) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 2;
- val precision = 128;
- val signed = metadata.isSigned(index);
- }
- case FLOAT =>
- new datatype.ApproximateNumeric[Double](DataType.DOUBLE) {
- override val nullable = isNullable(metadata,index);
- val precisionRadix = 2;
- val precision = 128;
- val signed = metadata.isSigned(index);
- }
- /* Character string data types. */
- case CHAR => new datatype.Character {
- override val nullable = isNullable(metadata,index);
- val length = metadata.getColumnDisplaySize(index);
- }
- case CLOB => new datatype.CharacterLargeObject {
- override val nullable = isNullable(metadata,index);
- }
- case LONGVARCHAR => {
- if (metadata.getColumnDisplaySize(index) >= 0)
- new datatype.CharacterVarying {
- override val nullable = isNullable(metadata,index);
- def length = metadata.getColumnDisplaySize(index);
- }
- else // A PostgreSQL Hack
- new datatype.CharacterLargeObject {
- override val nullable = isNullable(metadata,index);
- }
- }
- case VARCHAR => {
- if (metadata.getColumnDisplaySize(index) >= 0)
- new datatype.CharacterVarying {
- override val nullable = isNullable(metadata,index);
- def length = metadata.getColumnDisplaySize(index);
- }
- else // A PostgreSQL Hack
- new datatype.CharacterLargeObject {
- override val nullable = isNullable(metadata,index);
- }
- }
- /* Undefined cases. */
- case OTHER => new datatype.Unknown {
- override val nullable = isNullable(metadata, index);
- }
- /* Unsupported data types. */
- case REF | ARRAY | STRUCT =>
- sys.error ("I don't support composite data types yet.");
- case DATALINK | DISTINCT | JAVA_OBJECT | NULL =>
- sys.error ("I won't support strange data types.");
- /* Unsupported binary string data types. */
- case BINARY | BLOB | LONGVARBINARY | VARBINARY =>
- sys.error ("I don't support binary string data types yet.");
- /* Unsupported date and time data types. */
- case DATE | TIME | TIMESTAMP =>
- sys.error ("I don't support date and time data types yet.");
- /* Default case */
- case x => sys.error ("I don't know about this ("+metadata.getColumnTypeName(index)+") JDBC type.")
- }
- }
-}
diff --git a/src/dbc/scala/dbc/datatype/Numeric.scala b/src/dbc/scala/dbc/datatype/Numeric.scala
deleted file mode 100644
index c13f454dde..0000000000
--- a/src/dbc/scala/dbc/datatype/Numeric.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A type category for all SQL types that store numbers. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Numeric[Type](_nativeTypeId: DataType.Id) extends DataType {
-
- type NativeType = Type;
- val nativeTypeId = _nativeTypeId;
-
- /** The radix in which the precision (and scale when appliable) is defined.
- * ISO-9075 only allows 2 and 10 for this value.
- */
- def precisionRadix: Int;
-
- /** The number of significant digits for that number. */
- def precision: Int;
-
- /** Whether the number is signed or not. */
- def signed: scala.Boolean;
-
-}
diff --git a/src/dbc/scala/dbc/datatype/String.scala b/src/dbc/scala/dbc/datatype/String.scala
deleted file mode 100644
index 291504f777..0000000000
--- a/src/dbc/scala/dbc/datatype/String.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** A type category for all SQL types that store strings of elements.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class String extends DataType {
-
- /** The maximal possible length of the string defined in characters.
- * This is an implementation-specific value.
- */
- def maxLength: Option[Int] = None;
-
-}
diff --git a/src/dbc/scala/dbc/datatype/Unknown.scala b/src/dbc/scala/dbc/datatype/Unknown.scala
deleted file mode 100644
index 14a33c6be9..0000000000
--- a/src/dbc/scala/dbc/datatype/Unknown.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package datatype;
-
-
-/** The SQL type for a truth value. */
-@deprecated(DbcIsDeprecated, "2.9.0") class Unknown extends DataType {
-
- def isEquivalent(datatype: DataType) = datatype match {
- case dt: Unknown =>
- nativeTypeId == dt.nativeTypeId
- case _ =>
- false
- }
-
- def isSubtypeOf(datatype: DataType) = true;
-
- type NativeType = AnyRef;
- val nativeTypeId = DataType.OBJECT;
-
- /** A SQL-99 compliant string representation of the type. */
- override def sqlString: java.lang.String =
- sys.error("The 'UNKNOWN' data type cannot be represented.");
-
-}
diff --git a/src/dbc/scala/dbc/exception/IncompatibleSchema.scala b/src/dbc/scala/dbc/exception/IncompatibleSchema.scala
deleted file mode 100644
index c8d53bbf1a..0000000000
--- a/src/dbc/scala/dbc/exception/IncompatibleSchema.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package exception
-
-
-/** A type category for all SQL types that store constant-precision numbers. */
-@deprecated(DbcIsDeprecated, "2.9.0") case class IncompatibleSchema (
- expectedSchema: List[DataType],
- foundSchema: List[DataType]
-) extends Exception;
diff --git a/src/dbc/scala/dbc/package.scala b/src/dbc/scala/dbc/package.scala
deleted file mode 100644
index b1552e11d3..0000000000
--- a/src/dbc/scala/dbc/package.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-package scala
-
-package object dbc {
- final val DbcIsDeprecated =
- "scala.dbc will be removed after version 2.9. Use an active sql library such as scalaquery instead."
-} \ No newline at end of file
diff --git a/src/dbc/scala/dbc/result/Field.scala b/src/dbc/scala/dbc/result/Field.scala
deleted file mode 100644
index cd3309bb14..0000000000
--- a/src/dbc/scala/dbc/result/Field.scala
+++ /dev/null
@@ -1,63 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package result
-
-
-import scala.dbc.datatype._
-import scala.dbc.value._
-
-/** An ISO-9075:2003 (SQL) table field. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Field {
-
- /** The content (value) of the field. The type of this value is undefined,
- * transformation into a useful type will be done by an automatic view
- * function defined in the field object.
- */
- def content: Value
-
- final def value[Type <: Value]: Type =
- content.asInstanceOf[Type]
-
- final def exactNumericValue[NativeType] =
- content.asInstanceOf[dbc.value.ExactNumeric[NativeType]]
-
- final def approximateNumericValue[NativeType] =
- content.asInstanceOf[dbc.value.ApproximateNumeric[NativeType]]
-
- final def booleanValue =
- content.asInstanceOf[dbc.value.Boolean]
-
- final def characterValue =
- content.asInstanceOf[dbc.value.Character]
-
- final def characterLargeObjectValue =
- content.asInstanceOf[dbc.value.CharacterLargeObject]
-
- final def characterVaryingValue =
- content.asInstanceOf[dbc.value.CharacterVarying]
-
- final def unknownValue =
- content.asInstanceOf[dbc.value.Unknown]
-
- /** The tuple that contains this field. */
- def originatingTuple: Tuple
-
- /** The field metadata attached to this field. */
- def metadata: FieldMetadata
-
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object Field {
-
- implicit def fieldToValue (field: Field): Value = field.content
-
-}
diff --git a/src/dbc/scala/dbc/result/FieldMetadata.scala b/src/dbc/scala/dbc/result/FieldMetadata.scala
deleted file mode 100644
index 3c2de297d0..0000000000
--- a/src/dbc/scala/dbc/result/FieldMetadata.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package result
-
-
-/** The class <code>FieldMetadata</cocde> provides informations attached to
- * a field about its content and its relationship to the originating database.
- */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class FieldMetadata {
-
- /** The name of the field. */
- def name: String
-
- /** The index of the field in the tuple. */
- def index: Int
-
- /** The expected type of the field. This information is used for automatic
- * transformation of the field value into a usable type.
- */
- def datatype: DataType
-
- /** The name of the catalog in the database from which the field originates */
- def catalog: String
-
- /** The name of the schema in the database from which the field originates */
- def schema: String
-
- /** The name of the table in the database from which the field originates */
- def table: String
-
-}
diff --git a/src/dbc/scala/dbc/result/Relation.scala b/src/dbc/scala/dbc/result/Relation.scala
deleted file mode 100644
index 98d653d61e..0000000000
--- a/src/dbc/scala/dbc/result/Relation.scala
+++ /dev/null
@@ -1,84 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package result
-
-
-/** An ISO-9075:2003 (SQL) table. This is equivalent to a relation in the
- * relational model. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Relation
-extends collection.AbstractIterable[Tuple]
- with Iterable[Tuple] {
-
- /** The statement that generated this relation. */
- def statement: scala.dbc.statement.Relation
-
- /** A JDBC result containing this relation. */
- protected def sqlResult: java.sql.ResultSet
-
- /** A JDBC metadata object attached to the relation. */
- protected def sqlMetadata: java.sql.ResultSetMetaData = sqlResult.getMetaData()
-
- /** Metadata about all fields in a tuple of the relation. */
- def metadata: List[FieldMetadata] =
- for (count <- List.range(1, sqlMetadata.getColumnCount()+1)) yield
- new FieldMetadata {
- val name: String = sqlMetadata.getColumnName(count)
- val index: Int = count
- val datatype: DataType = dbc.datatype.Factory.create(sqlMetadata,count)
- val catalog: String = sqlMetadata.getCatalogName(count)
- val schema: String = sqlMetadata.getSchemaName(count)
- val table: String = sqlMetadata.getTableName(count)
- }
-
- /** Metadata about the field at the given index. If there is no such
- * field <code>None</code> is returned instead. */
- def metadataFor (index:Int): Option[FieldMetadata] = {
- val meta = metadata
- if (meta.length > index)
- Some(meta(index))
- else
- None
- }
-
- /** Metadata about the field with the given column name. If there is no
- * such field, <code>None</code> is returned instead. */
- def metadataFor (name:String): Option[FieldMetadata] =
- metadata.find(f=>(f.name==name));
-
- /** An iterator on the tuples of the relation.
- * <h3>Caution</h3> A Relation only has one single iterator, due to limitations
- * in DBMS. This means that if this method is called multiple times, all returned
- * iterators will share the same state. */
- def iterator: Iterator[Tuple] = new collection.AbstractIterator[Tuple] {
- protected val result: java.sql.ResultSet = Relation.this.sqlResult
- def hasNext: Boolean = resultNext
- private var resultNext = result.next()
- def next: Tuple = {
- if (resultNext) {
- val newTuple = new Tuple {
- val me = this
- val originatingRelation = Relation.this
- val fields: List[Field] = for (fieldMetadata <- metadata) yield
- new Field {
- val metadata = fieldMetadata
- val content = dbc.value.Factory.create(result,metadata.index,metadata.datatype)
- val originatingTuple = me
- }
- }
- resultNext = result.next()
- newTuple
- }
- else sys.error("next on empty iterator")
- }
- }
-
-}
diff --git a/src/dbc/scala/dbc/result/Status.scala b/src/dbc/scala/dbc/result/Status.scala
deleted file mode 100644
index d3152a58ab..0000000000
--- a/src/dbc/scala/dbc/result/Status.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package result;
-
-
-import scala.dbc.datatype._;
-
-/** An object containing the status of a query */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Status[ResultType] {
-
- /** The statement that generated this status result. */
- def statement: scala.dbc.statement.Statement;
-
- /** The number of elements modified or added by this statement. */
- def touchedCount: Option[Int];
-
- def result: ResultType;
-
-}
diff --git a/src/dbc/scala/dbc/result/Tuple.scala b/src/dbc/scala/dbc/result/Tuple.scala
deleted file mode 100644
index 80ab5c22aa..0000000000
--- a/src/dbc/scala/dbc/result/Tuple.scala
+++ /dev/null
@@ -1,42 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package result;
-
-
-/** An ISO-9075:2003 (SQL) table row. This is equivalent to a tuple in the relational model. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Tuple {
-
- /** All the fields contained in the tuple. */
- def fields: List[Field];
-
- /** The relation that contains the tuple. */
- def originatingRelation: Relation;
-
- /** The field at the given index. If there is no such field (that is the index is out of bounds), <code>None</code> is returned instead. */
- def apply (index:Int): Field =
- try {
- fields(index)
- } catch {
- case e =>
- throw new java.lang.IndexOutOfBoundsException("Field at index "+index+" does not exist in relation");
- }
-
- /** The field with the given column name. If there is no such field, <code>None</code> is returned instead. */
- def apply (name:String): Field = {
- def findField (fields: List[Field], name:String): Field = fields match {
- case Nil => throw new java.lang.IndexOutOfBoundsException("Field '"+name+"' does not exist in relation")
- case field :: _ if (field.metadata.name == name) => field
- case field :: fields => findField (fields, name)
- }
- findField (fields, name);
- }
-}
diff --git a/src/dbc/scala/dbc/statement/DerivedColumn.scala b/src/dbc/scala/dbc/statement/DerivedColumn.scala
deleted file mode 100644
index ae05df986a..0000000000
--- a/src/dbc/scala/dbc/statement/DerivedColumn.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class DerivedColumn {
-
- /** The value for the column. This value can be of any type but must be
- * calculated from fields that appear in a relation that takes part
- * in the query.
- */
- def valueExpression: Expression
-
- /** A new name for this field. This name must be unique for the query in
- * which the column takes part.
- */
- def asClause: Option[String]
-
- /** A SQL-99 compliant string representation of the derived column
- * sub-statement. This only has a meaning inside a select statement.
- */
- def sqlString: String =
- valueExpression.sqlInnerString +
- (asClause match {
- case None => ""
- case Some(ac) => " AS " + ac
- })
-
-}
diff --git a/src/dbc/scala/dbc/statement/Expression.scala b/src/dbc/scala/dbc/statement/Expression.scala
deleted file mode 100644
index c2da91e9ef..0000000000
--- a/src/dbc/scala/dbc/statement/Expression.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-/** An expression that calculates some value from fields. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Expression extends Relation {
-
- def fieldTypes: List[DataType] = Nil
-
- /** A SQL-99 compliant string representation of the expression. */
- def sqlString: String = "SELECT " + sqlInnerString
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement.
- */
- def sqlInnerString: String
-
-}
diff --git a/src/dbc/scala/dbc/statement/Insert.scala b/src/dbc/scala/dbc/statement/Insert.scala
deleted file mode 100644
index 189ccec54f..0000000000
--- a/src/dbc/scala/dbc/statement/Insert.scala
+++ /dev/null
@@ -1,31 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-import scala.dbc.statement.expression._
-
-/** An insertion of values into a table. */
-@deprecated(DbcIsDeprecated, "2.9.0") case class Insert(insertionTarget: String, insertionData: InsertionData)
- extends Status {
-
- /** A SQL-99 compliant string representation of the select statement. */
- def sqlString: String =
- "INSERT INTO " + insertionTarget + " " + insertionData.sqlString
-
- /** The name of the table where the data should be added. */
- //def insertionTarget: String
-
- /** The data that will be added tot he table. */
- //def insertionData: InsertionData
-
-}
diff --git a/src/dbc/scala/dbc/statement/InsertionData.scala b/src/dbc/scala/dbc/statement/InsertionData.scala
deleted file mode 100644
index e91ad7efe6..0000000000
--- a/src/dbc/scala/dbc/statement/InsertionData.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-import scala.dbc.statement.expression._
-
-/** Data to be inserted into a table in an <code>Insert</code>. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class InsertionData {
- def sqlString: String
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object InsertionData {
- /** Insertion of data resulting from a query on the database. */
- @deprecated(DbcIsDeprecated, "2.9.0") case class Subquery(query: Relation) extends InsertionData {
- def sqlString = query.sqlString
- }
- /** Insertion of data as explicitly defined values. */
- @deprecated(DbcIsDeprecated, "2.9.0") case class Constructor(
- columnNames: Option[List[String]],
- columnValues: List[Expression]
- ) extends InsertionData {
- def sqlString =
- (columnNames match {
- case None => ""
- case Some(cn) => cn.mkString(" (",", ",")")
- }) +
- " VALUES" +
- columnValues.map(e => e.sqlInnerString).mkString(" (",", ",")")
- }
-}
diff --git a/src/dbc/scala/dbc/statement/IsolationLevel.scala b/src/dbc/scala/dbc/statement/IsolationLevel.scala
deleted file mode 100644
index b31614c3dd..0000000000
--- a/src/dbc/scala/dbc/statement/IsolationLevel.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class IsolationLevel {
- def sqlString: String
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object IsolationLevel {
- case object ReadUncommitted extends IsolationLevel {
- def sqlString = "ISOLATION LEVEL READ UNCOMMITTED"
- }
- case object ReadCommitted extends IsolationLevel {
- def sqlString = "ISOLATION LEVEL READ COMMITTED"
- }
- case object RepeatableRead extends IsolationLevel {
- def sqlString = "ISOLATION LEVEL REPEATABLE READ"
- }
- case object Serializable extends IsolationLevel {
- def sqlString = "ISOLATION LEVEL SERIALIZABLE"
- }
-}
diff --git a/src/dbc/scala/dbc/statement/JoinType.scala b/src/dbc/scala/dbc/statement/JoinType.scala
deleted file mode 100644
index 698612b10d..0000000000
--- a/src/dbc/scala/dbc/statement/JoinType.scala
+++ /dev/null
@@ -1,56 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-/** A join behaviour in a <code>Jointure</code>. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class JoinType {
- /** A SQL-99 string representation of the join behaviour. */
- def sqlString: String
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object JoinType {
-
- /** A join behaviour where a joined tuple is created only when a
- * corresponding tuple exists in both original relations.
- */
- case object Inner extends JoinType {
- val sqlString = "INNER JOIN"
- }
-
- /** A join behaviour family where a joined tuple is created even when a
- * tuple has no corresponding tuple in the other relation. The fields
- * populated by values of the other tuple will receive the NULL value.
- */
- abstract class Outer extends JoinType
-
- object Outer {
- /** An outer join behaviour where there will be at least on tuple for
- * every tuple in the left relation.
- */
- case object Left extends Outer {
- val sqlString = "LEFT OUTER JOIN"
- }
- /** An outer join behaviour where there will be at least on tuple for
- * every tuple in the right relation.
- */
- case object Right extends Outer {
- val sqlString = "RIGHT OUTER JOIN"
- }
- /** An outer join behaviour where there will be at least on tuple for
- * every tuple in both right and left relations.
- */
- case object Full extends Outer {
- val sqlString = "FULL OUTER JOIN"
- }
- }
-}
diff --git a/src/dbc/scala/dbc/statement/Jointure.scala b/src/dbc/scala/dbc/statement/Jointure.scala
deleted file mode 100644
index 74c871cc3e..0000000000
--- a/src/dbc/scala/dbc/statement/Jointure.scala
+++ /dev/null
@@ -1,45 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-/** A jointure between two relations. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Jointure extends Relation {
-
- /** The relation on the left part of the join. */
- def leftRelation: Relation
-
- /** The relation on the right part of the join. */
- def rightRelation: Relation
-
- /** The type of the jointure. */
- def joinType: JoinType
-
- /** The condition on which the jointure needs be done. */
- def joinCondition: Option[Expression]
-
- /** A SQL-99 compliant string representation of the relation statement. */
- def sqlString: String = "SELECT * FROM " + sqlInnerString
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside a query.
- */
- def sqlInnerString: String =
- leftRelation.sqlInnerString + " " +
- joinType.sqlString + " " +
- rightRelation.sqlInnerString +
- (joinCondition match {
- case Some(jc) => jc.sqlString
- case None => ""
- })
-
-}
diff --git a/src/dbc/scala/dbc/statement/Relation.scala b/src/dbc/scala/dbc/statement/Relation.scala
deleted file mode 100644
index 787707ee82..0000000000
--- a/src/dbc/scala/dbc/statement/Relation.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement;
-
-
-/** A statement that returns a relation. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Relation extends Statement {
-
- def isCompatibleType: (DataType,DataType)=>Boolean =
- ((dt,wdt)=>dt.isSubtypeOf(wdt));
-
- def typeCheck (relation: result.Relation): Unit = {
- val sameType: Boolean = (
- relation.metadata.length == fieldTypes.length &&
- (relation.metadata.zip(fieldTypes).forall({case Pair(field,expectedType) =>
- isCompatibleType(field.datatype, expectedType)}))
- );
- if (!sameType)
- throw new exception.IncompatibleSchema(fieldTypes,relation.metadata.map(field=>field.datatype));
- }
-
- def fieldTypes: List[DataType];
-
- def sqlTypeString: String =
- if (fieldTypes.isEmpty)
- "UNTYPED"
- else
- fieldTypes.map(dt=>dt.sqlString).mkString("RELATION (",", ",")");
-
- /** A SQL-99 compliant string representation of the statement. */
- def sqlString: String;
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String;
-
- /** Executes the statement on the given database. */
- def execute (database: scala.dbc.Database): scala.dbc.result.Relation = {
- database.executeStatement(this);
- }
-
- def execute (database:scala.dbc.Database, debug:Boolean): scala.dbc.result.Relation = {
- database.executeStatement(this,debug);
- }
-
-}
diff --git a/src/dbc/scala/dbc/statement/Select.scala b/src/dbc/scala/dbc/statement/Select.scala
deleted file mode 100644
index a9ca0212ed..0000000000
--- a/src/dbc/scala/dbc/statement/Select.scala
+++ /dev/null
@@ -1,99 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-/** A statement that when executed on a database will return a relation.
- * The returned relation will be a subset of a table in the database or
- * a jointure between such subsets. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Select extends Relation {
-
- /** Defines if duplicated tuples should be removed from the returned
- * relation. <h3>Compatibility notice</h3> Some DBMS (PostgreSQL) allow
- * uniqueness constrains on an arbitrary field instead of the entire
- * tuple. */
- def setQuantifier: Option[SetQuantifier]
-
- /** Defines the output fields that a tuple in the returned relation will
- * contain, and their content with respect to the tables in the
- * database. If the fields are not specified (that is the list is
- * empty), all possible input fields will be returned. <h3>Compatibility
- * notice</h3> SQL's qualified asterisk select sublist is not
- * available. */
- def selectList: List[DerivedColumn]
-
- /** Defines the relations from which the query will obtain its data.*/
- def fromClause: List[Relation]
-
- /** Defines condition that must be true in the returned relation's tuples.
- * This value expression must return a boolean or boolean-compatible
- * value. This condition is applied before any GROUP BY clause.
- */
- def whereClause: Option[Expression]
-
- /** Defines the grouping of the returned relation's tuples. One tuple is
- * returned for every group. The value of <code>selectList</code> must
- * use aggregate functions for calculation.
- */
- def groupByClause: Option[List[Expression]]
-
- /** Defines conditions that must be true in the returned relation's tuples.
- * The value expression must return a boolean can only refer to fields
- * that are grouped or to any field from inside an aggregate function.
- */
- def havingClause: Option[Expression]
-
- /* def windowClause: Option[_]; */
-
- /** A SQL-99 compliant string representation of the select statement. */
- def sqlString: String = (
- "SELECT" +
- (setQuantifier match {
- case None => ""
- case Some(sq) => " " + sq.sqlString
- }) +
- (selectList match {
- case Nil => " *"
- case _ => (" " + selectList.tail.foldLeft(selectList.head.sqlString)
- ((name:String, dc:DerivedColumn) => name + ", " + dc.sqlString))
- }) +
- (fromClause match {
- case Nil => sys.error("Empty from clause is not allowed")
- case _ => (" FROM " + fromClause.tail.foldLeft(fromClause.head.sqlInnerString)
- ((name:String, rel:Relation) => name + ", " + rel.sqlInnerString))
- }) +
- (whereClause match {
- case None => ""
- case Some(expr) => " WHERE " + expr.sqlInnerString
- }) +
- (groupByClause match {
- case None => ""
- case Some(gbl) => gbl match {
- case Nil => sys.error("Empty group by clause is not allowed")
- case _ =>
- (" GROUP BY " +
- gbl.tail.foldLeft(gbl.head.sqlInnerString)
- ((name:String, gb) => name + ", " + gb.sqlInnerString))
- }
- }) +
- (havingClause match {
- case None => ""
- case Some(expr) => " HAVING " + expr.sqlString
- })
- );
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside a query.
- */
- def sqlInnerString: String = "("+sqlString+")"
-
-}
diff --git a/src/dbc/scala/dbc/statement/SetQuantifier.scala b/src/dbc/scala/dbc/statement/SetQuantifier.scala
deleted file mode 100644
index 77a4b79b8d..0000000000
--- a/src/dbc/scala/dbc/statement/SetQuantifier.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-/** A set quantifier that defines the collection type of a relation. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class SetQuantifier {
- /** A SQL-99 compliant string representation of the set quantifier. */
- def sqlString: String
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object SetQuantifier {
-
- /** A set quantifier that defines a relation as being a bag. That means
- * that duplicates are allowed.
- */
- case object AllTuples extends SetQuantifier {
- /** A SQL-99 compliant string representation of the set quantifier. */
- def sqlString: String = "ALL"
- }
-
- /** A set quantifier that defines a relation as being a set. That means
- * that duplicates are not allowed and will be pruned.
- */
- case object DistinctTuples extends SetQuantifier {
- /** A SQL-99 compliant string representation of the set quantifier. */
- def sqlString: String = "DISTINCT"
- }
-}
diff --git a/src/dbc/scala/dbc/statement/Status.scala b/src/dbc/scala/dbc/statement/Status.scala
deleted file mode 100644
index 0ce64b978d..0000000000
--- a/src/dbc/scala/dbc/statement/Status.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-import scala.dbc.Database
-import scala.dbc.result
-
-/** A statement that changes the status of the database. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Status extends Statement {
-
- /** A SQL-99 compliant string representation of the statement. */
- def sqlString: String
-
- /** Executes the statement on the given database. */
- def execute(database: Database): result.Status[Unit] = {
- database.executeStatement(this)
- }
-
- def execute(database: Database, debug: Boolean): result.Status[Unit] = {
- database.executeStatement(this, debug)
- }
-
-}
diff --git a/src/dbc/scala/dbc/statement/Table.scala b/src/dbc/scala/dbc/statement/Table.scala
deleted file mode 100644
index e729f801a3..0000000000
--- a/src/dbc/scala/dbc/statement/Table.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-
-
-/** A reference to a table in the database.
- * @author Gilles Dubochet
- * @version 1.0 */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Table extends Relation {
-
- /** The name of the table in the database. */
- def tableName: String
-
- /** The name that the table will be called in the enclosing statement. */
- def tableRename: Option[String]
-
- /** A SQL-99 compliant string representation of the relation statement. */
- def sqlString: String = "SELECT * FROM " + tableName
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside a query. */
- def sqlInnerString: String =
- tableName +
- (tableRename match {
- case None => ""
- case Some(rename) => " AS " + rename
- })
-
-}
diff --git a/src/dbc/scala/dbc/statement/Transaction.scala b/src/dbc/scala/dbc/statement/Transaction.scala
deleted file mode 100644
index 1740dae3f9..0000000000
--- a/src/dbc/scala/dbc/statement/Transaction.scala
+++ /dev/null
@@ -1,55 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement;
-
-
-/** A statement that changes the status of the database. */
-@deprecated(DbcIsDeprecated, "2.9.0") case class Transaction [ResultType] (
- transactionBody: (scala.dbc.Database=>ResultType),
- accessMode: Option[AccessMode],
- isolationLevel: Option[IsolationLevel]
-) extends Statement {
-
- /** A SQL-99 compliant string representation of the statement. */
- def sqlStartString: String = (
- "START TRANSACTION" +
- (Pair(accessMode,isolationLevel) match {
- case Pair(None,None) => ""
- case Pair(Some(am),None) => " " + am.sqlString
- case Pair(None,Some(il)) => " " + il.sqlString
- case Pair(Some(am),Some(il)) => " " + am.sqlString + ", " + il.sqlString
- })
- );
-
- def sqlCommitString: String = {
- "COMMIT"
- }
-
- def sqlAbortString: String = {
- "ROLLBACK"
- }
-
- //def transactionBody: (()=>Unit);
-
- //def accessMode: Option[AccessMode];
-
- //def isolationLevel: Option[IsolationLevel];
-
- def execute (database: scala.dbc.Database): scala.dbc.result.Status[ResultType] = {
- database.executeStatement(this);
- }
-
- def execute (database: scala.dbc.Database, debug: Boolean): scala.dbc.result.Status[ResultType] = {
- database.executeStatement(this,debug);
- }
-
-}
diff --git a/src/dbc/scala/dbc/statement/Update.scala b/src/dbc/scala/dbc/statement/Update.scala
deleted file mode 100644
index 836549a4be..0000000000
--- a/src/dbc/scala/dbc/statement/Update.scala
+++ /dev/null
@@ -1,47 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement;
-
-
-import scala.dbc.statement.expression._;
-
-/** An update of the state of a table. */
-@deprecated(DbcIsDeprecated, "2.9.0") case class Update (
- updateTarget: String,
- setClauses: List[SetClause],
- whereClause: Option[Expression]
-) extends Status {
-
-
- /** A SQL-99 compliant string representation of the select statement. */
- def sqlString: String = (
- "UPDATE " +
- updateTarget +
- " SET " + setClauses.map(sc=>sc.sqlString).mkString("",", ","") +
- (whereClause match {
- case None => ""
- case Some(expr) => " WHERE " + expr.sqlString
- })
- );
-
- /** The name of the table that should be updated. */
- //def updateTarget: String;
-
- /** The data that will be added tot he table. */
- //def setClauses: List[SetClause];
-
- /** Defines condition that must be true in the tuples that will be updated.
- * This value expression must return a boolean or boolean-compatible
- * value. */
- //def whereClause: Option[scala.dbc.statement.expression.Expression];
-
-}
diff --git a/src/dbc/scala/dbc/statement/expression/Aggregate.scala b/src/dbc/scala/dbc/statement/expression/Aggregate.scala
deleted file mode 100644
index c42bffe20e..0000000000
--- a/src/dbc/scala/dbc/statement/expression/Aggregate.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Aggregate extends Expression {
-
- def aggregateName: String;
-
- def setFunction: SetFunction;
-
- def filterClause: Option[Expression];
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = (
- aggregateName +
- "(" + setFunction.sqlString + ")" +
- (filterClause match {
- case None => ""
- case Some(fc) => " FILTER (WHERE " + fc.sqlString + ")"
- })
- )
-
-}
diff --git a/src/dbc/scala/dbc/statement/expression/BinaryOperator.scala b/src/dbc/scala/dbc/statement/expression/BinaryOperator.scala
deleted file mode 100644
index 32f016dbf6..0000000000
--- a/src/dbc/scala/dbc/statement/expression/BinaryOperator.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class BinaryOperator extends Expression {
-
- /** The name of the operator. */
- def operator: String;
-
- /** The expression applied on the left of the operator. */
- def leftOperand: Expression;
-
- /** The expression applied on the right of the operator. */
- def rightOperand: Expression;
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = {
- leftOperand.sqlInnerString + " " + operator + " " + rightOperand.sqlInnerString
- }
-
-}
diff --git a/src/dbc/scala/dbc/statement/expression/Constant.scala b/src/dbc/scala/dbc/statement/expression/Constant.scala
deleted file mode 100644
index 70ec7819dc..0000000000
--- a/src/dbc/scala/dbc/statement/expression/Constant.scala
+++ /dev/null
@@ -1,23 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Constant extends Expression {
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = constantValue.sqlString;
-
- /** The value of the constant. */
- def constantValue: Value;
-}
diff --git a/src/dbc/scala/dbc/statement/expression/Default.scala b/src/dbc/scala/dbc/statement/expression/Default.scala
deleted file mode 100644
index 78204d0172..0000000000
--- a/src/dbc/scala/dbc/statement/expression/Default.scala
+++ /dev/null
@@ -1,22 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-case object Default extends Expression {
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = "DEFAULT";
-
-}
diff --git a/src/dbc/scala/dbc/statement/expression/Field.scala b/src/dbc/scala/dbc/statement/expression/Field.scala
deleted file mode 100644
index 9a90903a99..0000000000
--- a/src/dbc/scala/dbc/statement/expression/Field.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Field extends Expression {
-
- /** The name of the schema in the database where the field is located. */
- def schemaName: Option[String] = None;
-
- /** The name of the table in the database where the field is located. */
- def tableName: Option[String];
-
- /** The name of the field in the database. */
- def fieldName: String;
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = (
- (schemaName match {
- case None => ""
- case Some(sn) => sn + "."
- }) +
- (tableName match {
- case None => ""
- case Some(tn) => tn + "."
- }) + fieldName
- )
-
-}
diff --git a/src/dbc/scala/dbc/statement/expression/FunctionCall.scala b/src/dbc/scala/dbc/statement/expression/FunctionCall.scala
deleted file mode 100644
index 962cf209b9..0000000000
--- a/src/dbc/scala/dbc/statement/expression/FunctionCall.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") case class FunctionCall (
- functionName: String,
- arguments: List[Expression]
-) extends Expression {
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = {
- functionName + "(" + arguments.mkString("",", ","") + ")"
- }
-
- /** The name of the function to call. */
- //def functionName: String;
-
- /** A list of all argument expressions to pass to the function, in order. */
- //def arguments: List[Expression];
-
-}
diff --git a/src/dbc/scala/dbc/statement/expression/Select.scala b/src/dbc/scala/dbc/statement/expression/Select.scala
deleted file mode 100644
index 7a6a4a21c4..0000000000
--- a/src/dbc/scala/dbc/statement/expression/Select.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Select extends Expression {
-
- /** The actual select statement */
- def selectStatement: statement.Select;
-
- /** A SQL-99 compliant string representation of the expression. */
- override def sqlString: String = selectStatement.sqlString;
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = "("+selectStatement.sqlString+")";
-
-}
diff --git a/src/dbc/scala/dbc/statement/expression/SetFunction.scala b/src/dbc/scala/dbc/statement/expression/SetFunction.scala
deleted file mode 100644
index 060b2236f2..0000000000
--- a/src/dbc/scala/dbc/statement/expression/SetFunction.scala
+++ /dev/null
@@ -1,40 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class SetFunction {
- /** A SQL-99 compliant string representation of the set quantifier. */
- def sqlString: String;
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object SetFunction {
- abstract class Asterisk extends SetFunction {
- def sqlString = "(*)";
- }
- abstract class General extends SetFunction {
- def setQuantifier: Option[SetQuantifier];
- def valueExpression: Expression;
- def sqlString = (
- "(" +
- (setQuantifier match {
- case None => ""
- case Some(sq) => sq.sqlString + " "
- }) +
- valueExpression.sqlString + ")"
- );
- }
- abstract class Binary extends SetFunction {
- def sqlString = sys.error("Binary set function is not supported yet.");
- }
-}
diff --git a/src/dbc/scala/dbc/statement/expression/TypeCast.scala b/src/dbc/scala/dbc/statement/expression/TypeCast.scala
deleted file mode 100644
index dbb8dc1b4d..0000000000
--- a/src/dbc/scala/dbc/statement/expression/TypeCast.scala
+++ /dev/null
@@ -1,32 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") case class TypeCast (
- expression: Expression,
- castType: DataType
-) extends Expression {
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = {
- "CAST (" + expression.sqlInnerString + " AS " + castType.sqlString + ")";
- }
-
- /** The expression that will be casted. */
- //def expression: Expression;
-
- /** The type to which to cast. */
- //def castType: scala.dbc.datatype.DataType;
-}
diff --git a/src/dbc/scala/dbc/statement/expression/UnaryOperator.scala b/src/dbc/scala/dbc/statement/expression/UnaryOperator.scala
deleted file mode 100644
index 4172c451fb..0000000000
--- a/src/dbc/scala/dbc/statement/expression/UnaryOperator.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package statement
-package expression;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class UnaryOperator extends Expression {
-
- /** The name of the operator */
- def operator: String;
-
- /** Whether the operator comes before the operand or not. */
- def operatorIsLeft: Boolean;
-
- /** The operand applied to the operator. */
- def operand: Expression;
-
- /** A SQL-99 compliant string representation of the relation sub-
- * statement. This only has a meaning inside another statement. */
- def sqlInnerString: String = operatorIsLeft match {
- case true => operator + " " + operand.sqlInnerString;
- case false => operand.sqlInnerString + " " + operator;
- }
-}
diff --git a/src/dbc/scala/dbc/syntax/DataTypeUtil.scala b/src/dbc/scala/dbc/syntax/DataTypeUtil.scala
deleted file mode 100644
index a0ebd1713e..0000000000
--- a/src/dbc/scala/dbc/syntax/DataTypeUtil.scala
+++ /dev/null
@@ -1,98 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package syntax;
-
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-@deprecated(DbcIsDeprecated, "2.9.0") object DataTypeUtil {
-
- final val java_lang_Integer_SIZE = 32;
- final val java_lang_Long_SIZE = 64;
-
- def boolean = new datatype.Boolean;
- def tinyint = new datatype.ExactNumeric[Byte](dbc.DataType.BYTE) {
- val precisionRadix = 2;
- val precision = 8;
- val signed = true;
- val scale = 0;
- }
- def smallint = new datatype.ExactNumeric[Short](dbc.DataType.SHORT) {
- val precisionRadix = 2;
- val precision = 16;
- val signed = true;
- val scale = 0;
- }
- def integer = new datatype.ExactNumeric[Int](dbc.DataType.INT) {
- val precisionRadix = 2;
- val precision = 32;
- val signed = true;
- val scale = 0;
- }
- def bigint = new datatype.ExactNumeric[Long](dbc.DataType.LONG) {
- val precisionRadix = 2;
- val precision = 64;
- val signed = true;
- val scale = 0;
- }
- def numeric (_precision:Int): DataType = numeric(_precision,0);
- def numeric (_precision:Int, _scale:Int): DataType =
- Pair(datatype.Factory.bytePrecision(_precision,true,true),_scale == 0) match {
- case Pair(bp,true) if (bp <= java_lang_Integer_SIZE) =>
- new datatype.ExactNumeric[Int](DataType.INT) {
- val precisionRadix = 10;
- val precision = _precision;
- val signed = true;
- val scale = 0;
- }
- case Pair(bp,true) if (bp <= java_lang_Long_SIZE) =>
- new datatype.ExactNumeric[Long](DataType.LONG) {
- val precisionRadix = 10;
- val precision = _precision;
- val signed = true;
- val scale = 0;
- }
- case Pair(_,true) =>
- new datatype.ExactNumeric[BigInteger](DataType.BIG_INTEGER) {
- val precisionRadix = 10;
- val precision = _precision;
- val signed = true;
- val scale = 0;
- }
- case Pair(_,false) =>
- new datatype.ExactNumeric[BigDecimal](DataType.BIG_DECIMAL) {
- val precisionRadix = 10;
- val precision = _precision;
- val signed = true;
- val scale = _scale;
- }
- }
- def real = new datatype.ApproximateNumeric[Float](DataType.FLOAT) {
- val precisionRadix = 2;
- val precision = 64;
- val signed = true;
- }
- def doublePrecision = new datatype.ApproximateNumeric[Double](DataType.DOUBLE) {
- val precisionRadix = 2;
- val precision = 128;
- val signed = true;
- }
- def character (_length: Int) = new datatype.Character {
- val length = _length;
- }
- def characterVarying (_length: Int) = new datatype.CharacterVarying {
- def length = _length;
- }
- def characterLargeObject = new datatype.CharacterLargeObject;
-
-}
diff --git a/src/dbc/scala/dbc/syntax/Database.scala b/src/dbc/scala/dbc/syntax/Database.scala
deleted file mode 100644
index 4357fb7d4c..0000000000
--- a/src/dbc/scala/dbc/syntax/Database.scala
+++ /dev/null
@@ -1,33 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package syntax;
-
-
-import java.net.URI;
-
-@deprecated(DbcIsDeprecated, "2.9.0") object Database {
-
- def database (server:String, username:String, password:String): dbc.Database = {
- val uri = new URI(server);
- // Java 1.5 if (uri.toString().contains("postgres")) {
- if (uri.toString().indexOf("postgres") != -1) {
- new dbc.Database(new vendor.PostgreSQL {
- val uri = new URI(server);
- val user = username;
- val pass = password;
- })
- } else {
- throw new Exception("No DBMS vendor support could be found for the given URI");
- }
- }
-
-}
diff --git a/src/dbc/scala/dbc/syntax/Statement.scala b/src/dbc/scala/dbc/syntax/Statement.scala
deleted file mode 100644
index baccbfaa64..0000000000
--- a/src/dbc/scala/dbc/syntax/Statement.scala
+++ /dev/null
@@ -1,274 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package syntax;
-
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-import StatementExpression._;
-
-/*
-
-ASSUMPTIONS:
-
-IMPROVABLE:
-For type safety, all types must be defined. If one is missing, none is taken into account.
-It is possible to redefine many types or renamings for a field, in that case,
- only the last one is taken into account ("a" as "b" as "c" of boolean as "e" of integer
- is equivalent to "a" as "e" of integer).
-
-FIXED:
-
-*/
-
-@deprecated(DbcIsDeprecated, "2.9.0") object Statement {
-
- // SELECT ZYGOTE ...
-
- def select: SelectZygote = new SelectZygote {
- val setQuantifier = None;
- }
- def selectBag: SelectZygote = new SelectZygote {
- val setQuantifier = Some(statement.SetQuantifier.AllTuples);
- }
- def selectSet: SelectZygote = new SelectZygote {
- val setQuantifier = Some(statement.SetQuantifier.DistinctTuples);
- }
-
- abstract class SelectZygote {
- def setQuantifier: Option[statement.SetQuantifier];
- def fields (sdc:SelectDerivedColumns): SelectOf = new SelectOf {
- val setQuantifier = SelectZygote.this.setQuantifier;
- val selectList = sdc.selectList;
- val selectTypes = sdc.selectTypes;
- }
- }
-
- abstract class SelectDerivedField {
- def fieldValue: StatementField;
- def fieldRename: Option[String] = {val x = None; x}
- def fieldType: Option[dbc.DataType] = {val x = None; x}
- def as (rename:String): SelectDerivedField = new SelectDerivedField {
- val fieldValue = SelectDerivedField.this.fieldValue;
- override val fieldRename = Some(rename);
- override val fieldType = SelectDerivedField.this.fieldType;
- }
- def of (datatype:dbc.DataType): SelectDerivedField = new SelectDerivedField {
- val fieldValue = SelectDerivedField.this.fieldValue;
- override val fieldRename = SelectDerivedField.this.fieldRename;
- override val fieldType = Some(datatype);
- }
- }
-
- implicit def statementFieldToSelectDerivedField (fv:StatementField): SelectDerivedField = new SelectDerivedField {
- val fieldValue = fv;
- }
-
- implicit def stringToSelectDerivedField (fv:String): SelectDerivedField = new SelectDerivedField {
- val fieldValue: StatementField = StatementExpression.stringToStatementField(fv);
- }
-
- abstract class SelectDerivedColumns {
- def selectList: List[statement.DerivedColumn];
- def selectTypes: List[DataType];
- def and (sdc:SelectDerivedColumns): SelectDerivedColumns = new SelectDerivedColumns {
- val selectList = SelectDerivedColumns.this.selectList ::: sdc.selectList;
- val selectTypes =
- if (SelectDerivedColumns.this.selectTypes.isEmpty | sdc.selectTypes.isEmpty)
- Nil
- else
- SelectDerivedColumns.this.selectTypes ::: sdc.selectTypes;
- }
- }
-
- implicit def selectDerivedFieldToSelectDerivedColumns (sdf:SelectDerivedField): SelectDerivedColumns = new SelectDerivedColumns {
- val selectList = List(new statement.DerivedColumn {
- val valueExpression = sdf.fieldValue.toStatement;
- val asClause = sdf.fieldRename;
- });
- val selectTypes = if (sdf.fieldType.isEmpty) Nil else List(sdf.fieldType.get);
- }
-
- implicit def stringToSelectDerivedColumns (sdfs:String): SelectDerivedColumns = {
- val sdf: SelectDerivedField = sdfs;
- selectDerivedFieldToSelectDerivedColumns(sdf);
- }
-
- // SELECT OF ...
-
- abstract class SelectOf {
- def setQuantifier: Option[statement.SetQuantifier];
- def selectList: List[statement.DerivedColumn];
- def selectTypes: List[DataType];
- def from (sst:SelectSourceTables): SelectBeyond = new SelectBeyond {
- val setQuantifier = SelectOf.this.setQuantifier;
- val selectList = SelectOf.this.selectList;
- val selectTypes = SelectOf.this.selectTypes;
- val fromClause = sst.fromClause;
- val whereClause = None;
- val groupByClause = None;
- val havingClause = None;
- }
- }
-
- abstract class SelectSourceTable {
- def fromRelation: statement.Relation;
- def innerJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
- val fromRelation = new statement.Jointure {
- val leftRelation = SelectSourceTable.this.fromRelation;
- val rightRelation = sst.fromRelation;
- val joinType = statement.JoinType.Inner;
- val joinCondition = None;
- val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
- }
- }
- def leftOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
- val fromRelation = new statement.Jointure {
- val leftRelation = SelectSourceTable.this.fromRelation;
- val rightRelation = sst.fromRelation;
- val joinType = statement.JoinType.Outer.Left;
- val joinCondition = None;
- val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
- }
- }
- def rightOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
- val fromRelation = new statement.Jointure {
- val leftRelation = SelectSourceTable.this.fromRelation;
- val rightRelation = sst.fromRelation;
- val joinType = statement.JoinType.Outer.Right;
- val joinCondition = None;
- val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
- }
- }
- def fullOuterJoin (sst: SelectSourceTable): SelectSourceTable = new SelectSourceTable {
- val fromRelation = new statement.Jointure {
- val leftRelation = SelectSourceTable.this.fromRelation;
- val rightRelation = sst.fromRelation;
- val joinType = statement.JoinType.Outer.Full;
- val joinCondition = None;
- val fieldTypes = leftRelation.fieldTypes ::: rightRelation.fieldTypes;
- }
- }
- }
-
- implicit def stringToSelectSourceTable (sct:String): SelectSourceTable = new SelectSourceTable {
- val fromRelation = new statement.Table {
- val tableName = sct;
- val tableRename = None;
- val fieldTypes = Nil;
- }
- }
-
- implicit def selectToSelectSourceTable (sct:statement.Select): SelectSourceTable = new SelectSourceTable {
- val fromRelation = sct;
- }
-
- abstract class SelectSourceTables {
- def fromClause: List[statement.Relation];
- def join (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables {
- val fromClause = SelectSourceTables.this.fromClause ::: List(sct.fromRelation);
- }
- }
-
- implicit def stringToSelectSourceTables (sct:String): SelectSourceTables = new SelectSourceTables {
- val fromClause = List(new statement.Table {
- val tableName = sct;
- val tableRename = None;
- val fieldTypes = Nil;
- });
- }
-
- implicit def selectToSelectSourceTables (sct:statement.Select): SelectSourceTables = new SelectSourceTables {
- val fromClause = List(sct);
- }
-
- implicit def selectSourceTableToSelectSourceTables (sct:SelectSourceTable): SelectSourceTables = new SelectSourceTables {
- val fromClause = List(sct.fromRelation);
- }
-
- // SELECT BEYOND ...
-
- abstract class SelectBeyond {
- def setQuantifier: Option[statement.SetQuantifier];
- def selectList: List[statement.DerivedColumn];
- def selectTypes: List[DataType];
- def fromClause: List[statement.Relation];
- def whereClause: Option[statement.Expression];
- def groupByClause: Option[List[statement.Expression]];
- def havingClause: Option[statement.Expression];
- def where (se:StatementExpression): SelectBeyond = new SelectBeyond {
- val setQuantifier = SelectBeyond.this.setQuantifier;
- val selectList = SelectBeyond.this.selectList;
- val selectTypes = SelectBeyond.this.selectTypes;
- val fromClause = SelectBeyond.this.fromClause;
- val whereClause = Some(se.toStatement);
- val groupByClause = SelectBeyond.this.groupByClause;
- val havingClause = SelectBeyond.this.havingClause;
- }
- def groupBy (sgb:SelectGroupBy): SelectBeyond = new SelectBeyond {
- val setQuantifier = SelectBeyond.this.setQuantifier;
- val selectList = SelectBeyond.this.selectList;
- val selectTypes = SelectBeyond.this.selectTypes;
- val fromClause = SelectBeyond.this.fromClause;
- val whereClause = SelectBeyond.this.whereClause;
- val groupByClause = Some(sgb.groupByClause);
- val havingClause = SelectBeyond.this.havingClause;
- }
- def having (se:StatementExpression): SelectBeyond = new SelectBeyond {
- val setQuantifier = SelectBeyond.this.setQuantifier;
- val selectList = SelectBeyond.this.selectList;
- val selectTypes = SelectBeyond.this.selectTypes;
- val fromClause = SelectBeyond.this.fromClause;
- val whereClause = SelectBeyond.this.whereClause;
- val groupByClause = SelectBeyond.this.groupByClause;
- val havingClause = Some(se.toStatement);
- }
- }
-
- implicit def selectBeyondToStatementSelect (sb:SelectBeyond): statement.Select = new statement.Select {
- val setQuantifier = sb.setQuantifier;
- val selectList = sb.selectList;
- val fromClause = sb.fromClause;
- val whereClause = sb.whereClause;
- val groupByClause = sb.groupByClause;
- val havingClause = sb.havingClause;
- val fieldTypes = sb.selectTypes;
- }
-
- abstract class SelectGroupBy {
- def groupByClause: List[statement.Expression];
- def then (se:StatementExpression): SelectGroupBy = new SelectGroupBy {
- val groupByClause =
- SelectGroupBy.this.groupByClause ::: List(se.toStatement);
- }
- def then (se:String): SelectGroupBy = new SelectGroupBy {
- val groupByClause =
- SelectGroupBy.this.groupByClause ::: List(new statement.expression.Field {
- val tableName = None;
- val fieldName = se;
- });
- }
- }
-
- implicit def statementExpressionToSelectGroupBy (se:StatementExpression): SelectGroupBy = new SelectGroupBy {
- val groupByClause = List(se.toStatement);
- }
-
- implicit def stringToSelectGroupBy (se:String): SelectGroupBy = new SelectGroupBy {
- val groupByClause = List(new statement.expression.Field {
- val tableName = None;
- val fieldName = se;
- });
- }
-
-}
diff --git a/src/dbc/scala/dbc/syntax/StatementExpression.scala b/src/dbc/scala/dbc/syntax/StatementExpression.scala
deleted file mode 100644
index 65bb0947f7..0000000000
--- a/src/dbc/scala/dbc/syntax/StatementExpression.scala
+++ /dev/null
@@ -1,221 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package syntax;
-
-
-import java.math.BigDecimal;
-import java.math.BigInteger;
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class StatementExpression {
-
- def toStatement: statement.Expression;
-
- def and (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "AND";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def or (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "OR";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def == (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "=";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def < (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "<";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def > (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = ">";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def <= (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "<=";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def >= (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = ">=";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def <> (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "<>";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def isNull: StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.UnaryOperator {
- val operator = "IS NULL";
- val operatorIsLeft = false;
- val operand = StatementExpression.this.toStatement;
- }
- }
- def isNotNull: StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.UnaryOperator {
- val operator = "IS NOT NULL";
- val operatorIsLeft = false;
- val operand = StatementExpression.this.toStatement;
- }
- }
- def + (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "+";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def - (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "-";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def * (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "*";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def / (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "/";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def % (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "%";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def ^ (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "^";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def not : StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.UnaryOperator {
- val operator = "!";
- val operatorIsLeft = false;
- val operand = StatementExpression.this.toStatement;
- }
- }
- def || (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "||";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def like (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "LIKE";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def similar (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "SIMILAR";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = se.toStatement;
- }
- }
- def in (se:statement.Select): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.BinaryOperator {
- val operator = "IN";
- val leftOperand = StatementExpression.this.toStatement;
- val rightOperand = new statement.expression.Select {
- val selectStatement = se;
- };
- }
- }
-
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object StatementExpression {
-
- def not (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.UnaryOperator {
- val operator = "NOT";
- val operatorIsLeft = true;
- val operand = se.toStatement;
- }
- }
- def abs (se:StatementExpression): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.UnaryOperator {
- val operator = "@";
- val operatorIsLeft = true;
- val operand = se.toStatement;
- }
- }
- def exists (se:statement.Select): StatementExpression = new StatementExpression {
- val toStatement = new statement.expression.UnaryOperator {
- val operator = "EXISTS";
- val operatorIsLeft = true;
- val operand = new statement.expression.Select {
- val selectStatement = se;
- };
- }
- }
-
- abstract class StatementField extends StatementExpression {
- def fieldName: String;
- def tableName: Option[String] = None;
- def in (tn:String): StatementField = new StatementField {
- val fieldName = StatementField.this.fieldName;
- override val tableName = Some(tn);
- }
- def toStatement: statement.expression.Field = new statement.expression.Field {
- override val schemaName = None;
- val tableName = StatementField.this.tableName;
- val fieldName = StatementField.this.fieldName;
- }
- }
-
- implicit def stringToStatementField (ef:String): StatementField = new StatementField {
- val fieldName = ef;
- }
-
-
-
-
-}
diff --git a/src/dbc/scala/dbc/value/ApproximateNumeric.scala b/src/dbc/scala/dbc/value/ApproximateNumeric.scala
deleted file mode 100644
index fa47d8815b..0000000000
--- a/src/dbc/scala/dbc/value/ApproximateNumeric.scala
+++ /dev/null
@@ -1,28 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class ApproximateNumeric [Type] extends Value {
-
- val dataType: datatype.ApproximateNumeric[Type];
-
- def sqlString = nativeValue.toString();
-
- }
-
-@deprecated(DbcIsDeprecated, "2.9.0") object ApproximateNumeric {
-
- implicit def approximateNumericToFloar (obj:value.ApproximateNumeric[Float]): Float = obj.nativeValue;
- implicit def approximateNumericToDouble (obj:value.ApproximateNumeric[Double]): Double = obj.nativeValue;
-
-}
diff --git a/src/dbc/scala/dbc/value/Boolean.scala b/src/dbc/scala/dbc/value/Boolean.scala
deleted file mode 100644
index 5221ce2328..0000000000
--- a/src/dbc/scala/dbc/value/Boolean.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Boolean extends Value {
-
- val dataType: datatype.Boolean;
-
- def sqlString = if (nativeValue) "TRUE" else "FALSE";
-
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object Boolean {
-
- implicit def booleanToBoolean (obj:value.Boolean): scala.Boolean = obj.nativeValue;
-
-}
diff --git a/src/dbc/scala/dbc/value/Character.scala b/src/dbc/scala/dbc/value/Character.scala
deleted file mode 100644
index 4ff983c591..0000000000
--- a/src/dbc/scala/dbc/value/Character.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-/** A SQL-99 value of type character string. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Character extends Value {
-
- override val dataType: datatype.Character;
-
- /** An SQL-99 compliant string representation of the value. */
- def sqlString: String = {
- "'" + nativeValue + "'"
- }
-
-}
-
-/** An object offering transformation methods (views) on the value.
- * This object must be visible in an expression to use value auto-
- * conversion. */
-@deprecated(DbcIsDeprecated, "2.9.0") object Character {
-
- /** A character string value as a native string. */
- implicit def characterToString (obj:value.Character): String = obj.nativeValue;
-
-}
diff --git a/src/dbc/scala/dbc/value/CharacterLargeObject.scala b/src/dbc/scala/dbc/value/CharacterLargeObject.scala
deleted file mode 100644
index b9e81eb3af..0000000000
--- a/src/dbc/scala/dbc/value/CharacterLargeObject.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-/** A SQL-99 value of type character large object. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class CharacterLargeObject extends Value {
-
- override val dataType: datatype.CharacterLargeObject;
-
- /** An SQL-99 compliant string representation of the value. */
- def sqlString: String = {
- "'" + nativeValue + "'"
- }
-
-}
-
-/** An object offering transformation methods (views) on the value.
- * This object must be visible in an expression to use value auto-
- * conversion. */
-@deprecated(DbcIsDeprecated, "2.9.0") object CharacterLargeObject {
-
- /** A character large object value as a native string. */
- implicit def characterLargeObjectToString (obj:value.CharacterLargeObject): String = obj.nativeValue;
-
-}
diff --git a/src/dbc/scala/dbc/value/CharacterVarying.scala b/src/dbc/scala/dbc/value/CharacterVarying.scala
deleted file mode 100644
index 72e7d06362..0000000000
--- a/src/dbc/scala/dbc/value/CharacterVarying.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-/** A SQL-99 value of type character varying string. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class CharacterVarying extends Value {
-
- override val dataType: datatype.CharacterVarying;
-
- /** An SQL-99 compliant string representation of the value. */
- def sqlString: String = {
- "'" + nativeValue + "'"
- }
-
-}
-
-/** An object offering transformation methods (views) on the value.
- * This object must be visible in an expression to use value auto-
- * conversion. */
-@deprecated(DbcIsDeprecated, "2.9.0") object CharacterVarying {
-
- /** A character varying string value as a native string. */
- implicit def characterVaryingToString (obj:value.CharacterVarying): String = obj.nativeValue;
-
-}
diff --git a/src/dbc/scala/dbc/value/Conversion.scala b/src/dbc/scala/dbc/value/Conversion.scala
deleted file mode 100644
index c9297e37db..0000000000
--- a/src/dbc/scala/dbc/value/Conversion.scala
+++ /dev/null
@@ -1,156 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-import java.math._;
-
-@deprecated(DbcIsDeprecated, "2.9.0") object Conversion {
-
- class Illegal (msg:String) extends Exception(msg);
-
- implicit def view1 (value:Value): Byte = {
- if (value.dataType.nativeTypeId == DataType.BYTE) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to byte: "+value)
- }
- }
-
- implicit def view2 (value:Value): Short = {
- if (value.dataType.nativeTypeId == DataType.BYTE) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
- v.nativeValue.toShort
- } else if (value.dataType.nativeTypeId == DataType.SHORT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to short: "+value)
- }
- }
-
- implicit def view3 (value:Value): Int = {
- if (value.dataType.nativeTypeId == DataType.BYTE) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
- v.nativeValue.toInt
- } else if (value.dataType.nativeTypeId == DataType.SHORT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
- v.nativeValue.toInt
- } else if (value.dataType.nativeTypeId == DataType.INT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to int: "+value)
- }
- }
-
- implicit def view4 (value:Value): Long = {
- if (value.dataType.nativeTypeId == DataType.BYTE) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
- v.nativeValue.toLong
- } else if (value.dataType.nativeTypeId == DataType.SHORT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
- v.nativeValue.toLong
- } else if (value.dataType.nativeTypeId == DataType.INT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
- v.nativeValue.toLong
- } else if (value.dataType.nativeTypeId == DataType.LONG) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to long: "+value)
- }
- }
-
- implicit def view5 (value:Value): BigInteger = {
- if (value.dataType.nativeTypeId == DataType.BYTE) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
- new BigInteger(v.nativeValue.toString(),10)
- } else if (value.dataType.nativeTypeId == DataType.SHORT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
- new BigInteger(v.nativeValue.toString(),10)
- } else if (value.dataType.nativeTypeId == DataType.INT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
- new BigInteger(v.nativeValue.toString(),10)
- } else if (value.dataType.nativeTypeId == DataType.LONG) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]];
- new BigInteger(v.nativeValue.toString(),10)
- } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to big integer: "+value)
- }
- }
-
- implicit def view6 (value:Value): BigDecimal = {
- if (value.dataType.nativeTypeId == DataType.BYTE) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Byte]];
- new BigDecimal(v.nativeValue.toString())
- } else if (value.dataType.nativeTypeId == DataType.SHORT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Short]];
- new BigDecimal(v.nativeValue.toString())
- } else if (value.dataType.nativeTypeId == DataType.INT) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Int]];
- new BigDecimal(v.nativeValue.toString())
- } else if (value.dataType.nativeTypeId == DataType.LONG) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[Long]];
- new BigDecimal(v.nativeValue.toString())
- } else if (value.dataType.nativeTypeId == DataType.BIG_INTEGER) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[BigInteger]];
- new BigDecimal(v.nativeValue)
- } else if (value.dataType.nativeTypeId == DataType.BIG_DECIMAL) {
- val v = value.asInstanceOf[dbc.value.ExactNumeric[BigDecimal]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to big decimal: "+value)
- }
- }
-
- implicit def view7 (value:Value): Float = {
- if (value.dataType.nativeTypeId == DataType.FLOAT) {
- val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to float: "+value)
- }
- }
-
- implicit def view8 (value:Value): Double = {
- if (value.dataType.nativeTypeId == DataType.FLOAT) {
- val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Float]];
- v.nativeValue.toFloat
- } else if (value.dataType.nativeTypeId == DataType.DOUBLE) {
- val v = value.asInstanceOf[dbc.value.ApproximateNumeric[Double]];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to double: "+value)
- }
- }
-
- implicit def view9 (value:Value): scala.Boolean = {
- if (value.dataType.nativeTypeId == DataType.BOOLEAN) {
- val v = value.asInstanceOf[dbc.value.Boolean];
- v.nativeValue
- } else {
- throw new Illegal("Cannot convert value to boolean: "+value)
- }
- }
-
- implicit def view10 (value:Value): String = value match {
- case v:dbc.value.Character => v.nativeValue;
- case v:dbc.value.CharacterLargeObject => v.nativeValue;
- case v:dbc.value.CharacterVarying => v.nativeValue;
- case _ => throw new Illegal("Cannot convert value to string")
- }
-
-}
diff --git a/src/dbc/scala/dbc/value/ExactNumeric.scala b/src/dbc/scala/dbc/value/ExactNumeric.scala
deleted file mode 100644
index 7cd8b89a8c..0000000000
--- a/src/dbc/scala/dbc/value/ExactNumeric.scala
+++ /dev/null
@@ -1,35 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-import java.math.BigInteger;
-import java.math.BigDecimal;
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class ExactNumeric [Type] extends Value {
-
- val dataType: datatype.ExactNumeric[Type];
-
- def sqlString = nativeValue.toString();
-
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object ExactNumeric {
-
- implicit def exactNumericToByte (obj:value.ExactNumeric[Byte]): Byte = obj.nativeValue;
- implicit def exactNumericToShort (obj:value.ExactNumeric[Short]): Short = obj.nativeValue;
- implicit def exactNumericToInt (obj:value.ExactNumeric[Int]): Int = obj.nativeValue;
- implicit def exactNumericToLong (obj:value.ExactNumeric[Long]): Long = obj.nativeValue;
- implicit def exactNumericToBigInteger (obj:value.ExactNumeric[BigInteger]): BigInteger = obj.nativeValue;
- implicit def exactNumericToBigDecimal (obj:value.ExactNumeric[BigDecimal]): BigDecimal = obj.nativeValue;
-
-}
diff --git a/src/dbc/scala/dbc/value/Factory.scala b/src/dbc/scala/dbc/value/Factory.scala
deleted file mode 100644
index 2d6101f6de..0000000000
--- a/src/dbc/scala/dbc/value/Factory.scala
+++ /dev/null
@@ -1,95 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-import java.math.BigInteger;
-import java.math.BigDecimal;
-
-@deprecated(DbcIsDeprecated, "2.9.0") object Factory {
-
- def create (result: java.sql.ResultSet, index: Int, expectedDataType: DataType): Value = {
- expectedDataType.nativeTypeId match {
- case DataType.OBJECT =>
- new value.Unknown {
- val dataType = expectedDataType.asInstanceOf[datatype.Unknown];
- val nativeValue: AnyRef = result.getObject(index);
- }
- case DataType.STRING => {
- expectedDataType match {
- case t:datatype.Character =>
- new value.Character {
- val dataType = t;
- val nativeValue: String = result.getString(index);
- }
- case t:datatype.CharacterVarying =>
- new value.CharacterVarying {
- val dataType = t;
- val nativeValue: String = result.getString(index);
- }
- case t:datatype.CharacterLargeObject =>
- new value.CharacterLargeObject {
- val dataType = t;
- val nativeValue: String = result.getString(index);
- }
- }
- }
- case DataType.BOOLEAN =>
- new value.Boolean {
- val dataType = expectedDataType.asInstanceOf[datatype.Boolean];
- val nativeValue: scala.Boolean = result.getBoolean(index);
- }
- case DataType.FLOAT =>
- new value.ApproximateNumeric[Float] {
- val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Float]];
- val nativeValue: Float = result.getFloat(index);
- }
- case DataType.DOUBLE =>
- new value.ApproximateNumeric[Double] {
- val dataType = expectedDataType.asInstanceOf[datatype.ApproximateNumeric[Double]];
- val nativeValue: Double = result.getDouble(index);
- }
- case DataType.BYTE =>
- new value.ExactNumeric[Byte] {
- val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Byte]];
- val nativeValue: Byte = result.getByte(index);
- }
- case DataType.SHORT =>
- new value.ExactNumeric[Short] {
- val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Short]];
- val nativeValue: Short = result.getShort(index);
- }
- case DataType.INT =>
- new value.ExactNumeric[Int] {
- val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Int]];
- val nativeValue: Int = result.getInt(index);
- }
- case DataType.LONG =>
- new value.ExactNumeric[Long] {
- val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[Long]];
- val nativeValue:Long = result.getLong(index);
- }
- case DataType.BIG_INTEGER =>
- new value.ExactNumeric[BigInteger] {
- val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigInteger]];
- val nativeValue: BigInteger = result.getBigDecimal(index).unscaledValue();
- }
- case DataType.BIG_DECIMAL =>
- new value.ExactNumeric[BigDecimal] {
- val dataType = expectedDataType.asInstanceOf[datatype.ExactNumeric[BigDecimal]];
- val nativeValue: BigDecimal = result.getBigDecimal(index);
- }
-
- }
- }
-
-}
diff --git a/src/dbc/scala/dbc/value/Unknown.scala b/src/dbc/scala/dbc/value/Unknown.scala
deleted file mode 100644
index 89764a5831..0000000000
--- a/src/dbc/scala/dbc/value/Unknown.scala
+++ /dev/null
@@ -1,27 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package value;
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Unknown extends Value {
-
- val dataType: datatype.Unknown;
-
- def sqlString = sys.error("An 'ANY' value cannot be represented.");
-
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object UnknownType {
-
- def view (obj:value.Unknown): AnyRef = obj.nativeValue;
-
-}
diff --git a/src/dbc/scala/dbc/vendor/PostgreSQL.scala b/src/dbc/scala/dbc/vendor/PostgreSQL.scala
deleted file mode 100644
index ac528d5f82..0000000000
--- a/src/dbc/scala/dbc/vendor/PostgreSQL.scala
+++ /dev/null
@@ -1,29 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.dbc
-package vendor;
-
-
-import compat.Platform
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class PostgreSQL extends Vendor {
-
- def uri:java.net.URI;
- def user:String;
- def pass:String;
-
- val retainedConnections = 5;
-
- val nativeDriverClass = Platform.getClassForName("org.postgresql.Driver");
-
- val urlProtocolString = "jdbc:postgresql:"
-
-}
diff --git a/src/detach/library/scala/remoting/Channel.scala b/src/detach/library/scala/remoting/Channel.scala
index 541e45a477..54b8fb100e 100644
--- a/src/detach/library/scala/remoting/Channel.scala
+++ b/src/detach/library/scala/remoting/Channel.scala
@@ -116,20 +116,20 @@ class Channel protected (socket: Socket) {
* the expected type.
*/
@throws(classOf[ChannelException])
- def receive[T](implicit expected: reflect.Manifest[T]): T = {
- val found = in.readObject().asInstanceOf[reflect.Manifest[_]]
+ def receive[T](implicit expected: reflect.ClassTag[T]): T = {
+ val found = in.readObject().asInstanceOf[reflect.ClassTag[_]]
info("receive: found="+found+", expected="+expected)
- import scala.reflect.Manifest
+ import scala.reflect.ClassTag
val x = found match {
- case Manifest.Unit => ()
- case Manifest.Boolean => in.readBoolean()
- case Manifest.Byte => in.readByte()
- case Manifest.Char => in.readChar()
- case Manifest.Short => in.readShort()
- case Manifest.Int => in.readInt()
- case Manifest.Long => in.readLong()
- case Manifest.Float => in.readFloat()
- case Manifest.Double => in.readDouble()
+ case ClassTag.Unit => ()
+ case ClassTag.Boolean => in.readBoolean()
+ case ClassTag.Byte => in.readByte()
+ case ClassTag.Char => in.readChar()
+ case ClassTag.Short => in.readShort()
+ case ClassTag.Int => in.readInt()
+ case ClassTag.Long => in.readLong()
+ case ClassTag.Float => in.readFloat()
+ case ClassTag.Double => in.readDouble()
case _ => in.readObject()
}
val res = if (found <:< expected)
@@ -144,12 +144,12 @@ class Channel protected (socket: Socket) {
/** <code>?</code> method may throw either an
* <code>ClassNotFoundException</code> or an <code>IOException</code>.
*/
- def ?[T](implicit m: reflect.Manifest[T]): T = receive[T](m)
+ def ?[T](implicit t: reflect.ClassTag[T]): T = receive[T](t)
/** <code>send</code> method may throw an <code>IOException</code>.
*/
- def send[T](x: T)(implicit m: reflect.Manifest[T]) {
- out writeObject m
+ def send[T](x: T)(implicit t: reflect.ClassTag[T]) {
+ out writeObject t
x match {
case x: Unit => // nop
case x: Boolean => out writeBoolean x
@@ -168,7 +168,7 @@ class Channel protected (socket: Socket) {
/** <code>!</code> method may throw an <code>IOException</code>.
*/
- def ![T](x: T)(implicit m: reflect.Manifest[T]) { send(x)(m) }
+ def ![T](x: T)(implicit m: reflect.ClassTag[T]) { send(x)(m) }
def close() {
try { socket.close() }
diff --git a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java
index e9389e9acb..4b5b3382f5 100644
--- a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java
+++ b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinPool.java
@@ -1,5 +1,4 @@
/*
-
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
@@ -12,22 +11,18 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
-//import java.util.concurrent.AbstractExecutorService;
+import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
-//import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
-interface RunnableFuture<T> extends Runnable {
- //TR placeholder for java.util.concurrent.RunnableFuture
-}
-
/**
* An {@link ExecutorService} for running {@link ForkJoinTask}s.
* A {@code ForkJoinPool} provides the entry point for submissions
@@ -127,7 +122,7 @@ interface RunnableFuture<T> extends Runnable {
* @since 1.7
* @author Doug Lea
*/
-public class ForkJoinPool /*extends AbstractExecutorService*/ {
+public class ForkJoinPool extends AbstractExecutorService {
/*
* Implementation Overview
@@ -634,7 +629,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
final ForkJoinPool pool; // the containing pool (may be null)
final ForkJoinWorkerThread owner; // owning thread or null if shared
volatile Thread parker; // == owner during call to park; else null
- ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
+ volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
ForkJoinTask<?> currentSteal; // current non-local task being executed
// Heuristic padding to ameliorate unfortunate memory placements
Object p00, p01, p02, p03, p04, p05, p06, p07;
@@ -726,12 +721,11 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
* version of this method because it is never needed.)
*/
final ForkJoinTask<?> pop() {
- ForkJoinTask<?> t; int m;
- ForkJoinTask<?>[] a = array;
- if (a != null && (m = a.length - 1) >= 0) {
+ ForkJoinTask<?>[] a; ForkJoinTask<?> t; int m;
+ if ((a = array) != null && (m = a.length - 1) >= 0) {
for (int s; (s = top - 1) - base >= 0;) {
- int j = ((m & s) << ASHIFT) + ABASE;
- if ((t = (ForkJoinTask<?>)U.getObjectVolatile(a, j)) == null)
+ long j = ((m & s) << ASHIFT) + ABASE;
+ if ((t = (ForkJoinTask<?>)U.getObject(a, j)) == null)
break;
if (U.compareAndSwapObject(a, j, t, null)) {
top = s;
@@ -835,54 +829,6 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
}
/**
- * If present, removes from queue and executes the given task, or
- * any other cancelled task. Returns (true) immediately on any CAS
- * or consistency check failure so caller can retry.
- *
- * @return false if no progress can be made
- */
- final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
- boolean removed = false, empty = true, progress = true;
- ForkJoinTask<?>[] a; int m, s, b, n;
- if ((a = array) != null && (m = a.length - 1) >= 0 &&
- (n = (s = top) - (b = base)) > 0) {
- for (ForkJoinTask<?> t;;) { // traverse from s to b
- int j = ((--s & m) << ASHIFT) + ABASE;
- t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
- if (t == null) // inconsistent length
- break;
- else if (t == task) {
- if (s + 1 == top) { // pop
- if (!U.compareAndSwapObject(a, j, task, null))
- break;
- top = s;
- removed = true;
- }
- else if (base == b) // replace with proxy
- removed = U.compareAndSwapObject(a, j, task,
- new EmptyTask());
- break;
- }
- else if (t.status >= 0)
- empty = false;
- else if (s + 1 == top) { // pop and throw away
- if (U.compareAndSwapObject(a, j, t, null))
- top = s;
- break;
- }
- if (--n == 0) {
- if (!empty && base == b)
- progress = false;
- break;
- }
- }
- }
- if (removed)
- task.doExec();
- return progress;
- }
-
- /**
* Initializes or doubles the capacity of array. Call either
* by owner or with lock held -- it is OK for base, but not
* top, to move while resizings are in progress.
@@ -944,69 +890,98 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
// Execution methods
/**
- * Removes and runs tasks until empty, using local mode
- * ordering. Normally called only after checking for apparent
- * non-emptiness.
+ * Pops and runs tasks until empty.
*/
- final void runLocalTasks() {
- // hoist checks from repeated pop/poll
- ForkJoinTask<?>[] a; int m;
- if ((a = array) != null && (m = a.length - 1) >= 0) {
- if (mode == 0) {
- for (int s; (s = top - 1) - base >= 0;) {
- int j = ((m & s) << ASHIFT) + ABASE;
- ForkJoinTask<?> t =
- (ForkJoinTask<?>)U.getObjectVolatile(a, j);
- if (t != null) {
- if (U.compareAndSwapObject(a, j, t, null)) {
- top = s;
- t.doExec();
- }
- }
- else
- break;
- }
+ private void popAndExecAll() {
+ // A bit faster than repeated pop calls
+ ForkJoinTask<?>[] a; int m, s; long j; ForkJoinTask<?> t;
+ while ((a = array) != null && (m = a.length - 1) >= 0 &&
+ (s = top - 1) - base >= 0 &&
+ (t = ((ForkJoinTask<?>)
+ U.getObject(a, j = ((m & s) << ASHIFT) + ABASE)))
+ != null) {
+ if (U.compareAndSwapObject(a, j, t, null)) {
+ top = s;
+ t.doExec();
}
- else {
- for (int b; (b = base) - top < 0;) {
- int j = ((m & b) << ASHIFT) + ABASE;
- ForkJoinTask<?> t =
- (ForkJoinTask<?>)U.getObjectVolatile(a, j);
- if (t != null) {
- if (base == b &&
- U.compareAndSwapObject(a, j, t, null)) {
- base = b + 1;
- t.doExec();
- }
- } else if (base == b) {
- if (b + 1 == top)
+ }
+ }
+
+ /**
+ * Polls and runs tasks until empty.
+ */
+ private void pollAndExecAll() {
+ for (ForkJoinTask<?> t; (t = poll()) != null;)
+ t.doExec();
+ }
+
+ /**
+ * If present, removes from queue and executes the given task, or
+ * any other cancelled task. Returns (true) immediately on any CAS
+ * or consistency check failure so caller can retry.
+ *
+ * @return 0 if no progress can be made, else positive
+ * (this unusual convention simplifies use with tryHelpStealer.)
+ */
+ final int tryRemoveAndExec(ForkJoinTask<?> task) {
+ int stat = 1;
+ boolean removed = false, empty = true;
+ ForkJoinTask<?>[] a; int m, s, b, n;
+ if ((a = array) != null && (m = a.length - 1) >= 0 &&
+ (n = (s = top) - (b = base)) > 0) {
+ for (ForkJoinTask<?> t;;) { // traverse from s to b
+ int j = ((--s & m) << ASHIFT) + ABASE;
+ t = (ForkJoinTask<?>)U.getObjectVolatile(a, j);
+ if (t == null) // inconsistent length
+ break;
+ else if (t == task) {
+ if (s + 1 == top) { // pop
+ if (!U.compareAndSwapObject(a, j, task, null))
break;
- Thread.yield(); // wait for lagging update
+ top = s;
+ removed = true;
}
+ else if (base == b) // replace with proxy
+ removed = U.compareAndSwapObject(a, j, task,
+ new EmptyTask());
+ break;
+ }
+ else if (t.status >= 0)
+ empty = false;
+ else if (s + 1 == top) { // pop and throw away
+ if (U.compareAndSwapObject(a, j, t, null))
+ top = s;
+ break;
+ }
+ if (--n == 0) {
+ if (!empty && base == b)
+ stat = 0;
+ break;
}
}
}
+ if (removed)
+ task.doExec();
+ return stat;
}
/**
* Executes a top-level task and any local tasks remaining
* after execution.
- *
- * @return true unless terminating
*/
- final boolean runTask(ForkJoinTask<?> t) {
- boolean alive = true;
+ final void runTask(ForkJoinTask<?> t) {
if (t != null) {
currentSteal = t;
t.doExec();
- if (top != base) // conservative guard
- runLocalTasks();
+ if (top != base) { // process remaining local tasks
+ if (mode == 0)
+ popAndExecAll();
+ else
+ pollAndExecAll();
+ }
++nsteals;
currentSteal = null;
}
- else if (runState < 0) // terminating
- alive = false;
- return alive;
}
/**
@@ -1072,7 +1047,6 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
ASHIFT = 31 - Integer.numberOfLeadingZeros(s);
}
}
-
/**
* Per-thread records for threads that submit to pools. Currently
* holds only pseudo-random seed / index that is used to choose
@@ -1165,7 +1139,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
* traversal parameters at the expense of sometimes blocking when
* we could be helping.
*/
- private static final int MAX_HELP = 32;
+ private static final int MAX_HELP = 64;
/**
* Secondary time-based bound (in nanosecs) for helping attempts
@@ -1175,7 +1149,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
* value should roughly approximate the time required to create
* and/or activate a worker thread.
*/
- private static final long COMPENSATION_DELAY = 100L * 1000L; // 0.1 millisec
+ private static final long COMPENSATION_DELAY = 1L << 18; // ~0.25 millisec
/**
* Increment for seed generators. See class ThreadLocal for
@@ -1326,22 +1300,28 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
*
* @param w the worker's queue
*/
+
final void registerWorker(WorkQueue w) {
Mutex lock = this.lock;
lock.lock();
try {
WorkQueue[] ws = workQueues;
if (w != null && ws != null) { // skip on shutdown/failure
- int rs, n;
- while ((n = ws.length) < // ensure can hold total
- (parallelism + (short)(ctl >>> TC_SHIFT) << 1))
- workQueues = ws = Arrays.copyOf(ws, n << 1);
- int m = n - 1;
+ int rs, n = ws.length, m = n - 1;
int s = nextSeed += SEED_INCREMENT; // rarely-colliding sequence
w.seed = (s == 0) ? 1 : s; // ensure non-zero seed
int r = (s << 1) | 1; // use odd-numbered indices
- while (ws[r &= m] != null) // step by approx half size
- r += ((n >>> 1) & SQMASK) + 2;
+ if (ws[r &= m] != null) { // collision
+ int probes = 0; // step by approx half size
+ int step = (n <= 4) ? 2 : ((n >>> 1) & SQMASK) + 2;
+ while (ws[r = (r + step) & m] != null) {
+ if (++probes >= n) {
+ workQueues = ws = Arrays.copyOf(ws, n <<= 1);
+ m = n - 1;
+ probes = 0;
+ }
+ }
+ }
w.eventCount = w.poolIndex = r; // establish before recording
ws[r] = w; // also update seq
runState = ((rs = runState) & SHUTDOWN) | ((rs + 2) & ~SHUTDOWN);
@@ -1488,7 +1468,6 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
}
}
-
// Scanning for tasks
/**
@@ -1496,7 +1475,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
*/
final void runWorker(WorkQueue w) {
w.growArray(false); // initialize queue array in this thread
- do {} while (w.runTask(scan(w)));
+ do { w.runTask(scan(w)); } while (w.runState >= 0);
}
/**
@@ -1559,8 +1538,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
q.base = b + 1; // specialization of pollAt
return t;
}
- else if ((t != null || b + 1 != q.top) &&
- (ec < 0 || j <= m)) {
+ else if (ec < 0 || j <= m) {
rs = 0; // mark scan as imcomplete
break; // caller can retry after release
}
@@ -1568,6 +1546,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
if (--j < 0)
break;
}
+
long c = ctl; int e = (int)c, a = (int)(c >> AC_SHIFT), nr, ns;
if (e < 0) // decode ctl on empty scan
w.runState = -1; // pool is terminating
@@ -1635,7 +1614,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
*/
private void idleAwaitWork(WorkQueue w, long currentCtl, long prevCtl) {
if (w.eventCount < 0 && !tryTerminate(false, false) &&
- (int)prevCtl != 0 && ctl == currentCtl) {
+ (int)prevCtl != 0 && !hasQueuedSubmissions() && ctl == currentCtl) {
Thread wt = Thread.currentThread();
Thread.yield(); // yield before block
while (ctl == currentCtl) {
@@ -1670,70 +1649,79 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
* leaves hints in workers to speed up subsequent calls. The
* implementation is very branchy to cope with potential
* inconsistencies or loops encountering chains that are stale,
- * unknown, or so long that they are likely cyclic. All of these
- * cases are dealt with by just retrying by caller.
+ * unknown, or so long that they are likely cyclic.
*
* @param joiner the joining worker
* @param task the task to join
- * @return true if found or ran a task (and so is immediately retryable)
- */
- private boolean tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
- WorkQueue[] ws;
- int m, depth = MAX_HELP; // remaining chain depth
- boolean progress = false;
- if ((ws = workQueues) != null && (m = ws.length - 1) > 0 &&
- task.status >= 0) {
- ForkJoinTask<?> subtask = task; // current target
- outer: for (WorkQueue j = joiner;;) {
- WorkQueue stealer = null; // find stealer of subtask
- WorkQueue v = ws[j.stealHint & m]; // try hint
- if (v != null && v.currentSteal == subtask)
- stealer = v;
- else { // scan
- for (int i = 1; i <= m; i += 2) {
- if ((v = ws[i]) != null && v.currentSteal == subtask &&
- v != joiner) {
- stealer = v;
- j.stealHint = i; // save hint
- break;
- }
+ * @return 0 if no progress can be made, negative if task
+ * known complete, else positive
+ */
+ private int tryHelpStealer(WorkQueue joiner, ForkJoinTask<?> task) {
+ int stat = 0, steps = 0; // bound to avoid cycles
+ if (joiner != null && task != null) { // hoist null checks
+ restart: for (;;) {
+ ForkJoinTask<?> subtask = task; // current target
+ for (WorkQueue j = joiner, v;;) { // v is stealer of subtask
+ WorkQueue[] ws; int m, s, h;
+ if ((s = task.status) < 0) {
+ stat = s;
+ break restart;
}
- if (stealer == null)
- break;
- }
-
- for (WorkQueue q = stealer;;) { // try to help stealer
- ForkJoinTask[] a; ForkJoinTask<?> t; int b;
- if (task.status < 0)
- break outer;
- if ((b = q.base) - q.top < 0 && (a = q.array) != null) {
- progress = true;
- int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
- t = (ForkJoinTask<?>)U.getObjectVolatile(a, i);
- if (subtask.status < 0) // must recheck before taking
- break outer;
- if (t != null &&
- q.base == b &&
- U.compareAndSwapObject(a, i, t, null)) {
- q.base = b + 1;
- joiner.runSubtask(t);
+ if ((ws = workQueues) == null || (m = ws.length - 1) <= 0)
+ break restart; // shutting down
+ if ((v = ws[h = (j.stealHint | 1) & m]) == null ||
+ v.currentSteal != subtask) {
+ for (int origin = h;;) { // find stealer
+ if (((h = (h + 2) & m) & 15) == 1 &&
+ (subtask.status < 0 || j.currentJoin != subtask))
+ continue restart; // occasional staleness check
+ if ((v = ws[h]) != null &&
+ v.currentSteal == subtask) {
+ j.stealHint = h; // save hint
+ break;
+ }
+ if (h == origin)
+ break restart; // cannot find stealer
}
- else if (q.base == b)
- break outer; // possibly stalled
}
- else { // descend
- ForkJoinTask<?> next = stealer.currentJoin;
- if (--depth <= 0 || subtask.status < 0 ||
- next == null || next == subtask)
- break outer; // stale, dead-end, or cyclic
- subtask = next;
- j = stealer;
- break;
+ for (;;) { // help stealer or descend to its stealer
+ ForkJoinTask[] a; int b;
+ if (subtask.status < 0) // surround probes with
+ continue restart; // consistency checks
+ if ((b = v.base) - v.top < 0 && (a = v.array) != null) {
+ int i = (((a.length - 1) & b) << ASHIFT) + ABASE;
+ ForkJoinTask<?> t =
+ (ForkJoinTask<?>)U.getObjectVolatile(a, i);
+ if (subtask.status < 0 || j.currentJoin != subtask ||
+ v.currentSteal != subtask)
+ continue restart; // stale
+ stat = 1; // apparent progress
+ if (t != null && v.base == b &&
+ U.compareAndSwapObject(a, i, t, null)) {
+ v.base = b + 1; // help stealer
+ joiner.runSubtask(t);
+ }
+ else if (v.base == b && ++steps == MAX_HELP)
+ break restart; // v apparently stalled
+ }
+ else { // empty -- try to descend
+ ForkJoinTask<?> next = v.currentJoin;
+ if (subtask.status < 0 || j.currentJoin != subtask ||
+ v.currentSteal != subtask)
+ continue restart; // stale
+ else if (next == null || ++steps == MAX_HELP)
+ break restart; // dead-end or maybe cyclic
+ else {
+ subtask = next;
+ j = v;
+ break;
+ }
+ }
}
}
}
}
- return progress;
+ return stat;
}
/**
@@ -1833,44 +1821,50 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
* @return task status on exit
*/
final int awaitJoin(WorkQueue joiner, ForkJoinTask<?> task) {
- ForkJoinTask<?> prevJoin = joiner.currentJoin;
- joiner.currentJoin = task;
- long startTime = 0L;
- for (int k = 0, s; ; ++k) {
- if ((joiner.isEmpty() ? // try to help
- !tryHelpStealer(joiner, task) :
- !joiner.tryRemoveAndExec(task))) {
- if (k == 0) {
- startTime = System.nanoTime();
- tryPollForAndExec(joiner, task); // check uncommon case
- }
- else if ((k & (MAX_HELP - 1)) == 0 &&
- System.nanoTime() - startTime >= COMPENSATION_DELAY &&
- tryCompensate(task, null)) {
- if (task.trySetSignal() && task.status >= 0) {
- synchronized (task) {
- if (task.status >= 0) {
- try { // see ForkJoinTask
- task.wait(); // for explanation
- } catch (InterruptedException ie) {
+ int s;
+ if ((s = task.status) >= 0) {
+ ForkJoinTask<?> prevJoin = joiner.currentJoin;
+ joiner.currentJoin = task;
+ long startTime = 0L;
+ for (int k = 0;;) {
+ if ((s = (joiner.isEmpty() ? // try to help
+ tryHelpStealer(joiner, task) :
+ joiner.tryRemoveAndExec(task))) == 0 &&
+ (s = task.status) >= 0) {
+ if (k == 0) {
+ startTime = System.nanoTime();
+ tryPollForAndExec(joiner, task); // check uncommon case
+ }
+ else if ((k & (MAX_HELP - 1)) == 0 &&
+ System.nanoTime() - startTime >=
+ COMPENSATION_DELAY &&
+ tryCompensate(task, null)) {
+ if (task.trySetSignal()) {
+ synchronized (task) {
+ if (task.status >= 0) {
+ try { // see ForkJoinTask
+ task.wait(); // for explanation
+ } catch (InterruptedException ie) {
+ }
}
+ else
+ task.notifyAll();
}
- else
- task.notifyAll();
}
+ long c; // re-activate
+ do {} while (!U.compareAndSwapLong
+ (this, CTL, c = ctl, c + AC_UNIT));
}
- long c; // re-activate
- do {} while (!U.compareAndSwapLong
- (this, CTL, c = ctl, c + AC_UNIT));
}
+ if (s < 0 || (s = task.status) < 0) {
+ joiner.currentJoin = prevJoin;
+ break;
+ }
+ else if ((k++ & (MAX_HELP - 1)) == MAX_HELP >>> 1)
+ Thread.yield(); // for politeness
}
- if ((s = task.status) < 0) {
- joiner.currentJoin = prevJoin;
- return s;
- }
- else if ((k & (MAX_HELP - 1)) == MAX_HELP >>> 1)
- Thread.yield(); // for politeness
}
+ return s;
}
/**
@@ -1887,7 +1881,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
while ((s = task.status) >= 0 &&
(joiner.isEmpty() ?
tryHelpStealer(joiner, task) :
- joiner.tryRemoveAndExec(task)))
+ joiner.tryRemoveAndExec(task)) != 0)
;
return s;
}
@@ -1919,6 +1913,7 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
}
}
+
/**
* Runs tasks until {@code isQuiescent()}. We piggyback on
* active count ctl maintenance, but rather than blocking
@@ -1927,8 +1922,9 @@ public class ForkJoinPool /*extends AbstractExecutorService*/ {
*/
final void helpQuiescePool(WorkQueue w) {
for (boolean active = true;;) {
- if (w.base - w.top < 0)
- w.runLocalTasks(); // exhaust local queue
+ ForkJoinTask<?> localTask; // exhaust local queue
+ while ((localTask = w.nextLocalTask()) != null)
+ localTask.doExec();
WorkQueue q = findNonEmptyStealQueue(w);
if (q != null) {
ForkJoinTask<?> t; int b;
diff --git a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java
index 344f6887a6..2ba146c4da 100644
--- a/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java
+++ b/src/forkjoin/scala/concurrent/forkjoin/ForkJoinTask.java
@@ -16,7 +16,7 @@ import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
-//import java.util.concurrent.RunnableFuture;
+import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.ReentrantLock;
@@ -115,18 +115,19 @@ import java.lang.reflect.Constructor;
* <p>The ForkJoinTask class is not usually directly subclassed.
* Instead, you subclass one of the abstract classes that support a
* particular style of fork/join processing, typically {@link
- * RecursiveAction} for computations that do not return results, or
- * {@link RecursiveTask} for those that do. Normally, a concrete
- * ForkJoinTask subclass declares fields comprising its parameters,
- * established in a constructor, and then defines a {@code compute}
- * method that somehow uses the control methods supplied by this base
- * class. While these methods have {@code public} access (to allow
- * instances of different task subclasses to call each other's
- * methods), some of them may only be called from within other
- * ForkJoinTasks (as may be determined using method {@link
- * #inForkJoinPool}). Attempts to invoke them in other contexts
- * result in exceptions or errors, possibly including
- * {@code ClassCastException}.
+ * RecursiveAction} for most computations that do not return results,
+ * {@link RecursiveTask} for those that do, and {@link
+ * CountedCompleter} for those in which completed actions trigger
+ * other actions. Normally, a concrete ForkJoinTask subclass declares
+ * fields comprising its parameters, established in a constructor, and
+ * then defines a {@code compute} method that somehow uses the control
+ * methods supplied by this base class. While these methods have
+ * {@code public} access (to allow instances of different task
+ * subclasses to call each other's methods), some of them may only be
+ * called from within other ForkJoinTasks (as may be determined using
+ * method {@link #inForkJoinPool}). Attempts to invoke them in other
+ * contexts result in exceptions or errors, possibly including {@code
+ * ClassCastException}.
*
* <p>Method {@link #join} and its variants are appropriate for use
* only when completion dependencies are acyclic; that is, the
@@ -137,17 +138,17 @@ import java.lang.reflect.Constructor;
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
* may be of use in constructing custom subclasses for problems that
* are not statically structured as DAGs. To support such usages a
- * ForkJoinTask may be atomically <em>marked</em> using {@link
- * #markForkJoinTask} and checked for marking using {@link
- * #isMarkedForkJoinTask}. The ForkJoinTask implementation does not
- * use these {@code protected} methods or marks for any purpose, but
+ * ForkJoinTask may be atomically <em>tagged</em> with a {@code
+ * short} value using {@link #setForkJoinTaskTag} or {@link
+ * #compareAndSetForkJoinTaskTag} and checked using {@link
+ * #getForkJoinTaskTag}. The ForkJoinTask implementation does not
+ * use these {@code protected} methods or tags for any purpose, but
* they may be of use in the construction of specialized subclasses.
* For example, parallel graph traversals can use the supplied methods
* to avoid revisiting nodes/tasks that have already been processed.
- * Also, completion based designs can use them to record that one
- * subtask has completed. (Method names for marking are bulky in part
- * to encourage definition of methods that reflect their usage
- * patterns.)
+ * Also, completion based designs can use them to record that subtasks
+ * have completed. (Method names for tagging are bulky in part to
+ * encourage definition of methods that reflect their usage patterns.)
*
* <p>Most base support methods are {@code final}, to prevent
* overriding of implementations that are intrinsically tied to the
@@ -213,6 +214,10 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* thin-lock techniques, so use some odd coding idioms that tend
* to avoid them, mainly by arranging that every synchronized
* block performs a wait, notifyAll or both.
+ *
+ * These control bits occupy only (some of) the upper half (16
+ * bits) of status field. The lower bits are used for user-defined
+ * tags.
*/
/** The run status of this task */
@@ -221,13 +226,12 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
static final int NORMAL = 0xf0000000; // must be negative
static final int CANCELLED = 0xc0000000; // must be < NORMAL
static final int EXCEPTIONAL = 0x80000000; // must be < CANCELLED
- static final int SIGNAL = 0x00000001;
- static final int MARKED = 0x00000002;
+ static final int SIGNAL = 0x00010000; // must be >= 1 << 16
+ static final int SMASK = 0x0000ffff; // short bits for tags
/**
* Marks completion and wakes up threads waiting to join this
- * task. A specialization for NORMAL completion is in method
- * doExec.
+ * task.
*
* @param completion one of NORMAL, CANCELLED, EXCEPTIONAL
* @return completion status on exit
@@ -237,7 +241,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
if ((s = status) < 0)
return s;
if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
- if ((s & SIGNAL) != 0)
+ if ((s >>> 16) != 0)
synchronized (this) { notifyAll(); }
return completion;
}
@@ -259,26 +263,22 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
} catch (Throwable rex) {
return setExceptionalCompletion(rex);
}
- while ((s = status) >= 0 && completed) {
- if (U.compareAndSwapInt(this, STATUS, s, s | NORMAL)) {
- if ((s & SIGNAL) != 0)
- synchronized (this) { notifyAll(); }
- return NORMAL;
- }
- }
+ if (completed)
+ s = setCompletion(NORMAL);
}
return s;
}
/**
- * Tries to set SIGNAL status. Used by ForkJoinPool. Other
- * variants are directly incorporated into externalAwaitDone etc.
+ * Tries to set SIGNAL status unless already completed. Used by
+ * ForkJoinPool. Other variants are directly incorporated into
+ * externalAwaitDone etc.
*
* @return true if successful
*/
final boolean trySetSignal() {
- int s;
- return U.compareAndSwapInt(this, STATUS, s = status, s | SIGNAL);
+ int s = status;
+ return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL);
}
/**
@@ -328,7 +328,6 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
return s;
}
-
/**
* Implementation for join, get, quietlyJoin. Directly handles
* only cases of already-completed, external wait, and
@@ -417,25 +416,39 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* @return status on exit
*/
private int setExceptionalCompletion(Throwable ex) {
- int h = System.identityHashCode(this);
- final ReentrantLock lock = exceptionTableLock;
- lock.lock();
- try {
- expungeStaleExceptions();
- ExceptionNode[] t = exceptionTable;
- int i = h & (t.length - 1);
- for (ExceptionNode e = t[i]; ; e = e.next) {
- if (e == null) {
- t[i] = new ExceptionNode(this, ex, t[i]);
- break;
+ int s;
+ if ((s = status) >= 0) {
+ int h = System.identityHashCode(this);
+ final ReentrantLock lock = exceptionTableLock;
+ lock.lock();
+ try {
+ expungeStaleExceptions();
+ ExceptionNode[] t = exceptionTable;
+ int i = h & (t.length - 1);
+ for (ExceptionNode e = t[i]; ; e = e.next) {
+ if (e == null) {
+ t[i] = new ExceptionNode(this, ex, t[i]);
+ break;
+ }
+ if (e.get() == this) // already present
+ break;
}
- if (e.get() == this) // already present
- break;
+ } finally {
+ lock.unlock();
}
- } finally {
- lock.unlock();
+ s = setCompletion(EXCEPTIONAL);
}
- return setCompletion(EXCEPTIONAL);
+ ForkJoinTask<?> p = internalGetCompleter(); // propagate
+ if (p != null && p.status >= 0)
+ p.setExceptionalCompletion(ex);
+ return s;
+ }
+
+ /**
+ * Exception propagation support for tasks with completers.
+ */
+ ForkJoinTask<?> internalGetCompleter() {
+ return null;
}
/**
@@ -517,7 +530,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
Throwable ex;
if (e == null || (ex = e.ex) == null)
return null;
- if (e.thrower != Thread.currentThread().getId()) {
+ if (false && e.thrower != Thread.currentThread().getId()) {
Class<? extends Throwable> ec = ex.getClass();
try {
Constructor<?> noArgCtor = null;
@@ -907,6 +920,18 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
}
/**
+ * Completes this task normally without setting a value. The most
+ * recent value established by {@link #setRawResult} (or {@code
+ * null} by default) will be returned as the result of subsequent
+ * invocations of {@code join} and related operations.
+ *
+ * @since 1.8
+ */
+ public final void quietlyComplete() {
+ setCompletion(NORMAL);
+ }
+
+ /**
* Waits if necessary for the computation to complete, and then
* retrieves its result.
*
@@ -1225,15 +1250,18 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
protected abstract void setRawResult(V value);
/**
- * Immediately performs the base action of this task. This method
- * is designed to support extensions, and should not in general be
- * called otherwise. The return value controls whether this task
- * is considered to be done normally. It may return false in
+ * Immediately performs the base action of this task and returns
+ * true if, upon return from this method, this task is guaranteed
+ * to have completed normally. This method may return false
+ * otherwise, to indicate that this task is not necessarily
+ * complete (or is not known to be complete), for example in
* asynchronous actions that require explicit invocations of
- * {@link #complete} to become joinable. It may also throw an
- * (unchecked) exception to indicate abnormal exit.
+ * completion methods. This method may also throw an (unchecked)
+ * exception to indicate abnormal exit. This method is designed to
+ * support extensions, and should not in general be called
+ * otherwise.
*
- * @return {@code true} if completed normally
+ * @return {@code true} if this task is known to have completed normally
*/
protected abstract boolean exec();
@@ -1302,44 +1330,53 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
return wt.pool.nextTaskFor(wt.workQueue);
}
- // Mark-bit operations
+ // tag operations
/**
- * Returns true if this task is marked.
+ * Returns the tag for this task.
*
- * @return true if this task is marked
+ * @return the tag for this task
* @since 1.8
*/
- public final boolean isMarkedForkJoinTask() {
- return (status & MARKED) != 0;
+ public final short getForkJoinTaskTag() {
+ return (short)status;
}
/**
- * Atomically sets the mark on this task.
+ * Atomically sets the tag value for this task.
*
- * @return true if this task was previously unmarked
+ * @param tag the tag value
+ * @return the previous value of the tag
* @since 1.8
*/
- public final boolean markForkJoinTask() {
+ public final short setForkJoinTaskTag(short tag) {
for (int s;;) {
- if (((s = status) & MARKED) != 0)
- return false;
- if (U.compareAndSwapInt(this, STATUS, s, s | MARKED))
- return true;
+ if (U.compareAndSwapInt(this, STATUS, s = status,
+ (s & ~SMASK) | (tag & SMASK)))
+ return (short)s;
}
}
/**
- * Atomically clears the mark on this task.
+ * Atomically conditionally sets the tag value for this task.
+ * Among other applications, tags can be used as visit markers
+ * in tasks operating on graphs, as in methods that check: {@code
+ * if (task.compareAndSetForkJoinTaskTag((short)0, (short)1))}
+ * before processing, otherwise exiting because the node has
+ * already been visited.
*
- * @return true if this task was previously marked
+ * @param e the expected tag value
+ * @param tag the new tag value
+ * @return true if successful; i.e., the current value was
+ * equal to e and is now tag.
* @since 1.8
*/
- public final boolean unmarkForkJoinTask() {
+ public final boolean compareAndSetForkJoinTaskTag(short e, short tag) {
for (int s;;) {
- if (((s = status) & MARKED) == 0)
+ if ((short)(s = status) != e)
return false;
- if (U.compareAndSwapInt(this, STATUS, s, s & ~MARKED))
+ if (U.compareAndSwapInt(this, STATUS, s,
+ (s & ~SMASK) | (tag & SMASK)))
return true;
}
}
diff --git a/src/intellij/dbc.iml.SAMPLE b/src/intellij/dbc.iml.SAMPLE
index 5a6df4cfaa..d2647cfb26 100644
--- a/src/intellij/dbc.iml.SAMPLE
+++ b/src/intellij/dbc.iml.SAMPLE
@@ -12,9 +12,6 @@
</component>
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
- <content url="file://$MODULE_DIR$/../dbc">
- <sourceFolder url="file://$MODULE_DIR$/../dbc" isTestSource="false" />
- </content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="library" />
diff --git a/src/intellij/scala-lang.ipr.SAMPLE b/src/intellij/scala-lang.ipr.SAMPLE
index 93b6285cfb..94a9329dd6 100644
--- a/src/intellij/scala-lang.ipr.SAMPLE
+++ b/src/intellij/scala-lang.ipr.SAMPLE
@@ -197,7 +197,6 @@
<modules>
<module fileurl="file://$PROJECT_DIR$/actors.iml" filepath="$PROJECT_DIR$/actors.iml" />
<module fileurl="file://$PROJECT_DIR$/compiler.iml" filepath="$PROJECT_DIR$/compiler.iml" />
- <module fileurl="file://$PROJECT_DIR$/dbc.iml" filepath="$PROJECT_DIR$/dbc.iml" />
<module fileurl="file://$PROJECT_DIR$/library.iml" filepath="$PROJECT_DIR$/library.iml" />
<module fileurl="file://$PROJECT_DIR$/manual.iml" filepath="$PROJECT_DIR$/manual.iml" />
<module fileurl="file://$PROJECT_DIR$/partest.iml" filepath="$PROJECT_DIR$/partest.iml" />
diff --git a/src/library/rootdoc.txt b/src/library/rootdoc.txt
index 6145429f1e..da27a0084b 100644
--- a/src/library/rootdoc.txt
+++ b/src/library/rootdoc.txt
@@ -22,6 +22,6 @@ Many other packages exist. See the complete list on the left.
Identifiers in the scala package and the [[scala.Predef]] object are always in scope by default.
-Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, List is an alias for scala.collection.immutable.[[scala.collection.immutable.List]].
+Some of these identifiers are type aliases provided as shortcuts to commonly used classes. For example, `List` is an alias for scala.collection.immutable.[[scala.collection.immutable.List]].
-Other aliases refer to classes providing by the underlying platform. For example, on the JVM, String is an alias for java.lang.String.
+Other aliases refer to classes provided by the underlying platform. For example, on the JVM, `String` is an alias for `java.lang.String`.
diff --git a/src/library/scala/Array.scala b/src/library/scala/Array.scala
index 99c54ce58c..36e95b303d 100644
--- a/src/library/scala/Array.scala
+++ b/src/library/scala/Array.scala
@@ -12,17 +12,17 @@ import scala.collection.generic._
import scala.collection.{ mutable, immutable }
import mutable.{ ArrayBuilder, ArraySeq }
import compat.Platform.arraycopy
-import scala.reflect.ClassManifest
+import scala.reflect.ArrayTag
import scala.runtime.ScalaRunTime.{ array_apply, array_update }
/** Contains a fallback builder for arrays when the element type
- * does not have a class manifest. In that case a generic array is built.
+ * does not have a class tag. In that case a generic array is built.
*/
class FallbackArrayBuilding {
/** A builder factory that generates a generic array.
* Called instead of `Array.newBuilder` if the element type of an array
- * does not have a class manifest. Note that fallbackBuilder factory
+ * does not have a class tag. Note that fallbackBuilder factory
* needs an implicit parameter (otherwise it would not be dominated in
* implicit search by `Array.canBuildFrom`). We make sure that
* implicit search is always successful.
@@ -48,16 +48,16 @@ class FallbackArrayBuilding {
* @version 1.0
*/
object Array extends FallbackArrayBuilding {
- implicit def canBuildFrom[T](implicit m: ClassManifest[T]): CanBuildFrom[Array[_], T, Array[T]] =
+ implicit def canBuildFrom[T](implicit t: ArrayTag[T]): CanBuildFrom[Array[_], T, Array[T]] =
new CanBuildFrom[Array[_], T, Array[T]] {
- def apply(from: Array[_]) = ArrayBuilder.make[T]()(m)
- def apply() = ArrayBuilder.make[T]()(m)
+ def apply(from: Array[_]) = ArrayBuilder.make[T]()(t)
+ def apply() = ArrayBuilder.make[T]()(t)
}
/**
* Returns a new [[scala.collection.mutable.ArrayBuilder]].
*/
- def newBuilder[T](implicit m: ClassManifest[T]): ArrayBuilder[T] = ArrayBuilder.make[T]()(m)
+ def newBuilder[T](implicit t: ArrayTag[T]): ArrayBuilder[T] = ArrayBuilder.make[T]()(t)
private def slowcopy(src : AnyRef,
srcPos : Int,
@@ -98,14 +98,14 @@ object Array extends FallbackArrayBuilding {
}
/** Returns an array of length 0 */
- def empty[T: ClassManifest]: Array[T] = new Array[T](0)
+ def empty[T: ArrayTag]: Array[T] = new Array[T](0)
/** Creates an array with given elements.
*
* @param xs the elements to put in the array
* @return an array containing all elements from xs.
*/
- def apply[T: ClassManifest](xs: T*): Array[T] = {
+ def apply[T: ArrayTag](xs: T*): Array[T] = {
val array = new Array[T](xs.length)
var i = 0
for (x <- xs.iterator) { array(i) = x; i += 1 }
@@ -194,23 +194,23 @@ object Array extends FallbackArrayBuilding {
}
/** Creates array with given dimensions */
- def ofDim[T: ClassManifest](n1: Int): Array[T] =
+ def ofDim[T: ArrayTag](n1: Int): Array[T] =
new Array[T](n1)
/** Creates a 2-dimensional array */
- def ofDim[T: ClassManifest](n1: Int, n2: Int): Array[Array[T]] = {
+ def ofDim[T: ArrayTag](n1: Int, n2: Int): Array[Array[T]] = {
val arr: Array[Array[T]] = (new Array[Array[T]](n1): Array[Array[T]])
for (i <- 0 until n1) arr(i) = new Array[T](n2)
arr
// tabulate(n1)(_ => ofDim[T](n2))
}
/** Creates a 3-dimensional array */
- def ofDim[T: ClassManifest](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] =
+ def ofDim[T: ArrayTag](n1: Int, n2: Int, n3: Int): Array[Array[Array[T]]] =
tabulate(n1)(_ => ofDim[T](n2, n3))
/** Creates a 4-dimensional array */
- def ofDim[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] =
+ def ofDim[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int): Array[Array[Array[Array[T]]]] =
tabulate(n1)(_ => ofDim[T](n2, n3, n4))
/** Creates a 5-dimensional array */
- def ofDim[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] =
+ def ofDim[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int): Array[Array[Array[Array[Array[T]]]]] =
tabulate(n1)(_ => ofDim[T](n2, n3, n4, n5))
/** Concatenates all arrays into a single array.
@@ -218,7 +218,7 @@ object Array extends FallbackArrayBuilding {
* @param xss the given arrays
* @return the array created from concatenating `xss`
*/
- def concat[T: ClassManifest](xss: Array[T]*): Array[T] = {
+ def concat[T: ArrayTag](xss: Array[T]*): Array[T] = {
val b = newBuilder[T]
b.sizeHint(xss.map(_.size).sum)
for (xs <- xss) b ++= xs
@@ -239,7 +239,7 @@ object Array extends FallbackArrayBuilding {
* @return an Array of size n, where each element contains the result of computing
* `elem`.
*/
- def fill[T: ClassManifest](n: Int)(elem: => T): Array[T] = {
+ def fill[T: ArrayTag](n: Int)(elem: => T): Array[T] = {
val b = newBuilder[T]
b.sizeHint(n)
var i = 0
@@ -257,7 +257,7 @@ object Array extends FallbackArrayBuilding {
* @param n2 the number of elements in the 2nd dimension
* @param elem the element computation
*/
- def fill[T: ClassManifest](n1: Int, n2: Int)(elem: => T): Array[Array[T]] =
+ def fill[T: ArrayTag](n1: Int, n2: Int)(elem: => T): Array[Array[T]] =
tabulate(n1)(_ => fill(n2)(elem))
/** Returns a three-dimensional array that contains the results of some element
@@ -268,7 +268,7 @@ object Array extends FallbackArrayBuilding {
* @param n3 the number of elements in the 3nd dimension
* @param elem the element computation
*/
- def fill[T: ClassManifest](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] =
+ def fill[T: ArrayTag](n1: Int, n2: Int, n3: Int)(elem: => T): Array[Array[Array[T]]] =
tabulate(n1)(_ => fill(n2, n3)(elem))
/** Returns a four-dimensional array that contains the results of some element
@@ -280,7 +280,7 @@ object Array extends FallbackArrayBuilding {
* @param n4 the number of elements in the 4th dimension
* @param elem the element computation
*/
- def fill[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] =
+ def fill[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => T): Array[Array[Array[Array[T]]]] =
tabulate(n1)(_ => fill(n2, n3, n4)(elem))
/** Returns a five-dimensional array that contains the results of some element
@@ -293,7 +293,7 @@ object Array extends FallbackArrayBuilding {
* @param n5 the number of elements in the 5th dimension
* @param elem the element computation
*/
- def fill[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] =
+ def fill[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => T): Array[Array[Array[Array[Array[T]]]]] =
tabulate(n1)(_ => fill(n2, n3, n4, n5)(elem))
/** Returns an array containing values of a given function over a range of integer
@@ -303,7 +303,7 @@ object Array extends FallbackArrayBuilding {
* @param f The function computing element values
* @return A traversable consisting of elements `f(0),f(1), ..., f(n - 1)`
*/
- def tabulate[T: ClassManifest](n: Int)(f: Int => T): Array[T] = {
+ def tabulate[T: ArrayTag](n: Int)(f: Int => T): Array[T] = {
val b = newBuilder[T]
b.sizeHint(n)
var i = 0
@@ -321,7 +321,7 @@ object Array extends FallbackArrayBuilding {
* @param n2 the number of elements in the 2nd dimension
* @param f The function computing element values
*/
- def tabulate[T: ClassManifest](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] =
+ def tabulate[T: ArrayTag](n1: Int, n2: Int)(f: (Int, Int) => T): Array[Array[T]] =
tabulate(n1)(i1 => tabulate(n2)(f(i1, _)))
/** Returns a three-dimensional array containing values of a given function
@@ -332,7 +332,7 @@ object Array extends FallbackArrayBuilding {
* @param n3 the number of elements in the 3rd dimension
* @param f The function computing element values
*/
- def tabulate[T: ClassManifest](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] =
+ def tabulate[T: ArrayTag](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => T): Array[Array[Array[T]]] =
tabulate(n1)(i1 => tabulate(n2, n3)(f(i1, _, _)))
/** Returns a four-dimensional array containing values of a given function
@@ -344,7 +344,7 @@ object Array extends FallbackArrayBuilding {
* @param n4 the number of elements in the 4th dimension
* @param f The function computing element values
*/
- def tabulate[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] =
+ def tabulate[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => T): Array[Array[Array[Array[T]]]] =
tabulate(n1)(i1 => tabulate(n2, n3, n4)(f(i1, _, _, _)))
/** Returns a five-dimensional array containing values of a given function
@@ -357,7 +357,7 @@ object Array extends FallbackArrayBuilding {
* @param n5 the number of elements in the 5th dimension
* @param f The function computing element values
*/
- def tabulate[T: ClassManifest](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] =
+ def tabulate[T: ArrayTag](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => T): Array[Array[Array[Array[Array[T]]]]] =
tabulate(n1)(i1 => tabulate(n2, n3, n4, n5)(f(i1, _, _, _, _)))
/** Returns an array containing a sequence of increasing integers in a range.
@@ -396,7 +396,7 @@ object Array extends FallbackArrayBuilding {
* @param f the function that is repeatedly applied
* @return the array returning `len` values in the sequence `start, f(start), f(f(start)), ...`
*/
- def iterate[T: ClassManifest](start: T, len: Int)(f: T => T): Array[T] = {
+ def iterate[T: ArrayTag](start: T, len: Int)(f: T => T): Array[T] = {
val b = newBuilder[T]
if (len > 0) {
@@ -467,6 +467,19 @@ object Array extends FallbackArrayBuilding {
* @version 1.0
* @see [[http://www.scala-lang.org/docu/files/collections-api/collections_38.html#anchor "The Scala 2.8 Collections' API"]]
* section on `Array` by Martin Odersky for more information.
+ * @define coll array
+ * @define Coll `Array`
+ * @define orderDependent
+ * @define orderDependentFold
+ * @define mayNotTerminateInf
+ * @define willNotTerminateInf
+ * @define collectExample
+ * @define undefinedorder
+ * @define thatinfo the class of the returned collection. In the standard library configuration,
+ * `That` is either `Array[B]` if an ArrayTag is available for B or `ArraySeq[B]` otherwise.
+ * @define zipthatinfo $thatinfo
+ * @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current
+ * representation type `Repr` and the new element type `B`.
*/
final class Array[T](_length: Int) extends java.io.Serializable with java.lang.Cloneable {
diff --git a/src/library/scala/Boolean.scala b/src/library/scala/Boolean.scala
index 5078e59d28..edb82b33fe 100644
--- a/src/library/scala/Boolean.scala
+++ b/src/library/scala/Boolean.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Boolean]] => [[scala.runtime.RichBoolean]]
* which provides useful non-primitive operations.
*/
-final class Boolean extends AnyVal {
+final class Boolean private extends AnyVal {
/**
* Negates a Boolean expression.
*
@@ -110,7 +110,7 @@ final class Boolean extends AnyVal {
override def getClass(): Class[Boolean] = sys.error("stub")
}
-object Boolean extends AnyValCompanion {
+object Boolean extends AnyValCompanion {
/** Transform a value type into a boxed reference type.
*
diff --git a/src/library/scala/Byte.scala b/src/library/scala/Byte.scala
index f9c5f6003e..b5b3d88e3f 100644
--- a/src/library/scala/Byte.scala
+++ b/src/library/scala/Byte.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Byte]] => [[scala.runtime.RichByte]]
* which provides useful non-primitive operations.
*/
-final class Byte extends AnyVal {
+final class Byte private extends AnyVal {
def toByte: Byte = sys.error("stub")
def toShort: Short = sys.error("stub")
def toChar: Char = sys.error("stub")
@@ -27,7 +27,7 @@ final class Byte extends AnyVal {
def toDouble: Double = sys.error("stub")
/**
- * @return the bitwise negation of this value
+ * Returns the bitwise negation of this value.
* @example {{{
* ~5 == -6
* // in binary: ~00000101 ==
@@ -36,30 +36,30 @@ final class Byte extends AnyVal {
*/
def unary_~ : Int = sys.error("stub")
/**
- * @return this value, unmodified
+ * Returns this value, unmodified.
*/
def unary_+ : Int = sys.error("stub")
/**
- * @return the negation of this value
+ * Returns the negation of this value.
*/
def unary_- : Int = sys.error("stub")
def +(x: String): String = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -70,7 +70,7 @@ final class Byte extends AnyVal {
*/
def >>>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -81,7 +81,7 @@ final class Byte extends AnyVal {
*/
def >>>(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -92,7 +92,7 @@ final class Byte extends AnyVal {
*/
def >>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -104,181 +104,181 @@ final class Byte extends AnyVal {
def >>(x: Long): Int = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Double): Boolean = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -289,7 +289,7 @@ final class Byte extends AnyVal {
*/
def |(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -300,7 +300,7 @@ final class Byte extends AnyVal {
*/
def |(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -311,7 +311,7 @@ final class Byte extends AnyVal {
*/
def |(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -322,7 +322,7 @@ final class Byte extends AnyVal {
*/
def |(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -334,7 +334,7 @@ final class Byte extends AnyVal {
def |(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -345,7 +345,7 @@ final class Byte extends AnyVal {
*/
def &(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -356,7 +356,7 @@ final class Byte extends AnyVal {
*/
def &(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -367,7 +367,7 @@ final class Byte extends AnyVal {
*/
def &(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -378,7 +378,7 @@ final class Byte extends AnyVal {
*/
def &(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -390,7 +390,7 @@ final class Byte extends AnyVal {
def &(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -401,7 +401,7 @@ final class Byte extends AnyVal {
*/
def ^(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -412,7 +412,7 @@ final class Byte extends AnyVal {
*/
def ^(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -423,7 +423,7 @@ final class Byte extends AnyVal {
*/
def ^(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -434,7 +434,7 @@ final class Byte extends AnyVal {
*/
def ^(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -446,154 +446,154 @@ final class Byte extends AnyVal {
def ^(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Byte): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Short): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Char): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Int): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Float): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Double): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Byte): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Short): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Char): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Int): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Long): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Float): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Double): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Byte): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Short): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Char): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Int): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Long): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Float): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Double): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Byte): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Short): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Char): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Int): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Long): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Float): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Double): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Byte): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Short): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Char): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Int): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Long): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Float): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Double): Double = sys.error("stub")
override def getClass(): Class[Byte] = sys.error("stub")
}
-object Byte extends AnyValCompanion {
+object Byte extends AnyValCompanion {
/** The smallest value representable as a Byte.
*/
final val MinValue = java.lang.Byte.MIN_VALUE
@@ -622,5 +622,10 @@ object Byte extends AnyValCompanion {
/** The String representation of the scala.Byte companion object.
*/
override def toString = "object scala.Byte"
+ implicit def byte2short(x: Byte): Short = x.toShort
+ implicit def byte2int(x: Byte): Int = x.toInt
+ implicit def byte2long(x: Byte): Long = x.toLong
+ implicit def byte2float(x: Byte): Float = x.toFloat
+ implicit def byte2double(x: Byte): Double = x.toDouble
}
diff --git a/src/library/scala/Char.scala b/src/library/scala/Char.scala
index 3d459782cd..e0ac9a2550 100644
--- a/src/library/scala/Char.scala
+++ b/src/library/scala/Char.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Char]] => [[scala.runtime.RichChar]]
* which provides useful non-primitive operations.
*/
-final class Char extends AnyVal {
+final class Char private extends AnyVal {
def toByte: Byte = sys.error("stub")
def toShort: Short = sys.error("stub")
def toChar: Char = sys.error("stub")
@@ -27,7 +27,7 @@ final class Char extends AnyVal {
def toDouble: Double = sys.error("stub")
/**
- * @return the bitwise negation of this value
+ * Returns the bitwise negation of this value.
* @example {{{
* ~5 == -6
* // in binary: ~00000101 ==
@@ -36,30 +36,30 @@ final class Char extends AnyVal {
*/
def unary_~ : Int = sys.error("stub")
/**
- * @return this value, unmodified
+ * Returns this value, unmodified.
*/
def unary_+ : Int = sys.error("stub")
/**
- * @return the negation of this value
+ * Returns the negation of this value.
*/
def unary_- : Int = sys.error("stub")
def +(x: String): String = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -70,7 +70,7 @@ final class Char extends AnyVal {
*/
def >>>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -81,7 +81,7 @@ final class Char extends AnyVal {
*/
def >>>(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -92,7 +92,7 @@ final class Char extends AnyVal {
*/
def >>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -104,181 +104,181 @@ final class Char extends AnyVal {
def >>(x: Long): Int = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Double): Boolean = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -289,7 +289,7 @@ final class Char extends AnyVal {
*/
def |(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -300,7 +300,7 @@ final class Char extends AnyVal {
*/
def |(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -311,7 +311,7 @@ final class Char extends AnyVal {
*/
def |(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -322,7 +322,7 @@ final class Char extends AnyVal {
*/
def |(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -334,7 +334,7 @@ final class Char extends AnyVal {
def |(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -345,7 +345,7 @@ final class Char extends AnyVal {
*/
def &(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -356,7 +356,7 @@ final class Char extends AnyVal {
*/
def &(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -367,7 +367,7 @@ final class Char extends AnyVal {
*/
def &(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -378,7 +378,7 @@ final class Char extends AnyVal {
*/
def &(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -390,7 +390,7 @@ final class Char extends AnyVal {
def &(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -401,7 +401,7 @@ final class Char extends AnyVal {
*/
def ^(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -412,7 +412,7 @@ final class Char extends AnyVal {
*/
def ^(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -423,7 +423,7 @@ final class Char extends AnyVal {
*/
def ^(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -434,7 +434,7 @@ final class Char extends AnyVal {
*/
def ^(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -446,154 +446,154 @@ final class Char extends AnyVal {
def ^(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Byte): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Short): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Char): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Int): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Float): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Double): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Byte): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Short): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Char): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Int): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Long): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Float): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Double): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Byte): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Short): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Char): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Int): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Long): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Float): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Double): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Byte): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Short): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Char): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Int): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Long): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Float): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Double): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Byte): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Short): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Char): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Int): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Long): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Float): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Double): Double = sys.error("stub")
override def getClass(): Class[Char] = sys.error("stub")
}
-object Char extends AnyValCompanion {
+object Char extends AnyValCompanion {
/** The smallest value representable as a Char.
*/
final val MinValue = java.lang.Character.MIN_VALUE
@@ -622,5 +622,9 @@ object Char extends AnyValCompanion {
/** The String representation of the scala.Char companion object.
*/
override def toString = "object scala.Char"
+ implicit def char2int(x: Char): Int = x.toInt
+ implicit def char2long(x: Char): Long = x.toLong
+ implicit def char2float(x: Char): Float = x.toFloat
+ implicit def char2double(x: Char): Double = x.toDouble
}
diff --git a/src/library/scala/DelayedInit.scala b/src/library/scala/DelayedInit.scala
index e898bca720..52a38ca6f7 100644
--- a/src/library/scala/DelayedInit.scala
+++ b/src/library/scala/DelayedInit.scala
@@ -8,15 +8,41 @@
package scala
-/** Classes and traits inheriting the `DelayedInit` marker trait
- * will have their initialization code rewritten as follows:
+/** Classes and objects (but note, not traits) inheriting the `DelayedInit`
+ * marker trait will have their initialization code rewritten as follows:
* `code` becomes `delayedInit(code)`.
*
* Initialization code comprises all statements and all value definitions
* that are executed during initialization.
*
+ * Example:
+ * {{{
+ * trait Helper extends DelayedInit {
+ * def delayedInit(body: => Unit) = {
+ * println("dummy text, printed before initialization of C")
+ * body // evaluates the initialization code of C
+ * }
+ * }
+ *
+ * class C extends Helper {
+ * println("this is the initialization code of C")
+ * }
+ *
+ * object Test extends App {
+ * val c = new C
+ * }
+ * }}}
+ *
+ * Should result in the following being printed:
+ * {{{
+ * dummy text, printed before initialization of C
+ * this is the initialization code of C
+ * }}}
+ *
+ * @see "Delayed Initialization" subsection of the Scala Language Specification (section 5.1)
+ *
* @author Martin Odersky
*/
trait DelayedInit {
def delayedInit(x: => Unit): Unit
-}
+} \ No newline at end of file
diff --git a/src/library/scala/Double.scala b/src/library/scala/Double.scala
index 01414265c4..bb659b963a 100644
--- a/src/library/scala/Double.scala
+++ b/src/library/scala/Double.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Double]] => [[scala.runtime.RichDouble]]
* which provides useful non-primitive operations.
*/
-final class Double extends AnyVal {
+final class Double private extends AnyVal {
def toByte: Byte = sys.error("stub")
def toShort: Short = sys.error("stub")
def toChar: Char = sys.error("stub")
@@ -27,339 +27,339 @@ final class Double extends AnyVal {
def toDouble: Double = sys.error("stub")
/**
- * @return this value, unmodified
+ * Returns this value, unmodified.
*/
def unary_+ : Double = sys.error("stub")
/**
- * @return the negation of this value
+ * Returns the negation of this value.
*/
def unary_- : Double = sys.error("stub")
def +(x: String): String = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Double): Boolean = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Byte): Double = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Short): Double = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Char): Double = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Int): Double = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Long): Double = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Float): Double = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Double): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Byte): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Short): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Char): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Int): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Long): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Float): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Double): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Byte): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Short): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Char): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Int): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Long): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Float): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Double): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Byte): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Short): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Char): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Int): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Long): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Float): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Double): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Byte): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Short): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Char): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Int): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Long): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Float): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Double): Double = sys.error("stub")
override def getClass(): Class[Double] = sys.error("stub")
}
-object Double extends AnyValCompanion {
+object Double extends AnyValCompanion {
/** The smallest positive value greater than 0.0d which is
* representable as a Double.
*/
diff --git a/src/library/scala/Dynamic.scala b/src/library/scala/Dynamic.scala
index 32b57ee88f..faf834d310 100644
--- a/src/library/scala/Dynamic.scala
+++ b/src/library/scala/Dynamic.scala
@@ -9,12 +9,25 @@
package scala
/** A marker trait that enables dynamic invocations. Instances `x` of this
- * trait allow calls `x.meth(args)` for arbitrary method names `meth` and
- * argument lists `args`. If a call is not natively supported by `x`, it
- * is rewritten to `x.applyDynamic("meth", args)`.
+ * trait allow method invocations `x.meth(args)` for arbitrary method
+ * names `meth` and argument lists `args` as well as field accesses
+ * `x.field` for arbitrary field names `field`.
*
- * As of scala 2.9, `scalac` must receive the `-Xexperimental` option for
- * `Dynamic` to receive this treatment.
+ * If a call is not natively supported by `x` (i.e. if type checking
+ * fails), it is rewritten according to the following rules:
+ *
+ * {{{
+ * foo.method("blah") ~~> foo.applyDynamic("method")("blah")
+ * foo.method(x = "blah") ~~> foo.applyDynamicNamed("method")(("x", "blah"))
+ * foo.method(x = 1, 2) ~~> foo.applyDynamicNamed("method")(("x", 1), ("", 2))
+ * foo.field ~~> foo.selectDynamic("field")
+ * foo.varia = 10 ~~> foo.updateDynamic("varia")(10)
+ * foo.arr(10) = 13 ~~> foo.selectDynamic("arr").update(10, 13)
+ * foo.arr(10) ~~> foo.applyDynamics("arr")(10)
+ * }}}
+ *
+ * As of Scala 2.10, defining direct or indirect subclasses of this trait
+ * is only possible if the language feature `dynamics` is enabled.
*/
trait Dynamic
diff --git a/src/library/scala/Either.scala b/src/library/scala/Either.scala
index e454cdf5ec..20451600a9 100644
--- a/src/library/scala/Either.scala
+++ b/src/library/scala/Either.scala
@@ -10,6 +10,8 @@
package scala
+import language.implicitConversions
+
/** Represents a value of one of two possible types (a disjoint union.)
* Instances of Either are either an instance of [[scala.Left]] or [[scala.Right]].
*
@@ -201,12 +203,6 @@ final case class Right[+A, +B](b: B) extends Either[A, B] {
}
object Either {
- class MergeableEither[A](x: Either[A, A]) {
- def merge: A = x match {
- case Left(a) => a
- case Right(a) => a
- }
- }
/**
* Allows use of a ``merge`` method to extract values from Either instances
@@ -219,7 +215,14 @@ object Either {
* r.merge: Seq[Int] // Vector(1)
* }}}
*/
- implicit def either2mergeable[A](x: Either[A, A]): MergeableEither[A] = new MergeableEither(x)
+ implicit class MergeableEither[A](x: Either[A, A]) {
+ def merge: A = x match {
+ case Left(a) => a
+ case Right(a) => a
+ }
+ }
+ @deprecated("use MergeableEither instead", "2.10")
+ def either2mergeable[A](x: Either[A, A]): MergeableEither[A] = new MergeableEither(x)
/**
* Projects an `Either` into a `Left`.
@@ -258,7 +261,7 @@ object Either {
* case ex => Left(ex)
* }
*
- * // this will only be executed if interactWithDB returns a Some
+ * // this will only be executed if interactWithDB returns a Right
* val report =
* for (r <- interactWithDB(someQuery).right) yield generateReport(r)
* if (report.isRight)
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
index 80571943e5..ea0d20957d 100644
--- a/src/library/scala/Enumeration.scala
+++ b/src/library/scala/Enumeration.scala
@@ -70,10 +70,9 @@ abstract class Enumeration (initial: Int) extends Serializable {
/** The name of this enumeration.
*/
- override def toString = (
- (getClass.getName stripSuffix MODULE_SUFFIX_STRING split '.' last)
- split Pattern.quote(NAME_JOIN_STRING) last
- )
+ override def toString =
+ ((getClass.getName stripSuffix MODULE_SUFFIX_STRING split '.').last split
+ Pattern.quote(NAME_JOIN_STRING)).last
/** The mapping from the integer used to identify values to the actual
* values. */
@@ -81,7 +80,7 @@ abstract class Enumeration (initial: Int) extends Serializable {
/** The cache listing all values of this enumeration. */
@transient private var vset: ValueSet = null
- @transient private var vsetDefined = false
+ @transient @volatile private var vsetDefined = false
/** The mapping from the integer used to identify values to their
* names. */
diff --git a/src/library/scala/Float.scala b/src/library/scala/Float.scala
index ff5b3cb112..bb03581062 100644
--- a/src/library/scala/Float.scala
+++ b/src/library/scala/Float.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Float]] => [[scala.runtime.RichFloat]]
* which provides useful non-primitive operations.
*/
-final class Float extends AnyVal {
+final class Float private extends AnyVal {
def toByte: Byte = sys.error("stub")
def toShort: Short = sys.error("stub")
def toChar: Char = sys.error("stub")
@@ -27,339 +27,339 @@ final class Float extends AnyVal {
def toDouble: Double = sys.error("stub")
/**
- * @return this value, unmodified
+ * Returns this value, unmodified.
*/
def unary_+ : Float = sys.error("stub")
/**
- * @return the negation of this value
+ * Returns the negation of this value.
*/
def unary_- : Float = sys.error("stub")
def +(x: String): String = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Double): Boolean = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Byte): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Short): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Char): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Int): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Long): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Float): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Double): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Byte): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Short): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Char): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Int): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Long): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Float): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Double): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Byte): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Short): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Char): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Int): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Long): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Float): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Double): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Byte): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Short): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Char): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Int): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Long): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Float): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Double): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Byte): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Short): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Char): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Int): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Long): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Float): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Double): Double = sys.error("stub")
override def getClass(): Class[Float] = sys.error("stub")
}
-object Float extends AnyValCompanion {
+object Float extends AnyValCompanion {
/** The smallest positive value greater than 0.0f which is
* representable as a Float.
*/
@@ -401,5 +401,6 @@ object Float extends AnyValCompanion {
/** The String representation of the scala.Float companion object.
*/
override def toString = "object scala.Float"
+ implicit def float2double(x: Float): Double = x.toDouble
}
diff --git a/src/library/scala/Function0.scala b/src/library/scala/Function0.scala
index dceed26439..3690a0e65b 100644
--- a/src/library/scala/Function0.scala
+++ b/src/library/scala/Function0.scala
@@ -6,13 +6,13 @@
** |/ **
\* */
// GENERATED CODE: DO NOT EDIT.
-// genprod generated these sources at: Tue Feb 14 16:49:03 PST 2012
+// genprod generated these sources at: Mon Apr 30 07:46:11 PDT 2012
package scala
/** A function of 0 parameters.
- *
+ *
* In the following example, the definition of javaVersion is a
* shorthand for the anonymous class definition anonfun0:
*
@@ -24,7 +24,7 @@ package scala
* def apply(): String = sys.props("java.version")
* }
* assert(javaVersion() == anonfun0())
- * }
+ * }
* }}}
*
* Note that `Function1` does not define a total function, as might
diff --git a/src/library/scala/Function1.scala b/src/library/scala/Function1.scala
index 8995ef912b..f9b37fc6bd 100644
--- a/src/library/scala/Function1.scala
+++ b/src/library/scala/Function1.scala
@@ -11,7 +11,7 @@ package scala
/** A function of 1 parameter.
- *
+ *
* In the following example, the definition of succ is a
* shorthand for the anonymous class definition anonfun1:
*
@@ -22,7 +22,7 @@ package scala
* def apply(x: Int): Int = x + 1
* }
* assert(succ(0) == anonfun1(0))
- * }
+ * }
* }}}
*
* Note that `Function1` does not define a total function, as might
@@ -44,7 +44,7 @@ trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, s
* @param g a function A => T1
* @return a new function `f` such that `f(x) == apply(g(x))`
*/
- def compose[A](g: A => T1): A => R = { x => apply(g(x)) }
+ @annotation.unspecialized def compose[A](g: A => T1): A => R = { x => apply(g(x)) }
/** Composes two instances of Function1 in a new Function1, with this function applied first.
*
@@ -52,7 +52,7 @@ trait Function1[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, s
* @param g a function R => A
* @return a new function `f` such that `f(x) == g(apply(x))`
*/
- def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }
+ @annotation.unspecialized def andThen[A](g: R => A): T1 => A = { x => g(apply(x)) }
override def toString() = "<function1>"
}
diff --git a/src/library/scala/Function10.scala b/src/library/scala/Function10.scala
index 9e107fc53d..f7e5d414f2 100644
--- a/src/library/scala/Function10.scala
+++ b/src/library/scala/Function10.scala
@@ -21,16 +21,17 @@ trait Function10[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, +R] extends
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)).curried
}
-
/** Creates a tupled version of this function: instead of 10 arguments,
* it accepts a single [[scala.Tuple10]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)) == f(Tuple10(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)`
*/
- def tupled: Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] => R = {
+
+ @annotation.unspecialized def tupled: Tuple10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10] => R = {
case Tuple10(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10)
}
override def toString() = "<function10>"
diff --git a/src/library/scala/Function11.scala b/src/library/scala/Function11.scala
index 783a86ab5d..53742bf733 100644
--- a/src/library/scala/Function11.scala
+++ b/src/library/scala/Function11.scala
@@ -21,16 +21,17 @@ trait Function11[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, +R] ex
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)).curried
}
-
/** Creates a tupled version of this function: instead of 11 arguments,
* it accepts a single [[scala.Tuple11]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)) == f(Tuple11(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)`
*/
- def tupled: Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] => R = {
+
+ @annotation.unspecialized def tupled: Tuple11[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11] => R = {
case Tuple11(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11)
}
override def toString() = "<function11>"
diff --git a/src/library/scala/Function12.scala b/src/library/scala/Function12.scala
index 7f4dee6216..e349d9017d 100644
--- a/src/library/scala/Function12.scala
+++ b/src/library/scala/Function12.scala
@@ -21,16 +21,17 @@ trait Function12[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)).curried
}
-
/** Creates a tupled version of this function: instead of 12 arguments,
* it accepts a single [[scala.Tuple12]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)) == f(Tuple12(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)`
*/
- def tupled: Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] => R = {
+
+ @annotation.unspecialized def tupled: Tuple12[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12] => R = {
case Tuple12(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12)
}
override def toString() = "<function12>"
diff --git a/src/library/scala/Function13.scala b/src/library/scala/Function13.scala
index 23853dde69..10ec64b87a 100644
--- a/src/library/scala/Function13.scala
+++ b/src/library/scala/Function13.scala
@@ -21,16 +21,17 @@ trait Function13[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)).curried
}
-
/** Creates a tupled version of this function: instead of 13 arguments,
* it accepts a single [[scala.Tuple13]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)) == f(Tuple13(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)`
*/
- def tupled: Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] => R = {
+
+ @annotation.unspecialized def tupled: Tuple13[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13] => R = {
case Tuple13(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13)
}
override def toString() = "<function13>"
diff --git a/src/library/scala/Function14.scala b/src/library/scala/Function14.scala
index 372f1cfafb..82dd409223 100644
--- a/src/library/scala/Function14.scala
+++ b/src/library/scala/Function14.scala
@@ -21,16 +21,17 @@ trait Function14[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)).curried
}
-
/** Creates a tupled version of this function: instead of 14 arguments,
* it accepts a single [[scala.Tuple14]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)) == f(Tuple14(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)`
*/
- def tupled: Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] => R = {
+
+ @annotation.unspecialized def tupled: Tuple14[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14] => R = {
case Tuple14(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14)
}
override def toString() = "<function14>"
diff --git a/src/library/scala/Function15.scala b/src/library/scala/Function15.scala
index 47c7309695..be5fbeeca1 100644
--- a/src/library/scala/Function15.scala
+++ b/src/library/scala/Function15.scala
@@ -21,16 +21,17 @@ trait Function15[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)).curried
}
-
/** Creates a tupled version of this function: instead of 15 arguments,
* it accepts a single [[scala.Tuple15]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)) == f(Tuple15(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)`
*/
- def tupled: Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] => R = {
+
+ @annotation.unspecialized def tupled: Tuple15[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15] => R = {
case Tuple15(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15)
}
override def toString() = "<function15>"
diff --git a/src/library/scala/Function16.scala b/src/library/scala/Function16.scala
index 8eea42de5b..7a185b369c 100644
--- a/src/library/scala/Function16.scala
+++ b/src/library/scala/Function16.scala
@@ -21,16 +21,17 @@ trait Function16[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)).curried
}
-
/** Creates a tupled version of this function: instead of 16 arguments,
* it accepts a single [[scala.Tuple16]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)) == f(Tuple16(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)`
*/
- def tupled: Tuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16] => R = {
+
+ @annotation.unspecialized def tupled: Tuple16[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16] => R = {
case Tuple16(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16)
}
override def toString() = "<function16>"
diff --git a/src/library/scala/Function17.scala b/src/library/scala/Function17.scala
index 2d93af34f2..94e0000802 100644
--- a/src/library/scala/Function17.scala
+++ b/src/library/scala/Function17.scala
@@ -21,16 +21,17 @@ trait Function17[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)).curried
}
-
/** Creates a tupled version of this function: instead of 17 arguments,
* it accepts a single [[scala.Tuple17]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)) == f(Tuple17(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)`
*/
- def tupled: Tuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17] => R = {
+
+ @annotation.unspecialized def tupled: Tuple17[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17] => R = {
case Tuple17(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17)
}
override def toString() = "<function17>"
diff --git a/src/library/scala/Function18.scala b/src/library/scala/Function18.scala
index ffca98c443..a3ee6776ba 100644
--- a/src/library/scala/Function18.scala
+++ b/src/library/scala/Function18.scala
@@ -21,16 +21,17 @@ trait Function18[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)).curried
}
-
/** Creates a tupled version of this function: instead of 18 arguments,
* it accepts a single [[scala.Tuple18]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)) == f(Tuple18(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)`
*/
- def tupled: Tuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18] => R = {
+
+ @annotation.unspecialized def tupled: Tuple18[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18] => R = {
case Tuple18(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18)
}
override def toString() = "<function18>"
diff --git a/src/library/scala/Function19.scala b/src/library/scala/Function19.scala
index f661ea7707..038dcbb778 100644
--- a/src/library/scala/Function19.scala
+++ b/src/library/scala/Function19.scala
@@ -21,16 +21,17 @@ trait Function19[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)).curried
}
-
/** Creates a tupled version of this function: instead of 19 arguments,
* it accepts a single [[scala.Tuple19]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)) == f(Tuple19(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)`
*/
- def tupled: Tuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19] => R = {
+
+ @annotation.unspecialized def tupled: Tuple19[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19] => R = {
case Tuple19(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19)
}
override def toString() = "<function19>"
diff --git a/src/library/scala/Function2.scala b/src/library/scala/Function2.scala
index cacb96ef5d..0794a4048a 100644
--- a/src/library/scala/Function2.scala
+++ b/src/library/scala/Function2.scala
@@ -11,7 +11,7 @@ package scala
/** A function of 2 parameters.
- *
+ *
* In the following example, the definition of max is a
* shorthand for the anonymous class definition anonfun2:
*
@@ -23,7 +23,7 @@ package scala
* def apply(x: Int, y: Int): Int = if (x < y) y else x
* }
* assert(max(0, 1) == anonfun2(0, 1))
- * }
+ * }
* }}}
*
* Note that `Function1` does not define a total function, as might
@@ -40,16 +40,17 @@ trait Function2[@specialized(scala.Int, scala.Long, scala.Double) -T1, @speciali
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2) == apply(x1, x2)`
- */ def curried: T1 => T2 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => R = {
(x1: T1) => (x2: T2) => apply(x1, x2)
}
-
/** Creates a tupled version of this function: instead of 2 arguments,
* it accepts a single [[scala.Tuple2]] argument.
*
* @return a function `f` such that `f((x1, x2)) == f(Tuple2(x1, x2)) == apply(x1, x2)`
*/
- def tupled: Tuple2[T1, T2] => R = {
+
+ @annotation.unspecialized def tupled: Tuple2[T1, T2] => R = {
case Tuple2(x1, x2) => apply(x1, x2)
}
override def toString() = "<function2>"
diff --git a/src/library/scala/Function20.scala b/src/library/scala/Function20.scala
index e4fb9f280c..727684d6d5 100644
--- a/src/library/scala/Function20.scala
+++ b/src/library/scala/Function20.scala
@@ -21,16 +21,17 @@ trait Function20[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)).curried
}
-
/** Creates a tupled version of this function: instead of 20 arguments,
* it accepts a single [[scala.Tuple20]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)) == f(Tuple20(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)`
*/
- def tupled: Tuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20] => R = {
+
+ @annotation.unspecialized def tupled: Tuple20[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20] => R = {
case Tuple20(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20)
}
override def toString() = "<function20>"
diff --git a/src/library/scala/Function21.scala b/src/library/scala/Function21.scala
index 9823386856..2441278be8 100644
--- a/src/library/scala/Function21.scala
+++ b/src/library/scala/Function21.scala
@@ -21,16 +21,17 @@ trait Function21[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)).curried
}
-
/** Creates a tupled version of this function: instead of 21 arguments,
* it accepts a single [[scala.Tuple21]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)) == f(Tuple21(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)`
*/
- def tupled: Tuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21] => R = {
+
+ @annotation.unspecialized def tupled: Tuple21[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21] => R = {
case Tuple21(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21)
}
override def toString() = "<function21>"
diff --git a/src/library/scala/Function22.scala b/src/library/scala/Function22.scala
index e708f7f49a..1f70b190a6 100644
--- a/src/library/scala/Function22.scala
+++ b/src/library/scala/Function22.scala
@@ -21,16 +21,17 @@ trait Function22[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, -T10, -T11, -T12,
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9)(x10)(x11)(x12)(x13)(x14)(x15)(x16)(x17)(x18)(x19)(x20)(x21)(x22) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => T22 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => T10 => T11 => T12 => T13 => T14 => T15 => T16 => T17 => T18 => T19 => T20 => T21 => T22 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9, x10: T10, x11: T11, x12: T12, x13: T13, x14: T14, x15: T15, x16: T16, x17: T17, x18: T18, x19: T19, x20: T20, x21: T21, x22: T22) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)).curried
}
-
/** Creates a tupled version of this function: instead of 22 arguments,
* it accepts a single [[scala.Tuple22]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)) == f(Tuple22(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)`
*/
- def tupled: Tuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22] => R = {
+
+ @annotation.unspecialized def tupled: Tuple22[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22] => R = {
case Tuple22(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22)
}
override def toString() = "<function22>"
diff --git a/src/library/scala/Function3.scala b/src/library/scala/Function3.scala
index 62a997c1b5..bbbde82056 100644
--- a/src/library/scala/Function3.scala
+++ b/src/library/scala/Function3.scala
@@ -21,16 +21,17 @@ trait Function3[-T1, -T2, -T3, +R] extends AnyRef { self =>
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3) == apply(x1, x2, x3)`
- */ def curried: T1 => T2 => T3 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => R = {
(x1: T1) => (x2: T2) => (x3: T3) => apply(x1, x2, x3)
}
-
/** Creates a tupled version of this function: instead of 3 arguments,
* it accepts a single [[scala.Tuple3]] argument.
*
* @return a function `f` such that `f((x1, x2, x3)) == f(Tuple3(x1, x2, x3)) == apply(x1, x2, x3)`
*/
- def tupled: Tuple3[T1, T2, T3] => R = {
+
+ @annotation.unspecialized def tupled: Tuple3[T1, T2, T3] => R = {
case Tuple3(x1, x2, x3) => apply(x1, x2, x3)
}
override def toString() = "<function3>"
diff --git a/src/library/scala/Function4.scala b/src/library/scala/Function4.scala
index 86d2faeac8..f100860a97 100644
--- a/src/library/scala/Function4.scala
+++ b/src/library/scala/Function4.scala
@@ -21,16 +21,17 @@ trait Function4[-T1, -T2, -T3, -T4, +R] extends AnyRef { self =>
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4) == apply(x1, x2, x3, x4)`
- */ def curried: T1 => T2 => T3 => T4 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => R = {
(x1: T1) => (x2: T2) => (x3: T3) => (x4: T4) => apply(x1, x2, x3, x4)
}
-
/** Creates a tupled version of this function: instead of 4 arguments,
* it accepts a single [[scala.Tuple4]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4)) == f(Tuple4(x1, x2, x3, x4)) == apply(x1, x2, x3, x4)`
*/
- def tupled: Tuple4[T1, T2, T3, T4] => R = {
+
+ @annotation.unspecialized def tupled: Tuple4[T1, T2, T3, T4] => R = {
case Tuple4(x1, x2, x3, x4) => apply(x1, x2, x3, x4)
}
override def toString() = "<function4>"
diff --git a/src/library/scala/Function5.scala b/src/library/scala/Function5.scala
index bd9af77f12..cba9b6ce52 100644
--- a/src/library/scala/Function5.scala
+++ b/src/library/scala/Function5.scala
@@ -21,16 +21,17 @@ trait Function5[-T1, -T2, -T3, -T4, -T5, +R] extends AnyRef { self =>
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5) == apply(x1, x2, x3, x4, x5)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5) => self.apply(x1, x2, x3, x4, x5)).curried
}
-
/** Creates a tupled version of this function: instead of 5 arguments,
* it accepts a single [[scala.Tuple5]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5)) == f(Tuple5(x1, x2, x3, x4, x5)) == apply(x1, x2, x3, x4, x5)`
*/
- def tupled: Tuple5[T1, T2, T3, T4, T5] => R = {
+
+ @annotation.unspecialized def tupled: Tuple5[T1, T2, T3, T4, T5] => R = {
case Tuple5(x1, x2, x3, x4, x5) => apply(x1, x2, x3, x4, x5)
}
override def toString() = "<function5>"
diff --git a/src/library/scala/Function6.scala b/src/library/scala/Function6.scala
index 4f601a468c..0b8addf7de 100644
--- a/src/library/scala/Function6.scala
+++ b/src/library/scala/Function6.scala
@@ -21,16 +21,17 @@ trait Function6[-T1, -T2, -T3, -T4, -T5, -T6, +R] extends AnyRef { self =>
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6) == apply(x1, x2, x3, x4, x5, x6)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6) => self.apply(x1, x2, x3, x4, x5, x6)).curried
}
-
/** Creates a tupled version of this function: instead of 6 arguments,
* it accepts a single [[scala.Tuple6]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6)) == f(Tuple6(x1, x2, x3, x4, x5, x6)) == apply(x1, x2, x3, x4, x5, x6)`
*/
- def tupled: Tuple6[T1, T2, T3, T4, T5, T6] => R = {
+
+ @annotation.unspecialized def tupled: Tuple6[T1, T2, T3, T4, T5, T6] => R = {
case Tuple6(x1, x2, x3, x4, x5, x6) => apply(x1, x2, x3, x4, x5, x6)
}
override def toString() = "<function6>"
diff --git a/src/library/scala/Function7.scala b/src/library/scala/Function7.scala
index 6978b6545d..2098658fa9 100644
--- a/src/library/scala/Function7.scala
+++ b/src/library/scala/Function7.scala
@@ -21,16 +21,17 @@ trait Function7[-T1, -T2, -T3, -T4, -T5, -T6, -T7, +R] extends AnyRef { self =>
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7) == apply(x1, x2, x3, x4, x5, x6, x7)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7) => self.apply(x1, x2, x3, x4, x5, x6, x7)).curried
}
-
/** Creates a tupled version of this function: instead of 7 arguments,
* it accepts a single [[scala.Tuple7]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7)) == f(Tuple7(x1, x2, x3, x4, x5, x6, x7)) == apply(x1, x2, x3, x4, x5, x6, x7)`
*/
- def tupled: Tuple7[T1, T2, T3, T4, T5, T6, T7] => R = {
+
+ @annotation.unspecialized def tupled: Tuple7[T1, T2, T3, T4, T5, T6, T7] => R = {
case Tuple7(x1, x2, x3, x4, x5, x6, x7) => apply(x1, x2, x3, x4, x5, x6, x7)
}
override def toString() = "<function7>"
diff --git a/src/library/scala/Function8.scala b/src/library/scala/Function8.scala
index 903551d939..08a480dce5 100644
--- a/src/library/scala/Function8.scala
+++ b/src/library/scala/Function8.scala
@@ -21,16 +21,17 @@ trait Function8[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, +R] extends AnyRef { sel
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8) == apply(x1, x2, x3, x4, x5, x6, x7, x8)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8)).curried
}
-
/** Creates a tupled version of this function: instead of 8 arguments,
* it accepts a single [[scala.Tuple8]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8)) == f(Tuple8(x1, x2, x3, x4, x5, x6, x7, x8)) == apply(x1, x2, x3, x4, x5, x6, x7, x8)`
*/
- def tupled: Tuple8[T1, T2, T3, T4, T5, T6, T7, T8] => R = {
+
+ @annotation.unspecialized def tupled: Tuple8[T1, T2, T3, T4, T5, T6, T7, T8] => R = {
case Tuple8(x1, x2, x3, x4, x5, x6, x7, x8) => apply(x1, x2, x3, x4, x5, x6, x7, x8)
}
override def toString() = "<function8>"
diff --git a/src/library/scala/Function9.scala b/src/library/scala/Function9.scala
index 0c273ba929..2e35f7949c 100644
--- a/src/library/scala/Function9.scala
+++ b/src/library/scala/Function9.scala
@@ -21,16 +21,17 @@ trait Function9[-T1, -T2, -T3, -T4, -T5, -T6, -T7, -T8, -T9, +R] extends AnyRef
/** Creates a curried version of this function.
*
* @return a function `f` such that `f(x1)(x2)(x3)(x4)(x5)(x6)(x7)(x8)(x9) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)`
- */ def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => R = {
+ */
+ @annotation.unspecialized def curried: T1 => T2 => T3 => T4 => T5 => T6 => T7 => T8 => T9 => R = {
(x1: T1) => ((x2: T2, x3: T3, x4: T4, x5: T5, x6: T6, x7: T7, x8: T8, x9: T9) => self.apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)).curried
}
-
/** Creates a tupled version of this function: instead of 9 arguments,
* it accepts a single [[scala.Tuple9]] argument.
*
* @return a function `f` such that `f((x1, x2, x3, x4, x5, x6, x7, x8, x9)) == f(Tuple9(x1, x2, x3, x4, x5, x6, x7, x8, x9)) == apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)`
*/
- def tupled: Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9] => R = {
+
+ @annotation.unspecialized def tupled: Tuple9[T1, T2, T3, T4, T5, T6, T7, T8, T9] => R = {
case Tuple9(x1, x2, x3, x4, x5, x6, x7, x8, x9) => apply(x1, x2, x3, x4, x5, x6, x7, x8, x9)
}
override def toString() = "<function9>"
diff --git a/src/library/scala/Int.scala b/src/library/scala/Int.scala
index 316bbced2d..d5d7ef011d 100644
--- a/src/library/scala/Int.scala
+++ b/src/library/scala/Int.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Int]] => [[scala.runtime.RichInt]]
* which provides useful non-primitive operations.
*/
-final class Int extends AnyVal {
+final class Int private extends AnyVal {
def toByte: Byte = sys.error("stub")
def toShort: Short = sys.error("stub")
def toChar: Char = sys.error("stub")
@@ -27,7 +27,7 @@ final class Int extends AnyVal {
def toDouble: Double = sys.error("stub")
/**
- * @return the bitwise negation of this value
+ * Returns the bitwise negation of this value.
* @example {{{
* ~5 == -6
* // in binary: ~00000101 ==
@@ -36,30 +36,30 @@ final class Int extends AnyVal {
*/
def unary_~ : Int = sys.error("stub")
/**
- * @return this value, unmodified
+ * Returns this value, unmodified.
*/
def unary_+ : Int = sys.error("stub")
/**
- * @return the negation of this value
+ * Returns the negation of this value.
*/
def unary_- : Int = sys.error("stub")
def +(x: String): String = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -70,7 +70,7 @@ final class Int extends AnyVal {
*/
def >>>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -81,7 +81,7 @@ final class Int extends AnyVal {
*/
def >>>(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -92,7 +92,7 @@ final class Int extends AnyVal {
*/
def >>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -104,181 +104,181 @@ final class Int extends AnyVal {
def >>(x: Long): Int = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Double): Boolean = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -289,7 +289,7 @@ final class Int extends AnyVal {
*/
def |(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -300,7 +300,7 @@ final class Int extends AnyVal {
*/
def |(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -311,7 +311,7 @@ final class Int extends AnyVal {
*/
def |(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -322,7 +322,7 @@ final class Int extends AnyVal {
*/
def |(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -334,7 +334,7 @@ final class Int extends AnyVal {
def |(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -345,7 +345,7 @@ final class Int extends AnyVal {
*/
def &(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -356,7 +356,7 @@ final class Int extends AnyVal {
*/
def &(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -367,7 +367,7 @@ final class Int extends AnyVal {
*/
def &(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -378,7 +378,7 @@ final class Int extends AnyVal {
*/
def &(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -390,7 +390,7 @@ final class Int extends AnyVal {
def &(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -401,7 +401,7 @@ final class Int extends AnyVal {
*/
def ^(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -412,7 +412,7 @@ final class Int extends AnyVal {
*/
def ^(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -423,7 +423,7 @@ final class Int extends AnyVal {
*/
def ^(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -434,7 +434,7 @@ final class Int extends AnyVal {
*/
def ^(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -446,154 +446,154 @@ final class Int extends AnyVal {
def ^(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Byte): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Short): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Char): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Int): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Float): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Double): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Byte): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Short): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Char): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Int): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Long): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Float): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Double): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Byte): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Short): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Char): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Int): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Long): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Float): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Double): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Byte): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Short): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Char): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Int): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Long): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Float): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Double): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Byte): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Short): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Char): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Int): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Long): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Float): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Double): Double = sys.error("stub")
override def getClass(): Class[Int] = sys.error("stub")
}
-object Int extends AnyValCompanion {
+object Int extends AnyValCompanion {
/** The smallest value representable as a Int.
*/
final val MinValue = java.lang.Integer.MIN_VALUE
@@ -622,5 +622,8 @@ object Int extends AnyValCompanion {
/** The String representation of the scala.Int companion object.
*/
override def toString = "object scala.Int"
+ implicit def int2long(x: Int): Long = x.toLong
+ implicit def int2float(x: Int): Float = x.toFloat
+ implicit def int2double(x: Int): Double = x.toDouble
}
diff --git a/src/library/scala/Long.scala b/src/library/scala/Long.scala
index ce8618c22a..85131b4f54 100644
--- a/src/library/scala/Long.scala
+++ b/src/library/scala/Long.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Long]] => [[scala.runtime.RichLong]]
* which provides useful non-primitive operations.
*/
-final class Long extends AnyVal {
+final class Long private extends AnyVal {
def toByte: Byte = sys.error("stub")
def toShort: Short = sys.error("stub")
def toChar: Char = sys.error("stub")
@@ -27,7 +27,7 @@ final class Long extends AnyVal {
def toDouble: Double = sys.error("stub")
/**
- * @return the bitwise negation of this value
+ * Returns the bitwise negation of this value.
* @example {{{
* ~5 == -6
* // in binary: ~00000101 ==
@@ -36,30 +36,30 @@ final class Long extends AnyVal {
*/
def unary_~ : Long = sys.error("stub")
/**
- * @return this value, unmodified
+ * Returns this value, unmodified.
*/
def unary_+ : Long = sys.error("stub")
/**
- * @return the negation of this value
+ * Returns the negation of this value.
*/
def unary_- : Long = sys.error("stub")
def +(x: String): String = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Int): Long = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Long): Long = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -70,7 +70,7 @@ final class Long extends AnyVal {
*/
def >>>(x: Int): Long = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -81,7 +81,7 @@ final class Long extends AnyVal {
*/
def >>>(x: Long): Long = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -92,7 +92,7 @@ final class Long extends AnyVal {
*/
def >>(x: Int): Long = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -104,181 +104,181 @@ final class Long extends AnyVal {
def >>(x: Long): Long = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Double): Boolean = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -289,7 +289,7 @@ final class Long extends AnyVal {
*/
def |(x: Byte): Long = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -300,7 +300,7 @@ final class Long extends AnyVal {
*/
def |(x: Short): Long = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -311,7 +311,7 @@ final class Long extends AnyVal {
*/
def |(x: Char): Long = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -322,7 +322,7 @@ final class Long extends AnyVal {
*/
def |(x: Int): Long = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -334,7 +334,7 @@ final class Long extends AnyVal {
def |(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -345,7 +345,7 @@ final class Long extends AnyVal {
*/
def &(x: Byte): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -356,7 +356,7 @@ final class Long extends AnyVal {
*/
def &(x: Short): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -367,7 +367,7 @@ final class Long extends AnyVal {
*/
def &(x: Char): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -378,7 +378,7 @@ final class Long extends AnyVal {
*/
def &(x: Int): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -390,7 +390,7 @@ final class Long extends AnyVal {
def &(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -401,7 +401,7 @@ final class Long extends AnyVal {
*/
def ^(x: Byte): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -412,7 +412,7 @@ final class Long extends AnyVal {
*/
def ^(x: Short): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -423,7 +423,7 @@ final class Long extends AnyVal {
*/
def ^(x: Char): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -434,7 +434,7 @@ final class Long extends AnyVal {
*/
def ^(x: Int): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -446,154 +446,154 @@ final class Long extends AnyVal {
def ^(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Byte): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Short): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Char): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Int): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Float): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Double): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Byte): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Short): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Char): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Int): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Long): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Float): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Double): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Byte): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Short): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Char): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Int): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Long): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Float): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Double): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Byte): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Short): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Char): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Int): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Long): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Float): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Double): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Byte): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Short): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Char): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Int): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Long): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Float): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Double): Double = sys.error("stub")
override def getClass(): Class[Long] = sys.error("stub")
}
-object Long extends AnyValCompanion {
+object Long extends AnyValCompanion {
/** The smallest value representable as a Long.
*/
final val MinValue = java.lang.Long.MIN_VALUE
@@ -622,5 +622,7 @@ object Long extends AnyValCompanion {
/** The String representation of the scala.Long companion object.
*/
override def toString = "object scala.Long"
+ implicit def long2float(x: Long): Float = x.toFloat
+ implicit def long2double(x: Long): Double = x.toDouble
}
diff --git a/src/library/scala/LowPriorityImplicits.scala b/src/library/scala/LowPriorityImplicits.scala
index 447a3c3819..491cd417a3 100644
--- a/src/library/scala/LowPriorityImplicits.scala
+++ b/src/library/scala/LowPriorityImplicits.scala
@@ -12,6 +12,7 @@ import scala.collection.{ mutable, immutable, generic }
import mutable.WrappedArray
import immutable.WrappedString
import generic.CanBuildFrom
+import language.implicitConversions
/** The `LowPriorityImplicits` class provides implicit values that
* are valid in all Scala compilation units without explicit qualification,
diff --git a/src/library/scala/Option.scala b/src/library/scala/Option.scala
index 6db4904b93..44c8fba45f 100644
--- a/src/library/scala/Option.scala
+++ b/src/library/scala/Option.scala
@@ -9,6 +9,9 @@
package scala
object Option {
+
+ import language.implicitConversions
+
/** An implicit conversion that converts an option to an iterable value
*/
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList
@@ -79,6 +82,17 @@ object Option {
* @define option [[scala.Option]]
* @define p `p`
* @define f `f`
+ * @define coll option
+ * @define Coll `Option`
+ * @define orderDependent
+ * @define orderDependentFold
+ * @define mayNotTerminateInf
+ * @define willNotTerminateInf
+ * @define collectExample
+ * @define undefinedorder
+ * @define thatinfo the class of the returned collection. In the standard library configuration, `That` is `Iterable[B]`
+ * @define bfinfo an implicit value of class `CanBuildFrom` which determines the result class `That` from the current
+ * representation type `Repr` and the new element type `B`.
*/
sealed abstract class Option[+A] extends Product with Serializable {
self =>
@@ -130,6 +144,18 @@ sealed abstract class Option[+A] extends Product with Serializable {
@inline final def map[B](f: A => B): Option[B] =
if (isEmpty) None else Some(f(this.get))
+ /** Returns the result of applying $f to this $option's
+ * value if the $option is nonempty. Otherwise, evaluates
+ * expression $ifEmpty.
+ *
+ * @note This is equivalent to `$option map f getOrElse ifEmpty`.
+ *
+ * @param ifEmpty the expression to evaluate if empty.
+ * @param f the function to apply if nonempty.
+ */
+ @inline final def fold[B](ifEmpty: => B)(f: A => B): B =
+ if (isEmpty) ifEmpty else f(this.get)
+
/** Returns the result of applying $f to this $option's value if
* this $option is nonempty.
* Returns $none if this $option is empty.
diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala
index b5006e7948..500ee87c46 100644
--- a/src/library/scala/Predef.scala
+++ b/src/library/scala/Predef.scala
@@ -14,6 +14,7 @@ import mutable.ArrayOps
import generic.CanBuildFrom
import annotation.{ elidable, implicitNotFound }
import annotation.elidable.ASSERTION
+import language.{implicitConversions, existentials}
/** The `Predef` object provides definitions that are accessible in all Scala
* compilation units without explicit qualification.
@@ -100,8 +101,8 @@ object Predef extends LowPriorityImplicits {
// Manifest types, companions, and incantations for summoning
type ClassManifest[T] = scala.reflect.ClassManifest[T]
- type Manifest[T] = scala.reflect.Manifest[T]
type OptManifest[T] = scala.reflect.OptManifest[T]
+ type Manifest[T] = scala.reflect.Manifest[T]
val ClassManifest = scala.reflect.ClassManifest
val Manifest = scala.reflect.Manifest
val NoManifest = scala.reflect.NoManifest
@@ -110,6 +111,26 @@ object Predef extends LowPriorityImplicits {
def classManifest[T](implicit m: ClassManifest[T]) = m
def optManifest[T](implicit m: OptManifest[T]) = m
+ // Tag types and companions, and incantations for summoning
+ type ArrayTag[T] = scala.reflect.ArrayTag[T]
+ type ErasureTag[T] = scala.reflect.ErasureTag[T]
+ type ClassTag[T] = scala.reflect.ClassTag[T]
+ type TypeTag[T] = scala.reflect.TypeTag[T]
+ type ConcreteTypeTag[T] = scala.reflect.ConcreteTypeTag[T]
+ val ClassTag = scala.reflect.ClassTag // doesn't need to be lazy, because it's not a path-dependent type
+ // [Paul to Eugene] No lazy vals in Predef. Too expensive. Have to work harder on breaking initialization dependencies.
+ lazy val TypeTag = scala.reflect.TypeTag // needs to be lazy, because requires scala.reflect.mirror instance
+ lazy val ConcreteTypeTag = scala.reflect.ConcreteTypeTag
+
+ // [Eugene to Martin] it's really tedious to type "implicitly[...]" all the time, so I'm reintroducing these shortcuts
+ def arrayTag[T](implicit atag: ArrayTag[T]) = atag
+ def erasureTag[T](implicit etag: ErasureTag[T]) = etag
+ def classTag[T](implicit ctag: ClassTag[T]) = ctag
+ def tag[T](implicit ttag: TypeTag[T]) = ttag
+ def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+ def concreteTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
+ def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
+
// Minor variations on identity functions
def identity[A](x: A): A = x // @see `conforms` for the implicit version
@inline def implicitly[T](implicit e: T) = e // for summoning implicit values from the nether world -- TODO: when dependent method types are on by default, give this result type `e.type`, so that inliner has better chance of knowing which method to inline in calls like `implicitly[MatchingStrategy[Option]].zero`
@@ -286,69 +307,63 @@ object Predef extends LowPriorityImplicits {
// views --------------------------------------------------------------
- implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc)
-
- implicit def zipped2ToTraversable[El1, El2](zz: Tuple2[_, _]#Zipped[_, El1, _, El2]): Traversable[(El1, El2)] =
- new collection.AbstractTraversable[(El1, El2)] {
- def foreach[U](f: ((El1, El2)) => U): Unit = zz foreach Function.untupled(f)
- }
-
- implicit def zipped3ToTraversable[El1, El2, El3](zz: Tuple3[_, _, _]#Zipped[_, El1, _, El2, _, El3]): Traversable[(El1, El2, El3)] =
- new collection.AbstractTraversable[(El1, El2, El3)] {
- def foreach[U](f: ((El1, El2, El3)) => U): Unit = zz foreach Function.untupled(f)
- }
-
- implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = xs match {
- case x: Array[AnyRef] => refArrayOps[AnyRef](x).asInstanceOf[ArrayOps[T]]
- case x: Array[Int] => intArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Double] => doubleArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Long] => longArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Float] => floatArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Char] => charArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Byte] => byteArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Short] => shortArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Boolean] => booleanArrayOps(x).asInstanceOf[ArrayOps[T]]
- case x: Array[Unit] => unitArrayOps(x).asInstanceOf[ArrayOps[T]]
+ implicit def exceptionWrapper(exc: Throwable) = new runtime.RichException(exc)
+ implicit def tuple2ToZippedOps[T1, T2](x: (T1, T2)) = new runtime.Tuple2Zipped.Ops(x)
+ implicit def tuple3ToZippedOps[T1, T2, T3](x: (T1, T2, T3)) = new runtime.Tuple3Zipped.Ops(x)
+ implicit def seqToCharSequence(xs: collection.IndexedSeq[Char]): CharSequence = new runtime.SeqCharSequence(xs)
+ implicit def arrayToCharSequence(xs: Array[Char]): CharSequence = new runtime.ArrayCharSequence(xs, 0, xs.length)
+
+ implicit def genericArrayOps[T](xs: Array[T]): ArrayOps[T] = (xs match {
+ case x: Array[AnyRef] => refArrayOps[AnyRef](x)
+ case x: Array[Boolean] => booleanArrayOps(x)
+ case x: Array[Byte] => byteArrayOps(x)
+ case x: Array[Char] => charArrayOps(x)
+ case x: Array[Double] => doubleArrayOps(x)
+ case x: Array[Float] => floatArrayOps(x)
+ case x: Array[Int] => intArrayOps(x)
+ case x: Array[Long] => longArrayOps(x)
+ case x: Array[Short] => shortArrayOps(x)
+ case x: Array[Unit] => unitArrayOps(x)
case null => null
- }
+ }).asInstanceOf[ArrayOps[T]]
- implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs)
- implicit def intArrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs)
- implicit def doubleArrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs)
- implicit def longArrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs)
- implicit def floatArrayOps(xs: Array[Float]): ArrayOps[Float] = new ArrayOps.ofFloat(xs)
- implicit def charArrayOps(xs: Array[Char]): ArrayOps[Char] = new ArrayOps.ofChar(xs)
- implicit def byteArrayOps(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps.ofByte(xs)
- implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs)
implicit def booleanArrayOps(xs: Array[Boolean]): ArrayOps[Boolean] = new ArrayOps.ofBoolean(xs)
- implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs)
+ implicit def byteArrayOps(xs: Array[Byte]): ArrayOps[Byte] = new ArrayOps.ofByte(xs)
+ implicit def charArrayOps(xs: Array[Char]): ArrayOps[Char] = new ArrayOps.ofChar(xs)
+ implicit def doubleArrayOps(xs: Array[Double]): ArrayOps[Double] = new ArrayOps.ofDouble(xs)
+ implicit def floatArrayOps(xs: Array[Float]): ArrayOps[Float] = new ArrayOps.ofFloat(xs)
+ implicit def intArrayOps(xs: Array[Int]): ArrayOps[Int] = new ArrayOps.ofInt(xs)
+ implicit def longArrayOps(xs: Array[Long]): ArrayOps[Long] = new ArrayOps.ofLong(xs)
+ implicit def refArrayOps[T <: AnyRef](xs: Array[T]): ArrayOps[T] = new ArrayOps.ofRef[T](xs)
+ implicit def shortArrayOps(xs: Array[Short]): ArrayOps[Short] = new ArrayOps.ofShort(xs)
+ implicit def unitArrayOps(xs: Array[Unit]): ArrayOps[Unit] = new ArrayOps.ofUnit(xs)
// Primitive Widenings --------------------------------------------------------------
- implicit def byte2short(x: Byte): Short = x.toShort
- implicit def byte2int(x: Byte): Int = x.toInt
- implicit def byte2long(x: Byte): Long = x.toLong
- implicit def byte2float(x: Byte): Float = x.toFloat
- implicit def byte2double(x: Byte): Double = x.toDouble
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def byte2short(x: Byte): Short = x.toShort
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def byte2int(x: Byte): Int = x.toInt
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def byte2long(x: Byte): Long = x.toLong
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def byte2float(x: Byte): Float = x.toFloat
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def byte2double(x: Byte): Double = x.toDouble
- implicit def short2int(x: Short): Int = x.toInt
- implicit def short2long(x: Short): Long = x.toLong
- implicit def short2float(x: Short): Float = x.toFloat
- implicit def short2double(x: Short): Double = x.toDouble
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def short2int(x: Short): Int = x.toInt
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def short2long(x: Short): Long = x.toLong
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def short2float(x: Short): Float = x.toFloat
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def short2double(x: Short): Double = x.toDouble
- implicit def char2int(x: Char): Int = x.toInt
- implicit def char2long(x: Char): Long = x.toLong
- implicit def char2float(x: Char): Float = x.toFloat
- implicit def char2double(x: Char): Double = x.toDouble
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def char2int(x: Char): Int = x.toInt
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def char2long(x: Char): Long = x.toLong
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def char2float(x: Char): Float = x.toFloat
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def char2double(x: Char): Double = x.toDouble
- implicit def int2long(x: Int): Long = x.toLong
- implicit def int2float(x: Int): Float = x.toFloat
- implicit def int2double(x: Int): Double = x.toDouble
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def int2long(x: Int): Long = x.toLong
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def int2float(x: Int): Float = x.toFloat
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def int2double(x: Int): Double = x.toDouble
- implicit def long2float(x: Long): Float = x.toFloat
- implicit def long2double(x: Long): Double = x.toDouble
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def long2float(x: Long): Float = x.toFloat
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def long2double(x: Long): Double = x.toDouble
- implicit def float2double(x: Float): Double = x.toDouble
+ @deprecated("Use a method in an AnyVal's companion object", "2.10.0") def float2double(x: Float): Double = x.toDouble
// "Autoboxing" and "Autounboxing" ---------------------------------------------------
@@ -385,29 +400,17 @@ object Predef extends LowPriorityImplicits {
// Strings and CharSequences --------------------------------------------------------------
- implicit def any2stringadd(x: Any) = new runtime.StringAdd(x)
@inline implicit def any2stringfmt(x: Any) = new runtime.StringFormat(x)
@inline implicit def augmentString(x: String): StringOps = new StringOps(x)
+ implicit def any2stringadd(x: Any) = new runtime.StringAdd(x)
implicit def unaugmentString(x: StringOps): String = x.repr
- implicit def stringCanBuildFrom: CanBuildFrom[String, Char, String] =
- new CanBuildFrom[String, Char, String] {
- def apply(from: String) = apply()
- def apply() = mutable.StringBuilder.newBuilder
- }
-
- implicit def seqToCharSequence(xs: collection.IndexedSeq[Char]): CharSequence = new CharSequence {
- def length: Int = xs.length
- def charAt(index: Int): Char = xs(index)
- def subSequence(start: Int, end: Int): CharSequence = seqToCharSequence(xs.slice(start, end))
- override def toString: String = xs.mkString("")
- }
+ @deprecated("Use StringCanBuildFrom", "2.10.0")
+ def stringCanBuildFrom: CanBuildFrom[String, Char, String] = StringCanBuildFrom
- implicit def arrayToCharSequence(xs: Array[Char]): CharSequence = new CharSequence {
- def length: Int = xs.length
- def charAt(index: Int): Char = xs(index)
- def subSequence(start: Int, end: Int): CharSequence = arrayToCharSequence(xs.slice(start, end))
- override def toString: String = xs.mkString("")
+ implicit val StringCanBuildFrom: CanBuildFrom[String, Char, String] = new CanBuildFrom[String, Char, String] {
+ def apply(from: String) = apply()
+ def apply() = mutable.StringBuilder.newBuilder
}
// Type Constraints --------------------------------------------------------------
@@ -447,13 +450,6 @@ object Predef extends LowPriorityImplicits {
implicit def tpEquals[A]: A =:= A = singleton_=:=.asInstanceOf[A =:= A]
}
- // less useful due to #2781
- @deprecated("Use From => To instead", "2.9.0")
- sealed abstract class <%<[-From, +To] extends (From => To) with Serializable
- object <%< {
- implicit def conformsOrViewsAs[A <% B, B]: A <%< B = new (A <%< B) {def apply(x: A) = x}
- }
-
/** A type for which there is always an implicit value.
* @see fallbackCanBuildFrom in Array.scala
*/
diff --git a/src/library/scala/Product1.scala b/src/library/scala/Product1.scala
index d268b35f60..edd095c5c6 100644
--- a/src/library/scala/Product1.scala
+++ b/src/library/scala/Product1.scala
@@ -28,7 +28,7 @@ trait Product1[@specialized(Int, Long, Double) +T1] extends Any with Product {
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product10.scala b/src/library/scala/Product10.scala
index cae9e5a664..8daefde699 100644
--- a/src/library/scala/Product10.scala
+++ b/src/library/scala/Product10.scala
@@ -28,7 +28,7 @@ trait Product10[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10] extends Any w
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product11.scala b/src/library/scala/Product11.scala
index 0647b28414..90b4e8013e 100644
--- a/src/library/scala/Product11.scala
+++ b/src/library/scala/Product11.scala
@@ -28,7 +28,7 @@ trait Product11[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11] extends
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product12.scala b/src/library/scala/Product12.scala
index a080aafa7a..d5997ea05a 100644
--- a/src/library/scala/Product12.scala
+++ b/src/library/scala/Product12.scala
@@ -28,7 +28,7 @@ trait Product12[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12] e
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product13.scala b/src/library/scala/Product13.scala
index 425aebf3e7..db8e0f3722 100644
--- a/src/library/scala/Product13.scala
+++ b/src/library/scala/Product13.scala
@@ -28,7 +28,7 @@ trait Product13[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product14.scala b/src/library/scala/Product14.scala
index 3d7e4896ef..113c07e8c4 100644
--- a/src/library/scala/Product14.scala
+++ b/src/library/scala/Product14.scala
@@ -28,7 +28,7 @@ trait Product14[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product15.scala b/src/library/scala/Product15.scala
index 7bca7a2a1b..a6ad9c7594 100644
--- a/src/library/scala/Product15.scala
+++ b/src/library/scala/Product15.scala
@@ -28,7 +28,7 @@ trait Product15[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product16.scala b/src/library/scala/Product16.scala
index c5042cbc90..cbf47ece94 100644
--- a/src/library/scala/Product16.scala
+++ b/src/library/scala/Product16.scala
@@ -28,7 +28,7 @@ trait Product16[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product17.scala b/src/library/scala/Product17.scala
index b5651ec712..f56836bfd8 100644
--- a/src/library/scala/Product17.scala
+++ b/src/library/scala/Product17.scala
@@ -28,7 +28,7 @@ trait Product17[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product18.scala b/src/library/scala/Product18.scala
index 088a48ae32..5b86bcff65 100644
--- a/src/library/scala/Product18.scala
+++ b/src/library/scala/Product18.scala
@@ -28,7 +28,7 @@ trait Product18[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product19.scala b/src/library/scala/Product19.scala
index 4f4a98c6a0..ed4bf36c93 100644
--- a/src/library/scala/Product19.scala
+++ b/src/library/scala/Product19.scala
@@ -28,7 +28,7 @@ trait Product19[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product2.scala b/src/library/scala/Product2.scala
index eb67e5d46e..e27e54eff9 100644
--- a/src/library/scala/Product2.scala
+++ b/src/library/scala/Product2.scala
@@ -28,7 +28,7 @@ trait Product2[@specialized(Int, Long, Double) +T1, @specialized(Int, Long, Doub
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product20.scala b/src/library/scala/Product20.scala
index 80f63f1bb4..47437a20af 100644
--- a/src/library/scala/Product20.scala
+++ b/src/library/scala/Product20.scala
@@ -28,7 +28,7 @@ trait Product20[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product21.scala b/src/library/scala/Product21.scala
index 7056844271..319d2725c0 100644
--- a/src/library/scala/Product21.scala
+++ b/src/library/scala/Product21.scala
@@ -28,7 +28,7 @@ trait Product21[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product22.scala b/src/library/scala/Product22.scala
index 05e95f92dd..6ab3737acd 100644
--- a/src/library/scala/Product22.scala
+++ b/src/library/scala/Product22.scala
@@ -28,7 +28,7 @@ trait Product22[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9, +T10, +T11, +T12, +
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product3.scala b/src/library/scala/Product3.scala
index 91556bb962..1cfbd7956b 100644
--- a/src/library/scala/Product3.scala
+++ b/src/library/scala/Product3.scala
@@ -28,7 +28,7 @@ trait Product3[+T1, +T2, +T3] extends Any with Product {
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product4.scala b/src/library/scala/Product4.scala
index 1f9070c155..843571fd60 100644
--- a/src/library/scala/Product4.scala
+++ b/src/library/scala/Product4.scala
@@ -28,7 +28,7 @@ trait Product4[+T1, +T2, +T3, +T4] extends Any with Product {
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product5.scala b/src/library/scala/Product5.scala
index 52dd284f55..df73bba3dd 100644
--- a/src/library/scala/Product5.scala
+++ b/src/library/scala/Product5.scala
@@ -28,7 +28,7 @@ trait Product5[+T1, +T2, +T3, +T4, +T5] extends Any with Product {
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product6.scala b/src/library/scala/Product6.scala
index 9624bdbe3e..36906ca54e 100644
--- a/src/library/scala/Product6.scala
+++ b/src/library/scala/Product6.scala
@@ -28,7 +28,7 @@ trait Product6[+T1, +T2, +T3, +T4, +T5, +T6] extends Any with Product {
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product7.scala b/src/library/scala/Product7.scala
index 36d4b149db..e7b2c13ad1 100644
--- a/src/library/scala/Product7.scala
+++ b/src/library/scala/Product7.scala
@@ -28,7 +28,7 @@ trait Product7[+T1, +T2, +T3, +T4, +T5, +T6, +T7] extends Any with Product {
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product8.scala b/src/library/scala/Product8.scala
index 28c78f9c89..916e57ec39 100644
--- a/src/library/scala/Product8.scala
+++ b/src/library/scala/Product8.scala
@@ -28,7 +28,7 @@ trait Product8[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8] extends Any with Product
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/library/scala/Product9.scala b/src/library/scala/Product9.scala
index d69c550abe..d5e72edc0b 100644
--- a/src/library/scala/Product9.scala
+++ b/src/library/scala/Product9.scala
@@ -28,7 +28,7 @@ trait Product9[+T1, +T2, +T3, +T4, +T5, +T6, +T7, +T8, +T9] extends Any with Pro
* otherwise throws an `IndexOutOfBoundsException`.
*
* @param n number of the projection to be returned
- * @return same as `._(n+1)`, for example `productElement(1)` is the same as `._1`.
+ * @return same as `._(n+1)`, for example `productElement(0)` is the same as `._1`.
* @throws IndexOutOfBoundsException
*/
diff --git a/src/dbc/scala/dbc/statement/Statement.scala b/src/library/scala/ScalaObject.scala
index fc5374262d..7cd64becbe 100644
--- a/src/dbc/scala/dbc/statement/Statement.scala
+++ b/src/library/scala/ScalaObject.scala
@@ -6,11 +6,11 @@
** |/ **
\* */
+package scala
-
-package scala.dbc
-package statement
-
-
-/** An ISO-9075:2003 (SQL) statement. */
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class Statement
+/** Until scala 2.10.0 this marker trait was added to
+ * scala-compiled classes. Now it only exists for backward
+ * compatibility.
+ */
+@deprecated("ScalaObject will be removed", "2.10.0")
+trait ScalaObject
diff --git a/src/library/scala/Short.scala b/src/library/scala/Short.scala
index 5664c3b44c..1060a9db16 100644
--- a/src/library/scala/Short.scala
+++ b/src/library/scala/Short.scala
@@ -17,7 +17,7 @@ package scala
* There is an implicit conversion from [[scala.Short]] => [[scala.runtime.RichShort]]
* which provides useful non-primitive operations.
*/
-final class Short extends AnyVal {
+final class Short private extends AnyVal {
def toByte: Byte = sys.error("stub")
def toShort: Short = sys.error("stub")
def toChar: Char = sys.error("stub")
@@ -27,7 +27,7 @@ final class Short extends AnyVal {
def toDouble: Double = sys.error("stub")
/**
- * @return the bitwise negation of this value
+ * Returns the bitwise negation of this value.
* @example {{{
* ~5 == -6
* // in binary: ~00000101 ==
@@ -36,30 +36,30 @@ final class Short extends AnyVal {
*/
def unary_~ : Int = sys.error("stub")
/**
- * @return this value, unmodified
+ * Returns this value, unmodified.
*/
def unary_+ : Int = sys.error("stub")
/**
- * @return the negation of this value
+ * Returns the negation of this value.
*/
def unary_- : Int = sys.error("stub")
def +(x: String): String = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the new right bits with zeroes.
* @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}
*/
def <<(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -70,7 +70,7 @@ final class Short extends AnyVal {
*/
def >>>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted right by the specified number of bits,
+ * Returns this value bit-shifted right by the specified number of bits,
* filling the new left bits with zeroes.
* @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}
* @example {{{
@@ -81,7 +81,7 @@ final class Short extends AnyVal {
*/
def >>>(x: Long): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -92,7 +92,7 @@ final class Short extends AnyVal {
*/
def >>(x: Int): Int = sys.error("stub")
/**
- * @return this value bit-shifted left by the specified number of bits,
+ * Returns this value bit-shifted left by the specified number of bits,
* filling in the right bits with the same value as the left-most bit of this.
* The effect of this is to retain the sign of the value.
* @example {{{
@@ -104,181 +104,181 @@ final class Short extends AnyVal {
def >>(x: Long): Int = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is equal x, `false` otherwise
+ * Returns `true` if this value is equal to x, `false` otherwise.
*/
def ==(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is not equal to x, `false` otherwise
+ * Returns `true` if this value is not equal to x, `false` otherwise.
*/
def !=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than x, `false` otherwise
+ * Returns `true` if this value is less than x, `false` otherwise.
*/
def <(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is less than or equal to x, `false` otherwise
+ * Returns `true` if this value is less than or equal to x, `false` otherwise.
*/
def <=(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than x, `false` otherwise
+ * Returns `true` if this value is greater than x, `false` otherwise.
*/
def >(x: Double): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Byte): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Short): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Char): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Int): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Long): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Float): Boolean = sys.error("stub")
/**
- * @return `true` if this value is greater than or equal to x, `false` otherwise
+ * Returns `true` if this value is greater than or equal to x, `false` otherwise.
*/
def >=(x: Double): Boolean = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -289,7 +289,7 @@ final class Short extends AnyVal {
*/
def |(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -300,7 +300,7 @@ final class Short extends AnyVal {
*/
def |(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -311,7 +311,7 @@ final class Short extends AnyVal {
*/
def |(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -322,7 +322,7 @@ final class Short extends AnyVal {
*/
def |(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise OR of this value and x
+ * Returns the bitwise OR of this value and `x`.
* @example {{{
* (0xf0 | 0xaa) == 0xfa
* // in binary: 11110000
@@ -334,7 +334,7 @@ final class Short extends AnyVal {
def |(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -345,7 +345,7 @@ final class Short extends AnyVal {
*/
def &(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -356,7 +356,7 @@ final class Short extends AnyVal {
*/
def &(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -367,7 +367,7 @@ final class Short extends AnyVal {
*/
def &(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -378,7 +378,7 @@ final class Short extends AnyVal {
*/
def &(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise AND of this value and x
+ * Returns the bitwise AND of this value and `x`.
* @example {{{
* (0xf0 & 0xaa) == 0xa0
* // in binary: 11110000
@@ -390,7 +390,7 @@ final class Short extends AnyVal {
def &(x: Long): Long = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -401,7 +401,7 @@ final class Short extends AnyVal {
*/
def ^(x: Byte): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -412,7 +412,7 @@ final class Short extends AnyVal {
*/
def ^(x: Short): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -423,7 +423,7 @@ final class Short extends AnyVal {
*/
def ^(x: Char): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -434,7 +434,7 @@ final class Short extends AnyVal {
*/
def ^(x: Int): Int = sys.error("stub")
/**
- * @return the bitwise XOR of this value and x
+ * Returns the bitwise XOR of this value and `x`.
* @example {{{
* (0xf0 ^ 0xaa) == 0x5a
* // in binary: 11110000
@@ -446,154 +446,154 @@ final class Short extends AnyVal {
def ^(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Byte): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Short): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Char): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Int): Int = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Long): Long = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Float): Float = sys.error("stub")
/**
- * @return the sum of this value and x
+ * Returns the sum of this value and `x`.
*/
def +(x: Double): Double = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Byte): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Short): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Char): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Int): Int = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Long): Long = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Float): Float = sys.error("stub")
/**
- * @return the difference of this value and x
+ * Returns the difference of this value and `x`.
*/
def -(x: Double): Double = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Byte): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Short): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Char): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Int): Int = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Long): Long = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Float): Float = sys.error("stub")
/**
- * @return the product of this value and x
+ * Returns the product of this value and `x`.
*/
def *(x: Double): Double = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Byte): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Short): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Char): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Int): Int = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Long): Long = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Float): Float = sys.error("stub")
/**
- * @return the quotient of this value and x
+ * Returns the quotient of this value and `x`.
*/
def /(x: Double): Double = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Byte): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Short): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Char): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Int): Int = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Long): Long = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Float): Float = sys.error("stub")
/**
- * @return the remainder of the division of this value by x
+ * Returns the remainder of the division of this value by `x`.
*/
def %(x: Double): Double = sys.error("stub")
override def getClass(): Class[Short] = sys.error("stub")
}
-object Short extends AnyValCompanion {
+object Short extends AnyValCompanion {
/** The smallest value representable as a Short.
*/
final val MinValue = java.lang.Short.MIN_VALUE
@@ -622,5 +622,9 @@ object Short extends AnyValCompanion {
/** The String representation of the scala.Short companion object.
*/
override def toString = "object scala.Short"
+ implicit def short2int(x: Short): Int = x.toInt
+ implicit def short2long(x: Short): Long = x.toLong
+ implicit def short2float(x: Short): Float = x.toFloat
+ implicit def short2double(x: Short): Double = x.toDouble
}
diff --git a/src/library/scala/StringContext.scala b/src/library/scala/StringContext.scala
index 1b01355108..be9e0c290a 100644
--- a/src/library/scala/StringContext.scala
+++ b/src/library/scala/StringContext.scala
@@ -79,15 +79,13 @@ case class StringContext(parts: String*) {
* start a format specifier), then the string format specifier `%s` is inserted.
*
* 2. Any `%` characters not in formatting positions are left in the resulting
- * string literally. This is achieved by replacing each such occurrence by a string
- * format specifier `%s` and adding a corresponding argument string `"%"`.
+ * string literally. This is achieved by replacing each such occurrence by the
+ * format specifier `%%`.
*/
def f(args: Any*) = {
checkLengths(args: _*)
val pi = parts.iterator
- val ai = args.iterator
val bldr = new java.lang.StringBuilder
- val args1 = new ArrayBuffer[Any]
def copyString(first: Boolean): Unit = {
val str = treatEscapes(pi.next())
val strIsEmpty = str.length == 0
@@ -98,23 +96,23 @@ case class StringContext(parts: String*) {
bldr append "%s"
idx = 1
}
- val len = str.length
- while (idx < len) {
- if (str(idx) == '%') {
- bldr append (str substring (start, idx)) append "%s"
- args1 += "%"
- start = idx + 1
+ if (!strIsEmpty) {
+ val len = str.length
+ while (idx < len) {
+ if (str(idx) == '%') {
+ bldr append (str substring (start, idx)) append "%%"
+ start = idx + 1
+ }
+ idx += 1
}
- idx += 1
+ bldr append (str substring (start, idx))
}
- if (!strIsEmpty) bldr append (str substring (start, idx))
}
copyString(first = true)
while (pi.hasNext) {
- args1 += ai.next()
copyString(first = false)
}
- bldr.toString format (args1: _*)
+ bldr.toString format (args: _*)
}
}
@@ -144,7 +142,7 @@ object StringContext {
var cur = 0
var idx = 0
def output(ch: Char) = {
- bldr append str substring (start, cur)
+ bldr append str.substring (start, cur)
bldr append ch
start = idx
}
diff --git a/src/library/scala/Tuple2.scala b/src/library/scala/Tuple2.scala
index b1befca4fa..5e77127080 100644
--- a/src/library/scala/Tuple2.scala
+++ b/src/library/scala/Tuple2.scala
@@ -9,9 +9,6 @@
package scala
-import scala.collection.{ TraversableLike => TLike, IterableLike => ILike }
-import scala.collection.generic.{ CanBuildFrom => CBF }
-
/** A tuple of 2 elements; the canonical representation of a [[scala.Product2]].
*
@@ -30,105 +27,4 @@ case class Tuple2[@specialized(Int, Long, Double, Char, Boolean, AnyRef) +T1, @s
*/
def swap: Tuple2[T2,T1] = Tuple2(_2, _1)
- @deprecated("Use `zipped` instead.", "2.9.0")
- def zip[Repr1, El1, El2, To](implicit w1: T1 => TLike[El1, Repr1],
- w2: T2 => Iterable[El2],
- cbf1: CBF[Repr1, (El1, El2), To]): To = {
- zipped map ((x, y) => ((x, y)))
- }
-
- /** Wraps a tuple in a `Zipped`, which supports 2-ary generalisations of `map`, `flatMap`, `filter`, etc.
- * Note that there must be an implicit value to convert this tuple's types into a [[scala.collection.TraversableLike]]
- * or [[scala.collection.IterableLike]].
- * {{{
- * scala> val tuple = (List(1,2,3),List('a','b','c'))
- * tuple: (List[Int], List[Char]) = (List(1, 2, 3),List(a, b, c))
- *
- * scala> tuple.zipped map { (x,y) => x + ":" + y }
- * res6: List[java.lang.String] = List(1:a, 2:b, 3:c)
- * }}}
- *
- * @see Zipped
- * Note: will not terminate for infinite-sized collections.
- */
- def zipped[Repr1, El1, Repr2, El2](implicit w1: T1 => TLike[El1, Repr1], w2: T2 => ILike[El2, Repr2]): Zipped[Repr1, El1, Repr2, El2]
- = new Zipped[Repr1, El1, Repr2, El2](_1, _2)
-
- class Zipped[+Repr1, +El1, +Repr2, +El2](coll1: TLike[El1, Repr1], coll2: ILike[El2, Repr2]) { // coll2: ILike for filter
- def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- b.sizeHint(coll1)
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext)
- b += f(el1, elems2.next)
- else
- return b.result
- }
-
- b.result
- }
-
- def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext)
- b ++= f(el1, elems2.next)
- else
- return b.result
- }
-
- b.result
- }
-
- def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = {
- val b1 = cbf1(coll1.repr)
- val b2 = cbf2(coll2.repr)
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext) {
- val el2 = elems2.next
- if (f(el1, el2)) {
- b1 += el1
- b2 += el2
- }
- }
- else return (b1.result, b2.result)
- }
-
- (b1.result, b2.result)
- }
-
- def exists(f: (El1, El2) => Boolean): Boolean = {
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext) {
- if (f(el1, elems2.next))
- return true
- }
- else return false
- }
- false
- }
-
- def forall(f: (El1, El2) => Boolean): Boolean =
- !exists((x, y) => !f(x, y))
-
- def foreach[U](f: (El1, El2) => U): Unit = {
- val elems2 = coll2.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext)
- f(el1, elems2.next)
- else
- return
- }
- }
- }
-
}
diff --git a/src/library/scala/Tuple3.scala b/src/library/scala/Tuple3.scala
index 0d5399308b..5ed13602e3 100644
--- a/src/library/scala/Tuple3.scala
+++ b/src/library/scala/Tuple3.scala
@@ -9,9 +9,6 @@
package scala
-import scala.collection.{ TraversableLike => TLike, IterableLike => ILike }
-import scala.collection.generic.{ CanBuildFrom => CBF }
-
/** A tuple of 3 elements; the canonical representation of a [[scala.Product3]].
*
@@ -25,121 +22,4 @@ case class Tuple3[+T1, +T2, +T3](_1: T1, _2: T2, _3: T3)
{
override def toString() = "(" + _1 + "," + _2 + "," + _3 + ")"
-
- @deprecated("Use `zipped` instead.", "2.9.0")
- def zip[Repr1, El1, El2, El3, To](implicit w1: T1 => TLike[El1, Repr1],
- w2: T2 => Iterable[El2],
- w3: T3 => Iterable[El3],
- cbf1: CBF[Repr1, (El1, El2, El3), To]): To = {
- zipped map ((x, y, z) => ((x, y, z)))
- }
-
- /** Wraps a tuple in a `Zipped`, which supports 3-ary generalisations of `map`, `flatMap`, `filter`, etc.
- * Note that there must be an implicit value to convert this tuple's types into a [[scala.collection.TraversableLike]]
- * or [[scala.collection.IterableLike]].
- * {{{
- * scala> val tuple = (List(1,2,3),List('a','b','c'),List("x","y","z"))
- * tuple: (List[Int], List[Char], List[java.lang.String]) = (List(1, 2, 3),List(a, b, c),List(x, y, z))
- *
- * scala> tuple.zipped map { (x,y,z) => x + ":" + y + ":" + z}
- * res8: List[java.lang.String] = List(1:a:x, 2:b:y, 3:c:z)
- * }}}
- *
- * @see Zipped
- * Note: will not terminate for infinite-sized collections.
- */
- def zipped[Repr1, El1, Repr2, El2, Repr3, El3](implicit w1: T1 => TLike[El1, Repr1],
- w2: T2 => ILike[El2, Repr2],
- w3: T3 => ILike[El3, Repr3]): Zipped[Repr1, El1, Repr2, El2, Repr3, El3]
- = new Zipped[Repr1, El1, Repr2, El2, Repr3, El3](_1, _2, _3)
-
- class Zipped[+Repr1, +El1, +Repr2, +El2, +Repr3, +El3](coll1: TLike[El1, Repr1],
- coll2: ILike[El2, Repr2],
- coll3: ILike[El3, Repr3]) {
- def map[B, To](f: (El1, El2, El3) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext)
- b += f(el1, elems2.next, elems3.next)
- else
- return b.result
- }
- b.result
- }
-
- def flatMap[B, To](f: (El1, El2, El3) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
- val b = cbf(coll1.repr)
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext)
- b ++= f(el1, elems2.next, elems3.next)
- else
- return b.result
- }
- b.result
- }
-
- def filter[To1, To2, To3](f: (El1, El2, El3) => Boolean)(
- implicit cbf1: CBF[Repr1, El1, To1],
- cbf2: CBF[Repr2, El2, To2],
- cbf3: CBF[Repr3, El3, To3]): (To1, To2, To3) = {
- val b1 = cbf1(coll1.repr)
- val b2 = cbf2(coll2.repr)
- val b3 = cbf3(coll3.repr)
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
- def result = (b1.result, b2.result, b3.result)
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext) {
- val el2 = elems2.next
- val el3 = elems3.next
-
- if (f(el1, el2, el3)) {
- b1 += el1
- b2 += el2
- b3 += el3
- }
- }
- else return result
- }
-
- result
- }
-
- def exists(f: (El1, El2, El3) => Boolean): Boolean = {
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext) {
- if (f(el1, elems2.next, elems3.next))
- return true
- }
- else return false
- }
- false
- }
-
- def forall(f: (El1, El2, El3) => Boolean): Boolean =
- !exists((x, y, z) => !f(x, y, z))
-
- def foreach[U](f: (El1, El2, El3) => U): Unit = {
- val elems2 = coll2.iterator
- val elems3 = coll3.iterator
-
- for (el1 <- coll1) {
- if (elems2.hasNext && elems3.hasNext)
- f(el1, elems2.next, elems3.next)
- else
- return
- }
- }
- }
-
}
diff --git a/src/library/scala/Unit.scala b/src/library/scala/Unit.scala
index f6ed0121ab..3da5c083d4 100644
--- a/src/library/scala/Unit.scala
+++ b/src/library/scala/Unit.scala
@@ -16,11 +16,11 @@ package scala
* runtime system. A method with return type `Unit` is analogous to a Java
* method which is declared `void`.
*/
-final class Unit extends AnyVal {
+final class Unit private extends AnyVal {
override def getClass(): Class[Unit] = sys.error("stub")
}
-object Unit extends AnyValCompanion {
+object Unit extends AnyValCompanion {
/** Transform a value type into a boxed reference type.
*
diff --git a/src/library/scala/annotation/ClassfileAnnotation.scala b/src/library/scala/annotation/ClassfileAnnotation.scala
index 582e51996a..2fde5aae80 100644
--- a/src/library/scala/annotation/ClassfileAnnotation.scala
+++ b/src/library/scala/annotation/ClassfileAnnotation.scala
@@ -9,7 +9,7 @@
package scala.annotation
/** A base class for classfile annotations. These are stored as
- * [[http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html#_top Java annotations]]]
+ * [[http://docs.oracle.com/javase/7/docs/technotes/guides/language/annotations.html#_top Java annotations]]]
* in classfiles.
*
* @author Martin Odersky
diff --git a/src/library/scala/annotation/bridge.scala b/src/library/scala/annotation/bridge.scala
index 690370854e..a56129fb96 100644
--- a/src/library/scala/annotation/bridge.scala
+++ b/src/library/scala/annotation/bridge.scala
@@ -10,4 +10,5 @@ package scala.annotation
/** If this annotation is present on a method, it will be treated as a bridge method.
*/
+@deprecated("Reconsider whether using this annotation will accomplish anything", "2.10.0")
private[scala] class bridge extends annotation.StaticAnnotation
diff --git a/src/library/scala/annotation/meta/companionClass.scala b/src/library/scala/annotation/meta/companionClass.scala
new file mode 100644
index 0000000000..8e53f6caf9
--- /dev/null
+++ b/src/library/scala/annotation/meta/companionClass.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation.meta
+
+/**
+ * When defining an implicit class, the Scala compiler creates an implicit
+ * conversion method for it. Annotations `@companionClass` and `@companionMethod`
+ * control where an annotation on the implicit class will go. By default, annotations
+ * on an implicit class end up only on the class.
+ *
+ */
+final class companionClass extends annotation.StaticAnnotation
diff --git a/src/library/scala/annotation/meta/companionMethod.scala b/src/library/scala/annotation/meta/companionMethod.scala
new file mode 100644
index 0000000000..379c4f3385
--- /dev/null
+++ b/src/library/scala/annotation/meta/companionMethod.scala
@@ -0,0 +1,17 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation.meta
+
+/**
+ * When defining an implicit class, the Scala compiler creates an implicit
+ * conversion method for it. Annotations `@companionClass` and `@companionMethod`
+ * control where an annotation on the implicit class will go. By default, annotations
+ * on an implicit class end up only on the class.
+ *
+ */
+final class companionMethod extends annotation.StaticAnnotation
diff --git a/src/library/scala/annotation/meta/companionObject.scala b/src/library/scala/annotation/meta/companionObject.scala
new file mode 100644
index 0000000000..d329df5c42
--- /dev/null
+++ b/src/library/scala/annotation/meta/companionObject.scala
@@ -0,0 +1,14 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+package scala.annotation.meta
+
+/**
+ * Currently unused; intended as an annotation target for classes such as case classes
+ * that automatically generate a companion object
+ */
+final class companionObject extends annotation.StaticAnnotation
diff --git a/src/dbc/scala/dbc/exception/UnsupportedFeature.scala b/src/library/scala/annotation/meta/languageFeature.scala
index dd6f904077..23acc01b51 100644
--- a/src/dbc/scala/dbc/exception/UnsupportedFeature.scala
+++ b/src/library/scala/annotation/meta/languageFeature.scala
@@ -1,16 +1,13 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
+package scala.annotation.meta
-
-
-package scala.dbc
-package exception
-
-
-/** A type category for all SQL types that store constant-precision numbers. */
-@deprecated(DbcIsDeprecated, "2.9.0") case class UnsupportedFeature (msg: String) extends Exception;
+/**
+ * An annotation giving particulars for a language feature in object `scala.language`.
+ */
+final class languageFeature(feature: String, enableRequired: Boolean) extends annotation.StaticAnnotation
diff --git a/src/library/scala/annotation/switch.scala b/src/library/scala/annotation/switch.scala
index 3734686b27..ee068f50d4 100644
--- a/src/library/scala/annotation/switch.scala
+++ b/src/library/scala/annotation/switch.scala
@@ -9,8 +9,8 @@ package scala.annotation
/** An annotation to be applied to a match expression. If present,
* the compiler will verify that the match has been compiled to a
- * [[http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc14.html tableswitch]]
- * or [[http://java.sun.com/docs/books/jvms/second_edition/html/Instructions2.doc8.html#lookupswitch lookupswitch]]
+ * [[http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc14.html tableswitch]]
+ * or [[http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc8.html#lookupswitch lookupswitch]]
* and issue an error if it instead compiles into a series of conditional expressions.
* Example usage:
{{{
diff --git a/src/dbc/scala/dbc/statement/SetClause.scala b/src/library/scala/annotation/unspecialized.scala
index 3af509c026..28d9aa169c 100644
--- a/src/dbc/scala/dbc/statement/SetClause.scala
+++ b/src/library/scala/annotation/unspecialized.scala
@@ -1,21 +1,17 @@
/* __ *\
** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */
+package scala.annotation
-
-package scala.dbc
-package statement
-
-
-import scala.dbc.statement.expression._
-
-/** Data to be inserted into a table in an <code>Insert</code>. */
-@deprecated(DbcIsDeprecated, "2.9.0") case class SetClause(name: String, expr: Expression) {
- val value: Pair[String,Expression] = (name, expr)
- def sqlString: String = value._1 + " = " + value._2.sqlInnerString
-}
+/** A method annotation which suppresses the creation of
+ * additional specialized forms based on enclosing specialized
+ * type parameters.
+ *
+ * @since 2.10
+ */
+class unspecialized extends annotation.StaticAnnotation
diff --git a/src/library/scala/collection/BitSet.scala b/src/library/scala/collection/BitSet.scala
index 59b53faf7e..90e837b219 100644
--- a/src/library/scala/collection/BitSet.scala
+++ b/src/library/scala/collection/BitSet.scala
@@ -22,7 +22,7 @@ trait BitSet extends SortedSet[Int]
/** $factoryInfo
* @define coll bitset
- * @define Coll BitSet
+ * @define Coll `BitSet`
*/
object BitSet extends BitSetFactory[BitSet] {
val empty: BitSet = immutable.BitSet.empty
diff --git a/src/library/scala/collection/BitSetLike.scala b/src/library/scala/collection/BitSetLike.scala
index e4f9fd436a..c0aaa9f28e 100644
--- a/src/library/scala/collection/BitSetLike.scala
+++ b/src/library/scala/collection/BitSetLike.scala
@@ -30,7 +30,7 @@ import mutable.StringBuilder
* @version 2.8
* @since 2.8
* @define coll bitset
- * @define Coll BitSet
+ * @define Coll `BitSet`
*/
trait BitSetLike[+This <: BitSetLike[This] with SortedSet[Int]] extends SortedSetLike[Int, This] { self =>
diff --git a/src/library/scala/collection/DefaultMap.scala b/src/library/scala/collection/DefaultMap.scala
index 3af535bdaa..d00414751a 100644
--- a/src/library/scala/collection/DefaultMap.scala
+++ b/src/library/scala/collection/DefaultMap.scala
@@ -41,7 +41,7 @@ trait DefaultMap[A, +B] extends Map[A, B] { self =>
*/
override def - (key: A): Map[A, B] = {
val b = newBuilder
- b ++= this filter (key !=)
+ b ++= this filter (key != _)
b.result
}
}
diff --git a/src/library/scala/collection/GenIterableLike.scala b/src/library/scala/collection/GenIterableLike.scala
index 8fa5981969..290a3b26b5 100644
--- a/src/library/scala/collection/GenIterableLike.scala
+++ b/src/library/scala/collection/GenIterableLike.scala
@@ -16,7 +16,7 @@ import generic.{ CanBuildFrom => CBF, _ }
* This trait contains abstract methods and methods that can be implemented
* directly in terms of other methods.
*
- * @define Coll GenIterable
+ * @define Coll `GenIterable`
* @define coll general iterable collection
*
* @author Martin Odersky
@@ -141,7 +141,4 @@ trait GenIterableLike[+A, +Repr] extends Any with GenTraversableLike[A, Repr] {
*/
def zipAll[B, A1 >: A, That](that: GenIterable[B], thisElem: A1, thatElem: B)(implicit bf: CBF[Repr, (A1, B), That]): That
- def isEmpty = iterator.isEmpty
-
- def head = iterator.next
}
diff --git a/src/library/scala/collection/GenMapLike.scala b/src/library/scala/collection/GenMapLike.scala
index 114169c849..d611eaea43 100644
--- a/src/library/scala/collection/GenMapLike.scala
+++ b/src/library/scala/collection/GenMapLike.scala
@@ -11,7 +11,7 @@ package scala.collection
/** A trait for all maps upon which operations may be
* implemented in parallel.
*
- * @define Coll GenMap
+ * @define Coll `GenMap`
* @define coll general map
* @author Martin Odersky
* @author Aleksandar Prokopec
diff --git a/src/library/scala/collection/GenSeqLike.scala b/src/library/scala/collection/GenSeqLike.scala
index 755abcd2bf..fd7892c9f9 100644
--- a/src/library/scala/collection/GenSeqLike.scala
+++ b/src/library/scala/collection/GenSeqLike.scala
@@ -9,7 +9,6 @@
package scala.collection
import generic._
-import annotation.bridge
/** A template trait for all sequences which may be traversed
* in parallel.
@@ -142,7 +141,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
* $mayNotTerminateInf
*
*/
- def indexOf[B >: A](elem: B, from: Int): Int = indexWhere(elem ==, from)
+ def indexOf[B >: A](elem: B, from: Int): Int = indexWhere(elem == _, from)
/** Finds index of last occurrence of some value in this $coll.
*
@@ -157,7 +156,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
* $willNotTerminateInf
*
*/
- def lastIndexOf[B >: A](elem: B): Int = lastIndexWhere(elem ==)
+ def lastIndexOf[B >: A](elem: B): Int = lastIndexWhere(elem == _)
/** Finds index of last occurrence of some value in this $coll before or at a given end index.
*
@@ -170,7 +169,7 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
* @usecase def lastIndexOf(elem: A, end: Int): Int
* @inheritdoc
*/
- def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem ==, end)
+ def lastIndexOf[B >: A](elem: B, end: Int): Int = lastIndexWhere(elem == _, end)
/** Finds index of last element satisfying some predicate.
*
@@ -228,9 +227,6 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
*/
def startsWith[B](that: GenSeq[B]): Boolean = startsWith(that, 0)
- @bridge
- def startsWith[B](that: Seq[B]): Boolean = startsWith(that: GenSeq[B])
-
/** Tests whether this $coll contains the given sequence at a given index.
*
* '''Note''': If the both the receiver object `this` and the argument
@@ -413,10 +409,6 @@ trait GenSeqLike[+A, +Repr] extends Any with GenIterableLike[A, Repr] with Equal
*/
def union[B >: A, That](that: GenSeq[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = this ++ that
- @bridge
- def union[B >: A, That](that: Seq[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
- union(that: GenSeq[B])(bf)
-
/** Computes the multiset difference between this $coll and another sequence.
*
* @param that the sequence of elements to remove
diff --git a/src/library/scala/collection/GenSetLike.scala b/src/library/scala/collection/GenSetLike.scala
index f729f82bb4..219374abc6 100644
--- a/src/library/scala/collection/GenSetLike.scala
+++ b/src/library/scala/collection/GenSetLike.scala
@@ -8,7 +8,6 @@
package scala.collection
-import annotation.bridge
/** A template trait for sets which may possibly
* have their operations implemented in parallel.
@@ -51,9 +50,6 @@ extends GenIterableLike[A, Repr]
*/
def intersect(that: GenSet[A]): Repr = this filter that
- @bridge
- def intersect(that: Set[A]): Repr = intersect(that: GenSet[A])
-
/** Computes the intersection between this set and another set.
*
* '''Note:''' Same as `intersect`.
@@ -63,9 +59,6 @@ extends GenIterableLike[A, Repr]
*/
def &(that: GenSet[A]): Repr = this intersect that
- @bridge
- def &(that: Set[A]): Repr = &(that: GenSet[A])
-
/** Computes the union between of set and another set.
*
* @param that the set to form the union with.
@@ -83,9 +76,6 @@ extends GenIterableLike[A, Repr]
*/
def | (that: GenSet[A]): Repr = this union that
- @bridge
- def | (that: Set[A]): Repr = | (that: GenSet[A])
-
/** Computes the difference of this set and another set.
*
* @param that the set of elements to exclude.
@@ -103,9 +93,6 @@ extends GenIterableLike[A, Repr]
*/
def &~(that: GenSet[A]): Repr = this diff that
- @bridge
- def &~(that: Set[A]): Repr = &~(that: GenSet[A])
-
/** Tests whether this set is a subset of another set.
*
* @param that the set to test.
@@ -114,9 +101,6 @@ extends GenIterableLike[A, Repr]
*/
def subsetOf(that: GenSet[A]): Boolean = this forall that
- @bridge
- def subsetOf(that: Set[A]): Boolean = subsetOf(that: GenSet[A])
-
/** Compares this set with another object for equality.
*
* '''Note:''' This operation contains an unchecked cast: if `that`
diff --git a/src/library/scala/collection/GenTraversableLike.scala b/src/library/scala/collection/GenTraversableLike.scala
index fd03e0f446..df652f99d9 100644
--- a/src/library/scala/collection/GenTraversableLike.scala
+++ b/src/library/scala/collection/GenTraversableLike.scala
@@ -43,7 +43,7 @@ import annotation.migration
* @define traversableInfo
* This is a base trait of all kinds of Scala collections.
*
- * @define Coll GenTraversable
+ * @define Coll `GenTraversable`
* @define coll general collection
* @define collectExample
* @tparam A the collection element type.
@@ -59,12 +59,24 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with
def size: Int
+ /** Selects the first element of this $coll.
+ * $orderDependent
+ * @return the first element of this $coll.
+ * @throws `NoSuchElementException` if the $coll is empty.
+ */
def head: A
-
+
+ /** Optionally selects the first element.
+ * $orderDependent
+ * @return the first element of this $coll if it is nonempty,
+ * `None` if it is empty.
+ */
+ def headOption: Option[A]
+
/** Tests whether this $coll can be repeatedly traversed.
* @return `true`
*/
- final def isTraversableAgain = true
+ def isTraversableAgain: Boolean
/** Selects all elements except the first.
* $orderDependent
@@ -72,11 +84,30 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with
* except the first one.
* @throws `UnsupportedOperationException` if the $coll is empty.
*/
- def tail: Repr = {
- if (isEmpty) throw new UnsupportedOperationException("empty.tail")
- drop(1)
- }
+ def tail: Repr
+ /** Selects the last element.
+ * $orderDependent
+ * @return The last element of this $coll.
+ * @throws NoSuchElementException If the $coll is empty.
+ */
+ def last: A
+
+ /** Optionally selects the last element.
+ * $orderDependent
+ * @return the last element of this $coll$ if it is nonempty,
+ * `None` if it is empty.
+ */
+ def lastOption: Option[A]
+
+ /** Selects all elements except the last.
+ * $orderDependent
+ * @return a $coll consisting of all elements of this $coll
+ * except the last one.
+ * @throws `UnsupportedOperationException` if the $coll is empty.
+ */
+ def init: Repr
+
/** Computes a prefix scan of the elements of the collection.
*
* Note: The neutral element `z` may be applied more than once.
@@ -91,7 +122,7 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with
*/
def scan[B >: A, That](z: B)(op: (B, B) => B)(implicit cbf: CanBuildFrom[Repr, B, That]): That
- /** Produces a collection containing cummulative results of applying the
+ /** Produces a collection containing cumulative results of applying the
* operator going left to right.
*
* $willNotTerminateInf
@@ -106,8 +137,8 @@ trait GenTraversableLike[+A, +Repr] extends Any with GenTraversableOnce[A] with
*/
def scanLeft[B, That](z: B)(op: (B, A) => B)(implicit bf: CanBuildFrom[Repr, B, That]): That
- /** Produces a collection containing cummulative results of applying the operator going right to left.
- * The head of the collection is the last cummulative result.
+ /** Produces a collection containing cumulative results of applying the operator going right to left.
+ * The head of the collection is the last cumulative result.
* $willNotTerminateInf
* $orderDependent
*
diff --git a/src/library/scala/collection/GenTraversableOnce.scala b/src/library/scala/collection/GenTraversableOnce.scala
index a7ec7618b7..f4e3848d98 100644
--- a/src/library/scala/collection/GenTraversableOnce.scala
+++ b/src/library/scala/collection/GenTraversableOnce.scala
@@ -14,7 +14,7 @@ package scala.collection
* Methods in this trait are either abstract or can be implemented in terms
* of other methods.
*
- * @define Coll GenTraversableOnce
+ * @define Coll `GenTraversableOnce`
* @define coll collection or iterator
* @define possiblyparinfo
* This trait may possibly have operations implemented in parallel.
@@ -459,7 +459,7 @@ trait GenTraversableOnce[+A] extends Any {
/** Converts this $coll to an array.
*
- * @tparam B the type of the elements of the array. A `ClassManifest` for
+ * @tparam B the type of the elements of the array. An `ArrayTag` for
* this type must be available.
* @return an array containing all elements of this $coll.
*
@@ -469,9 +469,9 @@ trait GenTraversableOnce[+A] extends Any {
* $willNotTerminateInf
*
* @return an array containing all elements of this $coll.
- * A `ClassManifest` must be available for the element type of this $coll.
+ * An `ArrayTag` must be available for the element type of this $coll.
*/
- def toArray[A1 >: A: ClassManifest]: Array[A1]
+ def toArray[A1 >: A: ArrayTag]: Array[A1]
/** Converts this $coll to a list.
* $willNotTerminateInf
diff --git a/src/library/scala/collection/IndexedSeq.scala b/src/library/scala/collection/IndexedSeq.scala
index 4a3586a375..56dd0bffff 100644
--- a/src/library/scala/collection/IndexedSeq.scala
+++ b/src/library/scala/collection/IndexedSeq.scala
@@ -26,7 +26,7 @@ trait IndexedSeq[+A] extends Seq[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `Vector`.
* @define coll indexed sequence
- * @define Coll IndexedSeq
+ * @define Coll `IndexedSeq`
*/
object IndexedSeq extends SeqFactory[IndexedSeq] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/IndexedSeqLike.scala b/src/library/scala/collection/IndexedSeqLike.scala
index d1f7d1cb36..11f481e425 100644
--- a/src/library/scala/collection/IndexedSeqLike.scala
+++ b/src/library/scala/collection/IndexedSeqLike.scala
@@ -26,7 +26,7 @@ import scala.annotation.tailrec
* access and length computation. They are defined in terms of abstract methods
* `apply` for indexing and `length`.
*
- * Indexed sequences do not add any new methods wrt `Seq`, but promise
+ * Indexed sequences do not add any new methods to `Seq`, but promise
* efficient implementations of random access patterns.
*
* @tparam A the element type of the $coll
diff --git a/src/library/scala/collection/Iterable.scala b/src/library/scala/collection/Iterable.scala
index b1752a5c67..f543c6f80f 100644
--- a/src/library/scala/collection/Iterable.scala
+++ b/src/library/scala/collection/Iterable.scala
@@ -40,7 +40,7 @@ trait Iterable[+A] extends Traversable[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `Vector`.
* @define coll iterable collection
- * @define Coll Iterable
+ * @define Coll `Iterable`
*/
object Iterable extends TraversableFactory[Iterable] {
diff --git a/src/library/scala/collection/IterableLike.scala b/src/library/scala/collection/IterableLike.scala
index fb6d154952..f4397f2167 100644
--- a/src/library/scala/collection/IterableLike.scala
+++ b/src/library/scala/collection/IterableLike.scala
@@ -12,7 +12,6 @@ package scala.collection
import generic._
import immutable.{ List, Stream }
import annotation.unchecked.uncheckedVariance
-import annotation.bridge
/** A template trait for iterable collections of type `Iterable[A]`.
* $iterableInfo
@@ -134,7 +133,7 @@ self =>
it.next
i += 1
}
- b ++= it result
+ (b ++= it).result
}
override /*TraversableLike*/ def takeWhile(p: A => Boolean): Repr = {
@@ -239,10 +238,6 @@ self =>
b.result
}
- @bridge
- def zip[A1 >: A, B, That](that: Iterable[B])(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That =
- zip(that: GenIterable[B])(bf)
-
def zipAll[B, A1 >: A, That](that: GenIterable[B], thisElem: A1, thatElem: B)(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That = {
val b = bf(repr)
val these = this.iterator
@@ -256,10 +251,6 @@ self =>
b.result
}
- @bridge
- def zipAll[B, A1 >: A, That](that: Iterable[B], thisElem: A1, thatElem: B)(implicit bf: CanBuildFrom[Repr, (A1, B), That]): That =
- zipAll(that: GenIterable[B], thisElem, thatElem)(bf)
-
def zipWithIndex[A1 >: A, That](implicit bf: CanBuildFrom[Repr, (A1, Int), That]): That = {
val b = bf(repr)
var i = 0
@@ -280,9 +271,6 @@ self =>
!these.hasNext && !those.hasNext
}
- @bridge
- def sameElements[B >: A](that: Iterable[B]): Boolean = sameElements(that: GenIterable[B])
-
override /*TraversableLike*/ def toStream: Stream[A] = iterator.toStream
/** Method called from equality methods, so that user-defined subclasses can
diff --git a/src/library/scala/collection/IterableViewLike.scala b/src/library/scala/collection/IterableViewLike.scala
index ce2daf08d4..c842475590 100644
--- a/src/library/scala/collection/IterableViewLike.scala
+++ b/src/library/scala/collection/IterableViewLike.scala
@@ -11,6 +11,7 @@ package scala.collection
import generic._
import TraversableView.NoBuilder
import immutable.Stream
+import language.implicitConversions
/** A template trait for non-strict views of iterable collections.
* $iterableViewInfo
diff --git a/src/library/scala/collection/Iterator.scala b/src/library/scala/collection/Iterator.scala
index 7b57a91c41..e9a7906527 100644
--- a/src/library/scala/collection/Iterator.scala
+++ b/src/library/scala/collection/Iterator.scala
@@ -21,6 +21,15 @@ import immutable.Stream
*/
object Iterator {
+ /** With the advent of `TraversableOnce` and `Iterator`, it can be useful to have a builder which
+ * operates on `Iterator`s so they can be treated uniformly along with the collections.
+ * See `scala.util.Random.shuffle` for an example.
+ */
+ implicit def IteratorCanBuildFrom[A] = new TraversableOnce.BufferedCanBuildFrom[A, Iterator] {
+ def bufferToColl[B](coll: ArrayBuffer[B]) = coll.iterator
+ def traversableToColl[B](t: GenTraversable[B]) = t.toIterator
+ }
+
/** The iterator which produces no values. */
val empty: Iterator[Nothing] = new AbstractIterator[Nothing] {
def hasNext: Boolean = false
@@ -329,14 +338,16 @@ trait Iterator[+A] extends TraversableOnce[A] {
def ++[B >: A](that: => GenTraversableOnce[B]): Iterator[B] = new AbstractIterator[B] {
// optimize a little bit to prevent n log n behavior.
private var cur : Iterator[B] = self
+ private var selfExhausted : Boolean = false
// since that is by-name, make sure it's only referenced once -
// if "val it = that" is inside the block, then hasNext on an empty
// iterator will continually reevaluate it. (ticket #3269)
lazy val it = that.toIterator
// the eq check is to avoid an infinite loop on "x ++ x"
- def hasNext = cur.hasNext || ((cur eq self) && {
+ def hasNext = cur.hasNext || (!selfExhausted && {
it.hasNext && {
cur = it
+ selfExhausted = true
true
}
})
@@ -380,6 +391,24 @@ trait Iterator[+A] extends TraversableOnce[A] {
def next() = if (hasNext) { hdDefined = false; hd } else empty.next()
}
+
+ /** Tests whether every element of this iterator relates to the
+ * corresponding element of another collection by satisfying a test predicate.
+ *
+ * @param that the other collection
+ * @param p the test predicate, which relates elements from both collections
+ * @tparam B the type of the elements of `that`
+ * @return `true` if both collections have the same length and
+ * `p(x, y)` is `true` for all corresponding elements `x` of this iterator
+ * and `y` of `that`, otherwise `false`
+ */
+ def corresponds[B](that: GenTraversableOnce[B])(p: (A, B) => Boolean): Boolean = {
+ val that0 = that.toIterator
+ while (hasNext && that0.hasNext)
+ if (!p(next, that0.next)) return false
+
+ hasNext == that0.hasNext
+ }
/** Creates an iterator over all the elements of this iterator that
* satisfy the predicate `p`. The order of the elements
diff --git a/src/library/scala/collection/LinearSeq.scala b/src/library/scala/collection/LinearSeq.scala
index be143cf96b..21ed91f7f3 100644
--- a/src/library/scala/collection/LinearSeq.scala
+++ b/src/library/scala/collection/LinearSeq.scala
@@ -26,7 +26,7 @@ trait LinearSeq[+A] extends Seq[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `Vector`.
* @define coll linear sequence
- * @define Coll LinearSeq
+ * @define Coll `LinearSeq`
*/
object LinearSeq extends SeqFactory[LinearSeq] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinearSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/Map.scala b/src/library/scala/collection/Map.scala
index 0c07d5bb74..42a56a9c5a 100644
--- a/src/library/scala/collection/Map.scala
+++ b/src/library/scala/collection/Map.scala
@@ -33,7 +33,7 @@ trait Map[A, +B] extends Iterable[(A, B)] with GenMap[A, B] with MapLike[A, B, M
}
/** $factoryInfo
- * @define Coll Map
+ * @define Coll `Map`
* @define coll map
*/
object Map extends MapFactory[Map] {
@@ -45,7 +45,7 @@ object Map extends MapFactory[Map] {
/** An abstract shell used by { mutable, immutable }.Map but not by collection.Map
* because of variance issues.
*/
- abstract class WithDefault[A, +B](underlying: Map[A, B], d: A => B) extends AbstractMap[A, B] with Map[A, B] {
+ abstract class WithDefault[A, +B](underlying: Map[A, B], d: A => B) extends AbstractMap[A, B] with Map[A, B] with Serializable {
override def size = underlying.size
def get(key: A) = underlying.get(key) // removed in 2.9: orElse Some(default(key))
def iterator = underlying.iterator
diff --git a/src/library/scala/collection/MapLike.scala b/src/library/scala/collection/MapLike.scala
index 8f88e62791..b2b687e75a 100644
--- a/src/library/scala/collection/MapLike.scala
+++ b/src/library/scala/collection/MapLike.scala
@@ -165,7 +165,7 @@ self =>
/** The implementation class of the set returned by `keySet`.
*/
- protected class DefaultKeySet extends AbstractSet[A] with Set[A] {
+ protected class DefaultKeySet extends AbstractSet[A] with Set[A] with Serializable {
def contains(key : A) = self.contains(key)
def iterator = keysIterator
def + (elem: A): Set[A] = (Set[A]() ++ this + elem).asInstanceOf[Set[A]] // !!! concrete overrides abstract problem
@@ -200,7 +200,7 @@ self =>
/** The implementation class of the iterable returned by `values`.
*/
- protected class DefaultValuesIterable extends AbstractIterable[B] with Iterable[B] {
+ protected class DefaultValuesIterable extends AbstractIterable[B] with Iterable[B] with Serializable {
def iterator = valuesIterator
override def size = self.size
override def foreach[C](f: B => C) = self.valuesIterator foreach f
@@ -297,9 +297,6 @@ self =>
def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1] =
((repr: Map[A, B1]) /: xs.seq) (_ + _)
- @bridge
- def ++[B1 >: B](xs: TraversableOnce[(A, B1)]): Map[A, B1] = ++(xs: GenTraversableOnce[(A, B1)])
-
/** Returns a new map with all key/value pairs for which the predicate
* `p` returns `true`.
*
diff --git a/src/library/scala/collection/Seq.scala b/src/library/scala/collection/Seq.scala
index fd03a49af4..34705ee058 100644
--- a/src/library/scala/collection/Seq.scala
+++ b/src/library/scala/collection/Seq.scala
@@ -27,7 +27,7 @@ trait Seq[+A] extends PartialFunction[Int, A]
/** $factoryInfo
* The current default implementation of a $Coll is a `List`.
* @define coll sequence
- * @define Coll Seq
+ * @define Coll `Seq`
*/
object Seq extends SeqFactory[Seq] {
/** $genericCanBuildFromInfo */
diff --git a/src/library/scala/collection/SeqExtractors.scala b/src/library/scala/collection/SeqExtractors.scala
index cb3cb27f18..de9ff93521 100644
--- a/src/library/scala/collection/SeqExtractors.scala
+++ b/src/library/scala/collection/SeqExtractors.scala
@@ -11,11 +11,13 @@ object +: {
/** An extractor used to init/last deconstruct sequences. */
object :+ {
/** Splits a sequence into init :+ tail.
- * @returns Some(init, tail) if sequence is non-empty.
- * None otherwise.
+ * @return Some(init, tail) if sequence is non-empty. None otherwise.
*/
def unapply[T,Coll <: SeqLike[T, Coll]](
t: Coll with SeqLike[T, Coll]): Option[(Coll, T)] =
if(t.isEmpty) None
else Some(t.init -> t.last)
}
+
+// Dummy to fool ant
+private abstract class SeqExtractors \ No newline at end of file
diff --git a/src/library/scala/collection/SeqLike.scala b/src/library/scala/collection/SeqLike.scala
index fd1d42d7e9..044bd624ae 100644
--- a/src/library/scala/collection/SeqLike.scala
+++ b/src/library/scala/collection/SeqLike.scala
@@ -12,7 +12,6 @@ import mutable.{ ListBuffer, ArraySeq }
import immutable.{ List, Range }
import generic._
import parallel.ParSeq
-import annotation.bridge
import scala.math.Ordering
/** A template trait for sequences of type `Seq[A]`
@@ -46,7 +45,7 @@ import scala.math.Ordering
* @version 1.0, 16/07/2003
* @since 2.8
*
- * @define Coll Seq
+ * @define Coll `Seq`
* @define coll sequence
* @define thatinfo the class of the returned collection. Where possible, `That` is
* the same class as the current collection class `Repr`, but this
@@ -185,7 +184,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
private[this] def init() = {
val m = mutable.HashMap[A, Int]()
- val (es, is) = thisCollection map (e => (e, m.getOrElseUpdate(e, m.size))) sortBy (_._2) unzip
+ val (es, is) = (thisCollection map (e => (e, m.getOrElseUpdate(e, m.size))) sortBy (_._2)).unzip
(es.toBuffer, is.toArray)
}
@@ -240,7 +239,7 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
val m = mutable.HashMap[A, Int]()
// e => (e, weight(e))
- val (es, is) = thisCollection map (e => (e, m.getOrElseUpdate(e, m.size))) sortBy (_._2) unzip
+ val (es, is) = (thisCollection map (e => (e, m.getOrElseUpdate(e, m.size))) sortBy (_._2)).unzip
val cs = new Array[Int](m.size)
is foreach (i => cs(i) += 1)
val ns = new Array[Int](cs.length)
@@ -296,9 +295,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
!j.hasNext
}
- @bridge
- def startsWith[B](that: Seq[B], offset: Int): Boolean = startsWith(that: GenSeq[B], offset)
-
def endsWith[B](that: GenSeq[B]): Boolean = {
val i = this.iterator.drop(length - that.length)
val j = that.iterator
@@ -309,10 +305,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
!j.hasNext
}
- @bridge
- def endsWith[B](that: Seq[B]): Boolean = endsWith(that: GenSeq[B])
-
-
/** Finds first index where this $coll contains a given sequence as a slice.
* $mayNotTerminateInf
* @param that the sequence to test
@@ -321,9 +313,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
*/
def indexOfSlice[B >: A](that: GenSeq[B]): Int = indexOfSlice(that, 0)
- @bridge
- def indexOfSlice[B >: A](that: Seq[B]): Int = indexOfSlice(that: GenSeq[B])
-
/** Finds first index after or at a start index where this $coll contains a given sequence as a slice.
* $mayNotTerminateInf
* @param that the sequence to test
@@ -354,9 +343,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
-1
}
- @bridge
- def indexOfSlice[B >: A](that: Seq[B], from: Int): Int = indexOfSlice(that: GenSeq[B], from)
-
/** Finds last index where this $coll contains a given sequence as a slice.
* $willNotTerminateInf
* @param that the sequence to test
@@ -365,9 +351,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
*/
def lastIndexOfSlice[B >: A](that: GenSeq[B]): Int = lastIndexOfSlice(that, length)
- @bridge
- def lastIndexOfSlice[B >: A](that: Seq[B]): Int = lastIndexOfSlice(that: GenSeq[B])
-
/** Finds last index before or at a given end index where this $coll contains a given sequence as a slice.
* @param that the sequence to test
* @param end the end index
@@ -385,9 +368,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
else SeqLike.kmpSearch(thisCollection, 0, clippedL+tl, that.seq, 0, tl, false)
}
- @bridge
- def lastIndexOfSlice[B >: A](that: Seq[B], end: Int): Int = lastIndexOfSlice(that: GenSeq[B], end)
-
/** Tests whether this $coll contains a given sequence as a slice.
* $mayNotTerminateInf
* @param that the sequence to test
@@ -396,15 +376,12 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
*/
def containsSlice[B](that: GenSeq[B]): Boolean = indexOfSlice(that) != -1
- @bridge
- def containsSlice[B](that: Seq[B]): Boolean = containsSlice(that: GenSeq[B])
-
/** Tests whether this $coll contains a given value as an element.
* $mayNotTerminateInf
*
* @param elem the element to test.
- * @return `true` if this $coll has an element that is
- * is equal (wrt `==`) to `elem`, `false` otherwise.
+ * @return `true` if this $coll has an element that is equal (as
+ * determined by `==`) to `elem`, `false` otherwise.
*/
def contains(elem: Any): Boolean = exists (_ == elem)
@@ -463,9 +440,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
b.result
}
- @bridge
- def diff[B >: A](that: Seq[B]): Repr = diff(that: GenSeq[B])
-
/** Computes the multiset intersection between this $coll and another sequence.
*
* @param that the sequence of elements to intersect with.
@@ -499,9 +473,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
b.result
}
- @bridge
- def intersect[B >: A](that: Seq[B]): Repr = intersect(that: GenSeq[B])
-
private def occCounts[B](sq: Seq[B]): mutable.Map[B, Int] = {
val occ = new mutable.HashMap[B, Int] { override def default(k: B) = 0 }
for (y <- sq.seq) occ(y) += 1
@@ -534,10 +505,6 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
b.result
}
- @bridge
- def patch[B >: A, That](from: Int, patch: Seq[B], replaced: Int)(implicit bf: CanBuildFrom[Repr, B, That]): That =
- this.patch(from, patch: GenSeq[B], replaced)(bf)
-
def updated[B >: A, That](index: Int, elem: B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
val (prefix, rest) = this.splitAt(index)
@@ -583,15 +550,11 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
!i.hasNext && !j.hasNext
}
- @bridge
- def corresponds[B](that: Seq[B])(p: (A,B) => Boolean): Boolean =
- corresponds(that: GenSeq[B])(p)
-
/** Sorts this $coll according to a comparison function.
* $willNotTerminateInf
*
- * The sort is stable. That is, elements that are equal wrt `lt` appear in the
- * same order in the sorted sequence as in the original.
+ * The sort is stable. That is, elements that are equal (as determined by
+ * `lt`) appear in the same order in the sorted sequence as in the original.
*
* @param lt the comparison function which tests whether
* its first argument precedes its second argument in
@@ -629,8 +592,8 @@ trait SeqLike[+A, +Repr] extends Any with IterableLike[A, Repr] with GenSeqLike[
/** Sorts this $coll according to an Ordering.
*
- * The sort is stable. That is, elements that are equal wrt `lt` appear in the
- * same order in the sorted sequence as in the original.
+ * The sort is stable. That is, elements that are equal (as determined by
+ * `lt`) appear in the same order in the sorted sequence as in the original.
*
* @see scala.math.Ordering
*
diff --git a/src/library/scala/collection/SeqProxyLike.scala b/src/library/scala/collection/SeqProxyLike.scala
index ce32ba97c2..3783ef771f 100644
--- a/src/library/scala/collection/SeqProxyLike.scala
+++ b/src/library/scala/collection/SeqProxyLike.scala
@@ -36,7 +36,7 @@ trait SeqProxyLike[+A, +Repr <: SeqLike[A, Repr] with Seq[A]] extends SeqLike[A,
override def indexOf[B >: A](elem: B): Int = self.indexOf(elem)
override def indexOf[B >: A](elem: B, from: Int): Int = self.indexOf(elem, from)
override def lastIndexOf[B >: A](elem: B): Int = self.lastIndexOf(elem)
- override def lastIndexOf[B >: A](elem: B, end: Int): Int = self.lastIndexWhere(elem ==, end)
+ override def lastIndexOf[B >: A](elem: B, end: Int): Int = self.lastIndexWhere(elem == _, end)
override def lastIndexWhere(p: A => Boolean): Int = self.lastIndexWhere(p, length - 1)
override def lastIndexWhere(p: A => Boolean, end: Int): Int = self.lastIndexWhere(p)
override def reverse: Repr = self.reverse
diff --git a/src/library/scala/collection/SeqViewLike.scala b/src/library/scala/collection/SeqViewLike.scala
index a32cad08e5..f64045c9f6 100644
--- a/src/library/scala/collection/SeqViewLike.scala
+++ b/src/library/scala/collection/SeqViewLike.scala
@@ -11,7 +11,6 @@ package scala.collection
import generic._
import Seq.fill
import TraversableView.NoBuilder
-import annotation.bridge
/** A template trait for non-strict views of sequences.
* $seqViewInfo
@@ -132,13 +131,9 @@ trait SeqViewLike[+A,
override def diff[B >: A](that: GenSeq[B]): This =
newForced(thisSeq diff that).asInstanceOf[This]
- @bridge def diff[B >: A](that: Seq[B]): This = diff(that: GenSeq[B])
-
override def intersect[B >: A](that: GenSeq[B]): This =
newForced(thisSeq intersect that).asInstanceOf[This]
- @bridge def intersect[B >: A](that: Seq[B]): This = intersect(that: GenSeq[B])
-
override def sorted[B >: A](implicit ord: Ordering[B]): This =
newForced(thisSeq sorted ord).asInstanceOf[This]
diff --git a/src/library/scala/collection/Set.scala b/src/library/scala/collection/Set.scala
index 4c67aad603..7424c9cb9a 100644
--- a/src/library/scala/collection/Set.scala
+++ b/src/library/scala/collection/Set.scala
@@ -35,7 +35,7 @@ trait Set[A] extends (A => Boolean)
* The current default implementation of a $Coll is one of `EmptySet`, `Set1`, `Set2`, `Set3`, `Set4` in
* class `immutable.Set` for sets of sizes up to 4, and a `immutable.HashSet` for sets of larger sizes.
* @define coll set
- * @define Coll Set
+ * @define Coll `Set`
*/
object Set extends SetFactory[Set] {
def newBuilder[A] = immutable.Set.newBuilder[A]
diff --git a/src/library/scala/collection/SetLike.scala b/src/library/scala/collection/SetLike.scala
index 7293f3775c..04ec4af830 100644
--- a/src/library/scala/collection/SetLike.scala
+++ b/src/library/scala/collection/SetLike.scala
@@ -127,9 +127,6 @@ self =>
*/
def ++ (elems: GenTraversableOnce[A]): This = (repr /: elems.seq)(_ + _)
- @bridge
- def ++ (elems: TraversableOnce[A]): This = ++ (elems: GenTraversableOnce[A])
-
/** Creates a new set with a given element removed from this set.
*
* @param elem the element to be removed
@@ -152,9 +149,6 @@ self =>
*/
def union(that: GenSet[A]): This = this ++ that
- @bridge
- def union(that: Set[A]): This = union(that: GenSet[A])
-
/** Computes the difference of this set and another set.
*
* @param that the set of elements to exclude.
@@ -163,9 +157,6 @@ self =>
*/
def diff(that: GenSet[A]): This = this -- that
- @bridge
- def diff(that: Set[A]): This = diff(that: GenSet[A])
-
/** An iterator over all subsets of this set of the given size.
* If the requested size is impossible, an empty iterator is returned.
*
diff --git a/src/library/scala/collection/Traversable.scala b/src/library/scala/collection/Traversable.scala
index 3fba3dfa79..cd85ea4d2d 100644
--- a/src/library/scala/collection/Traversable.scala
+++ b/src/library/scala/collection/Traversable.scala
@@ -13,7 +13,6 @@ package scala.collection
import generic._
import mutable.{Builder, Buffer, ArrayBuffer, ListBuffer}
import scala.util.control.Breaks
-import annotation.bridge
/** A trait for traversable collections.
* All operations are guaranteed to be performed in a single-threaded manner.
@@ -28,12 +27,6 @@ trait Traversable[+A] extends TraversableLike[A, Traversable[A]]
override def seq: Traversable[A] = this
- @bridge
- def flatten[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): Traversable[B] = super.flatten(asTraversable)
-
- @bridge
- def transpose[B](implicit asTraversable: A => /*<:<!!!*/ GenTraversableOnce[B]): Traversable[Traversable[B]] = super.transpose(asTraversable)
-
/* The following methods are inherited from TraversableLike
*
override def isEmpty: Boolean
@@ -75,7 +68,7 @@ trait Traversable[+A] extends TraversableLike[A, Traversable[A]]
override def copyToBuffer[B >: A](dest: Buffer[B])
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int)
override def copyToArray[B >: A](xs: Array[B], start: Int)
- override def toArray[B >: A : ClassManifest]: Array[B]
+ override def toArray[B >: A : ArrayTag]: Array[B]
override def toList: List[A]
override def toIterable: Iterable[A]
override def toSeq: Seq[A]
diff --git a/src/library/scala/collection/TraversableLike.scala b/src/library/scala/collection/TraversableLike.scala
index 1f5beb5109..3716a318d9 100644
--- a/src/library/scala/collection/TraversableLike.scala
+++ b/src/library/scala/collection/TraversableLike.scala
@@ -84,6 +84,8 @@ trait TraversableLike[+A, +Repr] extends Any
*/
def repr: Repr = this.asInstanceOf[Repr]
+ final def isTraversableAgain: Boolean = true
+
/** The underlying collection seen as an instance of `$Coll`.
* By default this is implemented as the current collection object itself,
* but this can be overridden.
@@ -155,10 +157,6 @@ trait TraversableLike[+A, +Repr] extends Any
b.result
}
- @bridge
- def ++[B >: A, That](that: TraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That =
- ++(that: GenTraversableOnce[B])(bf)
-
/** As with `++`, returns a new collection containing the elements from the left operand followed by the
* elements from the right operand.
*
@@ -487,7 +485,7 @@ trait TraversableLike[+A, +Repr] extends Any
if (n <= 0) {
val b = newBuilder
b.sizeHint(this)
- b ++= thisCollection result
+ (b ++= thisCollection).result
}
else sliceWithKnownDelta(n, Int.MaxValue, -n)
@@ -775,6 +773,6 @@ trait TraversableLike[+A, +Repr] extends Any
// A helper for tails and inits.
private def iterateUntilEmpty(f: Traversable[A @uV] => Traversable[A @uV]): Iterator[Repr] = {
val it = Iterator.iterate(thisCollection)(f) takeWhile (x => !x.isEmpty)
- it ++ Iterator(Nil) map (newBuilder ++= _ result)
+ it ++ Iterator(Nil) map (x => (newBuilder ++= x).result)
}
}
diff --git a/src/library/scala/collection/TraversableOnce.scala b/src/library/scala/collection/TraversableOnce.scala
index 62ea692b90..639610a30c 100644
--- a/src/library/scala/collection/TraversableOnce.scala
+++ b/src/library/scala/collection/TraversableOnce.scala
@@ -8,8 +8,9 @@
package scala.collection
-import mutable.{ Buffer, ListBuffer, ArrayBuffer }
+import mutable.{ Buffer, Builder, ListBuffer, ArrayBuffer }
import annotation.unchecked.{ uncheckedVariance => uV }
+import language.{implicitConversions, higherKinds}
/** A template trait for collections which can be traversed either once only
* or one or more times.
@@ -228,7 +229,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] {
def copyToArray[B >: A](xs: Array[B]): Unit =
copyToArray(xs, 0, xs.length)
- def toArray[B >: A : ClassManifest]: Array[B] = {
+ def toArray[B >: A : ArrayTag]: Array[B] = {
if (isTraversableAgain) {
val result = new Array[B](size)
copyToArray(result, 0)
@@ -239,7 +240,7 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] {
def toTraversable: Traversable[A]
- def toList: List[A] = new ListBuffer[A] ++= seq toList
+ def toList: List[A] = (new ListBuffer[A] ++= seq).toList
def toIterable: Iterable[A] = toStream
@@ -356,33 +357,52 @@ trait TraversableOnce[+A] extends Any with GenTraversableOnce[A] {
}
-
object TraversableOnce {
- implicit def traversableOnceCanBuildFrom[T] = new OnceCanBuildFrom[T]
- implicit def wrapTraversableOnce[A](trav: TraversableOnce[A]) = new MonadOps(trav)
+ @deprecated("use OnceCanBuildFrom instead")
+ def traversableOnceCanBuildFrom[T] = new OnceCanBuildFrom[T]
+ @deprecated("use MonadOps instead")
+ def wrapTraversableOnce[A](trav: TraversableOnce[A]) = new MonadOps(trav)
+
implicit def alternateImplicit[A](trav: TraversableOnce[A]) = new ForceImplicitAmbiguity
implicit def flattenTraversableOnce[A, CC[_]](travs: TraversableOnce[CC[A]])(implicit ev: CC[A] => TraversableOnce[A]) =
new FlattenOps[A](travs map ev)
-
- /** With the advent of TraversableOnce, it can be useful to have a builder which
- * operates on Iterators so they can be treated uniformly along with the collections.
- * See scala.util.Random.shuffle for an example.
- */
- class OnceCanBuildFrom[A] extends generic.CanBuildFrom[TraversableOnce[A], A, TraversableOnce[A]] {
- def newIterator = new ArrayBuffer[A] mapResult (_.iterator)
+
+ /* Functionality reused in Iterator.CanBuildFrom */
+ private[collection] abstract class BufferedCanBuildFrom[A, Coll[X] <: TraversableOnce[X]] extends generic.CanBuildFrom[Coll[_], A, Coll[A]] {
+ def bufferToColl[B](buff: ArrayBuffer[B]): Coll[B]
+ def traversableToColl[B](t: GenTraversable[B]): Coll[B]
+
+ def newIterator: Builder[A, Coll[A]] = new ArrayBuffer[A] mapResult bufferToColl
/** Creates a new builder on request of a collection.
* @param from the collection requesting the builder to be created.
* @return the result of invoking the `genericBuilder` method on `from`.
*/
- def apply(from: TraversableOnce[A]) = newIterator
+ def apply(from: Coll[_]): Builder[A, Coll[A]] = from match {
+ case xs: generic.GenericTraversableTemplate[_, _] => xs.genericBuilder.asInstanceOf[Builder[A, Traversable[A]]] mapResult {
+ case res => traversableToColl(res.asInstanceOf[GenTraversable[A]])
+ }
+ case _ => newIterator
+ }
/** Creates a new builder from scratch
* @return the result of invoking the `newBuilder` method of this factory.
*/
def apply() = newIterator
}
-
+
+ /** With the advent of `TraversableOnce`, it can be useful to have a builder which
+ * operates on `Iterator`s so they can be treated uniformly along with the collections.
+ * See `scala.util.Random.shuffle` or `scala.concurrent.Future.sequence` for an example.
+ */
+ class OnceCanBuildFrom[A] extends BufferedCanBuildFrom[A, TraversableOnce] {
+ def bufferToColl[B](buff: ArrayBuffer[B]) = buff.iterator
+ def traversableToColl[B](t: GenTraversable[B]) = t.seq
+ }
+
+ /** Evidence for building collections from `TraversableOnce` collections */
+ implicit def OnceCanBuildFrom[A] = new OnceCanBuildFrom[A]
+
class FlattenOps[A](travs: TraversableOnce[TraversableOnce[A]]) {
def flatten: Iterator[A] = new AbstractIterator[A] {
val its = travs.toIterator
@@ -394,7 +414,7 @@ object TraversableOnce {
class ForceImplicitAmbiguity
- class MonadOps[+A](trav: TraversableOnce[A]) {
+ implicit class MonadOps[+A](trav: TraversableOnce[A]) {
def map[B](f: A => B): TraversableOnce[B] = trav.toIterator map f
def flatMap[B](f: A => GenTraversableOnce[B]): TraversableOnce[B] = trav.toIterator flatMap f
def withFilter(p: A => Boolean) = trav.toIterator filter p
diff --git a/src/library/scala/collection/TraversableProxyLike.scala b/src/library/scala/collection/TraversableProxyLike.scala
index e7e797391e..20880e369d 100644
--- a/src/library/scala/collection/TraversableProxyLike.scala
+++ b/src/library/scala/collection/TraversableProxyLike.scala
@@ -73,7 +73,7 @@ trait TraversableProxyLike[+A, +Repr <: TraversableLike[A, Repr] with Traversabl
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = self.copyToArray(xs, start, len)
override def copyToArray[B >: A](xs: Array[B], start: Int) = self.copyToArray(xs, start)
override def copyToArray[B >: A](xs: Array[B]) = self.copyToArray(xs)
- override def toArray[B >: A: ClassManifest]: Array[B] = self.toArray
+ override def toArray[B >: A: ArrayTag]: Array[B] = self.toArray
override def toList: List[A] = self.toList
override def toIterable: Iterable[A] = self.toIterable
override def toSeq: Seq[A] = self.toSeq
diff --git a/src/library/scala/collection/TraversableViewLike.scala b/src/library/scala/collection/TraversableViewLike.scala
index fbecad98fe..5ca038fd2e 100644
--- a/src/library/scala/collection/TraversableViewLike.scala
+++ b/src/library/scala/collection/TraversableViewLike.scala
@@ -12,13 +12,14 @@ import generic._
import mutable.{ Builder, ArrayBuffer }
import TraversableView.NoBuilder
import annotation.migration
+import language.implicitConversions
trait ViewMkString[+A] {
self: Traversable[A] =>
// It is necessary to use thisSeq rather than toSeq to avoid cycles in the
// eager evaluation of vals in transformed view subclasses, see #4558.
- protected[this] def thisSeq: Seq[A] = new ArrayBuffer[A] ++= self result
+ protected[this] def thisSeq: Seq[A] = (new ArrayBuffer[A] ++= self).result
// Have to overload all three to work around #4299. The overload
// is because mkString should force a view but toString should not.
@@ -27,8 +28,16 @@ trait ViewMkString[+A] {
override def mkString(start: String, sep: String, end: String): String = {
thisSeq.addString(new StringBuilder(), start, sep, end).toString
}
- override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder =
- b append start append "..." append end
+ override def addString(b: StringBuilder, start: String, sep: String, end: String): StringBuilder = {
+ var first = true
+ b append start
+ for (x <- self) {
+ if (first) first = false else b append sep
+ b append x
+ }
+ b append end
+ b
+ }
}
/** A template trait for non-strict views of traversable collections.
@@ -40,17 +49,17 @@ trait ViewMkString[+A] {
* that takes a `View` as its `From` type parameter must yield the same view (or a generic
* superclass of it) as its result parameter. If that assumption is broken, cast errors might result.
*
- * @define viewInfo
+ * @define viewInfo
* A view is a lazy version of some collection. Collection transformers such as
* `map` or `filter` or `++` do not traverse any elements when applied on a view.
* Instead they create a new view which simply records that fact that the operation
* needs to be applied. The collection elements are accessed, and the view operations are applied,
* when a non-view result is needed, or when the `force` method is called on a view.
- * @define traversableViewInfo
+ * @define traversableViewInfo
* $viewInfo
*
* All views for traversable collections are defined by creating a new `foreach` method.
-
+ *
* @author Martin Odersky
* @version 2.8
* @since 2.8
diff --git a/src/library/scala/collection/concurrent/Map.scala b/src/library/scala/collection/concurrent/Map.scala
index 83445738d9..a724be42cc 100644
--- a/src/library/scala/collection/concurrent/Map.scala
+++ b/src/library/scala/collection/concurrent/Map.scala
@@ -19,7 +19,7 @@ package scala.collection.concurrent
* @tparam A the key type of the map
* @tparam B the value type of the map
*
- * @define Coll ConcurrentMap
+ * @define Coll `ConcurrentMap`
* @define coll concurrent map
* @define concurrentmapinfo
* This is a base trait for all Scala concurrent map implementations. It
diff --git a/src/library/scala/collection/convert/DecorateAsJava.scala b/src/library/scala/collection/convert/DecorateAsJava.scala
index e05bfc41cd..bde13f2830 100644
--- a/src/library/scala/collection/convert/DecorateAsJava.scala
+++ b/src/library/scala/collection/convert/DecorateAsJava.scala
@@ -12,6 +12,8 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import Decorators._
import WrapAsJava._
+import language.implicitConversions
+
/** A collection of decorators that allow to convert between
* Scala and Java collections using `asScala` and `asJava` methods.
diff --git a/src/library/scala/collection/convert/DecorateAsScala.scala b/src/library/scala/collection/convert/DecorateAsScala.scala
index 722f0b9af9..b170d8d139 100644
--- a/src/library/scala/collection/convert/DecorateAsScala.scala
+++ b/src/library/scala/collection/convert/DecorateAsScala.scala
@@ -12,6 +12,7 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import Decorators._
import WrapAsScala._
+import language.implicitConversions
trait DecorateAsScala {
/**
diff --git a/src/library/scala/collection/convert/WrapAsJava.scala b/src/library/scala/collection/convert/WrapAsJava.scala
index cdec72b9fe..ecf91deb3a 100644
--- a/src/library/scala/collection/convert/WrapAsJava.scala
+++ b/src/library/scala/collection/convert/WrapAsJava.scala
@@ -11,6 +11,7 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import Wrappers._
+import language.implicitConversions
trait WrapAsJava {
/**
diff --git a/src/library/scala/collection/convert/WrapAsScala.scala b/src/library/scala/collection/convert/WrapAsScala.scala
index 56e13b2105..14c64695ff 100644
--- a/src/library/scala/collection/convert/WrapAsScala.scala
+++ b/src/library/scala/collection/convert/WrapAsScala.scala
@@ -11,6 +11,7 @@ package convert
import java.{ lang => jl, util => ju }, java.util.{ concurrent => juc }
import Wrappers._
+import language.implicitConversions
trait WrapAsScala {
/**
diff --git a/src/library/scala/collection/generic/ClassManifestTraversableFactory.scala b/src/library/scala/collection/generic/ArrayTagTraversableFactory.scala
index e54ce9cdbf..ddae0a4d64 100644
--- a/src/library/scala/collection/generic/ClassManifestTraversableFactory.scala
+++ b/src/library/scala/collection/generic/ArrayTagTraversableFactory.scala
@@ -9,21 +9,23 @@
package scala.collection
package generic
-/** A template for companion objects of `ClassManifestTraversable` and
+import language.higherKinds
+
+/** A template for companion objects of `ClassTagTraversable` and
* subclasses thereof.
*
* @define coll collection
- * @define Coll Traversable
+ * @define Coll `Traversable`
* @define genericCanBuildFromInfo
* The standard `CanBuildFrom` instance for $Coll objects.
* @author Aleksandar Prokopec
* @since 2.8
*/
-abstract class ClassManifestTraversableFactory[CC[X] <: Traversable[X] with GenericClassManifestTraversableTemplate[X, CC]]
- extends GenericClassManifestCompanion[CC] {
+abstract class ArrayTagTraversableFactory[CC[X] <: Traversable[X] with GenericArrayTagTraversableTemplate[X, CC]]
+ extends GenericArrayTagCompanion[CC] {
- class GenericCanBuildFrom[A](implicit manif: ClassManifest[A]) extends CanBuildFrom[CC[_], A, CC[A]] {
- def apply(from: CC[_]) = from.genericClassManifestBuilder[A]
+ class GenericCanBuildFrom[A](implicit tag: ArrayTag[A]) extends CanBuildFrom[CC[_], A, CC[A]] {
+ def apply(from: CC[_]) = from.genericArrayTagBuilder[A]
def apply = newBuilder[A]
}
}
diff --git a/src/library/scala/collection/generic/BitSetFactory.scala b/src/library/scala/collection/generic/BitSetFactory.scala
index 796b12b0ac..da80b3964b 100644
--- a/src/library/scala/collection/generic/BitSetFactory.scala
+++ b/src/library/scala/collection/generic/BitSetFactory.scala
@@ -15,7 +15,7 @@ import scala.collection._
import mutable.Builder
/** @define coll collection
- * @define Coll Traversable
+ * @define Coll `Traversable`
* @define factoryInfo
* This object provides a set of operations to create `$Coll` values.
* @author Martin Odersky
diff --git a/src/dbc/scala/dbc/statement/AccessMode.scala b/src/library/scala/collection/generic/Clearable.scala
index 885e0012f2..6c8d9558b0 100644
--- a/src/dbc/scala/dbc/statement/AccessMode.scala
+++ b/src/library/scala/collection/generic/Clearable.scala
@@ -6,21 +6,21 @@
** |/ **
\* */
+package scala.collection
+package generic
-
-package scala.dbc
-package statement
-
-
-@deprecated(DbcIsDeprecated, "2.9.0") abstract class AccessMode {
- def sqlString: String
-}
-
-@deprecated(DbcIsDeprecated, "2.9.0") object AccessMode {
- case object ReadOnly extends AccessMode {
- def sqlString = "READ ONLY"
- }
- case object ReadWrite extends AccessMode {
- def sqlString = "READ WRITE"
- }
+/** This trait forms part of collections that can be cleared
+ * with a clear() call.
+ *
+ * @author Paul Phillips
+ * @version 2.10
+ * @since 2.10
+ * @define coll clearable collection
+ * @define Coll `Clearable`
+ */
+trait Clearable {
+ /** Clears the $coll's contents. After this operation, the
+ * $coll is empty.
+ */
+ def clear(): Unit
}
diff --git a/src/library/scala/collection/generic/GenMapFactory.scala b/src/library/scala/collection/generic/GenMapFactory.scala
index d6f6978ead..31fe4e100d 100644
--- a/src/library/scala/collection/generic/GenMapFactory.scala
+++ b/src/library/scala/collection/generic/GenMapFactory.scala
@@ -10,11 +10,12 @@ package scala.collection
package generic
import mutable.{Builder, MapBuilder}
+import language.higherKinds
/** A template for companion objects of `Map` and subclasses thereof.
*
* @define coll map
- * @define Coll Map
+ * @define Coll `Map`
* @define factoryInfo
* This object provides a set of operations needed to create `$Coll` values.
* @author Martin Odersky
diff --git a/src/library/scala/collection/generic/GenSeqFactory.scala b/src/library/scala/collection/generic/GenSeqFactory.scala
index ee6ecae3c2..19eeba9b1d 100644
--- a/src/library/scala/collection/generic/GenSeqFactory.scala
+++ b/src/library/scala/collection/generic/GenSeqFactory.scala
@@ -11,16 +11,11 @@
package scala.collection
package generic
-import annotation.bridge
+import language.higherKinds
/** A template for companion objects of Seq and subclasses thereof.
*
* @since 2.8
*/
abstract class GenSeqFactory[CC[X] <: GenSeq[X] with GenericTraversableTemplate[X, CC]]
-extends GenTraversableFactory[CC] {
-
- @bridge
- def unapplySeq[A](x: GenSeq[A]): Some[GenSeq[A]] = Some(x)
-
-}
+extends GenTraversableFactory[CC]
diff --git a/src/library/scala/collection/generic/GenSetFactory.scala b/src/library/scala/collection/generic/GenSetFactory.scala
index d83f248aff..4f812b337c 100644
--- a/src/library/scala/collection/generic/GenSetFactory.scala
+++ b/src/library/scala/collection/generic/GenSetFactory.scala
@@ -12,11 +12,12 @@ package scala.collection
package generic
import mutable.Builder
+import language.higherKinds
/** A template for companion objects of `Set` and subclasses thereof.
*
* @define coll set
- * @define Coll Set
+ * @define Coll `Set`
* @define factoryInfo
* This object provides a set of operations needed to create `$Coll` values.
* @author Martin Odersky
diff --git a/src/library/scala/collection/generic/GenTraversableFactory.scala b/src/library/scala/collection/generic/GenTraversableFactory.scala
index 34cbe1a7f2..94def7ab5d 100644
--- a/src/library/scala/collection/generic/GenTraversableFactory.scala
+++ b/src/library/scala/collection/generic/GenTraversableFactory.scala
@@ -10,6 +10,8 @@
package scala.collection
package generic
+import language.higherKinds
+
/** A template for companion objects of `Traversable` and subclasses thereof.
* This class provides a set of operations to create `$Coll` objects.
* It is typically inherited by companion objects of subclasses of `Traversable`.
@@ -17,7 +19,7 @@ package generic
* @since 2.8
*
* @define coll collection
- * @define Coll Traversable
+ * @define Coll `Traversable`
* @define factoryInfo
* This object provides a set of operations to create `$Coll` values.
* @author Martin Odersky
@@ -71,7 +73,7 @@ abstract class GenTraversableFactory[CC[X] <: GenTraversable[X] with GenericTrav
val b = newBuilder[A]
// At present we're using IndexedSeq as a proxy for "has a cheap size method".
if (xss forall (_.isInstanceOf[IndexedSeq[_]]))
- b.sizeHint(xss map (_.size) sum)
+ b.sizeHint(xss.map(_.size).sum)
for (xs <- xss.seq) b ++= xs
b.result
diff --git a/src/library/scala/collection/generic/GenericClassManifestCompanion.scala b/src/library/scala/collection/generic/GenericArrayTagCompanion.scala
index 546e82fb4a..959adbce6d 100644
--- a/src/library/scala/collection/generic/GenericClassManifestCompanion.scala
+++ b/src/library/scala/collection/generic/GenericArrayTagCompanion.scala
@@ -10,20 +10,21 @@ package scala.collection
package generic
import mutable.Builder
+import language.higherKinds
-/** This class represents companions of classes which require ClassManifests
+/** This class represents companions of classes which require ArrayTags
* for their element types.
*
* @author Aleksandar Prokopec
*/
-abstract class GenericClassManifestCompanion[+CC[X] <: Traversable[X]] {
+abstract class GenericArrayTagCompanion[+CC[X] <: Traversable[X]] {
type Coll = CC[_]
- def newBuilder[A](implicit ord: ClassManifest[A]): Builder[A, CC[A]]
+ def newBuilder[A](implicit ord: ArrayTag[A]): Builder[A, CC[A]]
- def empty[A: ClassManifest]: CC[A] = newBuilder[A].result
+ def empty[A: ArrayTag]: CC[A] = newBuilder[A].result
- def apply[A](elems: A*)(implicit ord: ClassManifest[A]): CC[A] = {
+ def apply[A](elems: A*)(implicit ord: ArrayTag[A]): CC[A] = {
val b = newBuilder[A]
b ++= elems
b.result
diff --git a/src/library/scala/collection/generic/GenericArrayTagTraversableTemplate.scala b/src/library/scala/collection/generic/GenericArrayTagTraversableTemplate.scala
new file mode 100644
index 0000000000..ac84683c59
--- /dev/null
+++ b/src/library/scala/collection/generic/GenericArrayTagTraversableTemplate.scala
@@ -0,0 +1,30 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2010-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.collection
+package generic
+
+import mutable.Builder
+import annotation.unchecked.uncheckedVariance
+import language.higherKinds
+
+/** This trait represents collections classes which require array
+ * tags for their element types.
+ *
+ * @author Aleksandar Prokopec
+ * @since 2.8
+ */
+trait GenericArrayTagTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance] {
+ implicit protected[this] val tag: ArrayTag[A]
+ def arrayTagCompanion: GenericArrayTagCompanion[CC]
+ def genericArrayTagBuilder[B](implicit tag: ArrayTag[B]): Builder[B, CC[B]] = arrayTagCompanion.newBuilder[B]
+ @deprecated("use arrayTagCompanion instead", "2.10.0")
+ def classManifestCompanion: GenericClassManifestCompanion[CC] = arrayTagCompanion
+ @deprecated("use genericArrayTagBuilder instead", "2.10.0")
+ def genericClassManifestBuilder[B](implicit manifest: ClassManifest[B]): Builder[B, CC[B]] = genericArrayTagBuilder[B](manifest)
+}
diff --git a/src/library/scala/collection/generic/GenericClassManifestTraversableTemplate.scala b/src/library/scala/collection/generic/GenericClassManifestTraversableTemplate.scala
deleted file mode 100644
index 12b5a495f0..0000000000
--- a/src/library/scala/collection/generic/GenericClassManifestTraversableTemplate.scala
+++ /dev/null
@@ -1,25 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2010-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-package scala.collection
-package generic
-
-import mutable.Builder
-import annotation.unchecked.uncheckedVariance
-
-/** This trait represents collections classes which require class
- * manifests for their element types.
- *
- * @author Aleksandar Prokopec
- * @since 2.8
- */
-trait GenericClassManifestTraversableTemplate[+A, +CC[X] <: Traversable[X]] extends HasNewBuilder[A, CC[A] @uncheckedVariance] {
- implicit protected[this] val manifest: ClassManifest[A]
- def classManifestCompanion: GenericClassManifestCompanion[CC]
- def genericClassManifestBuilder[B](implicit man: ClassManifest[B]): Builder[B, CC[B]] = classManifestCompanion.newBuilder[B]
-}
diff --git a/src/library/scala/collection/generic/GenericCompanion.scala b/src/library/scala/collection/generic/GenericCompanion.scala
index b36a1e297f..badceac713 100644
--- a/src/library/scala/collection/generic/GenericCompanion.scala
+++ b/src/library/scala/collection/generic/GenericCompanion.scala
@@ -10,6 +10,7 @@ package scala.collection
package generic
import mutable.Builder
+import language.higherKinds
/** A template class for companion objects of "regular" collection classes
* represent an unconstrained higher-kinded type. Typically
@@ -19,7 +20,7 @@ import mutable.Builder
* @author Martin Odersky
* @since 2.8
* @define coll collection
- * @define Coll CC
+ * @define Coll `CC`
*/
abstract class GenericCompanion[+CC[X] <: GenTraversable[X]] {
/** The underlying collection type with unknown element type */
diff --git a/src/library/scala/collection/generic/GenericOrderedCompanion.scala b/src/library/scala/collection/generic/GenericOrderedCompanion.scala
index c3baa28147..290dc435c8 100644
--- a/src/library/scala/collection/generic/GenericOrderedCompanion.scala
+++ b/src/library/scala/collection/generic/GenericOrderedCompanion.scala
@@ -10,6 +10,7 @@ package scala.collection
package generic
import mutable.Builder
+import language.higherKinds
/** This class represents companions of classes which require the ordered trait
* for their element types.
diff --git a/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala b/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala
index 5cfc4666b3..6e04420315 100644
--- a/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala
+++ b/src/library/scala/collection/generic/GenericOrderedTraversableTemplate.scala
@@ -13,8 +13,7 @@ package generic
import mutable.Builder
import annotation.unchecked.uncheckedVariance
-
-
+import language.higherKinds
/** This trait represents collections classes which require
* ordered element types.
diff --git a/src/library/scala/collection/generic/GenericParCompanion.scala b/src/library/scala/collection/generic/GenericParCompanion.scala
index 40fcfa31d0..484da5c6d9 100644
--- a/src/library/scala/collection/generic/GenericParCompanion.scala
+++ b/src/library/scala/collection/generic/GenericParCompanion.scala
@@ -11,11 +11,12 @@ package scala.collection.generic
import scala.collection.parallel.Combiner
import scala.collection.parallel.ParIterable
import scala.collection.parallel.ParMap
+import language.higherKinds
/** A template class for companion objects of parallel collection classes.
* They should be mixed in together with `GenericCompanion` type.
*
- * @define Coll ParIterable
+ * @define Coll `ParIterable`
* @tparam CC the type constructor representing the collection class
* @since 2.8
*/
diff --git a/src/library/scala/collection/generic/GenericParTemplate.scala b/src/library/scala/collection/generic/GenericParTemplate.scala
index 430dcb9e29..fc1c3f5eaa 100644
--- a/src/library/scala/collection/generic/GenericParTemplate.scala
+++ b/src/library/scala/collection/generic/GenericParTemplate.scala
@@ -14,6 +14,7 @@ import scala.collection.parallel.ParMap
import scala.collection.parallel.TaskSupport
import annotation.unchecked.uncheckedVariance
+import language.higherKinds
/** A template trait for collections having a companion.
*
diff --git a/src/library/scala/collection/generic/GenericSeqCompanion.scala b/src/library/scala/collection/generic/GenericSeqCompanion.scala
index 41e8d6dd39..90063c1ca2 100644
--- a/src/library/scala/collection/generic/GenericSeqCompanion.scala
+++ b/src/library/scala/collection/generic/GenericSeqCompanion.scala
@@ -10,15 +10,7 @@
package scala.collection
package generic
-import annotation.bridge
+import language.higherKinds
trait GenericSeqCompanion[CC[X] <: Traversable[X]]
- extends GenericCompanion[CC] {
-
- @bridge
- override def empty[A]: CC[A] = super.empty[A]
-
- @bridge
- override def apply[A](elems: A*): CC[A] = super.apply(elems: _*)
-
-}
+ extends GenericCompanion[CC] \ No newline at end of file
diff --git a/src/library/scala/collection/generic/GenericSetTemplate.scala b/src/library/scala/collection/generic/GenericSetTemplate.scala
index 6af6a36981..221bcfb379 100644
--- a/src/library/scala/collection/generic/GenericSetTemplate.scala
+++ b/src/library/scala/collection/generic/GenericSetTemplate.scala
@@ -8,7 +8,7 @@
package scala.collection
package generic
-
+import language.higherKinds
/**
* @since 2.8
*/
diff --git a/src/library/scala/collection/generic/GenericTraversableTemplate.scala b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
index 6586434924..69eab43150 100644
--- a/src/library/scala/collection/generic/GenericTraversableTemplate.scala
+++ b/src/library/scala/collection/generic/GenericTraversableTemplate.scala
@@ -14,6 +14,7 @@ package generic
import mutable.Builder
import annotation.migration
import annotation.unchecked.uncheckedVariance
+import language.higherKinds
/** A template class for companion objects of ``regular`` collection classes
* that represent an unconstrained higher-kinded type.
@@ -146,11 +147,6 @@ trait GenericTraversableTemplate[+A, +CC[X] <: GenTraversable[X]] extends HasNew
b.result
}
- // cannot have a bridge, because it would have the same signature as the target method after erasure
- // @bridge
- // def flatten[B](implicit asTraversable: A => /*<:<!!!*/ TraversableOnce[B]): CC[B] =
- // flatten[B](asTraversable: A => GenTraversableOnce[B])
-
/** Transposes this $coll of traversable collections into
* a $coll of ${coll}s.
*
diff --git a/src/library/scala/collection/generic/Growable.scala b/src/library/scala/collection/generic/Growable.scala
index f0a70c2b88..d6a263af2f 100644
--- a/src/library/scala/collection/generic/Growable.scala
+++ b/src/library/scala/collection/generic/Growable.scala
@@ -18,11 +18,11 @@ package generic
* @version 2.8
* @since 2.8
* @define coll growable collection
- * @define Coll Growable
+ * @define Coll `Growable`
* @define add add
* @define Add add
*/
-trait Growable[-A] {
+trait Growable[-A] extends Clearable {
/** ${Add}s a single element to this $coll.
*
@@ -50,5 +50,5 @@ trait Growable[-A] {
/** Clears the $coll's contents. After this operation, the
* $coll is empty.
*/
- def clear()
+ def clear(): Unit
}
diff --git a/src/library/scala/collection/generic/ImmutableMapFactory.scala b/src/library/scala/collection/generic/ImmutableMapFactory.scala
index bdb657f320..d893188e92 100644
--- a/src/library/scala/collection/generic/ImmutableMapFactory.scala
+++ b/src/library/scala/collection/generic/ImmutableMapFactory.scala
@@ -10,6 +10,8 @@
package scala.collection
package generic
+import language.higherKinds
+
/** A template for companion objects of `immutable.Map` and subclasses thereof.
* @author Martin Odersky
* @version 2.8
diff --git a/src/library/scala/collection/generic/ImmutableSetFactory.scala b/src/library/scala/collection/generic/ImmutableSetFactory.scala
index e128be70a1..7bd5bf2ef8 100644
--- a/src/library/scala/collection/generic/ImmutableSetFactory.scala
+++ b/src/library/scala/collection/generic/ImmutableSetFactory.scala
@@ -10,6 +10,7 @@ package scala.collection
package generic
import mutable.{ Builder, SetBuilder }
+import language.higherKinds
abstract class ImmutableSetFactory[CC[X] <: immutable.Set[X] with SetLike[X, CC[X]]]
extends SetFactory[CC] {
diff --git a/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala b/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala
index 89e19eed87..f415a52b4d 100644
--- a/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala
+++ b/src/library/scala/collection/generic/ImmutableSortedMapFactory.scala
@@ -11,10 +11,12 @@
package scala.collection
package generic
+import language.higherKinds
+
/** A template for companion objects of `SortedMap` and subclasses thereof.
*
* @since 2.8
- * @define Coll SortedMap
+ * @define Coll `SortedMap`
* @define coll sorted map
* @define factoryInfo
* This object provides a set of operations needed to create sorted maps of type `$Coll`.
diff --git a/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala b/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala
index fe807d9fe6..1317bb4796 100644
--- a/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala
+++ b/src/library/scala/collection/generic/ImmutableSortedSetFactory.scala
@@ -11,11 +11,13 @@
package scala.collection
package generic
+import language.higherKinds
+
/** A template for companion objects of `SortedSet` and subclasses thereof.
*
* @since 2.8
- * @define Coll immutable.SortedSet
- * @define coll immutable sorted
+ * @define Coll `immutable.SortedSet`
+ * @define coll immutable sorted set
* @define factoryInfo
* This object provides a set of operations needed to create sorted sets of type `$Coll`.
* @author Martin Odersky
@@ -23,4 +25,4 @@ package generic
* @define sortedSetCanBuildFromInfo
* The standard `CanBuildFrom` instance for sorted sets
*/
-abstract class ImmutableSortedSetFactory[CC[A] <: immutable.SortedSet[A] with SortedSetLike[A, CC[A]]] extends SortedSetFactory[CC] \ No newline at end of file
+abstract class ImmutableSortedSetFactory[CC[A] <: immutable.SortedSet[A] with SortedSetLike[A, CC[A]]] extends SortedSetFactory[CC]
diff --git a/src/library/scala/collection/generic/MapFactory.scala b/src/library/scala/collection/generic/MapFactory.scala
index a60e3032c1..ce44ae9bf4 100644
--- a/src/library/scala/collection/generic/MapFactory.scala
+++ b/src/library/scala/collection/generic/MapFactory.scala
@@ -11,7 +11,7 @@ package generic
import mutable.{Builder, MapBuilder}
-import annotation.bridge
+import language.higherKinds
/** A template for companion objects of `Map` and subclasses thereof.
*
@@ -35,6 +35,4 @@ abstract class MapFactory[CC[A, B] <: Map[A, B] with MapLike[A, B, CC[A, B]]] ex
def empty[A, B]: CC[A, B]
- @bridge
- override def apply[A, B](elems: (A, B)*): CC[A, B] = super.apply(elems: _*)
}
diff --git a/src/library/scala/collection/generic/MutableMapFactory.scala b/src/library/scala/collection/generic/MutableMapFactory.scala
index 076e41c9f8..8b38b4ddd5 100644
--- a/src/library/scala/collection/generic/MutableMapFactory.scala
+++ b/src/library/scala/collection/generic/MutableMapFactory.scala
@@ -12,6 +12,7 @@ package scala.collection
package generic
import mutable.Builder
+import language.higherKinds
/** A template for companion objects of `mutable.Map` and subclasses thereof.
* @author Martin Odersky
diff --git a/src/library/scala/collection/generic/MutableSetFactory.scala b/src/library/scala/collection/generic/MutableSetFactory.scala
index 6130ef2042..f130489814 100644
--- a/src/library/scala/collection/generic/MutableSetFactory.scala
+++ b/src/library/scala/collection/generic/MutableSetFactory.scala
@@ -10,6 +10,7 @@ package scala.collection
package generic
import mutable.{ Builder, GrowingBuilder }
+import language.higherKinds
abstract class MutableSetFactory[CC[X] <: mutable.Set[X] with mutable.SetLike[X, CC[X]]]
extends SetFactory[CC] {
diff --git a/src/library/scala/collection/generic/MutableSortedSetFactory.scala b/src/library/scala/collection/generic/MutableSortedSetFactory.scala
index cbbedc0231..0e90ed999c 100644
--- a/src/library/scala/collection/generic/MutableSortedSetFactory.scala
+++ b/src/library/scala/collection/generic/MutableSortedSetFactory.scala
@@ -10,10 +10,11 @@ package scala.collection
package generic
import scala.collection.mutable.{ Builder, GrowingBuilder }
+import language.higherKinds
/**
- * @define Coll mutable.SortedSet
- * @define coll mutable sorted
+ * @define Coll `mutable.SortedSet`
+ * @define coll mutable sorted set
*
* @author Lucien Pereira
*
diff --git a/src/library/scala/collection/generic/OrderedTraversableFactory.scala b/src/library/scala/collection/generic/OrderedTraversableFactory.scala
index 259e4123c4..92f166ae08 100644
--- a/src/library/scala/collection/generic/OrderedTraversableFactory.scala
+++ b/src/library/scala/collection/generic/OrderedTraversableFactory.scala
@@ -10,9 +10,7 @@
package scala.collection
package generic
-
-
-
+import language.higherKinds
abstract class OrderedTraversableFactory[CC[X] <: Traversable[X] with GenericOrderedTraversableTemplate[X, CC]]
extends GenericOrderedCompanion[CC] {
diff --git a/src/library/scala/collection/generic/ParFactory.scala b/src/library/scala/collection/generic/ParFactory.scala
index 558024d45c..41dca8fbe9 100644
--- a/src/library/scala/collection/generic/ParFactory.scala
+++ b/src/library/scala/collection/generic/ParFactory.scala
@@ -10,13 +10,14 @@ package scala.collection.generic
import scala.collection.parallel.ParIterable
import scala.collection.parallel.Combiner
+import language.higherKinds
/** A template class for companion objects of `ParIterable` and subclasses
* thereof. This class extends `TraversableFactory` and provides a set of
* operations to create `$Coll` objects.
*
* @define coll parallel collection
- * @define Coll ParIterable
+ * @define Coll `ParIterable`
* @since 2.8
*/
abstract class ParFactory[CC[X] <: ParIterable[X] with GenericParTemplate[X, CC]]
diff --git a/src/library/scala/collection/generic/ParMapFactory.scala b/src/library/scala/collection/generic/ParMapFactory.scala
index 2d89f79c13..5aedf67924 100644
--- a/src/library/scala/collection/generic/ParMapFactory.scala
+++ b/src/library/scala/collection/generic/ParMapFactory.scala
@@ -12,13 +12,14 @@ import scala.collection.parallel.ParMap
import scala.collection.parallel.ParMapLike
import scala.collection.parallel.Combiner
import scala.collection.mutable.Builder
+import language.higherKinds
/** A template class for companion objects of `ParMap` and subclasses thereof.
* This class extends `TraversableFactory` and provides a set of operations
* to create `$Coll` objects.
*
* @define coll parallel map
- * @define Coll ParMap
+ * @define Coll `ParMap`
* @author Aleksandar Prokopec
* @since 2.8
*/
diff --git a/src/library/scala/collection/generic/ParSetFactory.scala b/src/library/scala/collection/generic/ParSetFactory.scala
index c2cf971d73..30a36a734a 100644
--- a/src/library/scala/collection/generic/ParSetFactory.scala
+++ b/src/library/scala/collection/generic/ParSetFactory.scala
@@ -12,6 +12,7 @@ import collection.mutable.Builder
import collection.parallel.Combiner
import collection.parallel.ParSet
import collection.parallel.ParSetLike
+import language.higherKinds
/**
* @author Aleksandar Prokopec
diff --git a/src/library/scala/collection/generic/SeqFactory.scala b/src/library/scala/collection/generic/SeqFactory.scala
index 7bd92173ff..3f61de6ceb 100644
--- a/src/library/scala/collection/generic/SeqFactory.scala
+++ b/src/library/scala/collection/generic/SeqFactory.scala
@@ -10,6 +10,7 @@
package scala.collection
package generic
+import language.higherKinds
/** A template for companion objects of Seq and subclasses thereof.
*
diff --git a/src/library/scala/collection/generic/SetFactory.scala b/src/library/scala/collection/generic/SetFactory.scala
index 348743a120..646e99dd1e 100644
--- a/src/library/scala/collection/generic/SetFactory.scala
+++ b/src/library/scala/collection/generic/SetFactory.scala
@@ -12,14 +12,7 @@ package scala.collection
package generic
import mutable.Builder
-import annotation.bridge
+import language.higherKinds
abstract class SetFactory[CC[X] <: Set[X] with SetLike[X, CC[X]]]
- extends GenSetFactory[CC] with GenericSeqCompanion[CC] {
-
- @bridge
- override def empty[A]: CC[A] = super.empty[A]
-
- @bridge
- override def apply[A](elems: A*): CC[A] = super.apply(elems: _*)
-}
+ extends GenSetFactory[CC] with GenericSeqCompanion[CC] \ No newline at end of file
diff --git a/src/library/scala/collection/generic/Shrinkable.scala b/src/library/scala/collection/generic/Shrinkable.scala
index 88c7ce3a3d..0c9dafefb1 100644
--- a/src/library/scala/collection/generic/Shrinkable.scala
+++ b/src/library/scala/collection/generic/Shrinkable.scala
@@ -17,7 +17,7 @@ package generic
* @version 2.8
* @since 2.8
* @define coll shrinkable collection
- * @define Coll Shrinkable
+ * @define Coll `Shrinkable`
*/
trait Shrinkable[-A] {
diff --git a/src/library/scala/collection/generic/SortedMapFactory.scala b/src/library/scala/collection/generic/SortedMapFactory.scala
index 962a945037..f038c8b09b 100644
--- a/src/library/scala/collection/generic/SortedMapFactory.scala
+++ b/src/library/scala/collection/generic/SortedMapFactory.scala
@@ -12,6 +12,7 @@ package scala.collection
package generic
import mutable.{Builder, MapBuilder}
+import language.higherKinds
/** A template for companion objects of mutable.Map and subclasses thereof.
*
diff --git a/src/library/scala/collection/generic/SortedSetFactory.scala b/src/library/scala/collection/generic/SortedSetFactory.scala
index 45340cf6c1..bb261803a9 100644
--- a/src/library/scala/collection/generic/SortedSetFactory.scala
+++ b/src/library/scala/collection/generic/SortedSetFactory.scala
@@ -12,6 +12,7 @@ package scala.collection
package generic
import mutable.{Builder, SetBuilder}
+import language.higherKinds
/** A template for companion objects of Set and subclasses thereof.
*
diff --git a/src/library/scala/collection/generic/Subtractable.scala b/src/library/scala/collection/generic/Subtractable.scala
index 1ca9d706f0..cda71c0291 100644
--- a/src/library/scala/collection/generic/Subtractable.scala
+++ b/src/library/scala/collection/generic/Subtractable.scala
@@ -10,7 +10,6 @@
package scala.collection
package generic
-import annotation.bridge
/** This trait represents collection-like objects that can be reduced
* using a '+' operator. It defines variants of `-` and `--`
@@ -58,7 +57,4 @@ trait Subtractable[A, +Repr <: Subtractable[A, Repr]] { self =>
* except one less occurrence of each of the elements of `elems`.
*/
def --(xs: GenTraversableOnce[A]): Repr = (repr /: xs.seq) (_ - _)
-
- @bridge
- def --(xs: TraversableOnce[A]): Repr = --(xs: GenTraversableOnce[A])
}
diff --git a/src/library/scala/collection/generic/TraversableFactory.scala b/src/library/scala/collection/generic/TraversableFactory.scala
index e71de1252c..254a6a224f 100644
--- a/src/library/scala/collection/generic/TraversableFactory.scala
+++ b/src/library/scala/collection/generic/TraversableFactory.scala
@@ -10,7 +10,7 @@
package scala.collection
package generic
-import annotation.bridge
+import language.higherKinds
/** A template for companion objects of `Traversable` and subclasses thereof.
* This class provides a set of operations to create `$Coll` objects.
@@ -36,48 +36,5 @@ import annotation.bridge
* @see GenericCanBuildFrom
*/
trait TraversableFactory[CC[X] <: Traversable[X] with GenericTraversableTemplate[X, CC]]
- extends GenTraversableFactory[CC] with GenericSeqCompanion[CC] {
-
- @bridge
- override def concat[A](xss: Traversable[A]*): CC[A] = super.concat(xss: _*)
-
- @bridge
- override def fill[A](n: Int)(elem: => A): CC[A] = super.fill(n)(elem)
-
- @bridge
- override def fill[A](n1: Int, n2: Int)(elem: => A): CC[CC[A]] = super.fill(n1, n2)(elem)
-
- @bridge
- override def fill[A](n1: Int, n2: Int, n3: Int)(elem: => A): CC[CC[CC[A]]] = super.fill(n1, n2, n3)(elem)
-
- @bridge
- override def fill[A](n1: Int, n2: Int, n3: Int, n4: Int)(elem: => A): CC[CC[CC[CC[A]]]] = super.fill(n1, n2, n3, n4)(elem)
-
- @bridge
- override def fill[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(elem: => A): CC[CC[CC[CC[CC[A]]]]] = super.fill(n1, n2, n3, n4, n5)(elem)
-
- @bridge
- override def tabulate[A](n: Int)(f: Int => A): CC[A] = super.tabulate(n)(f)
-
- @bridge
- override def tabulate[A](n1: Int, n2: Int)(f: (Int, Int) => A): CC[CC[A]] = super.tabulate(n1, n2)(f)
-
- @bridge
- override def tabulate[A](n1: Int, n2: Int, n3: Int)(f: (Int, Int, Int) => A): CC[CC[CC[A]]] = super.tabulate(n1, n2, n3)(f)
-
- @bridge
- override def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int)(f: (Int, Int, Int, Int) => A): CC[CC[CC[CC[A]]]] = super.tabulate(n1, n2, n3, n4)(f)
-
- @bridge
- override def tabulate[A](n1: Int, n2: Int, n3: Int, n4: Int, n5: Int)(f: (Int, Int, Int, Int, Int) => A): CC[CC[CC[CC[CC[A]]]]] = super.tabulate(n1, n2, n3, n4, n5)(f)
-
- @bridge
- override def range[T: Integral](start: T, end: T): CC[T] = super.range(start, end)
-
- @bridge
- override def range[T: Integral](start: T, end: T, step: T): CC[T] = super.range(start, end, step)
-
- @bridge
- override def iterate[A](start: A, len: Int)(f: A => A): CC[A] = super.iterate(start, len)(f)
-}
+ extends GenTraversableFactory[CC] with GenericSeqCompanion[CC]
diff --git a/src/library/scala/collection/generic/TraversableForwarder.scala b/src/library/scala/collection/generic/TraversableForwarder.scala
index 3d723a1feb..3d5bc2704f 100644
--- a/src/library/scala/collection/generic/TraversableForwarder.scala
+++ b/src/library/scala/collection/generic/TraversableForwarder.scala
@@ -57,7 +57,7 @@ trait TraversableForwarder[+A] extends Traversable[A] {
override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int) = underlying.copyToArray(xs, start, len)
override def copyToArray[B >: A](xs: Array[B], start: Int) = underlying.copyToArray(xs, start)
override def copyToArray[B >: A](xs: Array[B]) = underlying.copyToArray(xs)
- override def toArray[B >: A: ClassManifest]: Array[B] = underlying.toArray
+ override def toArray[B >: A: ArrayTag]: Array[B] = underlying.toArray
override def toList: List[A] = underlying.toList
override def toIterable: Iterable[A] = underlying.toIterable
override def toSeq: Seq[A] = underlying.toSeq
diff --git a/src/library/scala/collection/generic/package.scala b/src/library/scala/collection/generic/package.scala
index 0457fef227..32006b4bf0 100644
--- a/src/library/scala/collection/generic/package.scala
+++ b/src/library/scala/collection/generic/package.scala
@@ -3,4 +3,13 @@ import generic.CanBuildFrom
package object generic {
type CanBuild[-Elem, +To] = CanBuildFrom[Nothing, Elem, To]
+
+ @deprecated("use ArrayTagTraversableFactory instead", "2.10.0")
+ type ClassManifestTraversableFactory[CC[X] <: Traversable[X] with GenericClassManifestTraversableTemplate[X, CC]] = ArrayTagTraversableFactory[CC]
+
+ @deprecated("use GenericArrayTagCompanion instead", "2.10.0")
+ type GenericClassManifestCompanion[+CC[X] <: Traversable[X]] = GenericArrayTagCompanion[CC]
+
+ @deprecated("use GenericArrayTagTraversableTemplate instead", "2.10.0")
+ type GenericClassManifestTraversableTemplate[+A, +CC[X] <: Traversable[X]] = GenericArrayTagTraversableTemplate[A, CC]
} \ No newline at end of file
diff --git a/src/library/scala/collection/immutable/BitSet.scala b/src/library/scala/collection/immutable/BitSet.scala
index 870d5534dc..1b676e2d2f 100644
--- a/src/library/scala/collection/immutable/BitSet.scala
+++ b/src/library/scala/collection/immutable/BitSet.scala
@@ -20,7 +20,7 @@ import mutable.{ Builder, SetBuilder }
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#immutable_bitsets "Scala's Collection Library overview"]]
* section on `Immutable BitSets` for more information.
*
- * @define Coll immutable.BitSet
+ * @define Coll `immutable.BitSet`
* @define coll immutable bitset
*/
@SerialVersionUID(1611436763290191562L)
@@ -63,7 +63,7 @@ abstract class BitSet extends scala.collection.AbstractSet[Int]
}
/** $factoryInfo
- * @define Coll immutable.BitSet
+ * @define Coll `immutable.BitSet`
* @define coll immutable bitset
*/
object BitSet extends BitSetFactory[BitSet] {
diff --git a/src/library/scala/collection/immutable/GenSeq.scala.disabled b/src/library/scala/collection/immutable/GenSeq.scala.disabled
index 5b59418b9f..b8bc420ec3 100644
--- a/src/library/scala/collection/immutable/GenSeq.scala.disabled
+++ b/src/library/scala/collection/immutable/GenSeq.scala.disabled
@@ -25,7 +25,7 @@ import mutable.Builder
*
* The class adds an `update` method to `collection.Seq`.
*
- * @define Coll mutable.Seq
+ * @define Coll `mutable.Seq`
* @define coll mutable sequence
*/
trait GenSeq[+A] extends GenIterable[A]
diff --git a/src/library/scala/collection/immutable/GenSet.scala.disabled b/src/library/scala/collection/immutable/GenSet.scala.disabled
index dc921b5245..828219580e 100644
--- a/src/library/scala/collection/immutable/GenSet.scala.disabled
+++ b/src/library/scala/collection/immutable/GenSet.scala.disabled
@@ -24,7 +24,7 @@ import mutable.Builder
*
* @since 1.0
* @author Matthias Zenger
- * @define Coll mutable.Set
+ * @define Coll `mutable.Set`
* @define coll mutable set
*/
trait GenSet[A] extends GenIterable[A]
diff --git a/src/library/scala/collection/immutable/HashMap.scala b/src/library/scala/collection/immutable/HashMap.scala
index 6b11371bec..13a0febfee 100644
--- a/src/library/scala/collection/immutable/HashMap.scala
+++ b/src/library/scala/collection/immutable/HashMap.scala
@@ -27,7 +27,7 @@ import parallel.immutable.ParHashMap
* @since 2.3
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#hash_tries "Scala's Collection Library overview"]]
* section on `Hash Tries` for more information.
- * @define Coll immutable.HashMap
+ * @define Coll `immutable.HashMap`
* @define coll immutable hash map
* @define mayNotTerminateInf
* @define willNotTerminateInf
@@ -96,7 +96,7 @@ class HashMap[A, +B] extends AbstractMap[A, B]
}
/** $factoryInfo
- * @define Coll immutable.HashMap
+ * @define Coll `immutable.HashMap`
* @define coll immutable hash map
*
* @author Tiark Rompf
diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala
index 79d2fb71cc..b956a4d838 100644
--- a/src/library/scala/collection/immutable/HashSet.scala
+++ b/src/library/scala/collection/immutable/HashSet.scala
@@ -26,7 +26,7 @@ import collection.parallel.immutable.ParHashSet
* @author Tiark Rompf
* @version 2.8
* @since 2.3
- * @define Coll immutable.HashSet
+ * @define Coll `immutable.HashSet`
* @define coll immutable hash set
*/
@SerialVersionUID(2L)
@@ -85,12 +85,12 @@ class HashSet[A] extends AbstractSet[A]
}
/** $factoryInfo
- * @define Coll immutable.HashSet
+ * @define Coll `immutable.HashSet`
* @define coll immutable hash set
*
* @author Tiark Rompf
* @since 2.3
- * @define Coll immutable.HashSet
+ * @define Coll `immutable.HashSet`
* @define coll immutable hash set
* @define mayNotTerminateInf
* @define willNotTerminateInf
diff --git a/src/library/scala/collection/immutable/IndexedSeq.scala b/src/library/scala/collection/immutable/IndexedSeq.scala
index e3939001d8..b37edc4254 100644
--- a/src/library/scala/collection/immutable/IndexedSeq.scala
+++ b/src/library/scala/collection/immutable/IndexedSeq.scala
@@ -29,7 +29,7 @@ trait IndexedSeq[+A] extends Seq[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `Vector`.
* @define coll indexed sequence
- * @define Coll IndexedSeq
+ * @define Coll `IndexedSeq`
*/
object IndexedSeq extends SeqFactory[IndexedSeq] {
class Impl[A](buf: ArrayBuffer[A]) extends AbstractSeq[A] with IndexedSeq[A] with Serializable {
diff --git a/src/library/scala/collection/immutable/IntMap.scala b/src/library/scala/collection/immutable/IntMap.scala
index 3c9c0c2f24..039a57041c 100644
--- a/src/library/scala/collection/immutable/IntMap.scala
+++ b/src/library/scala/collection/immutable/IntMap.scala
@@ -36,7 +36,7 @@ import IntMapUtils._
/** A companion object for integer maps.
*
- * @define Coll IntMap
+ * @define Coll `IntMap`
* @define mapCanBuildFromInfo
* The standard `CanBuildFrom` instance for `$Coll` objects.
* The created value is an instance of class `MapCanBuildFrom`.
@@ -150,7 +150,7 @@ import IntMap._
* @tparam T type of the values associated with integer keys.
*
* @since 2.7
- * @define Coll immutable.IntMap
+ * @define Coll `immutable.IntMap`
* @define coll immutable integer map
* @define mayNotTerminateInf
* @define willNotTerminateInf
diff --git a/src/library/scala/collection/immutable/Iterable.scala b/src/library/scala/collection/immutable/Iterable.scala
index d5fca2bdff..a1390ba189 100644
--- a/src/library/scala/collection/immutable/Iterable.scala
+++ b/src/library/scala/collection/immutable/Iterable.scala
@@ -18,7 +18,7 @@ import parallel.immutable.ParIterable
/** A base trait for iterable collections that are guaranteed immutable.
* $iterableInfo
*
- * @define Coll immutable.Iterable
+ * @define Coll `immutable.Iterable`
* @define coll immutable iterable collection
*/
trait Iterable[+A] extends Traversable[A]
@@ -34,7 +34,7 @@ trait Iterable[+A] extends Traversable[A]
}
/** $factoryInfo
- * @define Coll immutable.Iterable
+ * @define Coll `immutable.Iterable`
* @define coll immutable iterable collection
*/
object Iterable extends TraversableFactory[Iterable] {
diff --git a/src/library/scala/collection/immutable/LinearSeq.scala b/src/library/scala/collection/immutable/LinearSeq.scala
index 536894c287..2d6986740a 100644
--- a/src/library/scala/collection/immutable/LinearSeq.scala
+++ b/src/library/scala/collection/immutable/LinearSeq.scala
@@ -29,7 +29,7 @@ trait LinearSeq[+A] extends Seq[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `List`.
* @define coll immutable linear sequence
- * @define Coll immutable.LinearSeq
+ * @define Coll `immutable.LinearSeq`
*/
object LinearSeq extends SeqFactory[LinearSeq] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinearSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/immutable/List.scala b/src/library/scala/collection/immutable/List.scala
index 1b75c10113..b4c22c3b6c 100644
--- a/src/library/scala/collection/immutable/List.scala
+++ b/src/library/scala/collection/immutable/List.scala
@@ -141,7 +141,7 @@ sealed abstract class List[+A] extends AbstractSeq[A]
/** Builds a new list by applying a function to all elements of this list.
* Like `xs map f`, but returns `xs` unchanged if function
- * `f` maps all elements to themselves (wrt eq).
+ * `f` maps all elements to themselves (as determined by `eq`).
*
* @param f the function to apply to each element.
* @tparam B the element type of the returned collection.
@@ -382,7 +382,7 @@ final case class ::[B](private var hd: B, private[scala] var tl: List[B]) extend
/** $factoryInfo
* @define coll list
- * @define Coll List
+ * @define Coll `List`
*/
object List extends SeqFactory[List] {
diff --git a/src/library/scala/collection/immutable/ListMap.scala b/src/library/scala/collection/immutable/ListMap.scala
index e008fb86e3..9289b35632 100644
--- a/src/library/scala/collection/immutable/ListMap.scala
+++ b/src/library/scala/collection/immutable/ListMap.scala
@@ -105,9 +105,6 @@ extends AbstractMap[A, B]
override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): ListMap[A, B1] =
((repr: ListMap[A, B1]) /: xs.seq) (_ + _)
- @bridge def ++[B1 >: B](xs: TraversableOnce[(A, B1)]): ListMap[A, B1] =
- ++(xs: GenTraversableOnce[(A, B1)])
-
/** This creates a new mapping without the given `key`.
* If the map does not contain a mapping for the given key, the
* method returns the same map.
diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala
index 47e3245117..0331e01f35 100644
--- a/src/library/scala/collection/immutable/ListSet.scala
+++ b/src/library/scala/collection/immutable/ListSet.scala
@@ -33,7 +33,7 @@ object ListSet extends ImmutableSetFactory[ListSet] {
*/
class ListSetBuilder[Elem](initial: ListSet[Elem]) extends Builder[Elem, ListSet[Elem]] {
def this() = this(empty[Elem])
- protected val elems = new mutable.ListBuffer[Elem] ++= initial reverse
+ protected val elems = (new mutable.ListBuffer[Elem] ++= initial).reverse
protected val seen = new mutable.HashSet[Elem] ++= initial
def +=(x: Elem): this.type = {
@@ -100,9 +100,7 @@ class ListSet[A] extends AbstractSet[A]
*/
override def ++(xs: GenTraversableOnce[A]): ListSet[A] =
if (xs.isEmpty) this
- else new ListSet.ListSetBuilder(this) ++= xs.seq result
-
- @bridge def ++(xs: TraversableOnce[A]): ListSet[A] = ++(xs: GenTraversableOnce[A]): ListSet[A]
+ else (new ListSet.ListSetBuilder(this) ++= xs.seq).result
private[ListSet] def unchecked_+(e: A): ListSet[A] = new Node(e)
private[ListSet] def unchecked_outer: ListSet[A] =
diff --git a/src/library/scala/collection/immutable/LongMap.scala b/src/library/scala/collection/immutable/LongMap.scala
index 11b5d1e311..8a316f37de 100644
--- a/src/library/scala/collection/immutable/LongMap.scala
+++ b/src/library/scala/collection/immutable/LongMap.scala
@@ -36,7 +36,7 @@ import LongMapUtils._
/** A companion object for long maps.
*
- * @define Coll LongMap
+ * @define Coll `LongMap`
* @define mapCanBuildFromInfo
* The standard `CanBuildFrom` instance for `$Coll` objects.
* The created value is an instance of class `MapCanBuildFrom`.
@@ -147,7 +147,7 @@ import LongMap._;
* @tparam T type of the values associated with the long keys.
*
* @since 2.7
- * @define Coll immutable.LongMap
+ * @define Coll `immutable.LongMap`
* @define coll immutable long integer map
* @define mayNotTerminateInf
* @define willNotTerminateInf
diff --git a/src/library/scala/collection/immutable/Map.scala b/src/library/scala/collection/immutable/Map.scala
index bbefd983fd..e73da01ac4 100644
--- a/src/library/scala/collection/immutable/Map.scala
+++ b/src/library/scala/collection/immutable/Map.scala
@@ -66,7 +66,7 @@ trait Map[A, +B] extends Iterable[(A, B)]
}
/** $factoryInfo
- * @define Coll immutable.Map
+ * @define Coll `immutable.Map`
* @define coll immutable map
*/
object Map extends ImmutableMapFactory[Map] {
diff --git a/src/library/scala/collection/immutable/MapLike.scala b/src/library/scala/collection/immutable/MapLike.scala
index 80da1ab010..84c87b4eae 100644
--- a/src/library/scala/collection/immutable/MapLike.scala
+++ b/src/library/scala/collection/immutable/MapLike.scala
@@ -11,7 +11,6 @@ package immutable
import generic._
import parallel.immutable.ParMap
-import annotation.bridge
/**
* A generic template for immutable maps from keys of type `A`
@@ -86,8 +85,6 @@ trait MapLike[A, +B, +This <: MapLike[A, B, This] with Map[A, B]]
override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): immutable.Map[A, B1] =
((repr: immutable.Map[A, B1]) /: xs.seq) (_ + _)
- @bridge def ++[B1 >: B](xs: TraversableOnce[(A, B1)]): immutable.Map[A, B1] = ++(xs: GenTraversableOnce[(A, B1)])
-
/** Filters this map by retaining only keys satisfying a predicate.
* @param p the predicate used to test keys
* @return an immutable map consisting only of those key value pairs of this map where the key satisfies
diff --git a/src/library/scala/collection/immutable/NumericRange.scala b/src/library/scala/collection/immutable/NumericRange.scala
index 65bd9ab6f2..4c82d99c03 100644
--- a/src/library/scala/collection/immutable/NumericRange.scala
+++ b/src/library/scala/collection/immutable/NumericRange.scala
@@ -34,7 +34,7 @@ import generic._
*
* @author Paul Phillips
* @version 2.8
- * @define Coll NumericRange
+ * @define Coll `NumericRange`
* @define coll numeric range
* @define mayNotTerminateInf
* @define willNotTerminateInf
@@ -172,6 +172,13 @@ extends AbstractSeq[T] with IndexedSeq[T] with Serializable {
try containsTyped(x.asInstanceOf[T])
catch { case _: ClassCastException => false }
+ final override def sum[B >: T](implicit num: Numeric[B]): B = {
+ import num.Ops
+ if (isEmpty) this.num fromInt 0
+ else if (numRangeElements == 1) head
+ else ((this.num fromInt numRangeElements) * (head + last) / (this.num fromInt 2))
+ }
+
override lazy val hashCode = super.hashCode()
override def equals(other: Any) = other match {
case x: NumericRange[_] =>
diff --git a/src/library/scala/collection/immutable/PagedSeq.scala b/src/library/scala/collection/immutable/PagedSeq.scala
index 97c7c789f8..94953ce38b 100644
--- a/src/library/scala/collection/immutable/PagedSeq.scala
+++ b/src/library/scala/collection/immutable/PagedSeq.scala
@@ -25,7 +25,7 @@ object PagedSeq {
final val UndeterminedEnd = Int.MaxValue
/** Constructs a paged sequence from an iterator */
- def fromIterator[T: ClassManifest](source: Iterator[T]): PagedSeq[T] =
+ def fromIterator[T: ArrayTag](source: Iterator[T]): PagedSeq[T] =
new PagedSeq[T]((data: Array[T], start: Int, len: Int) => {
var i = 0
while (i < len && source.hasNext) {
@@ -36,7 +36,7 @@ object PagedSeq {
})
/** Constructs a paged sequence from an iterable */
- def fromIterable[T: ClassManifest](source: Iterable[T]): PagedSeq[T] =
+ def fromIterable[T: ArrayTag](source: Iterable[T]): PagedSeq[T] =
fromIterator(source.iterator)
/** Constructs a paged character sequence from a string iterator */
@@ -115,16 +115,16 @@ import PagedSeq._
* It returns the number of elements produced, or -1 if end of logical input stream was reached
* before reading any element.
*
- * @tparam T the type of the elements contained in this paged sequence, with a `ClassManifest` context bound.
+ * @tparam T the type of the elements contained in this paged sequence, with an `ArrayTag` context bound.
*
* @author Martin Odersky
* @since 2.7
- * @define Coll PagedSeq
+ * @define Coll `PagedSeq`
* @define coll paged sequence
* @define mayNotTerminateInf
* @define willNotTerminateInf
*/
-class PagedSeq[T: ClassManifest] protected(
+class PagedSeq[T: ArrayTag] protected(
more: (Array[T], Int, Int) => Int,
first1: Page[T],
start: Int,
@@ -205,7 +205,7 @@ extends scala.collection.AbstractSeq[T]
/** Page containing up to PageSize characters of the input sequence.
*/
-private class Page[T: ClassManifest](val num: Int) {
+private class Page[T: ArrayTag](val num: Int) {
private final val PageSize = 4096
diff --git a/src/library/scala/collection/immutable/Queue.scala b/src/library/scala/collection/immutable/Queue.scala
index da04446281..e980dda847 100644
--- a/src/library/scala/collection/immutable/Queue.scala
+++ b/src/library/scala/collection/immutable/Queue.scala
@@ -30,7 +30,7 @@ import annotation.tailrec
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#immutable_queues "Scala's Collection Library overview"]]
* section on `Immutable Queues` for more information.
*
- * @define Coll immutable.Queue
+ * @define Coll `immutable.Queue`
* @define coll immutable queue
* @define mayNotTerminateInf
* @define willNotTerminateInf
@@ -131,7 +131,7 @@ class Queue[+A] protected(protected val in: List[A], protected val out: List[A])
}
/** $factoryInfo
- * @define Coll immutable.Queue
+ * @define Coll `immutable.Queue`
* @define coll immutable queue
*/
object Queue extends SeqFactory[Queue] {
diff --git a/src/library/scala/collection/immutable/Range.scala b/src/library/scala/collection/immutable/Range.scala
index b72d83f896..033331b58b 100644
--- a/src/library/scala/collection/immutable/Range.scala
+++ b/src/library/scala/collection/immutable/Range.scala
@@ -10,7 +10,6 @@
package scala.collection.immutable
import scala.collection.parallel.immutable.ParRange
-import annotation.bridge
/** The `Range` class represents integer values in range
* ''[start;end)'' with non-zero step value `step`.
@@ -328,16 +327,16 @@ object Range {
*/
def apply(start: Int, end: Int, step: Int): Range = new Range(start, end, step)
- /** Make an range from `start` to `end` inclusive with step value 1.
+ /** Make a range from `start` until `end` (exclusive) with step value 1.
*/
def apply(start: Int, end: Int): Range = new Range(start, end, 1)
- /** Make an inclusive range from start to end with given step value.
+ /** Make an inclusive range from `start` to `end` with given step value.
* @note step != 0
*/
@inline def inclusive(start: Int, end: Int, step: Int): Range.Inclusive = new Inclusive(start, end, step)
- /** Make an inclusive range from start to end with step value 1.
+ /** Make an inclusive range from `start` to `end` with step value 1.
*/
@inline def inclusive(start: Int, end: Int): Range.Inclusive = new Inclusive(start, end, 1)
@@ -398,10 +397,4 @@ object Range {
def apply(start: Int, end: Int, step: Int) = NumericRange(start, end, step)
def inclusive(start: Int, end: Int, step: Int) = NumericRange.inclusive(start, end, step)
}
-
- @deprecated("use Range instead", "2.9.0")
- trait ByOne extends Range {
-// @bridge override def foreach[@specialized(Unit) U](f: Int => U) =
-// super.foreach(f)
- }
}
diff --git a/src/library/scala/collection/immutable/Seq.scala b/src/library/scala/collection/immutable/Seq.scala
index 882ca12612..1104eb1b4f 100644
--- a/src/library/scala/collection/immutable/Seq.scala
+++ b/src/library/scala/collection/immutable/Seq.scala
@@ -19,7 +19,7 @@ import parallel.immutable.ParSeq
* that are guaranteed immutable.
*
* $seqInfo
- * @define Coll immutable.Seq
+ * @define Coll `immutable.Seq`
* @define coll immutable sequence
*/
trait Seq[+A] extends Iterable[A]
@@ -36,7 +36,7 @@ trait Seq[+A] extends Iterable[A]
}
/** $factoryInfo
- * @define Coll immutable.Seq
+ * @define Coll `immutable.Seq`
* @define coll immutable sequence
*/
object Seq extends SeqFactory[Seq] {
diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala
index cd972d6c30..f783f2d562 100644
--- a/src/library/scala/collection/immutable/Set.scala
+++ b/src/library/scala/collection/immutable/Set.scala
@@ -21,7 +21,7 @@ import parallel.immutable.ParSet
* @since 1.0
* @author Matthias Zenger
* @author Martin Odersky
- * @define Coll immutable.Set
+ * @define Coll `immutable.Set`
* @define coll immutable set
*/
trait Set[A] extends Iterable[A]
@@ -38,7 +38,7 @@ trait Set[A] extends Iterable[A]
}
/** $factoryInfo
- * @define Coll immutable.Set
+ * @define Coll `immutable.Set`
* @define coll immutable set
*/
object Set extends ImmutableSetFactory[Set] {
diff --git a/src/library/scala/collection/immutable/SortedMap.scala b/src/library/scala/collection/immutable/SortedMap.scala
index 902a0f8457..526f7a1ffe 100644
--- a/src/library/scala/collection/immutable/SortedMap.scala
+++ b/src/library/scala/collection/immutable/SortedMap.scala
@@ -14,7 +14,6 @@ package immutable
import generic._
import mutable.Builder
import annotation.unchecked.uncheckedVariance
-import annotation.bridge
/** A map whose keys are sorted.
*
@@ -77,8 +76,6 @@ trait SortedMap[A, +B] extends Map[A, B]
*/
override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): SortedMap[A, B1] =
((repr: SortedMap[A, B1]) /: xs.seq) (_ + _)
-
- @bridge def ++[B1 >: B](xs: TraversableOnce[(A, B1)]): SortedMap[A, B1] = ++(xs: GenTraversableOnce[(A, B1)])
}
/** $factoryInfo
diff --git a/src/library/scala/collection/immutable/SortedSet.scala b/src/library/scala/collection/immutable/SortedSet.scala
index e1637ce78b..62fa4e0335 100644
--- a/src/library/scala/collection/immutable/SortedSet.scala
+++ b/src/library/scala/collection/immutable/SortedSet.scala
@@ -21,7 +21,7 @@ import mutable.Builder
* @author Martin Odersky
* @version 2.8
* @since 2.4
- * @define Coll immutable.SortedSet
+ * @define Coll `immutable.SortedSet`
* @define coll immutable sorted set
*/
trait SortedSet[A] extends Set[A] with scala.collection.SortedSet[A] with SortedSetLike[A, SortedSet[A]] {
@@ -30,7 +30,7 @@ trait SortedSet[A] extends Set[A] with scala.collection.SortedSet[A] with Sorted
}
/** $factoryInfo
- * @define Coll immutable.SortedSet
+ * @define Coll `immutable.SortedSet`
* @define coll immutable sorted set
*/
object SortedSet extends ImmutableSortedSetFactory[SortedSet] {
diff --git a/src/library/scala/collection/immutable/Stack.scala b/src/library/scala/collection/immutable/Stack.scala
index 50fc2795c0..c63c1ce232 100644
--- a/src/library/scala/collection/immutable/Stack.scala
+++ b/src/library/scala/collection/immutable/Stack.scala
@@ -13,7 +13,7 @@ import generic._
import mutable.{ ArrayBuffer, Builder }
/** $factoryInfo
- * @define Coll immutable.Stack
+ * @define Coll `immutable.Stack`
* @define coll immutable stack
*/
object Stack extends SeqFactory[Stack] {
@@ -37,7 +37,7 @@ object Stack extends SeqFactory[Stack] {
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#immutable_stacks "Scala's Collection Library overview"]]
* section on `Immutable stacks` for more information.
*
- * @define Coll immutable.Stack
+ * @define Coll `immutable.Stack`
* @define coll immutable stack
* @define orderDependent
* @define orderDependentFold
diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala
index 2eb2f8eb09..f3e7214c5f 100644
--- a/src/library/scala/collection/immutable/Stream.scala
+++ b/src/library/scala/collection/immutable/Stream.scala
@@ -13,6 +13,7 @@ import generic._
import mutable.{Builder, StringBuilder, LazyBuilder, ListBuffer}
import scala.annotation.tailrec
import Stream.cons
+import language.implicitConversions
/** The class `Stream` implements lazy lists where elements
* are only evaluated when they are needed. Here is an example:
@@ -176,7 +177,7 @@ import Stream.cons
* section on `Streams` for more information.
* @define naturalsEx def naturalsFrom(i: Int): Stream[Int] = i #:: naturalsFrom(i + 1)
- * @define Coll Stream
+ * @define Coll `Stream`
* @define coll stream
* @define orderDependent
* @define orderDependentFold
@@ -804,9 +805,9 @@ self =>
these
}
- /** Builds a new stream from this stream in which any duplicates (wrt to ==)
- * have been removed. Among duplicate elements, only the first one is
- * retained in the resulting `Stream`.
+ /** Builds a new stream from this stream in which any duplicates (as
+ * determined by `==`) have been removed. Among duplicate elements, only the
+ * first one is retained in the resulting `Stream`.
*
* @return A new `Stream` representing the result of applying distinctness to
* the original `Stream`.
@@ -821,7 +822,7 @@ self =>
*/
override def distinct: Stream[A] =
if (isEmpty) this
- else cons(head, tail.filter(head !=).distinct)
+ else cons(head, tail.filter(head != _).distinct)
/** Returns a new sequence of given length containing the elements of this
* sequence followed by zero or more occurrences of given elements.
diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala
index fc4e7bf0a8..d1605bf637 100644
--- a/src/library/scala/collection/immutable/StringLike.scala
+++ b/src/library/scala/collection/immutable/StringLike.scala
@@ -33,7 +33,7 @@ import StringLike._
* @tparam Repr The type of the actual collection inheriting `StringLike`.
*
* @since 2.8
- * @define Coll String
+ * @define Coll `String`
* @define coll string
* @define orderDependent
* @define orderDependentFold
@@ -60,7 +60,7 @@ self =>
val end = until min length
if (start >= end) newBuilder.result
- else newBuilder ++= toString.substring(start, end) result
+ else (newBuilder ++= toString.substring(start, end)).result
}
/** Return the current string concatenated `n` times.
@@ -239,7 +239,7 @@ self =>
else
throw new IllegalArgumentException("For input string: \"null\"")
- override def toArray[B >: Char : ClassManifest]: Array[B] =
+ override def toArray[B >: Char : ArrayTag]: Array[B] =
toString.toCharArray.asInstanceOf[Array[B]]
private def unwrapArg(arg: Any): AnyRef = arg match {
diff --git a/src/library/scala/collection/immutable/StringOps.scala b/src/library/scala/collection/immutable/StringOps.scala
index 97609b4c4d..633821ecea 100644
--- a/src/library/scala/collection/immutable/StringOps.scala
+++ b/src/library/scala/collection/immutable/StringOps.scala
@@ -25,7 +25,7 @@ import mutable.StringBuilder
* @param repr the actual representation of this string operations object.
*
* @since 2.8
- * @define Coll StringOps
+ * @define Coll `StringOps`
* @define coll string
*/
final class StringOps(override val repr: String) extends AnyVal with StringLike[String] {
diff --git a/src/library/scala/collection/immutable/Traversable.scala b/src/library/scala/collection/immutable/Traversable.scala
index 7830b38d69..59d3b4e029 100644
--- a/src/library/scala/collection/immutable/Traversable.scala
+++ b/src/library/scala/collection/immutable/Traversable.scala
@@ -30,7 +30,7 @@ trait Traversable[+A] extends scala.collection.Traversable[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `Vector`.
* @define coll immutable traversable collection
- * @define Coll immutable.Traversable
+ * @define Coll `immutable.Traversable`
*/
object Traversable extends TraversableFactory[Traversable] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Traversable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/immutable/TreeMap.scala b/src/library/scala/collection/immutable/TreeMap.scala
index dc4f79be35..4c1a5f2e03 100644
--- a/src/library/scala/collection/immutable/TreeMap.scala
+++ b/src/library/scala/collection/immutable/TreeMap.scala
@@ -14,7 +14,6 @@ package immutable
import generic._
import immutable.{RedBlackTree => RB}
import mutable.Builder
-import annotation.bridge
/** $factoryInfo
* @define Coll immutable.TreeMap
@@ -162,8 +161,6 @@ class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering: Orderi
override def ++[B1 >: B] (xs: GenTraversableOnce[(A, B1)]): TreeMap[A, B1] =
((repr: TreeMap[A, B1]) /: xs.seq) (_ + _)
- @bridge def ++[B1 >: B] (xs: TraversableOnce[(A, B1)]): TreeMap[A, B1] = ++(xs: GenTraversableOnce[(A, B1)])
-
/** A new TreeMap with the entry added is returned,
* assuming that key is <em>not</em> in the TreeMap.
*
diff --git a/src/library/scala/collection/immutable/TreeSet.scala b/src/library/scala/collection/immutable/TreeSet.scala
index 1b3d72ceb7..882e828c5b 100644
--- a/src/library/scala/collection/immutable/TreeSet.scala
+++ b/src/library/scala/collection/immutable/TreeSet.scala
@@ -16,7 +16,7 @@ import immutable.{RedBlackTree => RB}
import mutable.{ Builder, SetBuilder }
/** $factoryInfo
- * @define Coll immutable.TreeSet
+ * @define Coll `immutable.TreeSet`
* @define coll immutable tree set
*/
object TreeSet extends ImmutableSortedSetFactory[TreeSet] {
@@ -40,7 +40,7 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] {
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-immutable-collection-classes.html#redblack_trees "Scala's Collection Library overview"]]
* section on `Red-Black Trees` for more information.
*
- * @define Coll immutable.TreeSet
+ * @define Coll `immutable.TreeSet`
* @define coll immutable tree set
* @define orderDependent
* @define orderDependentFold
diff --git a/src/library/scala/collection/immutable/TrieIterator.scala b/src/library/scala/collection/immutable/TrieIterator.scala
index c77334b732..ead1a8c744 100644
--- a/src/library/scala/collection/immutable/TrieIterator.scala
+++ b/src/library/scala/collection/immutable/TrieIterator.scala
@@ -75,7 +75,7 @@ private[collection] abstract class TrieIterator[+T](elems: Array[Iterable[T]]) e
}
private[this] def iteratorWithSize(arr: Array[Iterable[T]]): (Iterator[T], Int) =
- (newIterator(arr), arr map (_.size) sum)
+ (newIterator(arr), arr.map(_.size).sum)
private[this] def arrayToIterators(arr: Array[Iterable[T]]): SplitIterators = {
val (fst, snd) = arr.splitAt(arr.length / 2)
diff --git a/src/library/scala/collection/immutable/Vector.scala b/src/library/scala/collection/immutable/Vector.scala
index 55c31feec2..1395a8f52d 100644
--- a/src/library/scala/collection/immutable/Vector.scala
+++ b/src/library/scala/collection/immutable/Vector.scala
@@ -40,7 +40,7 @@ object Vector extends SeqFactory[Vector] {
*
* @tparam A the element type
*
- * @define Coll Vector
+ * @define Coll `Vector`
* @define coll vector
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `Vector[B]` because an implicit of type `CanBuildFrom[Vector, B, That]`
diff --git a/src/library/scala/collection/immutable/WrappedString.scala b/src/library/scala/collection/immutable/WrappedString.scala
index de8aeea7e1..aa7e5b3c4a 100644
--- a/src/library/scala/collection/immutable/WrappedString.scala
+++ b/src/library/scala/collection/immutable/WrappedString.scala
@@ -25,7 +25,7 @@ import mutable.{Builder, StringBuilder}
* @param self a string contained within this wrapped string
*
* @since 2.8
- * @define Coll WrappedString
+ * @define Coll `WrappedString`
* @define coll wrapped string
*/
class WrappedString(val self: String) extends AbstractSeq[Char] with IndexedSeq[Char] with StringLike[WrappedString] {
diff --git a/src/library/scala/collection/interfaces/IterableMethods.scala b/src/library/scala/collection/interfaces/IterableMethods.scala
index 2054922e59..8efc3fe6f9 100644
--- a/src/library/scala/collection/interfaces/IterableMethods.scala
+++ b/src/library/scala/collection/interfaces/IterableMethods.scala
@@ -11,7 +11,6 @@ package interfaces
import generic._
import mutable.Buffer
-import scala.reflect.ClassManifest
import annotation.unchecked.uncheckedVariance
/**
diff --git a/src/library/scala/collection/interfaces/SeqMethods.scala b/src/library/scala/collection/interfaces/SeqMethods.scala
index 1f5b08d036..4327073d21 100644
--- a/src/library/scala/collection/interfaces/SeqMethods.scala
+++ b/src/library/scala/collection/interfaces/SeqMethods.scala
@@ -11,7 +11,6 @@ package interfaces
import generic._
import mutable.Buffer
-import scala.reflect.ClassManifest
/**
* @since 2.8
diff --git a/src/library/scala/collection/interfaces/SetMethods.scala b/src/library/scala/collection/interfaces/SetMethods.scala
index ffe141ed82..3b6214f45c 100644
--- a/src/library/scala/collection/interfaces/SetMethods.scala
+++ b/src/library/scala/collection/interfaces/SetMethods.scala
@@ -11,7 +11,6 @@ package interfaces
import generic._
import mutable.Buffer
-import scala.reflect.ClassManifest
import annotation.unchecked.uncheckedVariance
/**
diff --git a/src/library/scala/collection/interfaces/TraversableOnceMethods.scala b/src/library/scala/collection/interfaces/TraversableOnceMethods.scala
index 471e977134..543d59d118 100644
--- a/src/library/scala/collection/interfaces/TraversableOnceMethods.scala
+++ b/src/library/scala/collection/interfaces/TraversableOnceMethods.scala
@@ -46,7 +46,7 @@ trait TraversableOnceMethods[+A] {
def copyToBuffer[B >: A](dest: mutable.Buffer[B]): Unit
// conversions
- def toArray[B >: A : ClassManifest]: Array[B]
+ def toArray[B >: A : ArrayTag]: Array[B]
def toBuffer[B >: A]: mutable.Buffer[B]
def toIndexedSeq: immutable.IndexedSeq[A]
def toIterable: Iterable[A]
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index bfdc08536c..3034fc2bce 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -29,7 +29,7 @@ import parallel.mutable.ParArray
*
* @tparam A the type of this arraybuffer's elements.
*
- * @define Coll ArrayBuffer
+ * @define Coll `ArrayBuffer`
* @define coll arraybuffer
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `ArrayBuffer[B]` because an implicit of type `CanBuildFrom[ArrayBuffer, B, ArrayBuffer[B]]`
@@ -187,7 +187,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
*
* $factoryInfo
* @define coll array buffer
- * @define Coll ArrayBuffer
+ * @define Coll `ArrayBuffer`
*/
object ArrayBuffer extends SeqFactory[ArrayBuffer] {
/** $genericCanBuildFromInfo */
diff --git a/src/library/scala/collection/mutable/ArrayBuilder.scala b/src/library/scala/collection/mutable/ArrayBuilder.scala
index f0e4c79abf..293e85a97e 100644
--- a/src/library/scala/collection/mutable/ArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/ArrayBuilder.scala
@@ -12,7 +12,8 @@ package scala.collection
package mutable
import generic._
-import scala.reflect.ClassManifest
+import scala.reflect.ArrayTag
+import scala.runtime.ScalaRunTime
/** A builder class for arrays.
*
@@ -30,17 +31,31 @@ object ArrayBuilder {
/** Creates a new arraybuilder of type `T`.
*
- * @tparam T type of the elements for the array builder, with a `ClassManifest` context bound.
+ * @tparam T type of the elements for the array builder, with a `ArrayTag` context bound.
* @return a new empty array builder.
*/
- def make[T: ClassManifest](): ArrayBuilder[T] =
- implicitly[ClassManifest[T]].newArrayBuilder()
+ def make[T: ArrayTag](): ArrayBuilder[T] = {
+ val tag = implicitly[ArrayTag[T]]
+ val erasure = ScalaRunTime.arrayElementClass(tag)
+ erasure match {
+ case java.lang.Byte.TYPE => new ArrayBuilder.ofByte().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Short.TYPE => new ArrayBuilder.ofShort().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Character.TYPE => new ArrayBuilder.ofChar().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Integer.TYPE => new ArrayBuilder.ofInt().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Long.TYPE => new ArrayBuilder.ofLong().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Float.TYPE => new ArrayBuilder.ofFloat().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Double.TYPE => new ArrayBuilder.ofDouble().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Boolean.TYPE => new ArrayBuilder.ofBoolean().asInstanceOf[ArrayBuilder[T]]
+ case java.lang.Void.TYPE => new ArrayBuilder.ofUnit().asInstanceOf[ArrayBuilder[T]]
+ case _ => new ArrayBuilder.ofRef[T with AnyRef]()(tag.asInstanceOf[ArrayTag[T with AnyRef]]).asInstanceOf[ArrayBuilder[T]]
+ }
+ }
/** A class for array builders for arrays of reference types.
*
- * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ClassManifest` context bound.
+ * @tparam T type of elements for the array builder, subtype of `AnyRef` with a `ArrayTag` context bound.
*/
- class ofRef[T <: AnyRef : ClassManifest] extends ArrayBuilder[T] {
+ class ofRef[T <: AnyRef : ArrayTag] extends ArrayBuilder[T] {
private var elems: Array[T] = _
private var capacity: Int = 0
diff --git a/src/library/scala/collection/mutable/ArrayLike.scala b/src/library/scala/collection/mutable/ArrayLike.scala
index 23d36252d2..04601845c4 100644
--- a/src/library/scala/collection/mutable/ArrayLike.scala
+++ b/src/library/scala/collection/mutable/ArrayLike.scala
@@ -18,7 +18,7 @@ import generic._
* @tparam A type of the elements contained in the array like object.
* @tparam Repr the type of the actual collection containing the elements.
*
- * @define Coll ArrayLike
+ * @define Coll `ArrayLike`
* @version 2.8
* @since 2.8
*/
diff --git a/src/library/scala/collection/mutable/ArrayOps.scala b/src/library/scala/collection/mutable/ArrayOps.scala
index 5f7c508181..57e81fdb9c 100644
--- a/src/library/scala/collection/mutable/ArrayOps.scala
+++ b/src/library/scala/collection/mutable/ArrayOps.scala
@@ -12,7 +12,8 @@ package scala.collection
package mutable
import compat.Platform.arraycopy
-import scala.reflect.ClassManifest
+import scala.reflect.ArrayTag
+import scala.runtime.ScalaRunTime._
import parallel.mutable.ParArray
@@ -29,7 +30,7 @@ import parallel.mutable.ParArray
*
* @tparam T type of the elements contained in this array.
*
- * @define Coll ArrayOps
+ * @define Coll `ArrayOps`
* @define orderDependent
* @define orderDependentFold
* @define mayNotTerminateInf
@@ -37,10 +38,8 @@ import parallel.mutable.ParArray
*/
abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParallelizable[T, ParArray[T]] {
- private def rowBuilder[U]: Builder[U, Array[U]] =
- Array.newBuilder(
- ClassManifest.fromClass(
- repr.getClass.getComponentType.getComponentType.asInstanceOf[Predef.Class[U]]))
+ private def elementClass: Class[_] =
+ arrayElementClass(repr.getClass)
override def copyToArray[U >: T](xs: Array[U], start: Int, len: Int) {
var l = math.min(len, repr.length)
@@ -48,11 +47,13 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza
Array.copy(repr, 0, xs, start, l)
}
- override def toArray[U >: T : ClassManifest]: Array[U] =
- if (implicitly[ClassManifest[U]].erasure eq repr.getClass.getComponentType)
+ override def toArray[U >: T : ArrayTag]: Array[U] = {
+ val thatElementClass = arrayElementClass(implicitly[ArrayTag[U]])
+ if (elementClass eq thatElementClass)
repr.asInstanceOf[Array[U]]
else
super.toArray[U]
+ }
override def par = ParArray.handoff(repr)
@@ -63,9 +64,9 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza
* @param asArray A function that converts elements of this array to rows - arrays of type `U`.
* @return An array obtained by concatenating rows of this array.
*/
- def flatten[U, To](implicit asTrav: T => collection.Traversable[U], m: ClassManifest[U]): Array[U] = {
+ def flatten[U, To](implicit asTrav: T => collection.Traversable[U], m: ArrayTag[U]): Array[U] = {
val b = Array.newBuilder[U]
- b.sizeHint(map{case is: collection.IndexedSeq[_] => is.size case _ => 0} sum)
+ b.sizeHint(map{case is: collection.IndexedSeq[_] => is.size case _ => 0}.sum)
for (xs <- this)
b ++= asTrav(xs)
b.result
@@ -78,7 +79,8 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza
* @return An array obtained by replacing elements of this arrays with rows the represent.
*/
def transpose[U](implicit asArray: T => Array[U]): Array[Array[U]] = {
- val bs = asArray(head) map (_ => rowBuilder[U])
+ def mkRowBuilder() = Array.newBuilder(ClassTag[U](arrayElementClass(elementClass)))
+ val bs = asArray(head) map (_ => mkRowBuilder())
for (xs <- this) {
var i = 0
for (x <- asArray(xs)) {
@@ -86,9 +88,7 @@ abstract class ArrayOps[T] extends ArrayLike[T, Array[T]] with CustomParalleliza
i += 1
}
}
- val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder(
- ClassManifest.fromClass(
- repr.getClass.getComponentType.asInstanceOf[Predef.Class[Array[U]]]))
+ val bb: Builder[Array[U], Array[Array[U]]] = Array.newBuilder(ClassTag[Array[U]](elementClass))
for (b <- bs) bb += b.result
bb.result
}
@@ -109,8 +109,7 @@ object ArrayOps {
override protected[this] def thisCollection: WrappedArray[T] = new WrappedArray.ofRef[T](repr)
override protected[this] def toCollection(repr: Array[T]): WrappedArray[T] = new WrappedArray.ofRef[T](repr)
- override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(
- ClassManifest.classType[T](repr.getClass.getComponentType))
+ override protected[this] def newBuilder = new ArrayBuilder.ofRef[T]()(ClassTag[T](arrayElementClass(repr.getClass)))
def length: Int = repr.length
def apply(index: Int): T = repr(index)
diff --git a/src/library/scala/collection/mutable/ArraySeq.scala b/src/library/scala/collection/mutable/ArraySeq.scala
index cb86c416fe..d0eaee348b 100644
--- a/src/library/scala/collection/mutable/ArraySeq.scala
+++ b/src/library/scala/collection/mutable/ArraySeq.scala
@@ -27,7 +27,7 @@ import parallel.mutable.ParArray
* @tparam A type of the elements contained in this array sequence.
* @param length the length of the underlying array.
*
- * @define Coll ArraySeq
+ * @define Coll `ArraySeq`
* @define coll array sequence
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `ArraySeq[B]` because an implicit of type `CanBuildFrom[ArraySeq, B, ArraySeq[B]]`
@@ -93,7 +93,7 @@ extends AbstractSeq[A]
/** $factoryInfo
* @define coll array sequence
- * @define Coll ArraySeq
+ * @define Coll `ArraySeq`
*/
object ArraySeq extends SeqFactory[ArraySeq] {
/** $genericCanBuildFromInfo */
diff --git a/src/library/scala/collection/mutable/ArrayStack.scala b/src/library/scala/collection/mutable/ArrayStack.scala
index f5287312b9..04a318d0c3 100644
--- a/src/library/scala/collection/mutable/ArrayStack.scala
+++ b/src/library/scala/collection/mutable/ArrayStack.scala
@@ -15,13 +15,13 @@ import generic._
*
* $factoryInfo
* @define coll array stack
- * @define Coll ArrayStack
+ * @define Coll `ArrayStack`
*/
object ArrayStack extends SeqFactory[ArrayStack] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, ArrayStack[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
def newBuilder[A]: Builder[A, ArrayStack[A]] = new ArrayStack[A]
def empty: ArrayStack[Nothing] = new ArrayStack()
- def apply[A: ClassManifest](elems: A*): ArrayStack[A] = {
+ def apply[A: ArrayTag](elems: A*): ArrayStack[A] = {
val els: Array[AnyRef] = elems.reverseMap(_.asInstanceOf[AnyRef])(breakOut)
if (els.length == 0) new ArrayStack()
else new ArrayStack[A](els, els.length)
@@ -51,7 +51,7 @@ object ArrayStack extends SeqFactory[ArrayStack] {
*
* @tparam T type of the elements contained in this array stack.
*
- * @define Coll ArrayStack
+ * @define Coll `ArrayStack`
* @define coll array stack
* @define orderDependent
* @define orderDependentFold
diff --git a/src/library/scala/collection/mutable/BitSet.scala b/src/library/scala/collection/mutable/BitSet.scala
index 6b9673dae6..58b45aa2a2 100644
--- a/src/library/scala/collection/mutable/BitSet.scala
+++ b/src/library/scala/collection/mutable/BitSet.scala
@@ -21,7 +21,7 @@ import BitSetLike.{LogWL, updateArray}
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_bitsets "Scala's Collection Library overview"]]
* section on `Mutable Bitsets` for more information.
*
- * @define Coll BitSet
+ * @define Coll `BitSet`
* @define coll bitset
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `BitSet[B]` because an implicit of type `CanBuildFrom[BitSet, B, BitSet]`
@@ -114,7 +114,7 @@ class BitSet(protected var elems: Array[Long]) extends AbstractSet[Int]
/** $factoryInfo
* @define coll bitset
- * @define Coll BitSet
+ * @define Coll `BitSet`
*/
object BitSet extends BitSetFactory[BitSet] {
def empty: BitSet = new BitSet
diff --git a/src/library/scala/collection/mutable/Buffer.scala b/src/library/scala/collection/mutable/Buffer.scala
index 7326d5ec5b..dd225cfab9 100644
--- a/src/library/scala/collection/mutable/Buffer.scala
+++ b/src/library/scala/collection/mutable/Buffer.scala
@@ -25,7 +25,7 @@ import generic._
*
* @tparam A type of the elements contained in this buffer.
*
- * @define Coll Buffer
+ * @define Coll `Buffer`
* @define coll buffer
*/
@cloneable
@@ -37,7 +37,7 @@ trait Buffer[A] extends Seq[A]
/** $factoryInfo
* @define coll buffer
- * @define Coll Buffer
+ * @define Coll `Buffer`
*/
object Buffer extends SeqFactory[Buffer] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Buffer[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/BufferLike.scala b/src/library/scala/collection/mutable/BufferLike.scala
index 1dc2fc27d5..f82a596b32 100644
--- a/src/library/scala/collection/mutable/BufferLike.scala
+++ b/src/library/scala/collection/mutable/BufferLike.scala
@@ -223,9 +223,6 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]]
@migration("`++` creates a new buffer. Use `++=` to add an element from this buffer and return that buffer itself.", "2.8.0")
def ++(xs: GenTraversableOnce[A]): This = clone() ++= xs.seq
- @bridge
- def ++(xs: TraversableOnce[A]): This = ++(xs: GenTraversableOnce[A])
-
/** Creates a new collection with all the elements of this collection except `elem`.
*
* @param elem the element to remove.
@@ -255,6 +252,4 @@ trait BufferLike[A, +This <: BufferLike[A, This] with Buffer[A]]
*/
@migration("`--` creates a new buffer. Use `--=` to remove an element from this buffer and return that buffer itself.", "2.8.0")
override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq
-
- @bridge def --(xs: TraversableOnce[A]): This = --(xs: GenTraversableOnce[A])
}
diff --git a/src/library/scala/collection/mutable/BufferProxy.scala b/src/library/scala/collection/mutable/BufferProxy.scala
index 6a6bdd0077..aa1b20d240 100644
--- a/src/library/scala/collection/mutable/BufferProxy.scala
+++ b/src/library/scala/collection/mutable/BufferProxy.scala
@@ -25,7 +25,7 @@ import script._
*
* @tparam A type of the elements the buffer proxy contains.
*
- * @define Coll BufferProxy
+ * @define Coll `BufferProxy`
* @define coll buffer proxy
*/
trait BufferProxy[A] extends Buffer[A] with Proxy {
diff --git a/src/library/scala/collection/mutable/Builder.scala b/src/library/scala/collection/mutable/Builder.scala
index 44cc1c8582..bbf4f5889d 100644
--- a/src/library/scala/collection/mutable/Builder.scala
+++ b/src/library/scala/collection/mutable/Builder.scala
@@ -100,6 +100,8 @@ trait Builder[-Elem, +To] extends Growable[Elem] {
def +=(x: Elem): this.type = { self += x; this }
def clear() = self.clear()
override def ++=(xs: TraversableOnce[Elem]): this.type = { self ++= xs; this }
+ override def sizeHint(size: Int) = self.sizeHint(size)
+ override def sizeHintBounded(size: Int, boundColl: TraversableLike[_, _]) = self.sizeHintBounded(size, boundColl)
def result: NewTo = f(self.result)
}
}
diff --git a/src/library/scala/collection/mutable/ConcurrentMap.scala b/src/library/scala/collection/mutable/ConcurrentMap.scala
index f2b44d6737..ad6b609862 100644
--- a/src/library/scala/collection/mutable/ConcurrentMap.scala
+++ b/src/library/scala/collection/mutable/ConcurrentMap.scala
@@ -20,7 +20,7 @@ package mutable
* @tparam A the key type of the map
* @tparam B the value type of the map
*
- * @define Coll ConcurrentMap
+ * @define Coll `ConcurrentMap`
* @define coll concurrent map
* @define concurrentmapinfo
* This is a base trait for all Scala concurrent map implementations. It
diff --git a/src/library/scala/collection/mutable/DoubleLinkedList.scala b/src/library/scala/collection/mutable/DoubleLinkedList.scala
index 49378a4f4e..cba4e9725e 100644
--- a/src/library/scala/collection/mutable/DoubleLinkedList.scala
+++ b/src/library/scala/collection/mutable/DoubleLinkedList.scala
@@ -26,7 +26,7 @@ import generic._
*
* @tparam A the type of the elements contained in this double linked list.
*
- * @define Coll DoubleLinkedList
+ * @define Coll `DoubleLinkedList`
* @define coll double linked list
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `DoubleLinkedList[B]` because an implicit of type `CanBuildFrom[DoubleLinkedList, B, DoubleLinkedList[B]]`
@@ -67,7 +67,7 @@ class DoubleLinkedList[A]() extends AbstractSeq[A]
/** $factoryInfo
* @define coll double linked list
- * @define Coll DoubleLinkedList
+ * @define Coll `DoubleLinkedList`
*/
object DoubleLinkedList extends SeqFactory[DoubleLinkedList] {
/** $genericCanBuildFromInfo */
diff --git a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
index dfb70beeda..ebccacf976 100644
--- a/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
+++ b/src/library/scala/collection/mutable/DoubleLinkedListLike.scala
@@ -52,7 +52,7 @@ import annotation.migration
* @tparam A type of the elements contained in the double linked list
* @tparam This the type of the actual linked list holding the elements
*
- * @define Coll DoubleLinkedList
+ * @define Coll `DoubleLinkedList`
* @define coll double linked list
*/
trait DoubleLinkedListLike[A, This <: Seq[A] with DoubleLinkedListLike[A, This]] extends SeqLike[A, This] with LinkedListLike[A, This] { self =>
diff --git a/src/library/scala/collection/mutable/FlatArray.scala b/src/library/scala/collection/mutable/FlatArray.scala
deleted file mode 100644
index 3e43b66ecf..0000000000
--- a/src/library/scala/collection/mutable/FlatArray.scala
+++ /dev/null
@@ -1,157 +0,0 @@
-/* __ *\
-** ________ ___ / / ___ Scala API **
-** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
-** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
-** /____/\___/_/ |_/____/_/ | | **
-** |/ **
-\* */
-
-
-
-package scala.collection
-package mutable
-
-import scala.reflect.ClassManifest
-import generic.CanBuildFrom
-
-/**
- * A class representing `Array[T]`.
- *
- * @tparam T type of the elements in this wrapped array.
- *
- * @author Martin Odersky, Stephane Micheloud
- * @version 1.0
- * @since 2.8
- * @define Coll WrappedArray
- * @define coll wrapped array
- * @define orderDependent
- * @define orderDependentFold
- * @define mayNotTerminateInf
- * @define willNotTerminateInf
- */
-abstract sealed class FlatArray[T]
-extends AbstractSeq[T]
- with IndexedSeq[T]
- with IndexedSeqOptimized[T, FlatArray[T]]
-{
-
- override protected[this] def thisCollection: FlatArray[T] = this
- override protected[this] def toCollection(repr: FlatArray[T]): FlatArray[T] = repr
-
- /** The length of the array */
- def length: Int
-
- /** The element at given index */
- def apply(index: Int): T
-
- /** Update element at given index */
- def update(index: Int, elem: T): Unit
-
- override def stringPrefix = "FlatArray"
-
- override protected[this] def newBuilder: Builder[T, FlatArray[T]] = ??? // implemented in FlatArray.Impl
-
- /** Clones this object, including the underlying Array. */
- override def clone: FlatArray[T] = ??? // implemented in FlatArray.Impl
-}
-
-
-/** A companion object used to create instances of `WrappedArray`.
- */
-object FlatArray {
-
- def ofDim[Boxed, Unboxed](size:Int)
- (implicit boxings: BoxingConversions[Boxed, Unboxed],
- manifest: ClassManifest[Unboxed]): FlatArray[Boxed] = {
- val elems = Array.ofDim[Unboxed](size)
- new FlatArray.Impl(elems, boxings, manifest)
- }
-
- def empty[Boxed, Unboxed](implicit boxings: BoxingConversions[Boxed, Unboxed],
- elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = apply()
-
- def apply[Boxed, Unboxed](elems: Boxed*)
- (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = {
- val b = newBuilder[Boxed, Unboxed]
- b.sizeHint(elems.length)
- b ++= elems
- b.result
- }
-
- def newBuilder[Boxed, Unboxed]
- (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): Builder[Boxed, FlatArray[Boxed]] =
- new Bldr[Boxed, Unboxed](boxings, elemManifest)
-
- implicit def canBuildFrom[Boxed, Unboxed](
- implicit
- boxings: BoxingConversions[Boxed, Unboxed],
- elemManifest: ClassManifest[Unboxed]): CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] =
- new CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] {
- def apply(from: FlatArray[_]): Builder[Boxed, FlatArray[Boxed]] =
- newBuilder[Boxed, Unboxed]
- def apply: Builder[Boxed, FlatArray[Boxed]] =
- newBuilder[Boxed, Unboxed]
- }
-
- private class Bldr[Boxed, Unboxed](boxings: BoxingConversions[Boxed, Unboxed], manifest: ClassManifest[Unboxed]) extends Builder[Boxed, FlatArray[Boxed]] {
-
- private var elems: Array[Unboxed] = _
- private var capacity: Int = 0
- private var size: Int = 0
-
- private def resize(size: Int) {
- val newelems = manifest.newArray(size)
- if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size)
- elems = newelems
- capacity = size
- }
-
- override def sizeHint(size: Int) {
- if (capacity < size) resize(size)
- }
-
- private def ensureSize(size: Int) {
- if (capacity < size) {
- var newsize = if (capacity == 0) 16 else capacity * 2
- while (newsize < size) newsize *= 2
- resize(newsize)
- }
- }
-
- def +=(elem: Boxed): this.type = {
- ensureSize(size + 1)
- elems(size) = boxings.unbox(elem)
- size += 1
- this
- }
-
- def clear() {
- size = 0
- }
-
- def result(): FlatArray[Boxed] = {
- if (capacity == 0 || capacity != size) resize(size)
- new FlatArray.Impl(elems, boxings, manifest)
- }
- }
-
- private class Impl[Boxed, Unboxed](
- elems: Array[Unboxed],
- boxings: BoxingConversions[Boxed, Unboxed],
- elemManifest: ClassManifest[Unboxed]) extends FlatArray[Boxed] {
-
- def length = elems.length
-
- def apply(idx: Int): Boxed = boxings.box(elems(idx))
-
- def update(idx: Int, elem: Boxed) = elems(idx) = boxings.unbox(elem)
-
- /** Creates new builder for this collection ==> move to subclasses
- */
- override protected[this] def newBuilder: Builder[Boxed, FlatArray[Boxed]] =
- new Bldr[Boxed, Unboxed](boxings, elemManifest)
-
- /** Clones this object, including the underlying Array. */
- override def clone: FlatArray[Boxed] = new Impl[Boxed, Unboxed](elems.clone(), boxings, elemManifest)
- }
-}
diff --git a/src/library/scala/collection/mutable/GenSeq.scala.disabled b/src/library/scala/collection/mutable/GenSeq.scala.disabled
index 85e4065183..53ec5acc34 100644
--- a/src/library/scala/collection/mutable/GenSeq.scala.disabled
+++ b/src/library/scala/collection/mutable/GenSeq.scala.disabled
@@ -24,7 +24,7 @@ import generic._
*
* The class adds an `update` method to `collection.Seq`.
*
- * @define Coll mutable.Seq
+ * @define Coll `mutable.Seq`
* @define coll mutable sequence
*/
trait GenSeq[A] extends GenIterable[A]
diff --git a/src/library/scala/collection/mutable/GenSet.scala.disabled b/src/library/scala/collection/mutable/GenSet.scala.disabled
index ac11e634e8..9080abaf38 100644
--- a/src/library/scala/collection/mutable/GenSet.scala.disabled
+++ b/src/library/scala/collection/mutable/GenSet.scala.disabled
@@ -24,7 +24,7 @@ import generic._
*
* @since 1.0
* @author Matthias Zenger
- * @define Coll mutable.Set
+ * @define Coll `mutable.Set`
* @define coll mutable set
*/
trait GenSet[A] extends GenIterable[A]
diff --git a/src/library/scala/collection/mutable/GrowingBuilder.scala b/src/library/scala/collection/mutable/GrowingBuilder.scala
index 0b7385194e..df63177b87 100644
--- a/src/library/scala/collection/mutable/GrowingBuilder.scala
+++ b/src/library/scala/collection/mutable/GrowingBuilder.scala
@@ -18,7 +18,7 @@ import generic._
* @version 2.8
* @since 2.8
*
- * @define Coll GrowingBuilder
+ * @define Coll `GrowingBuilder`
* @define coll growing builder
*/
class GrowingBuilder[Elem, To <: Growable[Elem]](empty: To) extends Builder[Elem, To] {
diff --git a/src/library/scala/collection/mutable/HashMap.scala b/src/library/scala/collection/mutable/HashMap.scala
index 65a10f4ba9..bf640cdb90 100644
--- a/src/library/scala/collection/mutable/HashMap.scala
+++ b/src/library/scala/collection/mutable/HashMap.scala
@@ -21,7 +21,7 @@ import scala.collection.parallel.mutable.ParHashMap
* @tparam A the type of the keys contained in this hash map.
* @tparam B the type of the values assigned to keys in this hash map.
*
- * @define Coll mutable.HashMap
+ * @define Coll `mutable.HashMap`
* @define coll mutable hash map
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `HashMap[A, B]` if the elements contained in the resulting collection are
@@ -138,7 +138,7 @@ extends AbstractMap[A, B]
}
/** $factoryInfo
- * @define Coll mutable.HashMap
+ * @define Coll `mutable.HashMap`
* @define coll mutable hash map
*/
object HashMap extends MutableMapFactory[HashMap] {
diff --git a/src/library/scala/collection/mutable/HashSet.scala b/src/library/scala/collection/mutable/HashSet.scala
index 8ed6b925aa..e040d1e421 100644
--- a/src/library/scala/collection/mutable/HashSet.scala
+++ b/src/library/scala/collection/mutable/HashSet.scala
@@ -25,7 +25,7 @@ import collection.parallel.mutable.ParHashSet
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#hash_tables "Scala's Collection Library overview"]]
* section on `Hash Tables` for more information.
*
- * @define Coll mutable.HashSet
+ * @define Coll `mutable.HashSet`
* @define coll mutable hash set
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `HashSet[B]` because an implicit of type `CanBuildFrom[HashSet, B, HashSet[B]]`
@@ -98,7 +98,7 @@ extends AbstractSet[A]
}
/** $factoryInfo
- * @define Coll mutable.HashSet
+ * @define Coll `mutable.HashSet`
* @define coll mutable hash set
*/
object HashSet extends MutableSetFactory[HashSet] {
diff --git a/src/library/scala/collection/mutable/HashTable.scala b/src/library/scala/collection/mutable/HashTable.scala
index 06b7d40bfc..a2f78dbde9 100644
--- a/src/library/scala/collection/mutable/HashTable.scala
+++ b/src/library/scala/collection/mutable/HashTable.scala
@@ -187,7 +187,7 @@ trait HashTable[A, Entry >: Null <: HashEntry[A, Entry]] extends HashTable.HashU
}
/** Avoid iterator for a 2x faster traversal. */
- protected final def foreachEntry[C](f: Entry => C) {
+ protected def foreachEntry[C](f: Entry => C) {
val iterTable = table
var idx = lastPopulatedIndex
var es = iterTable(idx)
diff --git a/src/library/scala/collection/mutable/IndexedSeq.scala b/src/library/scala/collection/mutable/IndexedSeq.scala
index 0e2e06df84..686f90c9e8 100644
--- a/src/library/scala/collection/mutable/IndexedSeq.scala
+++ b/src/library/scala/collection/mutable/IndexedSeq.scala
@@ -29,7 +29,7 @@ trait IndexedSeq[A] extends Seq[A]
/** $factoryInfo
* The current default implementation of a $Coll is an `ArrayBuffer`.
* @define coll mutable indexed sequence
- * @define Coll mutable.IndexedSeq
+ * @define Coll `mutable.IndexedSeq`
*/
object IndexedSeq extends SeqFactory[IndexedSeq] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, IndexedSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/IndexedSeqLike.scala b/src/library/scala/collection/mutable/IndexedSeqLike.scala
index 0c1df17ead..4bd5ea1e89 100644
--- a/src/library/scala/collection/mutable/IndexedSeqLike.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqLike.scala
@@ -27,7 +27,7 @@ import generic._
* @tparam A the element type of the $coll
* @tparam Repr the type of the actual $coll containing the elements.
*
- * @define Coll IndexedSeq
+ * @define Coll `IndexedSeq`
* @define coll mutable indexed sequence
* @define indexedSeqInfo
* @author Martin Odersky
diff --git a/src/library/scala/collection/mutable/IndexedSeqView.scala b/src/library/scala/collection/mutable/IndexedSeqView.scala
index 593af92255..a0de2ec8ad 100644
--- a/src/library/scala/collection/mutable/IndexedSeqView.scala
+++ b/src/library/scala/collection/mutable/IndexedSeqView.scala
@@ -14,6 +14,7 @@ package mutable
import generic._
import TraversableView.NoBuilder
+import language.implicitConversions
/** A non-strict view of a mutable `IndexedSeq`.
* $viewInfo
diff --git a/src/library/scala/collection/mutable/Iterable.scala b/src/library/scala/collection/mutable/Iterable.scala
index 54fe11f98c..3b5ee63ea3 100644
--- a/src/library/scala/collection/mutable/Iterable.scala
+++ b/src/library/scala/collection/mutable/Iterable.scala
@@ -29,7 +29,7 @@ trait Iterable[A] extends Traversable[A]
/** $factoryInfo
* The current default implementation of a $Coll is an `ArrayBuffer`.
* @define coll mutable iterable collection
- * @define Coll mutable.Iterable
+ * @define Coll `mutable.Iterable`
*/
object Iterable extends TraversableFactory[Iterable] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Iterable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/LinearSeq.scala b/src/library/scala/collection/mutable/LinearSeq.scala
index 522ebfd277..443b458342 100644
--- a/src/library/scala/collection/mutable/LinearSeq.scala
+++ b/src/library/scala/collection/mutable/LinearSeq.scala
@@ -17,7 +17,7 @@ import generic._
* that can be mutated.
* $linearSeqInfo
*
- * @define Coll LinearSeq
+ * @define Coll `LinearSeq`
* @define coll linear sequence
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_lists "Scala's Collection Library overview"]]
* section on `Mutable Lists` for more information.
@@ -33,7 +33,7 @@ trait LinearSeq[A] extends Seq[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `MutableList`.
* @define coll mutable linear sequence
- * @define Coll mutable.LinearSeq
+ * @define Coll `mutable.LinearSeq`
*/
object LinearSeq extends SeqFactory[LinearSeq] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, LinearSeq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/LinkedHashMap.scala b/src/library/scala/collection/mutable/LinkedHashMap.scala
index e4090637ec..4150cf9eba 100644
--- a/src/library/scala/collection/mutable/LinkedHashMap.scala
+++ b/src/library/scala/collection/mutable/LinkedHashMap.scala
@@ -14,7 +14,7 @@ package mutable
import generic._
/** $factoryInfo
- * @define Coll LinkedHashMap
+ * @define Coll `LinkedHashMap`
* @define coll linked hash map
*/
object LinkedHashMap extends MutableMapFactory[LinkedHashMap] {
@@ -28,7 +28,7 @@ object LinkedHashMap extends MutableMapFactory[LinkedHashMap] {
* @tparam A the type of the keys contained in this hash map.
* @tparam B the type of the values assigned to keys in this hash map.
*
- * @define Coll LinkedHashMap
+ * @define Coll `LinkedHashMap`
* @define coll linked hash map
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `LinkedHashMap[A, B]` if the elements contained in the resulting collection are
@@ -132,6 +132,14 @@ class LinkedHashMap[A, B] extends AbstractMap[A, B]
}
}
+ protected override def foreachEntry[C](f: Entry => C) {
+ var cur = firstEntry
+ while (cur ne null) {
+ f(cur)
+ cur = cur.later
+ }
+ }
+
override def clear() {
clearTable()
firstEntry = null
diff --git a/src/library/scala/collection/mutable/LinkedHashSet.scala b/src/library/scala/collection/mutable/LinkedHashSet.scala
index f6d4915fef..3f789f9fa2 100644
--- a/src/library/scala/collection/mutable/LinkedHashSet.scala
+++ b/src/library/scala/collection/mutable/LinkedHashSet.scala
@@ -24,7 +24,7 @@ import generic._
*
* @tparam A the type of the elements contained in this set.
*
- * @define Coll LinkedHashSet
+ * @define Coll `LinkedHashSet`
* @define coll linked hash set
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `LinkedHashSet[B]` because an implicit of type `CanBuildFrom[LinkedHashSet, B, LinkedHashSet[B]]`
@@ -82,12 +82,12 @@ class LinkedHashSet[A] extends AbstractSet[A]
private def readObject(in: java.io.ObjectInputStream) {
ordered = new ListBuffer[A]
- init(in, ordered += )
+ init(in, ordered += _)
}
}
/** $factoryInfo
- * @define Coll LinkedHashSet
+ * @define Coll `LinkedHashSet`
* @define coll linked hash set
*/
object LinkedHashSet extends MutableSetFactory[LinkedHashSet] {
diff --git a/src/library/scala/collection/mutable/LinkedList.scala b/src/library/scala/collection/mutable/LinkedList.scala
index 8510827697..335ddccf56 100644
--- a/src/library/scala/collection/mutable/LinkedList.scala
+++ b/src/library/scala/collection/mutable/LinkedList.scala
@@ -40,7 +40,7 @@ import generic._
*
* @constructor Creates an "empty" list, defined as a single node with no data element and next pointing to itself.
- * @define Coll LinkedList
+ * @define Coll `LinkedList`
* @define coll linked list
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `LinkedList[B]` because an implicit of type `CanBuildFrom[LinkedList, B, LinkedList[B]]`
@@ -109,7 +109,7 @@ class LinkedList[A]() extends AbstractSeq[A]
}
/** $factoryInfo
- * @define Coll LinkedList
+ * @define Coll `LinkedList`
* @define coll linked list
*/
object LinkedList extends SeqFactory[LinkedList] {
diff --git a/src/library/scala/collection/mutable/LinkedListLike.scala b/src/library/scala/collection/mutable/LinkedListLike.scala
index ebec31ca98..07a8501ca4 100644
--- a/src/library/scala/collection/mutable/LinkedListLike.scala
+++ b/src/library/scala/collection/mutable/LinkedListLike.scala
@@ -29,7 +29,7 @@ import annotation.tailrec
* @tparam A type of the elements contained in the linked list
* @tparam This the type of the actual linked list holding the elements
*
- * @define Coll LinkedList
+ * @define Coll `LinkedList`
* @define coll linked list
*
* @define singleLinkedListExample
diff --git a/src/library/scala/collection/mutable/ListBuffer.scala b/src/library/scala/collection/mutable/ListBuffer.scala
index 96e73522b6..5c580f9c09 100644
--- a/src/library/scala/collection/mutable/ListBuffer.scala
+++ b/src/library/scala/collection/mutable/ListBuffer.scala
@@ -27,7 +27,7 @@ import java.io._
*
* @tparam A the type of this list buffer's elements.
*
- * @define Coll ListBuffer
+ * @define Coll `ListBuffer`
* @define coll list buffer
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `ListBuffer[B]` because an implicit of type `CanBuildFrom[ListBuffer, B, ListBuffer[B]]`
@@ -425,7 +425,7 @@ final class ListBuffer[A]
}
/** $factoryInfo
- * @define Coll ListBuffer
+ * @define Coll `ListBuffer`
* @define coll list buffer
*/
object ListBuffer extends SeqFactory[ListBuffer] {
diff --git a/src/library/scala/collection/mutable/ListMap.scala b/src/library/scala/collection/mutable/ListMap.scala
index d8d60d1c9a..61810c4ddf 100644
--- a/src/library/scala/collection/mutable/ListMap.scala
+++ b/src/library/scala/collection/mutable/ListMap.scala
@@ -18,7 +18,7 @@ import generic._
* @tparam A the type of the keys contained in this list map.
* @tparam B the type of the values assigned to keys in this list map.
*
- * @define Coll mutable.ListMap
+ * @define Coll `mutable.ListMap`
* @define coll mutable list map
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `ListMap[A, B]` if the elements contained in the resulting collection are
@@ -60,7 +60,7 @@ extends AbstractMap[A, B]
}
/** $factoryInfo
- * @define Coll mutable.ListMap
+ * @define Coll `mutable.ListMap`
* @define coll mutable list map
*/
object ListMap extends MutableMapFactory[ListMap] {
diff --git a/src/library/scala/collection/mutable/Map.scala b/src/library/scala/collection/mutable/Map.scala
index 0d40a1c70d..207b3f3324 100644
--- a/src/library/scala/collection/mutable/Map.scala
+++ b/src/library/scala/collection/mutable/Map.scala
@@ -63,7 +63,7 @@ trait Map[A, B]
/** $factoryInfo
* The current default implementation of a $Coll is a `HashMap`.
* @define coll mutable map
- * @define Coll mutable.Map
+ * @define Coll `mutable.Map`
*/
object Map extends MutableMapFactory[Map] {
/** $canBuildFromInfo */
diff --git a/src/library/scala/collection/mutable/MapLike.scala b/src/library/scala/collection/mutable/MapLike.scala
index b08a4b7bc9..b8b1152099 100644
--- a/src/library/scala/collection/mutable/MapLike.scala
+++ b/src/library/scala/collection/mutable/MapLike.scala
@@ -119,8 +119,6 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
override def ++[B1 >: B](xs: GenTraversableOnce[(A, B1)]): Map[A, B1] =
clone().asInstanceOf[Map[A, B1]] ++= xs.seq
- @bridge def ++[B1 >: B](xs: TraversableOnce[(A, B1)]): Map[A, B1] = ++(xs: GenTraversableOnce[(A, B1)])
-
/** Removes a key from this map, returning the value associated previously
* with that key as an option.
* @param key the key to be removed
@@ -224,6 +222,4 @@ trait MapLike[A, B, +This <: MapLike[A, B, This] with Map[A, B]]
*/
@migration("`--` creates a new map. Use `--=` to remove an element from this map and return that map itself.", "2.8.0")
override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq
-
- @bridge def --(xs: TraversableOnce[A]): This = --(xs: GenTraversableOnce[A])
}
diff --git a/src/library/scala/collection/mutable/MultiMap.scala b/src/library/scala/collection/mutable/MultiMap.scala
index 0f298c4a8a..d21624759d 100644
--- a/src/library/scala/collection/mutable/MultiMap.scala
+++ b/src/library/scala/collection/mutable/MultiMap.scala
@@ -19,7 +19,7 @@ package mutable
* `B` objects.
*
* @define coll multimap
- * @define Coll MultiMap
+ * @define Coll `MultiMap`
* @author Matthias Zenger
* @author Martin Odersky
* @version 2.8
diff --git a/src/library/scala/collection/mutable/OpenHashMap.scala b/src/library/scala/collection/mutable/OpenHashMap.scala
index 87e5c061fa..2634deb819 100644
--- a/src/library/scala/collection/mutable/OpenHashMap.scala
+++ b/src/library/scala/collection/mutable/OpenHashMap.scala
@@ -10,7 +10,7 @@ package scala.collection
package mutable
/**
- * @define Coll OpenHashMap
+ * @define Coll `OpenHashMap`
* @define coll open hash map
*
* @since 2.7
@@ -42,7 +42,7 @@ object OpenHashMap {
* @author David MacIver
* @since 2.7
*
- * @define Coll OpenHashMap
+ * @define Coll `OpenHashMap`
* @define coll open hash map
* @define mayNotTerminateInf
* @define willNotTerminateInf
diff --git a/src/library/scala/collection/mutable/PriorityQueue.scala b/src/library/scala/collection/mutable/PriorityQueue.scala
index 381cb09e18..12dee45bae 100644
--- a/src/library/scala/collection/mutable/PriorityQueue.scala
+++ b/src/library/scala/collection/mutable/PriorityQueue.scala
@@ -12,7 +12,6 @@ package scala.collection
package mutable
import generic._
-import annotation.bridge
/** This class implements priority queues using a heap.
* To prioritize elements of type A there must be an implicit
@@ -113,9 +112,6 @@ class PriorityQueue[A](implicit val ord: Ordering[A])
*/
def ++(xs: GenTraversableOnce[A]): PriorityQueue[A] = { this.clone() ++= xs.seq }
- @bridge
- def ++(xs: TraversableOnce[A]): PriorityQueue[A] = ++ (xs: GenTraversableOnce[A])
-
/** Adds all elements to the queue.
*
* @param elems the elements to add.
diff --git a/src/library/scala/collection/mutable/Queue.scala b/src/library/scala/collection/mutable/Queue.scala
index 77b1ae21cb..605d37aec6 100644
--- a/src/library/scala/collection/mutable/Queue.scala
+++ b/src/library/scala/collection/mutable/Queue.scala
@@ -23,7 +23,7 @@ import generic._
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#mutable_queues "Scala's Collection Library overview"]]
* section on `Queues` for more information.
*
- * @define Coll mutable.Queue
+ * @define Coll `mutable.Queue`
* @define coll mutable queue
* @define orderDependent
* @define orderDependentFold
diff --git a/src/library/scala/collection/mutable/Seq.scala b/src/library/scala/collection/mutable/Seq.scala
index 89b930e36f..ceed76cf88 100644
--- a/src/library/scala/collection/mutable/Seq.scala
+++ b/src/library/scala/collection/mutable/Seq.scala
@@ -21,7 +21,7 @@ import generic._
*
* The class adds an `update` method to `collection.Seq`.
*
- * @define Coll mutable.Seq
+ * @define Coll `mutable.Seq`
* @define coll mutable sequence
*/
trait Seq[A] extends Iterable[A]
@@ -36,7 +36,7 @@ trait Seq[A] extends Iterable[A]
/** $factoryInfo
* The current default implementation of a $Coll is an `ArrayBuffer`.
* @define coll mutable sequence
- * @define Coll mutable.Seq
+ * @define Coll `mutable.Seq`
*/
object Seq extends SeqFactory[Seq] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Seq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/Set.scala b/src/library/scala/collection/mutable/Set.scala
index 744768e8dd..33a99e9474 100644
--- a/src/library/scala/collection/mutable/Set.scala
+++ b/src/library/scala/collection/mutable/Set.scala
@@ -19,7 +19,7 @@ import generic._
*
* @since 1.0
* @author Matthias Zenger
- * @define Coll mutable.Set
+ * @define Coll `mutable.Set`
* @define coll mutable set
*/
trait Set[A] extends Iterable[A]
@@ -34,7 +34,7 @@ trait Set[A] extends Iterable[A]
/** $factoryInfo
* The current default implementation of a $Coll is a `HashSet`.
* @define coll mutable set
- * @define Coll mutable.Set
+ * @define Coll `mutable.Set`
*/
object Set extends MutableSetFactory[Set] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Set[A]] = setCanBuildFrom[A]
diff --git a/src/library/scala/collection/mutable/SetLike.scala b/src/library/scala/collection/mutable/SetLike.scala
index 5e201d9959..37313c8ca3 100644
--- a/src/library/scala/collection/mutable/SetLike.scala
+++ b/src/library/scala/collection/mutable/SetLike.scala
@@ -170,8 +170,6 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
@migration("`++` creates a new set. Use `++=` to add elements to this set and return that set itself.", "2.8.0")
override def ++(xs: GenTraversableOnce[A]): This = clone() ++= xs.seq
- @bridge def ++(xs: TraversableOnce[A]): This = ++(xs: GenTraversableOnce[A])
-
/** Creates a new set consisting of all the elements of this set except `elem`.
*
* @param elem the element to remove.
@@ -203,8 +201,6 @@ trait SetLike[A, +This <: SetLike[A, This] with Set[A]]
@migration("`--` creates a new set. Use `--=` to remove elements from this set and return that set itself.", "2.8.0")
override def --(xs: GenTraversableOnce[A]): This = clone() --= xs.seq
- @bridge def --(xs: TraversableOnce[A]): This = --(xs: GenTraversableOnce[A])
-
/** Send a message to this scriptable object.
*
* @param cmd the message to send.
diff --git a/src/library/scala/collection/mutable/SortedSet.scala b/src/library/scala/collection/mutable/SortedSet.scala
index f41a51d3ef..78d12f3d64 100644
--- a/src/library/scala/collection/mutable/SortedSet.scala
+++ b/src/library/scala/collection/mutable/SortedSet.scala
@@ -14,7 +14,7 @@ import generic._
/**
* Base trait for mutable sorted set.
*
- * @define Coll mutable.SortedSet
+ * @define Coll `mutable.SortedSet`
* @define coll mutable sorted set
*
* @author Lucien Pereira
@@ -31,7 +31,7 @@ trait SortedSet[A] extends collection.SortedSet[A] with collection.SortedSetLike
/**
* A template for mutable sorted set companion objects.
*
- * @define Coll mutable.SortedSet
+ * @define Coll `mutable.SortedSet`
* @define coll mutable sorted set
* @define factoryInfo
* This object provides a set of operations needed to create sorted sets of type mutable.SortedSet.
diff --git a/src/library/scala/collection/mutable/Stack.scala b/src/library/scala/collection/mutable/Stack.scala
index b70df05c55..042eac517a 100644
--- a/src/library/scala/collection/mutable/Stack.scala
+++ b/src/library/scala/collection/mutable/Stack.scala
@@ -20,7 +20,7 @@ import annotation.migration
*
* $factoryInfo
* @define coll mutable stack
- * @define Coll mutable.Stack
+ * @define Coll `mutable.Stack`
*/
object Stack extends SeqFactory[Stack] {
class StackBuilder[A] extends Builder[A, Stack[A]] {
@@ -46,7 +46,7 @@ object Stack extends SeqFactory[Stack] {
* @since 1
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#stacks "Scala's Collection Library overview"]]
* section on `Stacks` for more information.
- * @define Coll Stack
+ * @define Coll `Stack`
* @define coll stack
* @define orderDependent
* @define orderDependentFold
diff --git a/src/library/scala/collection/mutable/StringBuilder.scala b/src/library/scala/collection/mutable/StringBuilder.scala
index d9ad58f054..08c881dbb8 100644
--- a/src/library/scala/collection/mutable/StringBuilder.scala
+++ b/src/library/scala/collection/mutable/StringBuilder.scala
@@ -404,7 +404,7 @@ final class StringBuilder(private val underlying: JavaStringBuilder)
* @return the reversed StringBuilder
*/
@migration("`reverse` returns a new instance. Use `reverseContents` to update in place and return that StringBuilder itself.", "2.8.0")
- override def reverse: StringBuilder = new StringBuilder(new JavaStringBuilder(underlying) reverse)
+ override def reverse: StringBuilder = new StringBuilder(new JavaStringBuilder(underlying).reverse)
override def clone(): StringBuilder = new StringBuilder(new JavaStringBuilder(underlying))
diff --git a/src/library/scala/collection/mutable/SynchronizedBuffer.scala b/src/library/scala/collection/mutable/SynchronizedBuffer.scala
index 23552e9d52..a14605d60a 100644
--- a/src/library/scala/collection/mutable/SynchronizedBuffer.scala
+++ b/src/library/scala/collection/mutable/SynchronizedBuffer.scala
@@ -21,7 +21,7 @@ import script._
* @author Matthias Zenger
* @version 1.0, 08/07/2003
* @since 1
- * @define Coll SynchronizedBuffer
+ * @define Coll `SynchronizedBuffer`
* @define coll synchronized buffer
*/
trait SynchronizedBuffer[A] extends Buffer[A] {
diff --git a/src/library/scala/collection/mutable/SynchronizedMap.scala b/src/library/scala/collection/mutable/SynchronizedMap.scala
index 6e3ae13ada..037b8ec5f5 100644
--- a/src/library/scala/collection/mutable/SynchronizedMap.scala
+++ b/src/library/scala/collection/mutable/SynchronizedMap.scala
@@ -22,7 +22,7 @@ import annotation.migration
* @author Matthias Zenger, Martin Odersky
* @version 2.0, 31/12/2006
* @since 1
- * @define Coll SynchronizedMap
+ * @define Coll `SynchronizedMap`
* @define coll synchronized map
*/
trait SynchronizedMap[A, B] extends Map[A, B] {
diff --git a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
index 159b8312b2..bc32537798 100644
--- a/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
+++ b/src/library/scala/collection/mutable/SynchronizedPriorityQueue.scala
@@ -20,7 +20,7 @@ package mutable
* @author Matthias Zenger
* @version 1.0, 03/05/2004
* @since 1
- * @define Coll SynchronizedPriorityQueue
+ * @define Coll `SynchronizedPriorityQueue`
* @define coll synchronized priority queue
*/
class SynchronizedPriorityQueue[A](implicit ord: Ordering[A]) extends PriorityQueue[A] {
diff --git a/src/library/scala/collection/mutable/SynchronizedQueue.scala b/src/library/scala/collection/mutable/SynchronizedQueue.scala
index 56f74a5b9b..9e00c5d6fd 100644
--- a/src/library/scala/collection/mutable/SynchronizedQueue.scala
+++ b/src/library/scala/collection/mutable/SynchronizedQueue.scala
@@ -21,7 +21,7 @@ package mutable
* @author Matthias Zenger
* @version 1.0, 03/05/2004
* @since 1
- * @define Coll SynchronizedQueue
+ * @define Coll `SynchronizedQueue`
* @define coll synchronized queue
*/
class SynchronizedQueue[A] extends Queue[A] {
diff --git a/src/library/scala/collection/mutable/SynchronizedSet.scala b/src/library/scala/collection/mutable/SynchronizedSet.scala
index c945a859f3..c28764ff68 100644
--- a/src/library/scala/collection/mutable/SynchronizedSet.scala
+++ b/src/library/scala/collection/mutable/SynchronizedSet.scala
@@ -20,7 +20,7 @@ import script._
* @author Matthias Zenger
* @version 1.0, 08/07/2003
* @since 1
- * @define Coll SynchronizedSet
+ * @define Coll `SynchronizedSet`
* @define coll synchronized set
*/
trait SynchronizedSet[A] extends Set[A] {
diff --git a/src/library/scala/collection/mutable/SynchronizedStack.scala b/src/library/scala/collection/mutable/SynchronizedStack.scala
index a09ae21901..8363222295 100644
--- a/src/library/scala/collection/mutable/SynchronizedStack.scala
+++ b/src/library/scala/collection/mutable/SynchronizedStack.scala
@@ -21,7 +21,7 @@ package mutable
* @author Matthias Zenger
* @version 1.0, 03/05/2004
* @since 1
- * @define Coll SynchronizedStack
+ * @define Coll `SynchronizedStack`
* @define coll synchronized stack
*/
class SynchronizedStack[A] extends Stack[A] {
diff --git a/src/library/scala/collection/mutable/Traversable.scala b/src/library/scala/collection/mutable/Traversable.scala
index 04b67c0bad..28241fdec9 100644
--- a/src/library/scala/collection/mutable/Traversable.scala
+++ b/src/library/scala/collection/mutable/Traversable.scala
@@ -29,7 +29,7 @@ trait Traversable[A] extends scala.collection.Traversable[A]
/** $factoryInfo
* The current default implementation of a $Coll is an `ArrayBuffer`.
* @define coll mutable traversable collection
- * @define Coll mutable.Traversable
+ * @define Coll `mutable.Traversable`
*/
object Traversable extends TraversableFactory[Traversable] {
implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Traversable[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]
diff --git a/src/library/scala/collection/mutable/TreeSet.scala b/src/library/scala/collection/mutable/TreeSet.scala
index 02ee811193..00675b9119 100644
--- a/src/library/scala/collection/mutable/TreeSet.scala
+++ b/src/library/scala/collection/mutable/TreeSet.scala
@@ -12,7 +12,7 @@ package mutable
import generic._
/**
- * @define Coll mutable.TreeSet
+ * @define Coll `mutable.TreeSet`
* @define coll mutable tree set
* @factoryInfo
* Companion object of TreeSet providing factory related utilities.
diff --git a/src/library/scala/collection/mutable/UnrolledBuffer.scala b/src/library/scala/collection/mutable/UnrolledBuffer.scala
index 09e6088782..cd76c7de4e 100644
--- a/src/library/scala/collection/mutable/UnrolledBuffer.scala
+++ b/src/library/scala/collection/mutable/UnrolledBuffer.scala
@@ -36,16 +36,16 @@ import annotation.tailrec
* should still be avoided for such a purpose.
*
* @define coll unrolled buffer
- * @define Coll UnrolledBuffer
+ * @define Coll `UnrolledBuffer`
* @author Aleksandar Prokopec
*
*/
@SerialVersionUID(1L)
-class UnrolledBuffer[T](implicit val manifest: ClassManifest[T])
+class UnrolledBuffer[T](implicit val tag: ArrayTag[T])
extends collection.mutable.AbstractBuffer[T]
with collection.mutable.Buffer[T]
with collection.mutable.BufferLike[T, UnrolledBuffer[T]]
- with GenericClassManifestTraversableTemplate[T, UnrolledBuffer]
+ with GenericArrayTagTraversableTemplate[T, UnrolledBuffer]
with collection.mutable.Builder[T, UnrolledBuffer[T]]
with Serializable
{
@@ -67,7 +67,7 @@ extends collection.mutable.AbstractBuffer[T]
private[collection] def calcNextLength(sz: Int) = sz
- def classManifestCompanion = UnrolledBuffer
+ def arrayTagCompanion = UnrolledBuffer
/** Concatenates the targer unrolled buffer to this unrolled buffer.
*
@@ -183,11 +183,11 @@ extends collection.mutable.AbstractBuffer[T]
}
-object UnrolledBuffer extends ClassManifestTraversableFactory[UnrolledBuffer] {
+object UnrolledBuffer extends ArrayTagTraversableFactory[UnrolledBuffer] {
/** $genericCanBuildFromInfo */
- implicit def canBuildFrom[T](implicit m: ClassManifest[T]): CanBuildFrom[Coll, T, UnrolledBuffer[T]] =
+ implicit def canBuildFrom[T](implicit t: ArrayTag[T]): CanBuildFrom[Coll, T, UnrolledBuffer[T]] =
new GenericCanBuildFrom[T]
- def newBuilder[T](implicit m: ClassManifest[T]): Builder[T, UnrolledBuffer[T]] = new UnrolledBuffer[T]
+ def newBuilder[T](implicit t: ArrayTag[T]): Builder[T, UnrolledBuffer[T]] = new UnrolledBuffer[T]
val waterline = 50
val waterlineDelim = 100
@@ -195,7 +195,7 @@ object UnrolledBuffer extends ClassManifestTraversableFactory[UnrolledBuffer] {
/** Unrolled buffer node.
*/
- class Unrolled[T: ClassManifest] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) {
+ class Unrolled[T: ArrayTag] private[collection] (var size: Int, var array: Array[T], var next: Unrolled[T], val buff: UnrolledBuffer[T] = null) {
private[collection] def this() = this(0, new Array[T](unrolledlength), null, null)
private[collection] def this(b: UnrolledBuffer[T]) = this(0, new Array[T](unrolledlength), null, b)
diff --git a/src/library/scala/collection/mutable/WeakHashMap.scala b/src/library/scala/collection/mutable/WeakHashMap.scala
index 4e09755acf..ec99197bb9 100644
--- a/src/library/scala/collection/mutable/WeakHashMap.scala
+++ b/src/library/scala/collection/mutable/WeakHashMap.scala
@@ -23,7 +23,7 @@ import convert.Wrappers._
* @see [[http://docs.scala-lang.org/overviews/collections/concrete-mutable-collection-classes.html#weak_hash_maps "Scala's Collection Library overview"]]
* section on `Weak Hash Maps` for more information.
*
- * @define Coll WeakHashMap
+ * @define Coll `WeakHashMap`
* @define coll weak hash map
* @define thatinfo the class of the returned collection. In the standard library configuration,
* `That` is always `WeakHashMap[A, B]` if the elements contained in the resulting collection are
@@ -43,7 +43,7 @@ class WeakHashMap[A, B] extends JMapWrapper[A, B](new java.util.WeakHashMap)
}
/** $factoryInfo
- * @define Coll WeakHashMap
+ * @define Coll `WeakHashMap`
* @define coll weak hash map
*/
object WeakHashMap extends MutableMapFactory[WeakHashMap] {
diff --git a/src/library/scala/collection/mutable/WrappedArray.scala b/src/library/scala/collection/mutable/WrappedArray.scala
index 4287bac249..86317819a1 100644
--- a/src/library/scala/collection/mutable/WrappedArray.scala
+++ b/src/library/scala/collection/mutable/WrappedArray.scala
@@ -11,7 +11,8 @@
package scala.collection
package mutable
-import scala.reflect.ClassManifest
+import scala.reflect.ArrayTag
+import scala.runtime.ScalaRunTime._
import scala.collection.generic._
import scala.collection.parallel.mutable.ParArray
@@ -23,7 +24,7 @@ import scala.collection.parallel.mutable.ParArray
* @author Martin Odersky, Stephane Micheloud
* @version 1.0
* @since 2.8
- * @define Coll WrappedArray
+ * @define Coll `WrappedArray`
* @define coll wrapped array
* @define orderDependent
* @define orderDependentFold
@@ -40,8 +41,11 @@ extends AbstractSeq[T]
override protected[this] def thisCollection: WrappedArray[T] = this
override protected[this] def toCollection(repr: WrappedArray[T]): WrappedArray[T] = repr
- /** The manifest of the element type */
- def elemManifest: ClassManifest[T]
+ /** The tag of the element type */
+ def elemTag: ArrayTag[T]
+
+ @deprecated("use elemTag instead", "2.10.0")
+ def elemManifest: ClassManifest[T] = ClassManifest.fromClass[T](arrayElementClass(elemTag).asInstanceOf[Class[T]])
/** The length of the array */
def length: Int
@@ -57,11 +61,16 @@ extends AbstractSeq[T]
override def par = ParArray.handoff(array)
- override def toArray[U >: T : ClassManifest]: Array[U] =
- if (implicitly[ClassManifest[U]].erasure eq array.getClass.getComponentType)
+ private def elementClass: Class[_] =
+ arrayElementClass(repr.getClass)
+
+ override def toArray[U >: T : ArrayTag]: Array[U] = {
+ val thatElementClass = arrayElementClass(implicitly[ArrayTag[U]])
+ if (elementClass eq thatElementClass)
array.asInstanceOf[Array[U]]
else
super.toArray[U]
+ }
override def stringPrefix = "WrappedArray"
@@ -71,7 +80,7 @@ extends AbstractSeq[T]
/** Creates new builder for this collection ==> move to subclasses
*/
override protected[this] def newBuilder: Builder[T, WrappedArray[T]] =
- new WrappedArrayBuilder[T](elemManifest)
+ new WrappedArrayBuilder[T](elemTag)
}
@@ -101,7 +110,7 @@ object WrappedArray {
case x: Array[Unit] => new ofUnit(x)
}).asInstanceOf[WrappedArray[T]]
- implicit def canBuildFrom[T](implicit m: ClassManifest[T]): CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] =
+ implicit def canBuildFrom[T](implicit m: ArrayTag[T]): CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] =
new CanBuildFrom[WrappedArray[_], T, WrappedArray[T]] {
def apply(from: WrappedArray[_]): Builder[T, WrappedArray[T]] =
ArrayBuilder.make[T]()(m) mapResult WrappedArray.make[T]
@@ -112,70 +121,70 @@ object WrappedArray {
def newBuilder[A]: Builder[A, IndexedSeq[A]] = new ArrayBuffer
final class ofRef[T <: AnyRef](val array: Array[T]) extends WrappedArray[T] with Serializable {
- lazy val elemManifest = ClassManifest.classType[T](array.getClass.getComponentType)
+ lazy val elemTag = ClassTag[T](arrayElementClass(array.getClass))
def length: Int = array.length
def apply(index: Int): T = array(index).asInstanceOf[T]
def update(index: Int, elem: T) { array(index) = elem }
}
final class ofByte(val array: Array[Byte]) extends WrappedArray[Byte] with Serializable {
- def elemManifest = ClassManifest.Byte
+ def elemTag = ClassTag.Byte
def length: Int = array.length
def apply(index: Int): Byte = array(index)
def update(index: Int, elem: Byte) { array(index) = elem }
}
final class ofShort(val array: Array[Short]) extends WrappedArray[Short] with Serializable {
- def elemManifest = ClassManifest.Short
+ def elemTag = ClassTag.Short
def length: Int = array.length
def apply(index: Int): Short = array(index)
def update(index: Int, elem: Short) { array(index) = elem }
}
final class ofChar(val array: Array[Char]) extends WrappedArray[Char] with Serializable {
- def elemManifest = ClassManifest.Char
+ def elemTag = ClassTag.Char
def length: Int = array.length
def apply(index: Int): Char = array(index)
def update(index: Int, elem: Char) { array(index) = elem }
}
final class ofInt(val array: Array[Int]) extends WrappedArray[Int] with Serializable {
- def elemManifest = ClassManifest.Int
+ def elemTag = ClassTag.Int
def length: Int = array.length
def apply(index: Int): Int = array(index)
def update(index: Int, elem: Int) { array(index) = elem }
}
final class ofLong(val array: Array[Long]) extends WrappedArray[Long] with Serializable {
- def elemManifest = ClassManifest.Long
+ def elemTag = ClassTag.Long
def length: Int = array.length
def apply(index: Int): Long = array(index)
def update(index: Int, elem: Long) { array(index) = elem }
}
final class ofFloat(val array: Array[Float]) extends WrappedArray[Float] with Serializable {
- def elemManifest = ClassManifest.Float
+ def elemTag = ClassTag.Float
def length: Int = array.length
def apply(index: Int): Float = array(index)
def update(index: Int, elem: Float) { array(index) = elem }
}
final class ofDouble(val array: Array[Double]) extends WrappedArray[Double] with Serializable {
- def elemManifest = ClassManifest.Double
+ def elemTag = ClassTag.Double
def length: Int = array.length
def apply(index: Int): Double = array(index)
def update(index: Int, elem: Double) { array(index) = elem }
}
final class ofBoolean(val array: Array[Boolean]) extends WrappedArray[Boolean] with Serializable {
- def elemManifest = ClassManifest.Boolean
+ def elemTag = ClassTag.Boolean
def length: Int = array.length
def apply(index: Int): Boolean = array(index)
def update(index: Int, elem: Boolean) { array(index) = elem }
}
final class ofUnit(val array: Array[Unit]) extends WrappedArray[Unit] with Serializable {
- def elemManifest = ClassManifest.Unit
+ def elemTag = ClassTag.Unit
def length: Int = array.length
def apply(index: Int): Unit = array(index)
def update(index: Int, elem: Unit) { array(index) = elem }
diff --git a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
index 9771a45a28..99a0b0ede3 100644
--- a/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
+++ b/src/library/scala/collection/mutable/WrappedArrayBuilder.scala
@@ -12,23 +12,39 @@ package scala.collection
package mutable
import generic._
-import scala.reflect.ClassManifest
+import scala.reflect.ArrayTag
+import scala.runtime.ScalaRunTime._
/** A builder class for arrays.
*
- * @tparam A type of elements that can be added to this builder.
- * @param manifest class manifest for objects of type `A`.
+ * @tparam A type of elements that can be added to this builder.
+ * @param tag class tag for objects of type `A`.
*
* @since 2.8
*/
-class WrappedArrayBuilder[A](manifest: ClassManifest[A]) extends Builder[A, WrappedArray[A]] {
+class WrappedArrayBuilder[A](tag: ArrayTag[A]) extends Builder[A, WrappedArray[A]] {
+
+ @deprecated("use tag instead", "2.10.0")
+ val manifest: ArrayTag[A] = tag
private var elems: WrappedArray[A] = _
private var capacity: Int = 0
private var size: Int = 0
private def mkArray(size: Int): WrappedArray[A] = {
- val newelems = manifest.newWrappedArray(size)
+ val erasure = arrayElementClass(tag)
+ val newelems = erasure match {
+ case java.lang.Byte.TYPE => new WrappedArray.ofByte(new Array[Byte](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Short.TYPE => new WrappedArray.ofShort(new Array[Short](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Character.TYPE => new WrappedArray.ofChar(new Array[Char](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Integer.TYPE => new WrappedArray.ofInt(new Array[Int](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Long.TYPE => new WrappedArray.ofLong(new Array[Long](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Float.TYPE => new WrappedArray.ofFloat(new Array[Float](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Double.TYPE => new WrappedArray.ofDouble(new Array[Double](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Boolean.TYPE => new WrappedArray.ofBoolean(new Array[Boolean](size)).asInstanceOf[WrappedArray[A]]
+ case java.lang.Void.TYPE => new WrappedArray.ofUnit(new Array[Unit](size)).asInstanceOf[WrappedArray[A]]
+ case _ => new WrappedArray.ofRef[A with AnyRef](tag.newArray(size).asInstanceOf[Array[A with AnyRef]]).asInstanceOf[WrappedArray[A]]
+ }
if (this.size > 0) Array.copy(elems.array, 0, newelems.array, 0, this.size)
newelems
}
diff --git a/src/library/scala/collection/parallel/ParIterable.scala b/src/library/scala/collection/parallel/ParIterable.scala
index 0b5faf15ee..0bd6abaf78 100644
--- a/src/library/scala/collection/parallel/ParIterable.scala
+++ b/src/library/scala/collection/parallel/ParIterable.scala
@@ -24,7 +24,7 @@ import scala.collection.parallel.mutable.ParArray
* @author Aleksandar Prokopec
* @since 2.9
*
- * @define Coll ParIterable
+ * @define Coll `ParIterable`
* @define coll parallel iterable
*/
trait ParIterable[+T]
diff --git a/src/library/scala/collection/parallel/ParIterableLike.scala b/src/library/scala/collection/parallel/ParIterableLike.scala
index 5551c04ce2..4cb229fc0f 100644
--- a/src/library/scala/collection/parallel/ParIterableLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableLike.scala
@@ -29,6 +29,7 @@ import java.util.concurrent.atomic.AtomicBoolean
import annotation.unchecked.uncheckedVariance
import annotation.unchecked.uncheckedStable
+import language.implicitConversions
/** A template trait for parallel collections of type `ParIterable[T]`.
@@ -154,15 +155,15 @@ extends GenIterableLike[T, Repr]
with HasNewCombiner[T, Repr]
{
self: ParIterableLike[T, Repr, Sequential] =>
-
+
@transient
@volatile
private var _tasksupport = defaultTaskSupport
-
+
protected def initTaskSupport() {
_tasksupport = defaultTaskSupport
}
-
+
def tasksupport = {
val ts = _tasksupport
if (ts eq null) {
@@ -170,17 +171,37 @@ self: ParIterableLike[T, Repr, Sequential] =>
defaultTaskSupport
} else ts
}
-
+
def tasksupport_=(ts: TaskSupport) = _tasksupport = ts
-
+
def seq: Sequential
def repr: Repr = this.asInstanceOf[Repr]
+ final def isTraversableAgain = true
+
def hasDefiniteSize = true
+ def isEmpty = size == 0
+
def nonEmpty = size != 0
-
+
+ def head = iterator.next
+
+ def headOption = if (nonEmpty) Some(head) else None
+
+ def tail = drop(1)
+
+ def last = {
+ var lst = head
+ for (x <- this.seq) lst = x
+ lst
+ }
+
+ def lastOption = if (nonEmpty) Some(last) else None
+
+ def init = take(size - 1)
+
/** Creates a new parallel iterator used to traverse the elements of this parallel collection.
* This iterator is more specific than the iterator of the returned by `iterator`, and augmented
* with additional accessor and transformer methods.
@@ -239,7 +260,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
trait BuilderOps[Elem, To] {
trait Otherwise[Cmb] {
- def otherwise(notbody: => Unit)(implicit m: ClassManifest[Cmb]): Unit
+ def otherwise(notbody: => Unit)(implicit t: ClassTag[Cmb]): Unit
}
def ifIs[Cmb](isbody: Cmb => Unit): Otherwise[Cmb]
@@ -281,8 +302,8 @@ self: ParIterableLike[T, Repr, Sequential] =>
protected implicit def builder2ops[Elem, To](cb: Builder[Elem, To]) = new BuilderOps[Elem, To] {
def ifIs[Cmb](isbody: Cmb => Unit) = new Otherwise[Cmb] {
- def otherwise(notbody: => Unit)(implicit m: ClassManifest[Cmb]) {
- if (cb.getClass == m.erasure) isbody(cb.asInstanceOf[Cmb]) else notbody
+ def otherwise(notbody: => Unit)(implicit t: ClassTag[Cmb]) {
+ if (cb.getClass == t.erasure) isbody(cb.asInstanceOf[Cmb]) else notbody
}
}
def isCombiner = cb.isInstanceOf[Combiner[_, _]]
@@ -753,7 +774,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
cntx.setIndexFlag(Int.MaxValue)
tasksupport.executeAndWaitResult(
new Span(0, pred, combinerFactory, combinerFactory, splitter assign cntx) mapResult {
- _._2.resultWithTaskSupport
+ _._2.resultWithTaskSupport
}
)
}
@@ -801,7 +822,7 @@ self: ParIterableLike[T, Repr, Sequential] =>
def size = splitter.remaining
}
- override def toArray[U >: T: ClassManifest]: Array[U] = {
+ override def toArray[U >: T: ArrayTag]: Array[U] = {
val arr = new Array[U](size)
copyToArray(arr)
arr
diff --git a/src/library/scala/collection/parallel/ParIterableViewLike.scala b/src/library/scala/collection/parallel/ParIterableViewLike.scala
index 536139c812..91eefc2aa5 100644
--- a/src/library/scala/collection/parallel/ParIterableViewLike.scala
+++ b/src/library/scala/collection/parallel/ParIterableViewLike.scala
@@ -18,6 +18,7 @@ import scala.collection.GenSeq
import scala.collection.generic.{ CanBuildFrom, SliceInterval }
import scala.collection.generic.CanCombineFrom
import scala.collection.parallel.immutable.ParRange
+import language.implicitConversions
diff --git a/src/library/scala/collection/parallel/TaskSupport.scala b/src/library/scala/collection/parallel/TaskSupport.scala
index 59b75f523f..2eaa861429 100644
--- a/src/library/scala/collection/parallel/TaskSupport.scala
+++ b/src/library/scala/collection/parallel/TaskSupport.scala
@@ -48,7 +48,7 @@ extends TaskSupport with AdaptiveWorkStealingThreadPoolTasks
* By default, parallel collections are parametrized with this task support object, so parallel collections
* share the same execution context backend as the rest of the `scala.concurrent` package.
*/
-class ExecutionContextTaskSupport(val environment: ExecutionContext = scala.concurrent.executionContext)
+class ExecutionContextTaskSupport(val environment: ExecutionContext = scala.concurrent.defaultExecutionContext)
extends TaskSupport with ExecutionContextTasks
diff --git a/src/library/scala/collection/parallel/immutable/ParHashMap.scala b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
index e630a9dbed..ad882390c8 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashMap.scala
@@ -39,7 +39,7 @@ import collection.parallel.Task
* @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tries Scala's Parallel Collections Library overview]]
* section on Parallel Hash Tries for more information.
*
- * @define Coll immutable.ParHashMap
+ * @define Coll `immutable.ParHashMap`
* @define coll immutable parallel hash map
*/
@SerialVersionUID(1L)
@@ -140,7 +140,7 @@ self =>
/** $factoryInfo
- * @define Coll immutable.ParHashMap
+ * @define Coll `immutable.ParHashMap`
* @define coll immutable parallel hash map
*/
object ParHashMap extends ParMapFactory[ParHashMap] {
diff --git a/src/library/scala/collection/parallel/immutable/ParHashSet.scala b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
index 084637c5dc..d1899601d7 100644
--- a/src/library/scala/collection/parallel/immutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/immutable/ParHashSet.scala
@@ -38,7 +38,7 @@ import collection.parallel.Task
* @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_hash_tries Scala's Parallel Collections Library overview]]
* section on Parallel Hash Tries for more information.
*
- * @define Coll immutable.ParHashSet
+ * @define Coll `immutable.ParHashSet`
* @define coll immutable parallel hash set
*/
@SerialVersionUID(1L)
@@ -118,7 +118,7 @@ self =>
/** $factoryInfo
- * @define Coll immutable.ParHashSet
+ * @define Coll `immutable.ParHashSet`
* @define coll immutable parallel hash set
*/
object ParHashSet extends ParSetFactory[ParHashSet] {
diff --git a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled b/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
index fb411ec0ac..04bc8b8d29 100644
--- a/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
+++ b/src/library/scala/collection/parallel/immutable/ParNumericRange.scala.disabled
@@ -29,7 +29,7 @@ import scala.collection.parallel.ParIterableIterator
* @author Aleksandar Prokopec
* @since 2.9
*
- * @define Coll immutable.ParRange
+ * @define Coll `immutable.ParRange`
* @define coll immutable parallel range
*/
@SerialVersionUID(1L)
diff --git a/src/library/scala/collection/parallel/immutable/ParRange.scala b/src/library/scala/collection/parallel/immutable/ParRange.scala
index 277fd5fdd3..9553704caa 100644
--- a/src/library/scala/collection/parallel/immutable/ParRange.scala
+++ b/src/library/scala/collection/parallel/immutable/ParRange.scala
@@ -28,7 +28,7 @@ import scala.collection.Iterator
* @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_range Scala's Parallel Collections Library overview]]
* section on `ParRange` for more information.
*
- * @define Coll immutable.ParRange
+ * @define Coll `immutable.ParRange`
* @define coll immutable parallel range
*/
@SerialVersionUID(1L)
diff --git a/src/library/scala/collection/parallel/immutable/ParSeq.scala b/src/library/scala/collection/parallel/immutable/ParSeq.scala
index bf3d3a5aa8..dde6533c82 100644
--- a/src/library/scala/collection/parallel/immutable/ParSeq.scala
+++ b/src/library/scala/collection/parallel/immutable/ParSeq.scala
@@ -24,7 +24,7 @@ import scala.collection.GenSeq
/** An immutable variant of `ParSeq`.
*
- * @define Coll mutable.ParSeq
+ * @define Coll `mutable.ParSeq`
* @define coll mutable parallel sequence
*/
trait ParSeq[+T]
@@ -40,7 +40,7 @@ extends collection/*.immutable*/.GenSeq[T]
/** $factoryInfo
- * @define Coll mutable.ParSeq
+ * @define Coll `mutable.ParSeq`
* @define coll mutable parallel sequence
*/
object ParSeq extends ParFactory[ParSeq] {
diff --git a/src/library/scala/collection/parallel/immutable/ParSet.scala b/src/library/scala/collection/parallel/immutable/ParSet.scala
index d64858ed10..40429280ac 100644
--- a/src/library/scala/collection/parallel/immutable/ParSet.scala
+++ b/src/library/scala/collection/parallel/immutable/ParSet.scala
@@ -16,7 +16,7 @@ import scala.collection.parallel.Combiner
/** An immutable variant of `ParSet`.
*
- * @define Coll mutable.ParSet
+ * @define Coll `mutable.ParSet`
* @define coll mutable parallel set
*/
trait ParSet[T]
@@ -38,7 +38,7 @@ self =>
}
/** $factoryInfo
- * @define Coll mutable.ParSet
+ * @define Coll `mutable.ParSet`
* @define coll mutable parallel set
*/
object ParSet extends ParSetFactory[ParSet] {
diff --git a/src/library/scala/collection/parallel/immutable/ParVector.scala b/src/library/scala/collection/parallel/immutable/ParVector.scala
index 8baa84b77c..1ece663a1d 100644
--- a/src/library/scala/collection/parallel/immutable/ParVector.scala
+++ b/src/library/scala/collection/parallel/immutable/ParVector.scala
@@ -37,7 +37,7 @@ import immutable.VectorIterator
* @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_vector Scala's Parallel Collections Library overview]]
* section on `ParVector` for more information.
*
- * @define Coll immutable.ParVector
+ * @define Coll `immutable.ParVector`
* @define coll immutable parallel vector
*/
class ParVector[+T](private[this] val vector: Vector[T])
@@ -86,7 +86,7 @@ extends ParSeq[T]
/** $factoryInfo
- * @define Coll immutable.ParVector
+ * @define Coll `immutable.ParVector`
* @define coll immutable parallel vector
*/
object ParVector extends ParFactory[ParVector] {
diff --git a/src/library/scala/collection/parallel/mutable/ParArray.scala b/src/library/scala/collection/parallel/mutable/ParArray.scala
index 8cc0b95997..29d84408db 100644
--- a/src/library/scala/collection/parallel/mutable/ParArray.scala
+++ b/src/library/scala/collection/parallel/mutable/ParArray.scala
@@ -49,7 +49,7 @@ import scala.collection.GenTraversableOnce
* @see [[http://docs.scala-lang.org/overviews/parallel-collections/concrete-parallel-collections.html#parallel_array Scala's Parallel Collections Library overview]]
* section on `ParArray` for more information.
*
- * @define Coll ParArray
+ * @define Coll `ParArray`
* @define coll parallel array
*
*/
@@ -676,7 +676,7 @@ self =>
private def readObject(in: java.io.ObjectInputStream) {
in.defaultReadObject
-
+
// get raw array from arrayseq
array = arrayseq.array.asInstanceOf[Array[Any]]
}
@@ -685,7 +685,7 @@ self =>
/** $factoryInfo
- * @define Coll mutable.ParArray
+ * @define Coll `mutable.ParArray`
* @define coll parallel array
*/
object ParArray extends ParFactory[ParArray] {
@@ -706,7 +706,7 @@ object ParArray extends ParFactory[ParArray] {
case _ => new ParArray[T](new ExposedArraySeq[T](runtime.ScalaRunTime.toObjectArray(arr), sz))
}
- def createFromCopy[T <: AnyRef : ClassManifest](arr: Array[T]): ParArray[T] = {
+ def createFromCopy[T <: AnyRef : ArrayTag](arr: Array[T]): ParArray[T] = {
val newarr = new Array[T](arr.length)
Array.copy(arr, 0, newarr, 0, arr.length)
handoff(newarr)
diff --git a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala
index 35c748916c..d0c7f6050e 100644
--- a/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala
+++ b/src/library/scala/collection/parallel/mutable/ParFlatHashTable.scala
@@ -15,7 +15,7 @@ import collection.parallel.IterableSplitter
*
* @tparam T type of the elements in the $coll.
* @define coll table
- * @define Coll flat hash table
+ * @define Coll `ParFlatHashTable`
*
* @author Aleksandar Prokopec
*/
diff --git a/src/library/scala/collection/parallel/mutable/ParHashMap.scala b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
index 23b23d55a1..05b3f89fa1 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashMap.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashMap.scala
@@ -28,7 +28,7 @@ import collection.parallel.Task
*
* @tparam T type of the elements in the parallel hash map
*
- * @define Coll ParHashMap
+ * @define Coll `ParHashMap`
* @define coll parallel hash map
*
* @author Aleksandar Prokopec
@@ -141,7 +141,7 @@ self =>
/** $factoryInfo
- * @define Coll mutable.ParHashMap
+ * @define Coll `mutable.ParHashMap`
* @define coll parallel hash map
*/
object ParHashMap extends ParMapFactory[ParHashMap] {
diff --git a/src/library/scala/collection/parallel/mutable/ParHashSet.scala b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
index 4e9a38c13f..783f8dce77 100644
--- a/src/library/scala/collection/parallel/mutable/ParHashSet.scala
+++ b/src/library/scala/collection/parallel/mutable/ParHashSet.scala
@@ -25,7 +25,7 @@ import collection.parallel.Task
*
* @tparam T type of the elements in the $coll.
*
- * @define Coll ParHashSet
+ * @define Coll `ParHashSet`
* @define coll parallel hash set
*
* @author Aleksandar Prokopec
@@ -104,7 +104,7 @@ extends ParSet[T]
/** $factoryInfo
- * @define Coll mutable.ParHashSet
+ * @define Coll `mutable.ParHashSet`
* @define coll parallel hash set
*/
object ParHashSet extends ParSetFactory[ParHashSet] {
diff --git a/src/library/scala/collection/parallel/mutable/ParSeq.scala b/src/library/scala/collection/parallel/mutable/ParSeq.scala
index a48ba48d56..f46b369494 100644
--- a/src/library/scala/collection/parallel/mutable/ParSeq.scala
+++ b/src/library/scala/collection/parallel/mutable/ParSeq.scala
@@ -26,7 +26,7 @@ import scala.collection.GenSeq
/** A mutable variant of `ParSeq`.
*
- * @define Coll mutable.ParSeq
+ * @define Coll `mutable.ParSeq`
* @define coll mutable parallel sequence
*/
trait ParSeq[T] extends collection/*.mutable*/.GenSeq[T] // was: collection.mutable.Seq[T]
@@ -47,7 +47,7 @@ self =>
/** $factoryInfo
- * @define Coll mutable.ParSeq
+ * @define Coll `mutable.ParSeq`
* @define coll mutable parallel sequence
*/
object ParSeq extends ParFactory[ParSeq] {
diff --git a/src/library/scala/collection/parallel/mutable/ParSet.scala b/src/library/scala/collection/parallel/mutable/ParSet.scala
index 1d295fd5fe..6da4c8a7bc 100644
--- a/src/library/scala/collection/parallel/mutable/ParSet.scala
+++ b/src/library/scala/collection/parallel/mutable/ParSet.scala
@@ -21,7 +21,7 @@ import scala.collection.GenSet
/** A mutable variant of `ParSet`.
*
- * @define Coll mutable.ParSet
+ * @define Coll `mutable.ParSet`
* @define coll mutable parallel set
*
* @author Aleksandar Prokopec
@@ -41,7 +41,7 @@ self =>
/** $factoryInfo
- * @define Coll mutable.ParSet
+ * @define Coll `mutable.ParSet`
* @define coll mutable parallel set
*/
object ParSet extends ParSetFactory[ParSet] {
diff --git a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala
index 410b542a68..43d40776bf 100644
--- a/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala
+++ b/src/library/scala/collection/parallel/mutable/UnrolledParArrayCombiner.scala
@@ -26,7 +26,7 @@ import scala.collection.parallel.Task
-private[mutable] class DoublingUnrolledBuffer[T](implicit m: ClassManifest[T]) extends UnrolledBuffer[T]()(m) {
+private[mutable] class DoublingUnrolledBuffer[T](implicit t: ArrayTag[T]) extends UnrolledBuffer[T]()(t) {
override def calcNextLength(sz: Int) = if (sz < 10000) sz * 2 else sz
protected override def newUnrolled = new Unrolled[T](0, new Array[T](4), null, this)
}
diff --git a/src/library/scala/collection/parallel/package.scala b/src/library/scala/collection/parallel/package.scala
index 943e0208c7..e3124af12e 100644
--- a/src/library/scala/collection/parallel/package.scala
+++ b/src/library/scala/collection/parallel/package.scala
@@ -13,6 +13,7 @@ import scala.collection.generic.CanCombineFrom
import scala.collection.parallel.mutable.ParArray
import scala.collection.mutable.UnrolledBuffer
import annotation.unchecked.uncheckedVariance
+import language.implicitConversions
/** Package object for parallel collections.
*/
diff --git a/src/library/scala/concurrent/Awaitable.scala b/src/library/scala/concurrent/Awaitable.scala
index 052e6e2366..99bdfbc5a9 100644
--- a/src/library/scala/concurrent/Awaitable.scala
+++ b/src/library/scala/concurrent/Awaitable.scala
@@ -10,18 +10,23 @@ package scala.concurrent
-import scala.annotation.implicitNotFound
import scala.concurrent.util.Duration
trait Awaitable[+T] {
+ /**
+ * Should throw [[scala.concurrent.TimeoutException]] if it times out
+ * This method should not be called directly.
+ */
+ @throws(classOf[TimeoutException])
def ready(atMost: Duration)(implicit permit: CanAwait): this.type
/**
- * Throws exceptions if cannot produce a T within the specified time
+ * Throws exceptions if it cannot produce a T within the specified time.
* This method should not be called directly.
*/
+ @throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T
}
diff --git a/src/library/scala/concurrent/ConcurrentPackageObject.scala b/src/library/scala/concurrent/ConcurrentPackageObject.scala
index 0f882540f2..a3d985733e 100644
--- a/src/library/scala/concurrent/ConcurrentPackageObject.scala
+++ b/src/library/scala/concurrent/ConcurrentPackageObject.scala
@@ -12,7 +12,7 @@ import java.util.concurrent.{ Executors, ExecutorService, ThreadFactory }
import scala.concurrent.forkjoin.{ ForkJoinPool, ForkJoinWorkerThread }
import scala.concurrent.util.Duration
import ConcurrentPackageObject._
-
+import language.implicitConversions
/** This package object contains primitives for concurrent and parallel programming.
@@ -20,10 +20,9 @@ import ConcurrentPackageObject._
abstract class ConcurrentPackageObject {
/** A global execution environment for executing lightweight tasks.
*/
- lazy val executionContext =
- new impl.ExecutionContextImpl()
+ lazy val defaultExecutionContext = new impl.ExecutionContextImpl(null)
- private val currentExecutionContext = new ThreadLocal[ExecutionContext]
+ val currentExecutionContext = new ThreadLocal[ExecutionContext]
val handledFutureException: PartialFunction[Throwable, Throwable] = {
case t: Throwable if isFutureThrowable(t) => t
@@ -37,34 +36,42 @@ abstract class ConcurrentPackageObject {
case _ => true
}
- private[concurrent] def resolve[T](source: Either[Throwable, T]): Either[Throwable, T] = source match {
- case Left(t: scala.runtime.NonLocalReturnControl[_]) => Right(t.value.asInstanceOf[T])
- case Left(t: scala.util.control.ControlThrowable) => Left(new ExecutionException("Boxed ControlThrowable", t))
- case Left(t: InterruptedException) => Left(new ExecutionException("Boxed InterruptedException", t))
- case Left(e: Error) => Left(new ExecutionException("Boxed Error", e))
- case _ => source
+ private[concurrent] def resolveEither[T](source: Either[Throwable, T]): Either[Throwable, T] = source match {
+ case Left(t) => resolver(t)
+ case _ => source
}
- private[concurrent] def resolver[T] =
- resolverFunction.asInstanceOf[PartialFunction[Throwable, Either[Throwable, T]]]
-
+ private[concurrent] def resolver[T](throwable: Throwable): Either[Throwable, T] = throwable match {
+ case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value.asInstanceOf[T])
+ case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t))
+ case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t))
+ case e: Error => Left(new ExecutionException("Boxed Error", e))
+ case t => Left(t)
+ }
+
/* concurrency constructs */
- def future[T](body: =>T)(implicit execctx: ExecutionContext = executionContext): Future[T] =
+ /** Starts an asynchronous computation and returns a `Future` object with the result of that computation.
+ *
+ * The result becomes available once the asynchronous computation is completed.
+ *
+ * @tparam T the type of the result
+ * @param body the asychronous computation
+ * @param execctx the execution context on which the future is run
+ * @return the `Future` holding the result of the computation
+ */
+ def future[T](body: =>T)(implicit execctx: ExecutionContext = defaultExecutionContext): Future[T] =
Future[T](body)
- def promise[T]()(implicit execctx: ExecutionContext = executionContext): Promise[T] =
+ /** Creates a promise object which can be completed with a value.
+ *
+ * @tparam T the type of the value in the promise
+ * @param execctx the execution context on which the promise is created on
+ * @return the newly created `Promise` object
+ */
+ def promise[T]()(implicit execctx: ExecutionContext = defaultExecutionContext): Promise[T] =
Promise[T]()
- /** Wraps a block of code into an awaitable object. */
- def body2awaitable[T](body: =>T) = new Awaitable[T] {
- def ready(atMost: Duration)(implicit permit: CanAwait) = {
- body
- this
- }
- def result(atMost: Duration)(implicit permit: CanAwait) = body
- }
-
/** Used to block on a piece of code which potentially blocks.
*
* @param body A piece of code which contains potentially blocking or long running calls.
@@ -75,7 +82,7 @@ abstract class ConcurrentPackageObject {
* - TimeoutException - in the case that the blockable object timed out
*/
def blocking[T](body: =>T): T =
- blocking(body2awaitable(body), Duration.fromNanos(0))
+ blocking(impl.Future.body2awaitable(body), Duration.Inf)
/** Blocks on an awaitable object.
*
@@ -86,11 +93,12 @@ abstract class ConcurrentPackageObject {
* - InterruptedException - in the case that a wait within the blockable object was interrupted
* - TimeoutException - in the case that the blockable object timed out
*/
- def blocking[T](awaitable: Awaitable[T], atMost: Duration): T =
+ def blocking[T](awaitable: Awaitable[T], atMost: Duration): T = {
currentExecutionContext.get match {
- case null => Await.result(awaitable, atMost)
+ case null => awaitable.result(atMost)(Await.canAwaitEvidence)
case ec => ec.internalBlockingCall(awaitable, atMost)
}
+ }
@inline implicit final def int2durationops(x: Int): DurationOps = new DurationOps(x)
}
@@ -101,11 +109,11 @@ private[concurrent] object ConcurrentPackageObject {
// compiling a subset of sources; it seems that the wildcard is not
// properly handled, and you get messages like "type _$1 defined twice".
// This is consistent with other package object breakdowns.
- private val resolverFunction: PartialFunction[Throwable, Either[Throwable, _]] = {
- case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value)
- case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t))
- case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t))
- case e: Error => Left(new ExecutionException("Boxed Error", e))
- case t => Left(t)
- }
+ // private val resolverFunction: PartialFunction[Throwable, Either[Throwable, _]] = {
+ // case t: scala.runtime.NonLocalReturnControl[_] => Right(t.value)
+ // case t: scala.util.control.ControlThrowable => Left(new ExecutionException("Boxed ControlThrowable", t))
+ // case t: InterruptedException => Left(new ExecutionException("Boxed InterruptedException", t))
+ // case e: Error => Left(new ExecutionException("Boxed Error", e))
+ // case t => Left(t)
+ // }
}
diff --git a/src/library/scala/concurrent/ExecutionContext.scala b/src/library/scala/concurrent/ExecutionContext.scala
index 16d9a1f980..4666674b5b 100644
--- a/src/library/scala/concurrent/ExecutionContext.scala
+++ b/src/library/scala/concurrent/ExecutionContext.scala
@@ -11,7 +11,7 @@ package scala.concurrent
import java.util.concurrent.atomic.{ AtomicInteger }
-import java.util.concurrent.{ Executors, Future => JFuture, Callable }
+import java.util.concurrent.{ Executors, Future => JFuture, Callable, ExecutorService, Executor }
import scala.concurrent.util.Duration
import scala.concurrent.forkjoin.{ ForkJoinPool, RecursiveTask => FJTask, RecursiveAction, ForkJoinWorkerThread }
import scala.collection.generic.CanBuildFrom
@@ -20,21 +20,46 @@ import collection._
trait ExecutionContext {
-
+
+ /** Runs a block of code on this execution context.
+ */
def execute(runnable: Runnable): Unit
-
- def execute[U](body: () => U): Unit
-
+
+ /** Used internally by the framework - blocks execution for at most `atMost` time while waiting
+ * for an `awaitable` object to become ready.
+ *
+ * Clients should use `scala.concurrent.blocking` instead.
+ */
def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T
+ /** Reports that an asynchronous computation failed.
+ */
def reportFailure(t: Throwable): Unit
-
- /* implementations follow */
-
- private implicit val executionContext = this
-
+
}
+/** Contains factory methods for creating execution contexts.
+ */
+object ExecutionContext {
+
+ implicit def defaultExecutionContext: ExecutionContext = scala.concurrent.defaultExecutionContext
+
+ /** Creates an `ExecutionContext` from the given `ExecutorService`.
+ */
+ def fromExecutorService(e: ExecutorService, reporter: Throwable => Unit = defaultReporter): ExecutionContext with Executor = new impl.ExecutionContextImpl(e, reporter)
+
+ /** Creates an `ExecutionContext` from the given `Executor`.
+ */
+ def fromExecutor(e: Executor, reporter: Throwable => Unit = defaultReporter): ExecutionContext with Executor = new impl.ExecutionContextImpl(e, reporter)
+
+ def defaultReporter: Throwable => Unit = {
+ // `Error`s are currently wrapped by `resolver`.
+ // Also, re-throwing `Error`s here causes an exception handling test to fail.
+ //case e: Error => throw e
+ case t => t.printStackTrace()
+ }
+
+}
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index 5f703ac23b..70b3c3dbbb 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -18,12 +18,14 @@ import java.{ lang => jl }
import java.util.concurrent.atomic.{ AtomicReferenceFieldUpdater, AtomicInteger, AtomicBoolean }
import scala.concurrent.util.Duration
+import scala.concurrent.impl.NonFatal
import scala.Option
import scala.annotation.tailrec
import scala.collection.mutable.Stack
import scala.collection.mutable.Builder
import scala.collection.generic.CanBuildFrom
+import language.higherKinds
@@ -82,7 +84,6 @@ import scala.collection.generic.CanBuildFrom
* }}}
*/
trait Future[+T] extends Awaitable[T] {
-self =>
/* Callbacks */
@@ -117,7 +118,7 @@ self =>
case Right(v) => // do nothing
}
- /** When this future is completed, either through an exception, a timeout, or a value,
+ /** When this future is completed, either through an exception, or a value,
* apply the provided function.
*
* If the future has already been completed,
@@ -130,29 +131,25 @@ self =>
/* Miscellaneous */
- /** Creates a new promise.
- */
- def newPromise[S]: Promise[S]
-
/** Returns whether the future has already been completed with
* a value or an exception.
- *
+ *
* $nonDeterministic
- *
+ *
* @return `true` if the future is already completed, `false` otherwise
*/
def isCompleted: Boolean
-
+
/** The value of this `Future`.
- *
+ *
* If the future is not completed the returned value will be `None`.
* If the future is completed the value will be `Some(Success(t))`
* if it contains a valid result, or `Some(Failure(error))` if it contains
* an exception.
*/
def value: Option[Either[Throwable, T]]
-
-
+
+
/* Projections */
/** Returns a failed projection of this future.
@@ -168,14 +165,11 @@ self =>
* and throws a corresponding exception if the original future fails.
*/
def failed: Future[Throwable] = {
- def noSuchElem(v: T) =
- new NoSuchElementException("Future.failed not completed with a throwable. Instead completed with: " + v)
-
- val p = newPromise[Throwable]
+ val p = Promise[Throwable]()
onComplete {
case Left(t) => p success t
- case Right(v) => p failure noSuchElem(v)
+ case Right(v) => p failure (new NoSuchElementException("Future.failed not completed with a throwable. Instead completed with: " + v))
}
p.future
@@ -200,14 +194,14 @@ self =>
* $forComprehensionExample
*/
def map[S](f: T => S): Future[S] = {
- val p = newPromise[S]
+ val p = Promise[S]()
onComplete {
case Left(t) => p failure t
case Right(v) =>
try p success f(v)
catch {
- case t => p complete resolver(t)
+ case NonFatal(t) => p complete resolver(t)
}
}
@@ -222,7 +216,7 @@ self =>
* $forComprehensionExample
*/
def flatMap[S](f: T => Future[S]): Future[S] = {
- val p = newPromise[S]
+ val p = Promise[S]()
onComplete {
case Left(t) => p failure t
@@ -233,7 +227,7 @@ self =>
case Right(v) => p success v
}
} catch {
- case t: Throwable => p complete resolver(t)
+ case NonFatal(t) => p complete resolver(t)
}
}
@@ -245,7 +239,7 @@ self =>
* If the current future contains a value which satisfies the predicate, the new future will also hold that value.
* Otherwise, the resulting future will fail with a `NoSuchElementException`.
*
- * If the current future fails or times out, the resulting future also fails or times out, respectively.
+ * If the current future fails, then the resulting future also fails.
*
* Example:
* {{{
@@ -257,7 +251,7 @@ self =>
* }}}
*/
def filter(pred: T => Boolean): Future[T] = {
- val p = newPromise[T]
+ val p = Promise[T]()
onComplete {
case Left(t) => p failure t
@@ -266,7 +260,7 @@ self =>
if (pred(v)) p success v
else p failure new NoSuchElementException("Future.filter predicate is not satisfied by: " + v)
} catch {
- case t: Throwable => p complete resolver(t)
+ case NonFatal(t) => p complete resolver(t)
}
}
@@ -285,12 +279,12 @@ self =>
// def withFilter(q: S => Boolean): FutureWithFilter[S] = new FutureWithFilter[S](self, x => p(x) && q(x))
// }
- /** Creates a new future by mapping the value of the current future if the given partial function is defined at that value.
+ /** Creates a new future by mapping the value of the current future, if the given partial function is defined at that value.
*
* If the current future contains a value for which the partial function is defined, the new future will also hold that value.
* Otherwise, the resulting future will fail with a `NoSuchElementException`.
*
- * If the current future fails or times out, the resulting future also fails or times out, respectively.
+ * If the current future fails, then the resulting future also fails.
*
* Example:
* {{{
@@ -306,7 +300,7 @@ self =>
* }}}
*/
def collect[S](pf: PartialFunction[T, S]): Future[S] = {
- val p = newPromise[S]
+ val p = Promise[S]()
onComplete {
case Left(t) => p failure t
@@ -315,7 +309,7 @@ self =>
if (pf.isDefinedAt(v)) p success pf(v)
else p failure new NoSuchElementException("Future.collect partial function is not defined at: " + v)
} catch {
- case t: Throwable => p complete resolver(t)
+ case NonFatal(t) => p complete resolver(t)
}
}
@@ -335,12 +329,12 @@ self =>
* }}}
*/
def recover[U >: T](pf: PartialFunction[Throwable, U]): Future[U] = {
- val p = newPromise[U]
+ val p = Promise[U]()
onComplete {
case Left(t) if pf isDefinedAt t =>
try { p success pf(t) }
- catch { case t: Throwable => p complete resolver(t) }
+ catch { case NonFatal(t) => p complete resolver(t) }
case otherwise => p complete otherwise
}
@@ -361,14 +355,14 @@ self =>
* }}}
*/
def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]]): Future[U] = {
- val p = newPromise[U]
+ val p = Promise[U]()
onComplete {
case Left(t) if pf isDefinedAt t =>
try {
p completeWith pf(t)
} catch {
- case t: Throwable => p complete resolver(t)
+ case NonFatal(t) => p complete resolver(t)
}
case otherwise => p complete otherwise
}
@@ -385,19 +379,19 @@ self =>
* with the throwable stored in `that`.
*/
def zip[U](that: Future[U]): Future[(T, U)] = {
- val p = newPromise[(T, U)]
-
+ val p = Promise[(T, U)]()
+
this onComplete {
case Left(t) => p failure t
- case Right(r) => that onSuccess {
- case r2 => p success ((r, r2))
- }
- }
-
- that onFailure {
- case f => p failure f
+ case Right(r) =>
+ that onSuccess {
+ case r2 => p success ((r, r2))
+ }
+ that onFailure {
+ case f => p failure f
+ }
}
-
+
p.future
}
@@ -411,43 +405,42 @@ self =>
* {{{
* val f = future { sys.error("failed") }
* val g = future { 5 }
- * val h = f orElse g
+ * val h = f fallbackTo g
* await(h, 0) // evaluates to 5
* }}}
*/
def fallbackTo[U >: T](that: Future[U]): Future[U] = {
- val p = newPromise[U]
-
+ val p = Promise[U]()
onComplete {
- case Left(t) => that onComplete {
- case Left(_) => p failure t
- case Right(v) => p success v
- }
- case Right(v) => p success v
+ case r @ Right(_) ⇒ p complete r
+ case _ ⇒ p completeWith that
}
-
p.future
}
-
+
/** Creates a new `Future[S]` which is completed with this `Future`'s result if
* that conforms to `S`'s erased type or a `ClassCastException` otherwise.
*/
- def mapTo[S](implicit m: Manifest[S]): Future[S] = {
- val p = newPromise[S]
-
+ def mapTo[S](implicit tag: ClassTag[S]): Future[S] = {
+ def boxedType(c: Class[_]): Class[_] = {
+ if (c.isPrimitive) Future.toBoxed(c) else c
+ }
+
+ val p = Promise[S]()
+
onComplete {
case l: Left[Throwable, _] => p complete l.asInstanceOf[Either[Throwable, S]]
case Right(t) =>
p complete (try {
- Right(impl.Future.boxedType(m.erasure).cast(t).asInstanceOf[S])
+ Right(boxedType(tag.erasure).cast(t).asInstanceOf[S])
} catch {
case e: ClassCastException => Left(e)
})
}
-
+
p.future
}
-
+
/** Applies the side-effecting function to the result of this future, and returns
* a new future with the result of this future.
*
@@ -472,7 +465,7 @@ self =>
* }}}
*/
def andThen[U](pf: PartialFunction[Either[Throwable, T], U]): Future[T] = {
- val p = newPromise[T]
+ val p = Promise[T]()
onComplete {
case r =>
@@ -497,14 +490,14 @@ self =>
* }}}
*/
def either[U >: T](that: Future[U]): Future[U] = {
- val p = self.newPromise[U]
+ val p = Promise[U]()
val completePromise: PartialFunction[Either[Throwable, U], _] = {
case Left(t) => p tryFailure t
case Right(v) => p trySuccess v
}
- self onComplete completePromise
+ this onComplete completePromise
that onComplete completePromise
p.future
@@ -521,15 +514,38 @@ self =>
*/
object Future {
- def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = impl.Future(body)
+ import java.{ lang => jl }
+
+ private[concurrent] val toBoxed = Map[Class[_], Class[_]](
+ classOf[Boolean] -> classOf[jl.Boolean],
+ classOf[Byte] -> classOf[jl.Byte],
+ classOf[Char] -> classOf[jl.Character],
+ classOf[Short] -> classOf[jl.Short],
+ classOf[Int] -> classOf[jl.Integer],
+ classOf[Long] -> classOf[jl.Long],
+ classOf[Float] -> classOf[jl.Float],
+ classOf[Double] -> classOf[jl.Double],
+ classOf[Unit] -> classOf[scala.runtime.BoxedUnit]
+ )
+
+ /** Starts an asynchronous computation and returns a `Future` object with the result of that computation.
+ *
+ * The result becomes available once the asynchronous computation is completed.
+ *
+ * @tparam T the type of the result
+ * @param body the asychronous computation
+ * @param execctx the execution context on which the future is run
+ * @return the `Future` holding the result of the computation
+ */
+ def apply[T](body: =>T)(implicit execctx: ExecutionContext): Future[T] = impl.Future(body)
import scala.collection.mutable.Builder
import scala.collection.generic.CanBuildFrom
- /** Simple version of `Futures.traverse`. Transforms a `Traversable[Future[A]]` into a `Future[Traversable[A]]`.
+ /** Simple version of `Futures.traverse`. Transforms a `TraversableOnce[Future[A]]` into a `Future[TraversableOnce[A]]`.
* Useful for reducing many `Future`s into a single `Future`.
*/
- def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = {
+ def sequence[A, M[_] <: TraversableOnce[_]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = {
in.foldLeft(Promise.successful(cbf(in)).future) {
(fr, fa) => for (r <- fr; a <- fa.asInstanceOf[Future[A]]) yield (r += a)
} map (_.result)
@@ -537,7 +553,7 @@ object Future {
/** Returns a `Future` to the result of the first future in the list that is completed.
*/
- def firstCompletedOf[T](futures: Traversable[Future[T]])(implicit executor: ExecutionContext): Future[T] = {
+ def firstCompletedOf[T](futures: TraversableOnce[Future[T]])(implicit executor: ExecutionContext): Future[T] = {
val p = Promise[T]()
val completeFirst: Either[Throwable, T] => Unit = p tryComplete _
@@ -548,7 +564,8 @@ object Future {
/** Returns a `Future` that will hold the optional result of the first `Future` with a result that matches the predicate.
*/
- def find[T](futures: Traversable[Future[T]])(predicate: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = {
+ def find[T](futurestravonce: TraversableOnce[Future[T]])(predicate: T => Boolean)(implicit executor: ExecutionContext): Future[Option[T]] = {
+ val futures = futurestravonce.toBuffer
if (futures.isEmpty) Promise.successful[Option[T]](None).future
else {
val result = Promise[Option[T]]()
@@ -559,8 +576,9 @@ object Future {
case _ =>
}
} finally {
- if (ref.decrementAndGet == 0)
+ if (ref.decrementAndGet == 0) {
result tryComplete Right(None)
+ }
}
futures.foreach(_ onComplete search)
@@ -573,45 +591,44 @@ object Future {
* The fold is performed on the thread where the last future is completed,
* the result will be the first failure of any of the futures, or any failure in the actual fold,
* or the result of the fold.
- *
+ *
* Example:
* {{{
* val result = Await.result(Future.fold(futures)(0)(_ + _), 5 seconds)
* }}}
*/
- def fold[T, R](futures: Traversable[Future[T]])(zero: R)(foldFun: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = {
+ def fold[T, R](futures: TraversableOnce[Future[T]])(zero: R)(foldFun: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = {
if (futures.isEmpty) Promise.successful(zero).future
else sequence(futures).map(_.foldLeft(zero)(foldFun))
}
/** Initiates a fold over the supplied futures where the fold-zero is the result value of the `Future` that's completed first.
- *
+ *
* Example:
* {{{
* val result = Await.result(Futures.reduce(futures)(_ + _), 5 seconds)
* }}}
*/
- def reduce[T, R >: T](futures: Traversable[Future[T]])(op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = {
+ def reduce[T, R >: T](futures: TraversableOnce[Future[T]])(op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = {
if (futures.isEmpty) Promise[R].failure(new NoSuchElementException("reduce attempted on empty collection")).future
else sequence(futures).map(_ reduceLeft op)
}
-
- /** Transforms a `Traversable[A]` into a `Future[Traversable[B]]` using the provided function `A => Future[B]`.
+
+ /** Transforms a `TraversableOnce[A]` into a `Future[TraversableOnce[B]]` using the provided function `A => Future[B]`.
* This is useful for performing a parallel map. For example, to apply a function to all items of a list
* in parallel:
- *
+ *
* {{{
* val myFutureList = Future.traverse(myList)(x => Future(myFunc(x)))
* }}}
*/
- def traverse[A, B, M[_] <: Traversable[_]](in: M[A])(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], executor: ExecutionContext): Future[M[B]] =
+ def traverse[A, B, M[_] <: TraversableOnce[_]](in: M[A])(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]], executor: ExecutionContext): Future[M[B]] =
in.foldLeft(Promise.successful(cbf(in)).future) { (fr, a) =>
val fb = fn(a.asInstanceOf[A])
for (r <- fr; b <- fb) yield (r += b)
}.map(_.result)
-
-}
+}
diff --git a/src/library/scala/concurrent/FutureTaskRunner.scala b/src/library/scala/concurrent/FutureTaskRunner.scala
index 75e6299ad9..9d6f8a7a88 100644
--- a/src/library/scala/concurrent/FutureTaskRunner.scala
+++ b/src/library/scala/concurrent/FutureTaskRunner.scala
@@ -8,6 +8,8 @@
package scala.concurrent
+import language.{implicitConversions, higherKinds}
+
/** The `FutureTaskRunner</code> trait is a base trait of task runners
* that provide some sort of future abstraction.
*
diff --git a/src/library/scala/concurrent/JavaConversions.scala b/src/library/scala/concurrent/JavaConversions.scala
index 127a0e0055..9b5e741549 100644
--- a/src/library/scala/concurrent/JavaConversions.scala
+++ b/src/library/scala/concurrent/JavaConversions.scala
@@ -9,6 +9,7 @@
package scala.concurrent
import java.util.concurrent.{ExecutorService, Executor}
+import language.implicitConversions
/** The `JavaConversions` object provides implicit converstions supporting
* interoperability between Scala and Java concurrency classes.
diff --git a/src/library/scala/concurrent/ManagedBlocker.scala b/src/library/scala/concurrent/ManagedBlocker.scala
index 0b6d82e76f..9c6f4d51d6 100644
--- a/src/library/scala/concurrent/ManagedBlocker.scala
+++ b/src/library/scala/concurrent/ManagedBlocker.scala
@@ -12,7 +12,6 @@ package scala.concurrent
*
* @author Philipp Haller
*/
-@deprecated("Not used.", "2.10.0")
trait ManagedBlocker {
/**
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index 8f2bce5d1a..f7ec0714cf 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -35,7 +35,8 @@ trait Promise[T] {
*
* $promiseCompletion
*/
- def complete(result: Either[Throwable, T]): this.type = if (tryComplete(result)) this else throwCompleted
+ def complete(result: Either[Throwable, T]): this.type =
+ if (tryComplete(result)) this else throw new IllegalStateException("Promise already completed.")
/** Tries to complete the promise with either a value or the exception.
*
@@ -50,9 +51,16 @@ trait Promise[T] {
* @return This promise
*/
final def completeWith(other: Future[T]): this.type = {
- other onComplete {
- this complete _
- }
+ other onComplete { this complete _ }
+ this
+ }
+
+ /** Attempts to complete this promise with the specified future, once that future is completed.
+ *
+ * @return This promise
+ */
+ final def tryCompleteWith(other: Future[T]): this.type = {
+ other onComplete { this tryComplete _ }
this
}
@@ -62,7 +70,7 @@ trait Promise[T] {
*
* $promiseCompletion
*/
- def success(v: T): this.type = if (trySuccess(v)) this else throwCompleted
+ def success(v: T): this.type = complete(Right(v))
/** Tries to complete the promise with a value.
*
@@ -80,7 +88,7 @@ trait Promise[T] {
*
* $promiseCompletion
*/
- def failure(t: Throwable): this.type = if (tryFailure(t)) this else throwCompleted
+ def failure(t: Throwable): this.type = complete(Left(t))
/** Tries to complete the promise with an exception.
*
@@ -89,33 +97,33 @@ trait Promise[T] {
* @return If the promise has already been completed returns `false`, or `true` otherwise.
*/
def tryFailure(t: Throwable): Boolean = tryComplete(Left(t))
-
- /** Wraps a `Throwable` in an `ExecutionException` if necessary. TODO replace with `resolver` from scala.concurrent
- *
- * $allowedThrowables
- */
- protected def wrap(t: Throwable): Throwable = t match {
- case t: Throwable if isFutureThrowable(t) => t
- case _ => new ExecutionException(t)
- }
-
- private def throwCompleted = throw new IllegalStateException("Promise already completed.")
-
}
object Promise {
- /** Creates a new promise.
+ /** Creates a promise object which can be completed with a value.
+ *
+ * @tparam T the type of the value in the promise
+ * @param execctx the execution context on which the promise is created on
+ * @return the newly created `Promise` object
*/
def apply[T]()(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.DefaultPromise[T]()
- /** Creates an already completed Promise with the specified exception
+ /** Creates an already completed Promise with the specified exception.
+ *
+ * @tparam T the type of the value in the promise
+ * @param execctx the execution context on which the promise is created on
+ * @return the newly created `Promise` object
*/
def failed[T](exception: Throwable)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Left(exception))
- /** Creates an already completed Promise with the specified result
+ /** Creates an already completed Promise with the specified result.
+ *
+ * @tparam T the type of the value in the promise
+ * @param execctx the execution context on which the promise is created on
+ * @return the newly created `Promise` object
*/
def successful[T](result: T)(implicit executor: ExecutionContext): Promise[T] = new impl.Promise.KeptPromise[T](Right(result))
diff --git a/src/library/scala/concurrent/TaskRunner.scala b/src/library/scala/concurrent/TaskRunner.scala
index 500d79e07f..3180e9ce8a 100644
--- a/src/library/scala/concurrent/TaskRunner.scala
+++ b/src/library/scala/concurrent/TaskRunner.scala
@@ -8,6 +8,8 @@
package scala.concurrent
+import language.{higherKinds, implicitConversions}
+
/** The `TaskRunner` trait...
*
* @author Philipp Haller
diff --git a/src/library/scala/concurrent/ThreadPoolRunner.scala b/src/library/scala/concurrent/ThreadPoolRunner.scala
index a3e0253634..fd6882348a 100644
--- a/src/library/scala/concurrent/ThreadPoolRunner.scala
+++ b/src/library/scala/concurrent/ThreadPoolRunner.scala
@@ -9,6 +9,7 @@
package scala.concurrent
import java.util.concurrent.{ExecutorService, Callable, TimeUnit}
+import language.implicitConversions
/** The `ThreadPoolRunner` trait uses a `java.util.concurrent.ExecutorService`
* to run submitted tasks.
diff --git a/src/library/scala/concurrent/ThreadRunner.scala b/src/library/scala/concurrent/ThreadRunner.scala
index 28fcf57df8..76be94aa6b 100644
--- a/src/library/scala/concurrent/ThreadRunner.scala
+++ b/src/library/scala/concurrent/ThreadRunner.scala
@@ -9,6 +9,7 @@
package scala.concurrent
import java.lang.Thread
+import language.implicitConversions
/** The `ThreadRunner` trait...
*
diff --git a/src/library/scala/concurrent/impl/AbstractPromise.java b/src/library/scala/concurrent/impl/AbstractPromise.java
index 5280d67854..b1799c5fa9 100644
--- a/src/library/scala/concurrent/impl/AbstractPromise.java
+++ b/src/library/scala/concurrent/impl/AbstractPromise.java
@@ -9,13 +9,32 @@
package scala.concurrent.impl;
-
+import scala.concurrent.util.Unsafe;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
abstract class AbstractPromise {
- private volatile Object _ref = null;
+ private volatile Object _ref;
+
+ final static long _refoffset;
+
+ static {
+ try {
+ _refoffset = Unsafe.instance.objectFieldOffset(AbstractPromise.class.getDeclaredField("_ref"));
+ } catch (Throwable t) {
+ throw new ExceptionInInitializerError(t);
+ }
+ }
+
+ protected final boolean updateState(Object oldState, Object newState) {
+ return Unsafe.instance.compareAndSwapObject(this, _refoffset, oldState, newState);
+ }
+
+ protected final Object getState() {
+ return _ref;
+ }
+
protected final static AtomicReferenceFieldUpdater<AbstractPromise, Object> updater =
AtomicReferenceFieldUpdater.newUpdater(AbstractPromise.class, Object.class, "_ref");
-}
+} \ No newline at end of file
diff --git a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
index 9a94bfca4f..7dc3ed2988 100644
--- a/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
+++ b/src/library/scala/concurrent/impl/ExecutionContextImpl.scala
@@ -10,38 +10,39 @@ package scala.concurrent.impl
-import java.util.concurrent.{Callable, ExecutorService, Executors, ThreadFactory}
+import java.util.concurrent.{Callable, Executor, ExecutorService, Executors, ThreadFactory}
import scala.concurrent.forkjoin._
-import scala.concurrent.{ExecutionContext, resolver, Awaitable, body2awaitable}
+import scala.concurrent.{ExecutionContext, resolver, Awaitable}
import scala.concurrent.util.{ Duration }
-private[scala] class ExecutionContextImpl() extends ExecutionContext {
+private[scala] class ExecutionContextImpl(es: AnyRef, reporter: Throwable => Unit = ExecutionContext.defaultReporter)
+extends ExecutionContext with Executor {
import ExecutionContextImpl._
- val executorService: AnyRef = getExecutorService
+ val executorService: AnyRef = if (es eq null) getExecutorService else es
// to ensure that the current execution context thread local is properly set
- private def executorsThreadFactory = new ThreadFactory {
+ def executorsThreadFactory = new ThreadFactory {
def newThread(r: Runnable) = new Thread(new Runnable {
override def run() {
- currentExecutionContext.set(ExecutionContextImpl.this)
+ scala.concurrent.currentExecutionContext.set(ExecutionContextImpl.this)
r.run()
}
})
}
// to ensure that the current execution context thread local is properly set
- private def forkJoinPoolThreadFactory = new ForkJoinPool.ForkJoinWorkerThreadFactory {
+ def forkJoinPoolThreadFactory = new ForkJoinPool.ForkJoinWorkerThreadFactory {
def newThread(fjp: ForkJoinPool) = new ForkJoinWorkerThread(fjp) {
override def onStart() {
- currentExecutionContext.set(ExecutionContextImpl.this)
+ scala.concurrent.currentExecutionContext.set(ExecutionContextImpl.this)
}
}
}
- private def getExecutorService: AnyRef =
+ def getExecutorService: AnyRef =
if (scala.util.Properties.isJavaAtLeast("1.6")) {
val vendor = scala.util.Properties.javaVmVendor
if ((vendor contains "Oracle") || (vendor contains "Sun") || (vendor contains "Apple"))
@@ -56,40 +57,49 @@ private[scala] class ExecutionContextImpl() extends ExecutionContext {
def execute(runnable: Runnable): Unit = executorService match {
case fj: ForkJoinPool =>
- if (Thread.currentThread.isInstanceOf[ForkJoinWorkerThread]) {
- val fjtask = ForkJoinTask.adapt(runnable)
- fjtask.fork
- } else {
- fj.execute(runnable)
+ Thread.currentThread match {
+ case fjw: ForkJoinWorkerThread if fjw.getPool eq fj =>
+ val fjtask = runnable match {
+ case fjt: ForkJoinTask[_] => fjt
+ case _ => ForkJoinTask.adapt(runnable)
+ }
+ fjtask.fork
+ case _ =>
+ fj.execute(runnable)
}
- case executorService: ExecutorService =>
- executorService execute runnable
+ case executor: Executor =>
+ executor execute runnable
}
- def execute[U](body: () => U): Unit = execute(new Runnable {
- def run() = body()
- })
-
def internalBlockingCall[T](awaitable: Awaitable[T], atMost: Duration): T = {
Future.releaseStack(this)
- awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence)
+ executorService match {
+ case fj: ForkJoinPool =>
+ var result: T = null.asInstanceOf[T]
+ val managedBlocker = new ForkJoinPool.ManagedBlocker {
+ @volatile var isdone = false
+ def block() = {
+ result = awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence)
+ isdone = true
+ true
+ }
+ def isReleasable = isdone
+ }
+ ForkJoinPool.managedBlock(managedBlocker)
+ result
+ case _ =>
+ awaitable.result(atMost)(scala.concurrent.Await.canAwaitEvidence)
+ }
}
- def reportFailure(t: Throwable) = t match {
- case e: Error => throw e // rethrow serious errors
- case t => t.printStackTrace()
- }
+ def reportFailure(t: Throwable) = reporter(t)
}
-object ExecutionContextImpl {
-
- private[concurrent] def currentExecutionContext: ThreadLocal[ExecutionContextImpl] = new ThreadLocal[ExecutionContextImpl] {
- override protected def initialValue = null
- }
-
+private[concurrent] object ExecutionContextImpl {
+
}
diff --git a/src/library/scala/concurrent/impl/Future.scala b/src/library/scala/concurrent/impl/Future.scala
index 615ab061a5..20d4122e8f 100644
--- a/src/library/scala/concurrent/impl/Future.scala
+++ b/src/library/scala/concurrent/impl/Future.scala
@@ -10,36 +10,18 @@ package scala.concurrent.impl
-import scala.concurrent.{Awaitable, ExecutionContext}
+import scala.concurrent.util.Duration
+import scala.concurrent.{Awaitable, ExecutionContext, CanAwait}
import scala.collection.mutable.Stack
+
private[concurrent] trait Future[+T] extends scala.concurrent.Future[T] with Awaitable[T] {
implicit def executor: ExecutionContext
- /** For use only within a Future.flow block or another compatible Delimited Continuations reset block.
- *
- * Returns the result of this Future without blocking, by suspending execution and storing it as a
- * continuation until the result is available.
- */
- //def apply(): T @cps[Future[Any]] = shift(this flatMap (_: T => Future[Any]))
-
- /** Tests whether this Future has been completed.
- */
- final def isCompleted: Boolean = value.isDefined
-
- /** The contained value of this Future. Before this Future is completed
- * the value will be None. After completion the value will be Some(Right(t))
- * if it contains a valid result, or Some(Left(error)) if it contains
- * an exception.
- */
- def value: Option[Either[Throwable, T]]
-
- def onComplete[U](func: Either[Throwable, T] => U): this.type
-
}
-object Future {
+private[concurrent] object Future {
import java.{ lang => jl }
private val toBoxed = Map[Class[_], Class[_]](
@@ -54,23 +36,32 @@ object Future {
classOf[Unit] -> classOf[scala.runtime.BoxedUnit]
)
- def boxedType(c: Class[_]): Class[_] = {
- if (c.isPrimitive) toBoxed(c) else c
+ /** Wraps a block of code into an awaitable object. */
+ private[concurrent] def body2awaitable[T](body: =>T) = new Awaitable[T] {
+ def ready(atMost: Duration)(implicit permit: CanAwait) = {
+ body
+ this
+ }
+ def result(atMost: Duration)(implicit permit: CanAwait) = body
}
+ def boxedType(c: Class[_]): Class[_] = if (c.isPrimitive) toBoxed(c) else c
+
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = {
val promise = new Promise.DefaultPromise[T]()
+
+ //TODO: use `dispatchFuture`?
executor.execute(new Runnable {
- def run = {
- promise complete {
- try {
- Right(body)
- } catch {
- case e => scala.concurrent.resolver(e)
- }
+ def run = promise complete {
+ try Right(body) catch {
+ case NonFatal(e) =>
+ // Commenting out reporting for now, since it produces too much output in the tests
+ //executor.reportFailure(e)
+ scala.concurrent.resolver(e)
}
}
})
+
promise.future
}
@@ -96,7 +87,7 @@ object Future {
private[impl] def dispatchFuture(executor: ExecutionContext, task: () => Unit, force: Boolean = false): Unit =
_taskStack.get match {
- case stack if (stack ne null) && !force => stack push task
+ case stack if (stack ne null) && !force => stack push task // FIXME we can't mix tasks aimed for different ExecutionContexts see: https://github.com/akka/akka/blob/v2.0.1/akka-actor/src/main/scala/akka/dispatch/Future.scala#L373
case _ => executor.execute(new Runnable {
def run() {
try {
@@ -104,13 +95,7 @@ object Future {
_taskStack set taskStack
while (taskStack.nonEmpty) {
val next = taskStack.pop()
- try {
- next.apply()
- } catch {
- case e =>
- // TODO catching all and continue isn't good for OOME
- executor.reportFailure(e)
- }
+ try next() catch { case NonFatal(e) => executor reportFailure e }
}
} finally {
_taskStack.remove()
diff --git a/src/library/scala/concurrent/impl/NonFatal.scala b/src/library/scala/concurrent/impl/NonFatal.scala
new file mode 100644
index 0000000000..bc509e664c
--- /dev/null
+++ b/src/library/scala/concurrent/impl/NonFatal.scala
@@ -0,0 +1,37 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.concurrent
+package impl
+
+/**
+ * Extractor of non-fatal Throwables. Will not match fatal errors
+ * like VirtualMachineError (OutOfMemoryError)
+ * ThreadDeath, LinkageError and InterruptedException.
+ * StackOverflowError is matched, i.e. considered non-fatal.
+ *
+ * Usage to catch all harmless throwables:
+ * {{{
+ * try {
+ * // dangerous stuff
+ * } catch {
+ * case NonFatal(e) => log.error(e, "Something not that bad")
+ * }
+ * }}}
+ */
+private[concurrent] object NonFatal {
+
+ def unapply(t: Throwable): Option[Throwable] = t match {
+ case e: StackOverflowError ⇒ Some(e) // StackOverflowError ok even though it is a VirtualMachineError
+ // VirtualMachineError includes OutOfMemoryError and other fatal errors
+ case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError ⇒ None
+ case e ⇒ Some(e)
+ }
+
+}
+
diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala
index f7e073cb78..da70b3dea5 100644
--- a/src/library/scala/concurrent/impl/Promise.scala
+++ b/src/library/scala/concurrent/impl/Promise.scala
@@ -11,8 +11,7 @@ package scala.concurrent.impl
import java.util.concurrent.TimeUnit.{ NANOSECONDS, MILLISECONDS }
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater
-import scala.concurrent.{Awaitable, ExecutionContext, resolve, resolver, blocking, CanAwait, TimeoutException}
+import scala.concurrent.{Awaitable, ExecutionContext, resolveEither, resolver, blocking, CanAwait, TimeoutException}
//import scala.util.continuations._
import scala.concurrent.util.Duration
import scala.util
@@ -22,90 +21,16 @@ import scala.annotation.tailrec
private[concurrent] trait Promise[T] extends scala.concurrent.Promise[T] with Future[T] {
-
- def future = this
-
- def newPromise[S]: scala.concurrent.Promise[S] = new Promise.DefaultPromise()
-
- // TODO refine answer and return types here from Any to type parameters
- // then move this up in the hierarchy
- /*
- final def <<(value: T): Future[T] @cps[Future[Any]] = shift {
- cont: (Future[T] => Future[Any]) =>
- cont(complete(Right(value)))
- }
-
- final def <<(other: Future[T]): Future[T] @cps[Future[Any]] = shift {
- cont: (Future[T] => Future[Any]) =>
- val p = executor.promise[Any]
- val thisPromise = this
-
- thisPromise completeWith other
- thisPromise onComplete { v =>
- try {
- p completeWith cont(thisPromise)
- } catch {
- case e => p complete resolver(e)
- }
- }
-
- p.future
- }
- */
- // TODO finish this once we introduce something like dataflow streams
-
- /*
- final def <<(stream: PromiseStreamOut[T]): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) =>
- val fr = executor.promise[Any]
- val f = stream.dequeue(this)
- f.onComplete { _ =>
- try {
- fr completeWith cont(f)
- } catch {
- case e =>
- fr failure e
- }
- }
- fr
- }
- */
-
+ def future: this.type = this
}
object Promise {
-
- def dur2long(dur: Duration): Long = if (dur.isFinite) dur.toNanos else Long.MaxValue
-
- def EmptyPending[T](): FState[T] = emptyPendingValue.asInstanceOf[FState[T]]
-
- /** Represents the internal state.
- *
- * [adriaan] it's unsound to make FState covariant (tryComplete won't type check)
- */
- sealed trait FState[T] { def value: Option[Either[Throwable, T]] }
-
- case class Pending[T](listeners: List[Either[Throwable, T] => Any] = Nil) extends FState[T] {
- def value: Option[Either[Throwable, T]] = None
- }
-
- case class Success[T](value: Option[Either[Throwable, T]] = None) extends FState[T] {
- def result: T = value.get.right.get
- }
-
- case class Failure[T](value: Option[Either[Throwable, T]] = None) extends FState[T] {
- def exception: Throwable = value.get.left.get
- }
-
- private val emptyPendingValue = Pending[Nothing](Nil)
-
/** Default promise implementation.
*/
- class DefaultPromise[T](implicit val executor: ExecutionContext) extends AbstractPromise with Promise[T] {
- self =>
-
- updater.set(this, Promise.EmptyPending())
-
+ class DefaultPromise[T](implicit val executor: ExecutionContext) extends AbstractPromise with Promise[T] { self =>
+ updateState(null, Nil) // Start at "No callbacks" //FIXME switch to Unsafe instead of ARFU
+
protected final def tryAwait(atMost: Duration): Boolean = {
@tailrec
def awaitUnsafe(waitTimeNanos: Long): Boolean = {
@@ -115,7 +40,7 @@ object Promise {
val start = System.nanoTime()
try {
synchronized {
- while (value.isEmpty) wait(ms, ns)
+ if (!isCompleted) wait(ms, ns) // previously - this was a `while`, ending up in an infinite loop
}
} catch {
case e: InterruptedException =>
@@ -123,85 +48,64 @@ object Promise {
awaitUnsafe(waitTimeNanos - (System.nanoTime() - start))
} else
- value.isDefined
+ isCompleted
}
-
- blocking(concurrent.body2awaitable(awaitUnsafe(dur2long(atMost))), atMost)
+ //FIXME do not do this if there'll be no waiting
+ awaitUnsafe(if (atMost.isFinite) atMost.toNanos else Long.MaxValue)
}
+ @throws(classOf[TimeoutException])
def ready(atMost: Duration)(implicit permit: CanAwait): this.type =
- if (value.isDefined || tryAwait(atMost)) this
+ if (isCompleted || tryAwait(atMost)) this
else throw new TimeoutException("Futures timed out after [" + atMost.toMillis + "] milliseconds")
+ @throws(classOf[Exception])
def result(atMost: Duration)(implicit permit: CanAwait): T =
ready(atMost).value.get match {
case Left(e) => throw e
case Right(r) => r
}
- def value: Option[Either[Throwable, T]] = getState.value
-
- @inline
- private[this] final def updater = AbstractPromise.updater.asInstanceOf[AtomicReferenceFieldUpdater[AbstractPromise, FState[T]]]
-
- @inline
- protected final def updateState(oldState: FState[T], newState: FState[T]): Boolean = updater.compareAndSet(this, oldState, newState)
+ def value: Option[Either[Throwable, T]] = getState match {
+ case c: Either[_, _] => Some(c.asInstanceOf[Either[Throwable, T]])
+ case _ => None
+ }
- @inline
- protected final def getState: FState[T] = updater.get(this)
+ override def isCompleted(): Boolean = getState match { // Cheaper than boxing result into Option due to "def value"
+ case _: Either[_, _] => true
+ case _ => false
+ }
def tryComplete(value: Either[Throwable, T]): Boolean = {
- val callbacks: List[Either[Throwable, T] => Any] = {
- try {
- @tailrec
- def tryComplete(v: Either[Throwable, T]): List[Either[Throwable, T] => Any] = {
- getState match {
- case cur @ Pending(listeners) =>
- val newState =
- if (v.isLeft) Failure(Some(v.asInstanceOf[Left[Throwable, T]]))
- else Success(Some(v.asInstanceOf[Right[Throwable, T]]))
-
- if (updateState(cur, newState)) listeners
- else tryComplete(v)
- case _ => null
- }
+ val resolved = resolveEither(value)
+ (try {
+ @tailrec
+ def tryComplete(v: Either[Throwable, T]): List[Either[Throwable, T] => Unit] = {
+ getState match {
+ case raw: List[_] =>
+ val cur = raw.asInstanceOf[List[Either[Throwable, T] => Unit]]
+ if (updateState(cur, v)) cur else tryComplete(v)
+ case _ => null
}
- tryComplete(resolve(value))
- } finally {
- synchronized { notifyAll() } // notify any blockers from `tryAwait`
}
- }
-
- callbacks match {
+ tryComplete(resolved)
+ } finally {
+ synchronized { notifyAll() } //Notify any evil blockers
+ }) match {
case null => false
case cs if cs.isEmpty => true
- case cs =>
- Future.dispatchFuture(executor, {
- () => cs.foreach(f => notifyCompleted(f, value))
- })
- true
+ case cs => Future.dispatchFuture(executor, () => cs.foreach(f => notifyCompleted(f, resolved))); true
}
}
def onComplete[U](func: Either[Throwable, T] => U): this.type = {
- @tailrec // Returns whether the future has already been completed or not
- def tryAddCallback(): Boolean = {
- val cur = getState
- cur match {
- case _: Success[_] | _: Failure[_] => true
- case p: Pending[_] =>
- val pt = p.asInstanceOf[Pending[T]]
- if (updateState(pt, pt.copy(listeners = func :: pt.listeners))) false else tryAddCallback()
+ @tailrec //Tries to add the callback, if already completed, it dispatches the callback to be executed
+ def dispatchOrAddCallback(): Unit =
+ getState match {
+ case r: Either[_, _] => Future.dispatchFuture(executor, () => notifyCompleted(func, r.asInstanceOf[Either[Throwable, T]]))
+ case listeners: List[_] => if (updateState(listeners, func :: listeners)) () else dispatchOrAddCallback()
}
- }
-
- if (tryAddCallback()) {
- val result = value.get
- Future.dispatchFuture(executor, {
- () => notifyCompleted(func, result)
- })
- }
-
+ dispatchOrAddCallback()
this
}
@@ -209,7 +113,7 @@ object Promise {
try {
func(result)
} catch {
- case e => executor.reportFailure(e)
+ case NonFatal(e) => executor reportFailure e
}
}
}
@@ -220,15 +124,15 @@ object Promise {
*/
final class KeptPromise[T](suppliedValue: Either[Throwable, T])(implicit val executor: ExecutionContext) extends Promise[T] {
- val value = Some(resolve(suppliedValue))
+ val value = Some(resolveEither(suppliedValue))
+
+ override def isCompleted(): Boolean = true
def tryComplete(value: Either[Throwable, T]): Boolean = false
def onComplete[U](func: Either[Throwable, T] => U): this.type = {
val completedAs = value.get
- Future.dispatchFuture(executor, {
- () => func(completedAs)
- })
+ Future.dispatchFuture(executor, () => func(completedAs))
this
}
@@ -241,19 +145,3 @@ object Promise {
}
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/library/scala/concurrent/package.scala b/src/library/scala/concurrent/package.scala
index e2ae17498f..e8921ef531 100644
--- a/src/library/scala/concurrent/package.scala
+++ b/src/library/scala/concurrent/package.scala
@@ -26,19 +26,15 @@ package concurrent {
object Await {
private[concurrent] implicit val canAwaitEvidence = new CanAwait {}
- def ready[T](awaitable: Awaitable[T], atMost: Duration): Awaitable[T] = awaitable.ready(atMost)
+ def ready[T](awaitable: Awaitable[T], atMost: Duration): awaitable.type = {
+ blocking(awaitable, atMost)
+ awaitable
+ }
+
+ def result[T](awaitable: Awaitable[T], atMost: Duration): T = {
+ blocking(awaitable, atMost)
+ }
- def result[T](awaitable: Awaitable[T], atMost: Duration): T = awaitable.result(atMost)
- }
-
- /** A timeout exception.
- *
- * Futures are failed with a timeout exception when their timeout expires.
- *
- * Each timeout exception contains an origin future which originally timed out.
- */
- class FutureTimeoutException(origin: Future[_], message: String) extends TimeoutException(message) {
- def this(origin: Future[_]) = this(origin, "Future timed out.")
}
final class DurationOps private[concurrent] (x: Int) {
diff --git a/src/library/scala/concurrent/util/Duration.scala b/src/library/scala/concurrent/util/Duration.scala
index 33d034da76..bab664727e 100644
--- a/src/library/scala/concurrent/util/Duration.scala
+++ b/src/library/scala/concurrent/util/Duration.scala
@@ -1,57 +1,17 @@
-/**
- * Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
- */
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2012, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
package scala.concurrent.util
import java.util.concurrent.TimeUnit
import TimeUnit._
-import java.lang.{ Double ⇒ JDouble }
-
-object DurationImplicits {
- trait Classifier[C] {
- type R
- def convert(d: FiniteDuration): R
- }
-
- object span
- implicit object spanConvert extends Classifier[span.type] {
- type R = FiniteDuration
- def convert(d: FiniteDuration) = d
- }
-
- object fromNow
- implicit object fromNowConvert extends Classifier[fromNow.type] {
- type R = Deadline
- def convert(d: FiniteDuration) = Deadline.now + d
- }
-
- implicit def intToDurationInt(n: Int) = new DurationInt(n)
- implicit def longToDurationLong(n: Long) = new DurationLong(n)
- implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d)
-
- implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2)
- implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2)
- implicit def durationToPair(d: Duration) = (d.length, d.unit)
-
- /*
- * Avoid reflection based invocation by using non-duck type
- */
- class IntMult(i: Int) {
- def *(d: Duration) = d * i
- }
- implicit def intMult(i: Int) = new IntMult(i)
-
- class LongMult(l: Long) {
- def *(d: Duration) = d * l
- }
- implicit def longMult(l: Long) = new LongMult(l)
-
- class DoubleMult(f: Double) {
- def *(d: Duration) = d * f
- }
- implicit def doubleMult(f: Double) = new DoubleMult(f)
-}
+import java.lang.{ Double => JDouble }
+import language.implicitConversions
case class Deadline private (time: Duration) {
def +(other: Duration): Deadline = copy(time = time + other)
@@ -71,10 +31,7 @@ object Duration {
def apply(length: Long, unit: TimeUnit): FiniteDuration = new FiniteDuration(length, unit)
def apply(length: Double, unit: TimeUnit): FiniteDuration = fromNanos(unit.toNanos(1) * length)
- def apply(length: Long, unit: String): FiniteDuration = {
- val (mult, timeUnit) = Duration.timeUnit(unit)
- new FiniteDuration(length * mult, timeUnit)
- }
+ def apply(length: Long, unit: String): FiniteDuration = new FiniteDuration(length, Duration.timeUnit(unit))
/**
* Construct a Duration by parsing a String. In case of a format error, a
@@ -117,11 +74,11 @@ object Duration {
def unapply(s: String): Option[Duration] = s match {
case RE(length, d, h, m, s, ms, mus, ns) ⇒
if (d ne null)
- Some(Duration(JDouble.parseDouble(length) * 86400, SECONDS))
+ Some(Duration(JDouble.parseDouble(length), DAYS))
else if (h ne null)
- Some(Duration(JDouble.parseDouble(length) * 3600, SECONDS))
+ Some(Duration(JDouble.parseDouble(length), HOURS))
else if (m ne null)
- Some(Duration(JDouble.parseDouble(length) * 60, SECONDS))
+ Some(Duration(JDouble.parseDouble(length), MINUTES))
else if (s ne null)
Some(Duration(JDouble.parseDouble(length), SECONDS))
else if (ms ne null)
@@ -142,11 +99,11 @@ object Duration {
def fromNanos(nanos: Long): FiniteDuration = {
if (nanos % 86400000000000L == 0) {
- Duration(nanos / 1000000000L, SECONDS)
- } else if (nanos % 1000000000L == 0) {
- Duration(nanos / 1000000000L, SECONDS)
- } else if (nanos % 1000000000L == 0) {
- Duration(nanos / 1000000000L, SECONDS)
+ Duration(nanos / 86400000000000L, DAYS)
+ } else if (nanos % 3600000000000L == 0) {
+ Duration(nanos / 3600000000000L, HOURS)
+ } else if (nanos % 60000000000L == 0) {
+ Duration(nanos / 60000000000L, MINUTES)
} else if (nanos % 1000000000L == 0) {
Duration(nanos / 1000000000L, SECONDS)
} else if (nanos % 1000000L == 0) {
@@ -161,14 +118,14 @@ object Duration {
/**
* Parse TimeUnit from string representation.
*/
- protected[util] def timeUnit(unit: String): (Long, TimeUnit) = unit.toLowerCase match {
- case "d" | "day" | "days" ⇒ (86400, SECONDS)
- case "h" | "hour" | "hours" ⇒ (3600, SECONDS)
- case "min" | "minute" | "minutes" ⇒ (60, SECONDS)
- case "s" | "sec" | "second" | "seconds" ⇒ (1, SECONDS)
- case "ms" | "milli" | "millis" | "millisecond" | "milliseconds" ⇒ (1, MILLISECONDS)
- case "µs" | "micro" | "micros" | "microsecond" | "microseconds" ⇒ (1, MICROSECONDS)
- case "ns" | "nano" | "nanos" | "nanosecond" | "nanoseconds" ⇒ (1, NANOSECONDS)
+ protected[util] def timeUnit(unit: String): TimeUnit = unit.toLowerCase match {
+ case "d" | "day" | "days" => DAYS
+ case "h" | "hour" | "hours" => HOURS
+ case "min" | "minute" | "minutes" => MINUTES
+ case "s" | "sec" | "second" | "seconds" => SECONDS
+ case "ms" | "milli" | "millis" | "millisecond" | "milliseconds" => MILLISECONDS
+ case "µs" | "micro" | "micros" | "microsecond" | "microseconds" => MICROSECONDS
+ case "ns" | "nano" | "nanos" | "nanosecond" | "nanoseconds" => NANOSECONDS
}
val Zero: FiniteDuration = new FiniteDuration(0, NANOSECONDS)
@@ -185,26 +142,26 @@ object Duration {
}
trait Infinite {
- this: Duration ⇒
+ this: Duration =>
def +(other: Duration): Duration =
other match {
- case _: this.type ⇒ this
- case _: Infinite ⇒ throw new IllegalArgumentException("illegal addition of infinities")
- case _ ⇒ this
+ case _: this.type => this
+ case _: Infinite => throw new IllegalArgumentException("illegal addition of infinities")
+ case _ => this
}
def -(other: Duration): Duration =
other match {
- case _: this.type ⇒ throw new IllegalArgumentException("illegal subtraction of infinities")
- case _ ⇒ this
+ case _: this.type => throw new IllegalArgumentException("illegal subtraction of infinities")
+ case _ => this
}
def *(factor: Double): Duration = this
def /(factor: Double): Duration = this
def /(other: Duration): Double =
other match {
- case _: Infinite ⇒ throw new IllegalArgumentException("illegal division of infinities")
+ case _: Infinite => throw new IllegalArgumentException("illegal division of infinities")
// maybe questionable but pragmatic: Inf / 0 => Inf
- case x ⇒ Double.PositiveInfinity * (if ((this > Zero) ^ (other >= Zero)) -1 else 1)
+ case x => Double.PositiveInfinity * (if ((this > Zero) ^ (other >= Zero)) -1 else 1)
}
def finite_? = false
@@ -328,13 +285,9 @@ object FiniteDuration {
def compare(a: FiniteDuration, b: FiniteDuration) = a compare b
}
- def apply(length: Long, unit: TimeUnit) =
- new FiniteDuration(length, unit)
+ def apply(length: Long, unit: TimeUnit) = new FiniteDuration(length, unit)
- def apply(length: Long, unit: String) = {
- val (mult, timeUnit) = Duration.timeUnit(unit)
- new FiniteDuration(length * mult, timeUnit)
- }
+ def apply(length: Long, unit: String) = new FiniteDuration(length, Duration.timeUnit(unit))
}
@@ -348,17 +301,23 @@ class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration {
def toMinutes = unit.toMinutes(length)
def toHours = unit.toHours(length)
def toDays = unit.toDays(length)
- def toUnit(u: TimeUnit) = long2double(toNanos) / NANOSECONDS.convert(1, u)
+ def toUnit(u: TimeUnit) = toNanos.toDouble / NANOSECONDS.convert(1, u)
override def toString = this match {
- case Duration(1, SECONDS) ⇒ "1 second"
- case Duration(x, SECONDS) ⇒ x + " seconds"
- case Duration(1, MILLISECONDS) ⇒ "1 millisecond"
- case Duration(x, MILLISECONDS) ⇒ x + " milliseconds"
- case Duration(1, MICROSECONDS) ⇒ "1 microsecond"
- case Duration(x, MICROSECONDS) ⇒ x + " microseconds"
- case Duration(1, NANOSECONDS) ⇒ "1 nanosecond"
- case Duration(x, NANOSECONDS) ⇒ x + " nanoseconds"
+ case Duration(1, DAYS) => "1 day"
+ case Duration(x, DAYS) => x + " days"
+ case Duration(1, HOURS) => "1 hour"
+ case Duration(x, HOURS) => x + " hours"
+ case Duration(1, MINUTES) => "1 minute"
+ case Duration(x, MINUTES) => x + " minutes"
+ case Duration(1, SECONDS) => "1 second"
+ case Duration(x, SECONDS) => x + " seconds"
+ case Duration(1, MILLISECONDS) => "1 millisecond"
+ case Duration(x, MILLISECONDS) => x + " milliseconds"
+ case Duration(1, MICROSECONDS) => "1 microsecond"
+ case Duration(x, MICROSECONDS) => x + " microseconds"
+ case Duration(1, NANOSECONDS) => "1 nanosecond"
+ case Duration(x, NANOSECONDS) => x + " nanoseconds"
}
def compare(other: Duration) =
@@ -386,11 +345,11 @@ class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration {
}
}
- def *(factor: Double) = fromNanos(long2double(toNanos) * factor)
+ def *(factor: Double) = fromNanos(toNanos.toDouble * factor)
- def /(factor: Double) = fromNanos(long2double(toNanos) / factor)
+ def /(factor: Double) = fromNanos(toNanos.toDouble / factor)
- def /(other: Duration) = if (other.finite_?) long2double(toNanos) / other.toNanos else 0
+ def /(other: Duration) = if (other.finite_?) toNanos.toDouble / other.toNanos else 0
def unary_- = Duration(-length, unit)
@@ -404,7 +363,7 @@ class FiniteDuration(val length: Long, val unit: TimeUnit) extends Duration {
}
class DurationInt(n: Int) {
- import DurationImplicits.Classifier
+ import duration.Classifier
def nanoseconds = Duration(n, NANOSECONDS)
def nanos = Duration(n, NANOSECONDS)
@@ -424,14 +383,14 @@ class DurationInt(n: Int) {
def seconds = Duration(n, SECONDS)
def second = Duration(n, SECONDS)
- def minutes = Duration(n * 60, SECONDS)
- def minute = Duration(n * 60, SECONDS)
+ def minutes = Duration(n, MINUTES)
+ def minute = Duration(n, MINUTES)
- def hours = Duration(n * 3600, SECONDS)
- def hour = Duration(n * 3600, SECONDS)
+ def hours = Duration(n, HOURS)
+ def hour = Duration(n, HOURS)
- def days = Duration(n * 86400, SECONDS)
- def day = Duration(n * 86400, SECONDS)
+ def days = Duration(n, DAYS)
+ def day = Duration(n, DAYS)
def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
@@ -451,18 +410,18 @@ class DurationInt(n: Int) {
def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
- def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS))
- def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS))
+ def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
+ def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
- def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS))
- def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS))
+ def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
+ def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
- def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS))
- def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS))
+ def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
+ def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
}
class DurationLong(n: Long) {
- import DurationImplicits.Classifier
+ import duration.Classifier
def nanoseconds = Duration(n, NANOSECONDS)
def nanos = Duration(n, NANOSECONDS)
@@ -482,14 +441,14 @@ class DurationLong(n: Long) {
def seconds = Duration(n, SECONDS)
def second = Duration(n, SECONDS)
- def minutes = Duration(n * 60, SECONDS)
- def minute = Duration(n * 60, SECONDS)
+ def minutes = Duration(n, MINUTES)
+ def minute = Duration(n, MINUTES)
- def hours = Duration(n * 3600, SECONDS)
- def hour = Duration(n * 3600, SECONDS)
+ def hours = Duration(n, HOURS)
+ def hour = Duration(n, HOURS)
- def days = Duration(n * 86400, SECONDS)
- def day = Duration(n * 86400, SECONDS)
+ def days = Duration(n, DAYS)
+ def day = Duration(n, DAYS)
def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, NANOSECONDS))
@@ -509,18 +468,18 @@ class DurationLong(n: Long) {
def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, SECONDS))
- def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS))
- def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 60, SECONDS))
+ def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
+ def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, MINUTES))
- def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS))
- def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 3600, SECONDS))
+ def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
+ def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, HOURS))
- def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS))
- def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n * 86400, SECONDS))
+ def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
+ def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(n, DAYS))
}
class DurationDouble(d: Double) {
- import DurationImplicits.Classifier
+ import duration.Classifier
def nanoseconds = Duration(d, NANOSECONDS)
def nanos = Duration(d, NANOSECONDS)
@@ -540,14 +499,14 @@ class DurationDouble(d: Double) {
def seconds = Duration(d, SECONDS)
def second = Duration(d, SECONDS)
- def minutes = Duration(d * 60, SECONDS)
- def minute = Duration(d * 60, SECONDS)
+ def minutes = Duration(d, MINUTES)
+ def minute = Duration(d, MINUTES)
- def hours = Duration(d * 3600, SECONDS)
- def hour = Duration(d * 3600, SECONDS)
+ def hours = Duration(d, HOURS)
+ def hour = Duration(d, HOURS)
- def days = Duration(d * 86400, SECONDS)
- def day = Duration(d * 86400, SECONDS)
+ def days = Duration(d, DAYS)
+ def day = Duration(d, DAYS)
def nanoseconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS))
def nanos[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, NANOSECONDS))
@@ -567,12 +526,12 @@ class DurationDouble(d: Double) {
def seconds[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, SECONDS))
def second[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, SECONDS))
- def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 60, SECONDS))
- def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 60, SECONDS))
+ def minutes[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MINUTES))
+ def minute[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, MINUTES))
- def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 3600, SECONDS))
- def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 3600, SECONDS))
+ def hours[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, HOURS))
+ def hour[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, HOURS))
- def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 86400, SECONDS))
- def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d * 86400, SECONDS))
+ def days[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, DAYS))
+ def day[C, CC <: Classifier[C]](c: C)(implicit ev: CC): CC#R = ev.convert(Duration(d, DAYS))
}
diff --git a/src/library/scala/concurrent/util/Unsafe.java b/src/library/scala/concurrent/util/Unsafe.java
new file mode 100644
index 0000000000..0cd48758d5
--- /dev/null
+++ b/src/library/scala/concurrent/util/Unsafe.java
@@ -0,0 +1,35 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2003-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.concurrent.util;
+
+
+
+import java.lang.reflect.Field;
+
+
+
+public final class Unsafe {
+ public final static sun.misc.Unsafe instance;
+ static {
+ try {
+ sun.misc.Unsafe found = null;
+ for(Field field : sun.misc.Unsafe.class.getDeclaredFields()) {
+ if (field.getType() == sun.misc.Unsafe.class) {
+ field.setAccessible(true);
+ found = (sun.misc.Unsafe) field.get(null);
+ break;
+ }
+ }
+ if (found == null) throw new IllegalStateException("Can't find instance of sun.misc.Unsafe");
+ else instance = found;
+ } catch(Throwable t) {
+ throw new ExceptionInInitializerError(t);
+ }
+ }
+}
diff --git a/src/library/scala/concurrent/util/duration/Classifier.scala b/src/library/scala/concurrent/util/duration/Classifier.scala
new file mode 100644
index 0000000000..10faf0a5ce
--- /dev/null
+++ b/src/library/scala/concurrent/util/duration/Classifier.scala
@@ -0,0 +1,9 @@
+package scala.concurrent.util.duration
+
+import scala.concurrent.util.{ FiniteDuration }
+
+trait Classifier[C] {
+ type R
+ def convert(d: FiniteDuration): R
+}
+
diff --git a/src/library/scala/concurrent/util/duration/IntMult.scala b/src/library/scala/concurrent/util/duration/IntMult.scala
new file mode 100644
index 0000000000..94c58fb8c2
--- /dev/null
+++ b/src/library/scala/concurrent/util/duration/IntMult.scala
@@ -0,0 +1,18 @@
+package scala.concurrent.util.duration
+
+import scala.concurrent.util.{ Duration }
+
+/*
+ * Avoid reflection based invocation by using non-duck type
+ */
+protected[duration] class IntMult(i: Int) {
+ def *(d: Duration) = d * i
+}
+
+protected[duration] class LongMult(i: Long) {
+ def *(d: Duration) = d * i
+}
+
+protected[duration] class DoubleMult(f: Double) {
+ def *(d: Duration) = d * f
+}
diff --git a/src/library/scala/concurrent/util/duration/package.scala b/src/library/scala/concurrent/util/duration/package.scala
new file mode 100644
index 0000000000..e3cf229c61
--- /dev/null
+++ b/src/library/scala/concurrent/util/duration/package.scala
@@ -0,0 +1,31 @@
+package scala.concurrent.util
+
+import java.util.concurrent.TimeUnit
+import language.implicitConversions
+
+package object duration {
+
+ object span
+ implicit object spanConvert extends Classifier[span.type] {
+ type R = FiniteDuration
+ def convert(d: FiniteDuration) = d
+ }
+
+ object fromNow
+ implicit object fromNowConvert extends Classifier[fromNow.type] {
+ type R = Deadline
+ def convert(d: FiniteDuration) = Deadline.now + d
+ }
+
+ implicit def intToDurationInt(n: Int) = new DurationInt(n)
+ implicit def longToDurationLong(n: Long) = new DurationLong(n)
+ implicit def doubleToDurationDouble(d: Double) = new DurationDouble(d)
+
+ implicit def pairIntToDuration(p: (Int, TimeUnit)) = Duration(p._1, p._2)
+ implicit def pairLongToDuration(p: (Long, TimeUnit)) = Duration(p._1, p._2)
+ implicit def durationToPair(d: Duration) = (d.length, d.unit)
+
+ implicit def intMult(i: Int) = new IntMult(i)
+ implicit def longMult(l: Long) = new LongMult(l)
+ implicit def doubleMult(f: Double) = new DoubleMult(f)
+}
diff --git a/src/library/scala/io/BytePickle.scala b/src/library/scala/io/BytePickle.scala
index bec0cfb53f..3bb5ea9c2b 100644
--- a/src/library/scala/io/BytePickle.scala
+++ b/src/library/scala/io/BytePickle.scala
@@ -269,7 +269,7 @@ object BytePickle {
}
def string: SPU[String] = share(wrap(
- (a: Array[Byte]) => Codec fromUTF8 a mkString,
+ (a: Array[Byte]) => (Codec fromUTF8 a).mkString,
(s: String) => Codec toUTF8 s,
bytearray
))
diff --git a/src/library/scala/io/Codec.scala b/src/library/scala/io/Codec.scala
index d9cef0edb1..84cac88dcc 100644
--- a/src/library/scala/io/Codec.scala
+++ b/src/library/scala/io/Codec.scala
@@ -11,6 +11,7 @@ package scala.io
import java.nio.charset.{ Charset, CharsetDecoder, CharsetEncoder, CharacterCodingException, CodingErrorAction => Action }
import annotation.migration
+import language.implicitConversions
// Some notes about encodings for use in refining this implementation.
//
diff --git a/src/library/scala/io/Source.scala b/src/library/scala/io/Source.scala
index 3cee0ace79..5e09e13680 100644
--- a/src/library/scala/io/Source.scala
+++ b/src/library/scala/io/Source.scala
@@ -188,7 +188,7 @@ abstract class Source extends Iterator[Char] {
var nerrors = 0
var nwarnings = 0
- private def lineNum(line: Int): String = getLines() drop (line - 1) take 1 mkString
+ private def lineNum(line: Int): String = (getLines() drop (line - 1) take 1).mkString
class LineIterator extends AbstractIterator[String] with Iterator[String] {
private[this] val sb = new StringBuilder
diff --git a/src/library/scala/language.scala b/src/library/scala/language.scala
new file mode 100644
index 0000000000..df2eb0b910
--- /dev/null
+++ b/src/library/scala/language.scala
@@ -0,0 +1,124 @@
+package scala
+
+object language {
+
+ import languageFeature._
+
+ /** Where enabled, direct or indirect subclasses of trait scala.Dynamic can
+ * be defined. Unless dynamics is enabled, a definition of a class, trait,
+ * or object that has Dynamic as a base trait is rejected. Dynamic member
+ * selection of existing subclasses of trait Dynamic are unaffected;
+ * they can be used anywhere.
+ *
+ * _Why introduce the feature?_ To enable flexible DSLs and convenient interfacing
+ * with dynamic languages.
+ *
+ * _Why control it?_ Dynamic member selection can undermine static checkability
+ * of programs. Furthermore, dynamic member selection often relies on reflection,
+ * which is not available on all platforms.
+ */
+ implicit lazy val dynamics: dynamics = ???
+
+ /** Only where enabled, postfix operator notation `(expr op)` will be allowed.
+ *
+ * _Why keep the feature?_ Several DSLs written in Scala need the notation.
+ *
+ * _Why control it?_ Postfix operators interact poorly with semicolon inference.
+ * Most programmers avoid them for this reason.
+ */
+ implicit lazy val postfixOps: postfixOps = ???
+
+ /** Only where enabled, accesses to members of structural types that need
+ * reflection are supported. Reminder: A structural type is a type of the form
+ * `Parents { Decls }` where `Decls` contains declarations of new members that do
+ * not override any member in `Parents`. To access one of these members, a
+ * reflective call is needed.
+ *
+ * _Why keep the feature?_ Structural types provide great flexibility because
+ * they avoid the need to define inheritance hierarchies a priori. Besides,
+ * their definition falls out quite naturally from Scala’s concept of type refinement.
+ *
+ * _Why control it?+ Reflection is not available on all platforms. Popular tools
+ * such as ProGuard have problems dealing with it. Even where reflection is available,
+ * reflective dispatch can lead to surprising performance degradations.
+ */
+ implicit lazy val reflectiveCalls: reflectiveCalls = ???
+
+ /** Only where enabled, definitions of implicit conversions are allowed. An
+ * implicit conversion is an implicit value of unary function type `A => B`,
+ * or an implicit method that has in its first parameter section a single,
+ * non-implicit parameter. Examples:
+ *
+ * implicit def stringToInt(s: String): Int = s.length
+ * implicit val conv = (s: String) => s.length
+ * implicit def listToX(xs: List[T])(implicit f: T => X): X = …
+ *
+ * implicit values of other types are not affected, and neither are implicit
+ * classes.
+ *
+ * _Why keep the feature?_ Implicit conversions are central to many aspects
+ * of Scala’s core libraries.
+ *
+ * _Why control it?_ Implicit conversions are known to cause many pitfalls
+ * if over-used. And there is a tendency to over-use them because they look
+ * very powerful and their effects seem to be easy to understand. Also, in
+ * most situations using implicit parameters leads to a better design than
+ * implicit conversions.
+ */
+ implicit lazy val implicitConversions: implicitConversions = ???
+
+ /** Only where this flag is enabled, higher-kinded types can be written.
+ *
+ * _Why keep the feature?_ Higher-kinded types enable the definition of very general
+ * abstractions such as functor, monad, or arrow. A significant set of advanced
+ * libraries relies on them. Higher-kinded types are also at the core of the
+ * scala-virtualized effort to produce high-performance parallel DSLs through staging.
+ *
+ * _Why control it?_ Higher kinded types in Scala lead to a Turing-complete
+ * type system, where compiler termination is no longer guaranteed. They tend
+ * to be useful mostly for type-level computation and for highly generic design
+ * patterns. The level of abstraction implied by these design patterns is often
+ * a barrier to understanding for newcomers to a Scala codebase. Some syntactic
+ * aspects of higher-kinded types are hard to understand for the uninitiated and
+ * type inference is less effective for them than for normal types. Because we are
+ * not completely happy with them yet, it is possible that some aspects of
+ * higher-kinded types will change in future versions of Scala. So an explicit
+ * enabling also serves as a warning that code involving higher-kinded types
+ * might have to be slightly revised in the future.
+ */
+ implicit lazy val higherKinds: higherKinds = ???
+
+ /** Only where enabled, existential types that cannot be expressed as wildcard
+ * types can be written and are allowed in inferred types of values or return
+ * types of methods. Existential types with wildcard type syntax such as `List[_]`,
+ * or `Map[String, _]` are not affected.
+ *
+ * _Why keep the feature?_ Existential types are needed to make sense of Java’s wildcard
+ * types and raw types and the erased types of run-time values.
+ *
+ * Why control it? Having complex existential types in a code base usually makes
+ * application code very brittle, with a tendency to produce type errors with
+ * obscure error messages. Therefore, going overboard with existential types
+ * is generally perceived not to be a good idea. Also, complicated existential types
+ * might be no longer supported in a future simplification of the language.
+ */
+ implicit lazy val existentials: existentials = ???
+
+ object experimental {
+
+ import languageFeature.experimental._
+
+ /** Where enabled, macro definitions are allowed. Macro implementations and
+ * macro applications are unaffected; they can be used anywhere.
+ *
+ * _Why introduce the feature?_ Macros promise to make the language more regular,
+ * replacing ad-hoc language constructs with a general powerful abstraction
+ * capability that can express them. Macros are also a more disciplined and
+ * powerful replacement for compiler plugins.
+ *
+ * _Why control it?_ For their very power, macros can lead to code that is hard
+ * to debug and understand.
+ */
+ implicit lazy val macros: macros = ???
+ }
+}
diff --git a/src/library/scala/languageFeature.scala b/src/library/scala/languageFeature.scala
new file mode 100644
index 0000000000..c990f714c1
--- /dev/null
+++ b/src/library/scala/languageFeature.scala
@@ -0,0 +1,30 @@
+package scala
+
+import annotation.meta
+
+object languageFeature {
+
+ @meta.languageFeature("extension of type scala.Dynamic", true)
+ sealed trait dynamics
+
+ @meta.languageFeature("postfix operator #", false)
+ sealed trait postfixOps
+
+ @meta.languageFeature("reflective access of structural type member #", false)
+ sealed trait reflectiveCalls
+
+ @meta.languageFeature("implicit conversion #", false)
+ sealed trait implicitConversions
+
+ @meta.languageFeature("higher-kinded type", false)
+ sealed trait higherKinds
+
+ @meta.languageFeature("#, which cannot be expressed by wildcards, ", false)
+ sealed trait existentials
+
+ object experimental {
+ @meta.languageFeature("macro definition", true)
+ sealed trait macros
+ }
+}
+
diff --git a/src/library/scala/math/BigDecimal.scala b/src/library/scala/math/BigDecimal.scala
index cb42b76b51..74daa510ca 100644
--- a/src/library/scala/math/BigDecimal.scala
+++ b/src/library/scala/math/BigDecimal.scala
@@ -12,6 +12,7 @@ package scala.math
import java.{ lang => jl }
import java.math.{ MathContext, BigDecimal => BigDec }
import scala.collection.immutable.NumericRange
+import language.implicitConversions
/**
@@ -292,7 +293,7 @@ extends ScalaNumber with ScalaNumericConversions with Serializable {
/** Returns the absolute value of this BigDecimal
*/
- def abs: BigDecimal = this.bigDecimal abs
+ def abs: BigDecimal = this.bigDecimal.abs
/** Returns the sign of this BigDecimal, i.e.
* -1 if it is less than 0,
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index dbec30b2fe..ff52ca9bec 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -9,6 +9,7 @@
package scala.math
import java.math.BigInteger
+import language.implicitConversions
/**
* @author Martin Odersky
diff --git a/src/library/scala/math/Fractional.scala b/src/library/scala/math/Fractional.scala
index de09b184e0..0686569c16 100644
--- a/src/library/scala/math/Fractional.scala
+++ b/src/library/scala/math/Fractional.scala
@@ -8,6 +8,8 @@
package scala.math
+import language.implicitConversions
+
/**
* @since 2.8
*/
diff --git a/src/library/scala/math/Integral.scala b/src/library/scala/math/Integral.scala
index bb364a79b4..4b4de28228 100644
--- a/src/library/scala/math/Integral.scala
+++ b/src/library/scala/math/Integral.scala
@@ -10,6 +10,8 @@
package scala.math
+import language.implicitConversions
+
/**
* @since 2.8
*/
diff --git a/src/library/scala/math/Numeric.scala b/src/library/scala/math/Numeric.scala
index ff88e0ff4d..ee62706e49 100644
--- a/src/library/scala/math/Numeric.scala
+++ b/src/library/scala/math/Numeric.scala
@@ -8,6 +8,8 @@
package scala.math
+import language.implicitConversions
+
/**
* @since 2.8
*/
@@ -34,8 +36,8 @@ object Numeric {
def fromInt(x: Int): BigInt = BigInt(x)
def toInt(x: BigInt): Int = x.intValue
def toLong(x: BigInt): Long = x.longValue
- def toFloat(x: BigInt): Float = x.longValue.toFloat
- def toDouble(x: BigInt): Double = x.longValue.toDouble
+ def toFloat(x: BigInt): Float = x.floatValue
+ def toDouble(x: BigInt): Double = x.doubleValue
}
implicit object BigIntIsIntegral extends BigIntIsIntegral with Ordering.BigIntOrdering
diff --git a/src/library/scala/math/Ordered.scala b/src/library/scala/math/Ordered.scala
index b76030718f..80addea7f3 100644
--- a/src/library/scala/math/Ordered.scala
+++ b/src/library/scala/math/Ordered.scala
@@ -8,6 +8,8 @@
package scala.math
+import language.implicitConversions
+
/** A trait for data that have a single, natural ordering. See
* [[scala.math.Ordering]] before using this trait for
* more information about whether to use [[scala.math.Ordering]] instead.
diff --git a/src/library/scala/math/Ordering.scala b/src/library/scala/math/Ordering.scala
index 8fc74a9d5d..ab685815a1 100644
--- a/src/library/scala/math/Ordering.scala
+++ b/src/library/scala/math/Ordering.scala
@@ -9,6 +9,7 @@
package scala.math
import java.util.Comparator
+import language.{implicitConversions, higherKinds}
/** Ordering is a trait whose instances each represent a strategy for sorting
* instances of a type.
diff --git a/src/library/scala/math/package.scala b/src/library/scala/math/package.scala
index 0417461f85..71a7f8e5ed 100644
--- a/src/library/scala/math/package.scala
+++ b/src/library/scala/math/package.scala
@@ -115,21 +115,10 @@ package object math {
def min(x: Float, y: Float): Float = java.lang.Math.min(x, y)
def min(x: Double, y: Double): Double = java.lang.Math.min(x, y)
- def signum(x: Double): Double =
- if (x == 0d) 0d
- else if (x < 0) -1.0
- else if (x > 0) 1.0
- else x // NaN
-
- def signum(x: Float): Float =
- if (x == 0f) 0f
- else if (x < 0) -1.0f
- else if (x > 0) 1.0f
- else x // NaN
-
- def signum(x: Long): Long = java.lang.Long.signum(x)
-
def signum(x: Int): Int = java.lang.Integer.signum(x)
+ def signum(x: Long): Long = java.lang.Long.signum(x)
+ def signum(x: Float): Float = java.lang.Math.signum(x)
+ def signum(x: Double): Double = java.lang.Math.signum(x)
// -----------------------------------------------------------------------
// root functions
diff --git a/src/library/scala/package.scala b/src/library/scala/package.scala
index 1ef1911fd3..e3890d7a9d 100644
--- a/src/library/scala/package.scala
+++ b/src/library/scala/package.scala
@@ -6,7 +6,6 @@
** |/ **
\* */
-import annotation.bridge
/**
* Core Scala types. They are always available without an explicit import.
@@ -80,15 +79,6 @@ package object scala {
type Range = scala.collection.immutable.Range
val Range = scala.collection.immutable.Range
- // Migrated from Predef
- @deprecated("Use Thread.currentThread instead", "2.9.0")
- def currentThread = java.lang.Thread.currentThread()
-
- // Moved back into Predef to avoid unnecessary indirection by
- // way of the scala package object within the standard library,
- // but bridged for compatibility.
- @bridge def $scope = scala.xml.TopScope
-
// Numeric types which were moved into scala.math.*
type BigDecimal = scala.math.BigDecimal
@@ -132,13 +122,4 @@ package object scala {
type unchecked = annotation.unchecked.unchecked
type volatile = annotation.volatile
*/
-
- @deprecated("use scala.annotation.Annotation instead", "2.9.0")
- type Annotation = scala.annotation.Annotation
- @deprecated("use scala.annotation.ClassfileAnnotation instead", "2.9.0")
- type ClassfileAnnotation = scala.annotation.ClassfileAnnotation
- @deprecated("use scala.annotation.StaticAnnotation instead", "2.9.0")
- type StaticAnnotation = scala.annotation.StaticAnnotation
- @deprecated("use scala.annotation.TypeConstraint instead", "2.9.0")
- type TypeConstraint = scala.annotation.TypeConstraint
}
diff --git a/src/library/scala/reflect/ArrayTag.scala b/src/library/scala/reflect/ArrayTag.scala
new file mode 100644
index 0000000000..ba0c075723
--- /dev/null
+++ b/src/library/scala/reflect/ArrayTag.scala
@@ -0,0 +1,25 @@
+package scala.reflect
+
+/** An `ArrayTag[T]` is a descriptor that is requested by the compiler every time
+ * when an array is instantiated, but the element type is unknown at compile time.
+ *
+ * Implicit in the contract of `ArrayTag[T]` is the fact that `T`
+ * cannot contain unresolved references to type parameters or abstract types.
+ *
+ * Scala library provides a standard implementation of this trait,
+ * `ClassTag[T]` that explicitly carries the `java.lang.Class` erasure of type T
+ * and uses Java reflection to instantiate arrays.
+ *
+ * However other platforms (e.g. a Scala -> JS crosscompiler) may reimplement this trait as they see fit
+ * and then expose the implementation via an implicit macro.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+@annotation.implicitNotFound(msg = "No ArrayTag available for ${T}")
+trait ArrayTag[T] {
+ /** Produces an `ArrayTag` that knows how to build `Array[Array[T]]` */
+ def wrap: ArrayTag[Array[T]]
+
+ /** Produces a new array with element type `T` and length `len` */
+ def newArray(len: Int): Array[T]
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/ClassManifest.scala b/src/library/scala/reflect/ClassManifest.scala
index 37be067614..43e043fd40 100644
--- a/src/library/scala/reflect/ClassManifest.scala
+++ b/src/library/scala/reflect/ClassManifest.scala
@@ -6,23 +6,6 @@
** |/ **
\* */
-/* [Martin]
- * Todo: ClassManifests currently contain all available type arguments.
- * That's a waste of cycles if all that's needed is the class.
- * We should have instead consider a structure like this:
- *
- * OptManifest
- * / \
- * / \
- * PartialManifest ClassManifest
- * \ /
- * \ /
- * Manifest
- *
- * where PartialManifest means: generate as much as you can, use NoManifest
- * where nothing is known, and
- * ClassManifest means: generate exactly the top-level class, and nothing else.
- */
package scala.reflect
import scala.collection.mutable.{ WrappedArray, ArrayBuilder }
@@ -39,17 +22,12 @@ import java.lang.{ Class => jClass }
* be wrong when variance is involved or when a subtype has a different
* number of type arguments than a supertype.
*/
-trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
+@deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0")
+trait ClassManifest[T] extends OptManifest[T] with ClassTag[T] with Equals with Serializable {
/** A class representing the type `U` to which `T` would be erased. Note
* that there is no subtyping relationship between `T` and `U`. */
def erasure: jClass[_]
- /** The Scala type described by this manifest.
- */
- lazy val tpe: mirror.Type = mirror.classToType(erasure)
-
- def symbol: mirror.Symbol = mirror.classToSymbol(erasure)
-
private def subtype(sub: jClass[_], sup: jClass[_]): Boolean = {
def loop(left: Set[jClass[_]], seen: Set[jClass[_]]): Boolean = {
left.nonEmpty && {
@@ -110,7 +88,7 @@ trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
def >:>(that: ClassManifest[_]): Boolean =
that <:< this
- def canEqual(other: Any) = other match {
+ override def canEqual(other: Any) = other match {
case _: ClassManifest[_] => true
case _ => false
}
@@ -131,7 +109,7 @@ trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
def arrayManifest: ClassManifest[Array[T]] =
ClassManifest.classType[Array[T]](arrayClass[T](erasure), this)
- def newArray(len: Int): Array[T] =
+ override def newArray(len: Int): Array[T] =
java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]]
def newArray2(len: Int): Array[Array[T]] =
@@ -169,6 +147,7 @@ trait ClassManifest[T] extends OptManifest[T] with Equals with Serializable {
/** The object `ClassManifest` defines factory methods for manifests.
* It is intended for use by the compiler and should not be used in client code.
*/
+@deprecated("Use `@scala.reflect.ClassTag` instead", "2.10.0")
object ClassManifest {
val Byte = Manifest.Byte
val Short = Manifest.Short
@@ -207,18 +186,18 @@ object ClassManifest {
* pass varargs as arrays into this, we get an infinitely recursive call
* to boxArray. (Besides, having a separate case is more efficient)
*/
- def classType[T](clazz: jClass[_]): ClassManifest[T] =
+ def classType[T <: AnyRef](clazz: jClass[_]): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, Nil)
/** ClassManifest for the class type `clazz[args]`, where `clazz` is
* a top-level or static class and `args` are its type arguments */
- def classType[T](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
+ def classType[T <: AnyRef](clazz: jClass[_], arg1: OptManifest[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](None, clazz, arg1 :: args.toList)
/** ClassManifest for the class type `clazz[args]`, where `clazz` is
* a class with non-package prefix type `prefix` and type arguments `args`.
*/
- def classType[T](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
+ def classType[T <: AnyRef](prefix: OptManifest[_], clazz: jClass[_], args: OptManifest[_]*): ClassManifest[T] =
new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
def arrayType[T](arg: OptManifest[_]): ClassManifest[Array[T]] = arg match {
@@ -250,8 +229,8 @@ object ClassManifest {
}
/** Manifest for the class type `clazz[args]`, where `clazz` is
- * a top-level or static class: todo: we should try to merge this with Manifest's class */
-private class ClassTypeManifest[T](
+ * a top-level or static class */
+private class ClassTypeManifest[T <: AnyRef](
prefix: Option[OptManifest[_]],
val erasure: jClass[_],
override val typeArguments: List[OptManifest[_]]) extends ClassManifest[T]
@@ -260,4 +239,4 @@ private class ClassTypeManifest[T](
(if (prefix.isEmpty) "" else prefix.get.toString+"#") +
(if (erasure.isArray) "Array" else erasure.getName) +
argString
-}
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
new file mode 100644
index 0000000000..e485691747
--- /dev/null
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -0,0 +1,96 @@
+package scala.reflect
+
+import java.lang.{ Class => jClass }
+import scala.reflect.{ mirror => rm }
+import language.{implicitConversions, existentials}
+import scala.runtime.ScalaRunTime.arrayClass
+
+/** A `ClassTag[T]` wraps a Java class, which can be accessed via the `erasure` method.
+ *
+ * This is useful in itself, but also enables very important use case.
+ * Having this knowledge ClassTag can instantiate `Arrays`
+ * in those cases where the element type is unknown at compile time.
+ * Hence, ClassTag[T] conforms to the ArrayTag[T] trait.
+ *
+ * If an implicit value of type u.ClassTag[T] is required, the compiler will make one up on demand.
+ * The implicitly created value contains in its erasure field the Java class that is the result of erasing type T.
+ * In that value, any occurrences of type parameters or abstract types U which come themselves with a ClassTag
+ * or a reflect.mirror.ConcreteTypeTag are represented by the type referenced by that tag.
+ * If the type T contains unresolved references to type parameters or abstract types, a static error results.
+ *
+ * A ConcreteTypeTag member of the reflect.mirror object is convertible to a ClassTag via an implicit conversion
+ * (this is not possible to do in all reflection universes because an operation that converts a type to a Java class might not be available).
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+@annotation.implicitNotFound(msg = "No ClassTag available for ${T}")
+trait ClassTag[T] extends ArrayTag[T] with ErasureTag[T] with Equals with Serializable {
+ // please, don't add any APIs here, like it was with `newWrappedArray` and `newArrayBuilder`
+ // class tags, and all tags in general, should be as minimalistic as possible
+
+ /** Produces a `ClassTag` that knows how to build `Array[Array[T]]` */
+ def wrap: ClassTag[Array[T]] = ClassTag[Array[T]](arrayClass(erasure))
+
+ /** Produces a new array with element type `T` and length `len` */
+ def newArray(len: Int): Array[T] =
+ erasure match {
+ case java.lang.Byte.TYPE => new Array[Byte](len).asInstanceOf[Array[T]]
+ case java.lang.Short.TYPE => new Array[Short](len).asInstanceOf[Array[T]]
+ case java.lang.Character.TYPE => new Array[Char](len).asInstanceOf[Array[T]]
+ case java.lang.Integer.TYPE => new Array[Int](len).asInstanceOf[Array[T]]
+ case java.lang.Long.TYPE => new Array[Long](len).asInstanceOf[Array[T]]
+ case java.lang.Float.TYPE => new Array[Float](len).asInstanceOf[Array[T]]
+ case java.lang.Double.TYPE => new Array[Double](len).asInstanceOf[Array[T]]
+ case java.lang.Boolean.TYPE => new Array[Boolean](len).asInstanceOf[Array[T]]
+ case java.lang.Void.TYPE => new Array[Unit](len).asInstanceOf[Array[T]]
+ case _ => java.lang.reflect.Array.newInstance(erasure, len).asInstanceOf[Array[T]]
+ }
+
+ /** case class accessories */
+ override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
+ override def equals(x: Any) = x.isInstanceOf[ClassTag[_]] && this.erasure == x.asInstanceOf[ClassTag[_]].erasure
+ override def hashCode = scala.runtime.ScalaRunTime.hash(erasure)
+ override def toString = "ClassTag[" + erasure + "]"
+}
+
+object ClassTag {
+ private val NothingTYPE = classOf[scala.runtime.Nothing$]
+ private val NullTYPE = classOf[scala.runtime.Null$]
+ private val ObjectTYPE = classOf[java.lang.Object]
+ private val StringTYPE = classOf[java.lang.String]
+
+ val Byte : ClassTag[scala.Byte] = new ClassTag[scala.Byte]{ def erasure = java.lang.Byte.TYPE; private def readResolve() = ClassTag.Byte }
+ val Short : ClassTag[scala.Short] = new ClassTag[scala.Short]{ def erasure = java.lang.Short.TYPE; private def readResolve() = ClassTag.Short }
+ val Char : ClassTag[scala.Char] = new ClassTag[scala.Char]{ def erasure = java.lang.Character.TYPE; private def readResolve() = ClassTag.Char }
+ val Int : ClassTag[scala.Int] = new ClassTag[scala.Int]{ def erasure = java.lang.Integer.TYPE; private def readResolve() = ClassTag.Int }
+ val Long : ClassTag[scala.Long] = new ClassTag[scala.Long]{ def erasure = java.lang.Long.TYPE; private def readResolve() = ClassTag.Long }
+ val Float : ClassTag[scala.Float] = new ClassTag[scala.Float]{ def erasure = java.lang.Float.TYPE; private def readResolve() = ClassTag.Float }
+ val Double : ClassTag[scala.Double] = new ClassTag[scala.Double]{ def erasure = java.lang.Double.TYPE; private def readResolve() = ClassTag.Double }
+ val Boolean : ClassTag[scala.Boolean] = new ClassTag[scala.Boolean]{ def erasure = java.lang.Boolean.TYPE; private def readResolve() = ClassTag.Boolean }
+ val Unit : ClassTag[scala.Unit] = new ClassTag[scala.Unit]{ def erasure = java.lang.Void.TYPE; private def readResolve() = ClassTag.Unit }
+ val Any : ClassTag[scala.Any] = new ClassTag[scala.Any]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.Any }
+ val Object : ClassTag[java.lang.Object] = new ClassTag[java.lang.Object]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.Object }
+ val AnyVal : ClassTag[scala.AnyVal] = new ClassTag[scala.AnyVal]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.AnyVal }
+ val AnyRef : ClassTag[scala.AnyRef] = new ClassTag[scala.AnyRef]{ def erasure = ObjectTYPE; private def readResolve() = ClassTag.AnyRef }
+ val Nothing : ClassTag[scala.Nothing] = new ClassTag[scala.Nothing]{ def erasure = NothingTYPE; private def readResolve() = ClassTag.Nothing }
+ val Null : ClassTag[scala.Null] = new ClassTag[scala.Null]{ def erasure = NullTYPE; private def readResolve() = ClassTag.Null }
+ val String : ClassTag[java.lang.String] = new ClassTag[java.lang.String]{ def erasure = StringTYPE; private def readResolve() = ClassTag.String }
+
+ def apply[T](erasure1: jClass[_]): ClassTag[T] =
+ erasure1 match {
+ case java.lang.Byte.TYPE => ClassTag.Byte.asInstanceOf[ClassTag[T]]
+ case java.lang.Short.TYPE => ClassTag.Short.asInstanceOf[ClassTag[T]]
+ case java.lang.Character.TYPE => ClassTag.Char.asInstanceOf[ClassTag[T]]
+ case java.lang.Integer.TYPE => ClassTag.Int.asInstanceOf[ClassTag[T]]
+ case java.lang.Long.TYPE => ClassTag.Long.asInstanceOf[ClassTag[T]]
+ case java.lang.Float.TYPE => ClassTag.Float.asInstanceOf[ClassTag[T]]
+ case java.lang.Double.TYPE => ClassTag.Double.asInstanceOf[ClassTag[T]]
+ case java.lang.Boolean.TYPE => ClassTag.Boolean.asInstanceOf[ClassTag[T]]
+ case java.lang.Void.TYPE => ClassTag.Unit.asInstanceOf[ClassTag[T]]
+ case ObjectTYPE => ClassTag.Object.asInstanceOf[ClassTag[T]]
+ case StringTYPE => ClassTag.String.asInstanceOf[ClassTag[T]]
+ case _ => new ClassTag[T]{ def erasure = erasure1 }
+ }
+
+ def unapply[T](ctag: ClassTag[T]): Option[Class[_]] = Some(ctag.erasure)
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/DummyMirror.scala b/src/library/scala/reflect/DummyMirror.scala
new file mode 100644
index 0000000000..aa731f62db
--- /dev/null
+++ b/src/library/scala/reflect/DummyMirror.scala
@@ -0,0 +1,783 @@
+package scala.reflect
+
+import scala.reflect.api.AbsTreeGen
+import scala.reflect.api.Attachment
+import scala.reflect.api.Modifier
+import scala.reflect.api.Universe
+
+// todo. make Dummy objects not equal to themselves
+class DummyMirror(cl: ClassLoader) extends api.Mirror {
+ // Members declared in scala.reflect.api.AnnotationInfos
+ implicit def classfileAnnotArgTag: scala.reflect.ClassTag[ClassfileAnnotArg] = notSupported()
+ type AnnotationInfo = DummyAnnotationInfo.type
+ object DummyAnnotationInfo
+ val AnnotationInfo: AnnotationInfoExtractor = DummyAnnotationInfoExtractor
+ object DummyAnnotationInfoExtractor extends AnnotationInfoExtractor {
+ def apply(atp: Type, args: List[Tree], assocs: List[(Name, ClassfileAnnotArg)]): AnnotationInfo = DummyAnnotationInfo
+ def unapply(info: AnnotationInfo): Option[(Type, List[Tree], List[(Name, ClassfileAnnotArg)])] = notSupported()
+ }
+ type ClassfileAnnotArg = AnyRef
+ type LiteralAnnotArg = DummyLiteralAnnotArg.type
+ object DummyLiteralAnnotArg
+ val LiteralAnnotArg: LiteralAnnotArgExtractor = DummyLiteralAnnotArgExtractor
+ type ArrayAnnotArg = DummyArrayAnnotArg.type
+ object DummyArrayAnnotArg
+ val ArrayAnnotArg: ArrayAnnotArgExtractor = DummyArrayAnnotArgExtractor
+ type NestedAnnotArg = DummyNestedAnnotArg.type
+ object DummyNestedAnnotArg
+ val NestedAnnotArg: NestedAnnotArgExtractor = DummyNestedAnnotArgExtractor
+ object DummyLiteralAnnotArgExtractor extends LiteralAnnotArgExtractor {
+ def apply(const: Constant): LiteralAnnotArg = DummyLiteralAnnotArg
+ def unapply(arg: LiteralAnnotArg): Option[Constant] = notSupported()
+ }
+ object DummyArrayAnnotArgExtractor extends ArrayAnnotArgExtractor {
+ def apply(const: Array[ClassfileAnnotArg]): ArrayAnnotArg = DummyArrayAnnotArg
+ def unapply(arg: ArrayAnnotArg): Option[Array[ClassfileAnnotArg]] = notSupported()
+ }
+ object DummyNestedAnnotArgExtractor extends NestedAnnotArgExtractor {
+ def apply(anninfo: AnnotationInfo): NestedAnnotArg = DummyNestedAnnotArg
+ def unapply(arg: NestedAnnotArg): Option[AnnotationInfo] = notSupported()
+ }
+
+ // Members declared in scala.reflect.api.Constants
+ type Constant = DummyConstant.type
+ object DummyConstant extends AbsConstant {
+ val value: Any = notSupported()
+ def tpe: Type = notSupported()
+ def isNaN: Boolean = notSupported()
+ def booleanValue: Boolean = notSupported()
+ def byteValue: Byte = notSupported()
+ def shortValue: Short = notSupported()
+ def charValue: Char = notSupported()
+ def intValue: Int = notSupported()
+ def longValue: Long = notSupported()
+ def floatValue: Float = notSupported()
+ def doubleValue: Double = notSupported()
+ def stringValue: String = notSupported()
+ def typeValue: Type = notSupported()
+ def symbolValue: Symbol = notSupported()
+ def convertTo(pt: Type): Constant = notSupported()
+ }
+ val Constant: ConstantExtractor = DummyConstantExtractor
+ object DummyConstantExtractor extends ConstantExtractor {
+ def apply(const: Any): Constant = DummyConstant
+ def unapply(arg: Constant): Option[Any] = notSupported()
+ }
+
+ // Members declared in scala.reflect.api.FreeVars
+ type FreeTerm = DummyFreeTerm.type
+ val DummyFreeTerm = DummySymbol
+ val FreeTerm: FreeTermExtractor = DummyFreeTermExtractor
+ object DummyFreeTermExtractor extends FreeTermExtractor {
+ def unapply(freeTerm: FreeTerm): Option[(TermName, Type, Any, String)] = notSupported()
+ }
+ type FreeType = DummyFreeType.type
+ val DummyFreeType = DummySymbol
+ val FreeType: FreeTypeExtractor = DummyFreeTypeExtractor
+ object DummyFreeTypeExtractor extends FreeTypeExtractor {
+ def unapply(freeType: FreeType): Option[(TypeName, Type, String)] = notSupported()
+ }
+ def freeTerms(tree: Tree): List[FreeTerm] = notSupported()
+ def freeTypes(tree: Tree): List[FreeType] = notSupported()
+ def substituteFreeTypes(tpe: Type,subs: Map[FreeType,Type]): Type = notSupported()
+ def substituteFreeTypes(tree: Tree,subs: Map[FreeType,Type]): Tree = notSupported()
+
+ // Members declared in scala.reflect.api.Importers
+ def mkImporter(from0: scala.reflect.api.Universe): Importer{val from: from0.type} = notSupported()
+
+ // Members declared in scala.reflect.api.Mirror
+ def classLoader: ClassLoader = cl
+ def classLoader_=(x$1: ClassLoader): Unit = notSupported()
+ def classToSymbol(clazz: Class[_]): Symbol = notSupported()
+ def classToType(clazz: Class[_]): Type = notSupported()
+ def companionInstance(clazz: Symbol): AnyRef = notSupported()
+ def getValueOfField(receiver: AnyRef,field: Symbol): Any = notSupported()
+ def invoke(receiver: AnyRef,meth: Symbol)(args: Any*): Any = notSupported()
+ def setValueOfField(receiver: AnyRef,field: Symbol,value: Any): Unit = notSupported()
+ def symbolForName(name: String): Symbol = notSupported()
+ def symbolOfInstance(instance: Any): Symbol = notSupported()
+ def symbolToClass(sym: Symbol): Class[_] = notSupported()
+ def typeOfInstance(instance: Any): Type = notSupported()
+ def typeToClass(tpe: Type): Class[_] = notSupported()
+
+ // Members declared in scala.reflect.api.Names
+ type Name = DummyName.type
+ type TypeName = DummyName.type
+ type TermName = DummyName.type
+ object DummyName extends AbsName {
+ def isTermName: Boolean = notSupported()
+ def isTypeName: Boolean = notSupported()
+ def toTermName: TermName = notSupported()
+ def toTypeName: TypeName = notSupported()
+ def decoded: String = notSupported()
+ def encoded: String = notSupported()
+ def decodedName: Name = notSupported()
+ def encodedName: Name = notSupported()
+ }
+ def newTermName(s: String): TermName = notSupported()
+ def newTypeName(s: String): TypeName = notSupported()
+
+ // Members declared in scala.reflect.api.Positions
+ type Position = DummyPosition.type
+ object DummyPosition extends api.Position {
+ def pos: Position = notSupported()
+ def withPos(newPos: scala.reflect.api.Position): Attachment = notSupported()
+ def payload: Any = notSupported()
+ def withPayload(newPayload: Any): Attachment = notSupported()
+ def fileInfo: java.io.File = notSupported()
+ def fileContent: Array[Char] = notSupported()
+ def isDefined: Boolean = notSupported()
+ def isTransparent: Boolean = notSupported()
+ def isRange: Boolean = notSupported()
+ def isOpaqueRange: Boolean = notSupported()
+ def makeTransparent: Position = notSupported()
+ def start: Int = notSupported()
+ def startOrPoint: Int = notSupported()
+ def point: Int = notSupported()
+ def pointOrElse(default: Int): Int = notSupported()
+ def end: Int = notSupported()
+ def endOrPoint: Int = notSupported()
+ def withStart(off: Int): Position = notSupported()
+ def withEnd(off: Int): Position = notSupported()
+ def withPoint(off: Int): Position = notSupported()
+ def union(pos: scala.reflect.api.Position): Position = notSupported()
+ def focusStart: Position = notSupported()
+ def focus: Position = notSupported()
+ def focusEnd: Position = notSupported()
+ def includes(pos: scala.reflect.api.Position): Boolean = notSupported()
+ def properlyIncludes(pos: scala.reflect.api.Position): Boolean = notSupported()
+ def precedes(pos: scala.reflect.api.Position): Boolean = notSupported()
+ def properlyPrecedes(pos: scala.reflect.api.Position): Boolean = notSupported()
+ def overlaps(pos: scala.reflect.api.Position): Boolean = notSupported()
+ def sameRange(pos: scala.reflect.api.Position): Boolean = notSupported()
+ def line: Int = notSupported()
+ def column: Int = notSupported()
+ def toSingleLine: Position = notSupported()
+ def lineContent: String = notSupported()
+ def show: String = notSupported()
+ }
+ val NoPosition: Position = DummyPosition
+ def atPos[T <: Tree](pos: Position)(tree: T): T = tree
+ def ensureNonOverlapping(tree: Tree,others: List[Tree]): Unit = notSupported()
+ def wrappingPos(trees: List[Tree]): Position = notSupported()
+ def wrappingPos(default: Position,trees: List[Tree]): Position = notSupported()
+
+ // Members declared in scala.reflect.api.FrontEnds
+ def mkConsoleFrontEnd(minSeverity: Int): FrontEnd = notSupported()
+
+ // Members declared in scala.reflect.api.Scopes
+ type Scope = DummyScope.type
+ object DummyScope extends Iterable[Symbol] {
+ def iterator: Iterator[Symbol] = notSupported()
+ }
+ def newScope: Scope = DummyScope
+ def newScopeWith(elems: Symbol*): Scope = DummyScope
+ def newNestedScope(outer: Scope): Scope = DummyScope
+
+ // Members declared in scala.reflect.api.StandardDefinitions
+ val AnyRefTpe: Type = DummyType
+ val AnyTpe: Type = DummyType
+ val AnyValTpe: Type = DummyType
+ val BooleanTpe: Type = DummyType
+ val ByteTpe: Type = DummyType
+ val CharTpe: Type = DummyType
+ val DoubleTpe: Type = DummyType
+ val FloatTpe: Type = DummyType
+ val IntTpe: Type = DummyType
+ val LongTpe: Type = DummyType
+ val NothingTpe: Type = DummyType
+ val NullTpe: Type = DummyType
+ val ObjectTpe: Type = DummyType
+ val ShortTpe: Type = DummyType
+ val StringTpe: Type = DummyType
+ val UnitTpe: Type = DummyType
+ val definitions: AbsDefinitions = DummyDefinitions
+ object DummyDefinitions extends AbsDefinitions {
+ def ByNameParamClass = DummySymbol
+ def JavaRepeatedParamClass = DummySymbol
+ def RepeatedParamClass = DummySymbol
+ def AnyClass = DummyClassSymbol
+ def AnyRefClass = DummyTypeSymbol
+ def AnyValClass = DummyClassSymbol
+ def ArrayClass = DummyClassSymbol
+ def ArrayModule = DummySymbol
+ def ArrayModule_overloadedApply = DummySymbol
+ def Array_apply = DummySymbol
+ def Array_clone = DummySymbol
+ def Array_length = DummySymbol
+ def Array_update = DummySymbol
+ def BooleanClass = DummyClassSymbol
+ def ByteClass = DummyClassSymbol
+ def CharClass = DummyClassSymbol
+ def ClassClass = DummyClassSymbol
+ def ClassTagClass = DummyClassSymbol
+ def ClassTagModule = DummySymbol
+ def ConcreteTypeTagClass = DummyClassSymbol
+ def ConcreteTypeTagModule = DummySymbol
+ def ConsClass = DummySymbol
+ def DoubleClass = DummyClassSymbol
+ def EmptyPackage = DummyPackageSymbol
+ def EmptyPackageClass = DummySymbol
+ def FloatClass = DummyClassSymbol
+ def FunctionClass: Array[Symbol] = Array()
+ def IntClass = DummyClassSymbol
+ def IterableClass = DummySymbol
+ def IteratorClass = DummySymbol
+ def IteratorModule = DummySymbol
+ def Iterator_apply = DummySymbol
+ def JavaLangPackage = DummyPackageSymbol
+ def JavaLangPackageClass = DummySymbol
+ def ListClass = DummyClassSymbol
+ def ListModule = DummyModuleSymbol
+ def List_apply = DummySymbol
+ def LongClass = DummyClassSymbol
+ def NilModule = DummySymbol
+ def NoneModule = DummySymbol
+ def NothingClass = DummyClassSymbol
+ def NullClass = DummyClassSymbol
+ def ObjectClass = DummyClassSymbol
+ def OptionClass = DummySymbol
+ def PredefModule = DummyModuleSymbol
+ def ProductClass: Array[Symbol] = Array()
+ def RootClass = DummyClassSymbol
+ def RootPackage = DummyPackageSymbol
+ def ScalaPackage = DummyPackageSymbol
+ def ScalaPackageClass = DummySymbol
+ def ScalaPrimitiveValueClasses = Nil
+ def SeqClass = DummySymbol
+ def SeqModule = DummySymbol
+ def ShortClass = DummyClassSymbol
+ def SomeClass = DummySymbol
+ def SomeModule = DummySymbol
+ def StringBuilderClass = DummySymbol
+ def StringClass = DummyClassSymbol
+ def SymbolClass = DummySymbol
+ def TraversableClass = DummySymbol
+ def TupleClass: Array[Symbol] = Array()
+ def TypeTagClass = DummyClassSymbol
+ def TypeTagModule = DummySymbol
+ def UnitClass = DummyClassSymbol
+ def isNumericValueClass(sym: Symbol): Boolean = notSupported()
+ def isPrimitiveValueClass(sym: Symbol): Boolean = notSupported()
+ def vmClassType(arg: Type): Type = DummyType
+ def vmSignature(sym: Symbol,info: Type): String = notSupported()
+ }
+
+ // Members declared in scala.reflect.api.StandardNames
+ val nme: AbsTermNames = DummyAbsTermNames
+ val tpnme: AbsTypeNames = DummyAbsTypeNames
+ object DummyAbsTermNames extends AbsTermNames {
+ type NameType = TermName
+ val EMPTY: NameType = DummyName
+ val ANON_FUN_NAME: NameType = DummyName
+ val ANON_CLASS_NAME: NameType = DummyName
+ val EMPTY_PACKAGE_NAME: NameType = DummyName
+ val IMPORT: NameType = DummyName
+ val MODULE_VAR_SUFFIX: NameType = DummyName
+ val ROOT: NameType = DummyName
+ val PACKAGE: NameType = DummyName
+ val SPECIALIZED_SUFFIX: NameType = DummyName
+ val ERROR: NameType = DummyName
+ val NO_NAME: NameType = DummyName
+ val WILDCARD: NameType = DummyName
+ def flattenedName(segments: Name*): NameType = notSupported()
+ val EXPAND_SEPARATOR_STRING: String = ""
+ val ANYNAME: TermName = DummyName
+ val CONSTRUCTOR: TermName = DummyName
+ val FAKE_LOCAL_THIS: TermName = DummyName
+ val INITIALIZER: TermName = DummyName
+ val LAZY_LOCAL: TermName = DummyName
+ val LOCAL_SUFFIX_STRING: String = ""
+ val MIRROR_PREFIX: TermName = DummyName
+ val MIRROR_SHORT: TermName = DummyName
+ val MIRROR_FREE_PREFIX: TermName = DummyName
+ val MIRROR_FREE_THIS_SUFFIX: TermName = DummyName
+ val MIRROR_FREE_VALUE_SUFFIX: TermName = DummyName
+ val MIRROR_SYMDEF_PREFIX: TermName = DummyName
+ val MIXIN_CONSTRUCTOR: TermName = DummyName
+ val MODULE_INSTANCE_FIELD: TermName = DummyName
+ val OUTER: TermName = DummyName
+ val OUTER_LOCAL: TermName = DummyName
+ val OUTER_SYNTH: TermName = DummyName
+ val SELECTOR_DUMMY: TermName = DummyName
+ val SELF: TermName = DummyName
+ val SPECIALIZED_INSTANCE: TermName = DummyName
+ val STAR: TermName = DummyName
+ val THIS: TermName = DummyName
+ val BITMAP_NORMAL: TermName = DummyName
+ val BITMAP_TRANSIENT: TermName = DummyName
+ val BITMAP_CHECKINIT: TermName = DummyName
+ val BITMAP_CHECKINIT_TRANSIENT: TermName = DummyName
+ val INTERPRETER_IMPORT_WRAPPER: String = ""
+ val INTERPRETER_LINE_PREFIX: String = ""
+ val INTERPRETER_VAR_PREFIX: String = ""
+ val INTERPRETER_WRAPPER_SUFFIX: String = ""
+ val ROOTPKG: TermName = DummyName
+ val ADD: TermName = DummyName
+ val AND: TermName = DummyName
+ val ASR: TermName = DummyName
+ val DIV: TermName = DummyName
+ val EQ: TermName = DummyName
+ val EQL: TermName = DummyName
+ val GE: TermName = DummyName
+ val GT: TermName = DummyName
+ val HASHHASH: TermName = DummyName
+ val LE: TermName = DummyName
+ val LSL: TermName = DummyName
+ val LSR: TermName = DummyName
+ val LT: TermName = DummyName
+ val MINUS: TermName = DummyName
+ val MOD: TermName = DummyName
+ val MUL: TermName = DummyName
+ val NE: TermName = DummyName
+ val OR: TermName = DummyName
+ val PLUS : TermName = DummyName
+ val SUB: TermName = DummyName
+ val XOR: TermName = DummyName
+ val ZAND: TermName = DummyName
+ val ZOR: TermName = DummyName
+ val UNARY_~ : TermName = DummyName
+ val UNARY_+ : TermName = DummyName
+ val UNARY_- : TermName = DummyName
+ val UNARY_! : TermName = DummyName
+ val ??? : TermName = DummyName
+ val MODULE_SUFFIX_NAME: TermName = DummyName
+ val NAME_JOIN_NAME: TermName = DummyName
+ val IMPL_CLASS_SUFFIX: String = ""
+ val LOCALDUMMY_PREFIX: String = ""
+ val PROTECTED_PREFIX: String = ""
+ val PROTECTED_SET_PREFIX: String = ""
+ val SINGLETON_SUFFIX: String = ""
+ val SUPER_PREFIX_STRING: String = ""
+ val TRAIT_SETTER_SEPARATOR_STRING: String = ""
+ val SETTER_SUFFIX: TermName = DummyName
+ def isConstructorName(name: Name): Boolean = notSupported()
+ def isExceptionResultName(name: Name): Boolean = notSupported()
+ def isImplClassName(name: Name): Boolean = notSupported()
+ def isLocalDummyName(name: Name): Boolean = notSupported()
+ def isLocalName(name: Name): Boolean = notSupported()
+ def isLoopHeaderLabel(name: Name): Boolean = notSupported()
+ def isProtectedAccessorName(name: Name): Boolean = notSupported()
+ def isSuperAccessorName(name: Name): Boolean = notSupported()
+ def isReplWrapperName(name: Name): Boolean = notSupported()
+ def isSetterName(name: Name): Boolean = notSupported()
+ def isTraitSetterName(name: Name): Boolean = notSupported()
+ def isSingletonName(name: Name): Boolean = notSupported()
+ def isModuleName(name: Name): Boolean = notSupported()
+ def isOpAssignmentName(name: Name): Boolean = notSupported()
+ def segments(name: String, assumeTerm: Boolean): List[Name] = notSupported()
+ def originalName(name: Name): Name = notSupported()
+ def stripModuleSuffix(name: Name): Name = notSupported()
+ def unspecializedName(name: Name): Name = notSupported()
+ def splitSpecializedName(name: Name): (Name, String, String) = notSupported()
+ def dropLocalSuffix(name: Name): Name = notSupported()
+ def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName = notSupported()
+ def expandedSetterName(name: TermName, base: Symbol): TermName = notSupported()
+ def protName(name: Name): TermName = notSupported()
+ def protSetterName(name: Name): TermName = notSupported()
+ def getterName(name: TermName): TermName = notSupported()
+ def getterToLocal(name: TermName): TermName = notSupported()
+ def getterToSetter(name: TermName): TermName = notSupported()
+ def localToGetter(name: TermName): TermName = notSupported()
+ def setterToGetter(name: TermName): TermName = notSupported()
+ def defaultGetterName(name: Name, pos: Int): TermName = notSupported()
+ def defaultGetterToMethod(name: Name): TermName = notSupported()
+ def localDummyName(clazz: Symbol): TermName = notSupported()
+ def superName(name: Name): TermName = notSupported()
+ }
+ object DummyAbsTypeNames extends AbsTypeNames {
+ type NameType = TypeName
+ val EMPTY: NameType = DummyName
+ val ANON_FUN_NAME: NameType = DummyName
+ val ANON_CLASS_NAME: NameType = DummyName
+ val EMPTY_PACKAGE_NAME: NameType = DummyName
+ val IMPORT: NameType = DummyName
+ val MODULE_VAR_SUFFIX: NameType = DummyName
+ val ROOT: NameType = DummyName
+ val PACKAGE: NameType = DummyName
+ val SPECIALIZED_SUFFIX: NameType = DummyName
+ val ERROR: NameType = DummyName
+ val NO_NAME: NameType = DummyName
+ val WILDCARD: NameType = DummyName
+ def flattenedName(segments: Name*): NameType = notSupported()
+ val REFINE_CLASS_NAME: TypeName = DummyName
+ val BYNAME_PARAM_CLASS_NAME: TypeName = DummyName
+ val EQUALS_PATTERN_NAME: TypeName = DummyName
+ val JAVA_REPEATED_PARAM_CLASS_NAME: TypeName = DummyName
+ val LOCAL_CHILD: TypeName = DummyName
+ val REPEATED_PARAM_CLASS_NAME: TypeName = DummyName
+ val WILDCARD_STAR: TypeName = DummyName
+
+ def dropSingletonName(name: Name): TypeName = notSupported()
+ def singletonName(name: Name): TypeName = notSupported()
+ def implClassName(name: Name): TypeName = notSupported()
+ def interfaceName(implname: Name): TypeName = notSupported()
+ }
+
+ // Members declared in scala.reflect.api.Symbols
+ val NoSymbol = DummySymbol
+ type Symbol = DummySymbolApi
+ object DummySymbol extends DummySymbolApi
+ type TypeSymbol = DummyTypeSymbolApi
+ object DummyTypeSymbol extends DummyTypeSymbolApi
+ type TermSymbol = DummyTermSymbolApi
+ object DummyTermSymbol extends DummyTermSymbolApi
+ type MethodSymbol = DummyMethodSymbolApi
+ object DummyMethodSymbol extends DummyMethodSymbolApi
+ type ModuleSymbol = DummyModuleSymbolApi
+ object DummyModuleSymbol extends DummyModuleSymbolApi
+ type PackageSymbol = DummyPackageSymbolApi
+ object DummyPackageSymbol extends DummyPackageSymbolApi
+ type ClassSymbol = DummyClassSymbolApi
+ object DummyClassSymbol extends DummyClassSymbolApi
+ trait DummySymbolApi extends AbsSymbol {
+ this: Symbol =>
+
+ def pos: Position = notSupported()
+ def modifiers: Set[Modifier] = notSupported()
+ def hasModifier(mod: Modifier): Boolean = notSupported()
+ def annotations: List[AnnotationInfo] = notSupported()
+ def hasAnnotation(sym: Symbol): Boolean = notSupported()
+ def owner: Symbol = notSupported()
+ def name: Name = notSupported()
+ def fullName: String = notSupported()
+ def id: Int = notSupported()
+ def orElse(alt: => Symbol): Symbol = notSupported()
+ def filter(cond: Symbol => Boolean): Symbol = notSupported()
+ def suchThat(cond: Symbol => Boolean): Symbol = notSupported()
+ def privateWithin: Symbol = notSupported()
+ def companionSymbol: Symbol = notSupported()
+ def moduleClass: Symbol = notSupported()
+ def enclosingTopLevelClass: Symbol = notSupported()
+ def enclosingClass: Symbol = notSupported()
+ def enclosingMethod: Symbol = notSupported()
+ def enclosingPackageClass: Symbol = notSupported()
+ def isTerm : Boolean = notSupported()
+ def isPackage : Boolean = notSupported()
+ def isMethod : Boolean = notSupported()
+ def isOverloaded : Boolean = notSupported()
+ def isFreeTerm : Boolean = notSupported()
+ def isType : Boolean = notSupported()
+ def isClass : Boolean = notSupported()
+ def isPackageClass : Boolean = notSupported()
+ def isPrimitiveValueClass: Boolean = notSupported()
+ def isDerivedValueClass: Boolean = notSupported()
+ def isAliasType : Boolean = notSupported()
+ def isAbstractType : Boolean = notSupported()
+ def isSkolem : Boolean = notSupported()
+ def isExistential : Boolean = notSupported()
+ def isFreeType : Boolean = notSupported()
+ def isContravariant : Boolean = notSupported()
+ def isCovariant : Boolean = notSupported()
+ def isErroneous : Boolean = notSupported()
+ def typeSignature: Type = notSupported()
+ def typeSignatureIn(site: Type): Type = notSupported()
+ def asType: Type = notSupported()
+ def asTypeIn(site: Type): Type = notSupported()
+ def asTypeConstructor: Type = notSupported()
+ def thisPrefix: Type = notSupported()
+ def selfType: Type = notSupported()
+ def alternatives: List[Symbol] = notSupported()
+ def resolveOverloaded(pre: Type = NoPrefix, targs: Seq[Type] = List(), actuals: Seq[Type]): Symbol = notSupported()
+ def newNestedSymbol(name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol = notSupported()
+ def setInternalFlags(flags: Long): this.type = notSupported()
+ def setTypeSignature(tpe: Type): this.type = notSupported()
+ def setAnnotations(annots: AnnotationInfo*): this.type = notSupported()
+ def kind: String = notSupported()
+ }
+ trait DummyTypeSymbolApi extends DummySymbolApi with TypeSymbolApi {
+ this: TypeSymbol =>
+ }
+ trait DummyTermSymbolApi extends DummySymbolApi with TermSymbolApi {
+ this: TermSymbol =>
+ }
+ trait DummyMethodSymbolApi extends DummyTermSymbolApi with MethodSymbolApi {
+ this: MethodSymbol =>
+ }
+ trait DummyModuleSymbolApi extends DummyTermSymbolApi with ModuleSymbolApi {
+ this: ModuleSymbol =>
+ }
+ trait DummyPackageSymbolApi extends DummyModuleSymbolApi with PackageSymbolApi {
+ this: PackageSymbol =>
+ }
+ trait DummyClassSymbolApi extends DummyTypeSymbolApi with ClassSymbolApi {
+ this: ClassSymbol =>
+ }
+
+ // Members declared in scala.reflect.api.ToolBoxes
+ def mkToolBox(frontEnd: FrontEnd, options: String): AbsToolBox = notSupported()
+
+ // Members declared in scala.reflect.api.TreeBuildUtil
+ // type TreeGen = DummyTreeGen.type // [Eugene] cannot compile if uncomment this
+ val gen: TreeGen{val global: DummyMirror.this.type} = DummyTreeGen.asInstanceOf[TreeGen{val global: DummyMirror.this.type}]
+ def modifiersFromInternalFlags(flags: Long,privateWithin: Name,annotations: List[Tree]): Modifiers = DummyModifiers
+ def newFreeExistential(name: String,info: Type,value: => Any,flags: Long,origin: String) = DummySymbol
+ def newFreeTerm(name: String,info: Type,value: => Any,flags: Long,origin: String) = DummySymbol
+ def newFreeType(name: String,info: Type,value: => Any,flags: Long,origin: String) = DummySymbol
+ def selectOverloadedMethod(owner: Symbol,name: String,index: Int) = DummySymbol
+ def selectOverloadedMethodIfDefined(owner: Symbol,name: String,index: Int) = DummySymbol
+ def selectTerm(owner: Symbol,name: String) = DummySymbol
+ def selectTermIfDefined(owner: Symbol,name: String) = DummySymbol
+ def selectType(owner: Symbol,name: String) = DummySymbol
+ def selectTypeIfDefined(owner: Symbol,name: String) = DummySymbol
+ def staticClass(fullName: String) = DummySymbol
+ def staticClassIfDefined(fullName: String) = DummySymbol
+ def staticModule(fullName: String) = DummySymbol
+ def staticModuleIfDefined(fullName: String) = DummySymbol
+ def thisModuleType(fullName: String): Type = DummyType
+ object DummyTreeGen extends AbsTreeGen {
+ val global: Universe = DummyMirror.this
+ type TreeGenTree = global.Tree
+ type TreeGenType = global.Type
+ type TreeGenSymbol = global.Symbol
+ type TreeGenName = global.Name
+ def mkAttributedQualifier(tpe: TreeGenType): TreeGenTree = notSupported()
+ def mkAttributedQualifier(tpe: TreeGenType, termSym: TreeGenSymbol): TreeGenTree = notSupported()
+ def mkAttributedRef(pre: TreeGenType, sym: TreeGenSymbol): TreeGenTree = notSupported()
+ def mkAttributedRef(sym: TreeGenSymbol): TreeGenTree = notSupported()
+ def mkAttributedThis(sym: TreeGenSymbol): TreeGenTree = notSupported()
+ def mkAttributedIdent(sym: TreeGenSymbol): TreeGenTree = notSupported()
+ def mkAttributedSelect(qual: TreeGenTree, sym: TreeGenSymbol): TreeGenTree = notSupported()
+ def mkMethodCall(target: TreeGenTree,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(receiver: TreeGenTree,method: TreeGenSymbol,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(receiver: TreeGenSymbol,methodName: TreeGenName,args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(target: TreeGenTree,args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(method: TreeGenSymbol,args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(method: TreeGenSymbol,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkMethodCall(receiver: TreeGenSymbol,methodName: TreeGenName,targs: List[TreeGenType],args: List[TreeGenTree]): TreeGenTree = notSupported()
+ def mkNullaryCall(method: TreeGenSymbol,targs: List[TreeGenType]): TreeGenTree = notSupported()
+ }
+
+ // Members declared in scala.reflect.api.TreePrinters
+ def newTreePrinter(out: java.io.PrintWriter): TreePrinter = notSupported()
+
+ // Members declared in scala.reflect.api.Trees
+ def Apply(sym: Symbol,args: Tree*): Tree = Apply(EmptyTree, Nil)
+ def Bind(sym: Symbol,body: Tree): Bind = Bind(DummyName, EmptyTree)
+ def Block(stats: Tree*): Block = Block()
+ def CaseDef(pat: Tree,body: Tree): CaseDef = CaseDef(EmptyTree, EmptyTree, EmptyTree)
+ def ClassDef(sym: Symbol,impl: Template): ClassDef = ClassDef(DummyModifiers, DummyName, Nil, Template(Nil, emptyValDef, Nil))
+ def DefDef(sym: Symbol,rhs: List[List[Symbol]] => Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree)
+ def DefDef(sym: Symbol,rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree)
+ def DefDef(sym: Symbol,mods: Modifiers,rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree)
+ def DefDef(sym: Symbol,vparamss: List[List[ValDef]],rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree)
+ def DefDef(sym: Symbol,mods: Modifiers,vparamss: List[List[ValDef]],rhs: Tree): DefDef = DefDef(DummyModifiers, DummyName, Nil, Nil, EmptyTree, EmptyTree)
+ def Ident(sym: Symbol): Ident = Ident(DummyName)
+ def Ident(name: String): Ident = Ident(DummyName)
+ def LabelDef(sym: Symbol,params: List[Symbol],rhs: Tree): LabelDef = LabelDef(DummyName, Nil, EmptyTree)
+ type Modifiers = DummyModifiers.type
+ val NoMods: Modifiers = DummyModifiers
+ object DummyModifiers extends AbsModifiers {
+ def modifiers: Set[Modifier] = notSupported()
+ def hasModifier(mod: Modifier): Boolean = notSupported()
+ def privateWithin: Name = notSupported()
+ def annotations: List[Tree] = notSupported()
+ def mapAnnotations(f: List[Tree] => List[Tree]): Modifiers = notSupported()
+ }
+ def Modifiers(mods: Set[scala.reflect.api.Modifier],privateWithin: Name,annotations: List[Tree]): Modifiers = DummyModifiers
+ def ModuleDef(sym: Symbol,impl: Template): ModuleDef = ModuleDef(DummyModifiers, DummyName, Template(Nil, emptyValDef, Nil))
+ def New(sym: Symbol,args: Tree*): Tree = New(EmptyTree)
+ def New(tpe: Type,args: Tree*): Tree = New(EmptyTree)
+ def New(tpt: Tree,argss: List[List[Tree]]): Tree = New(EmptyTree)
+ def Select(qualifier: Tree,sym: Symbol): Select = Select(EmptyTree, DummyName)
+ def Select(qualifier: Tree,name: String): Select = Select(EmptyTree, DummyName)
+ def Super(sym: Symbol,mix: TypeName): Tree = Super(EmptyTree, DummyName)
+ def This(sym: Symbol): Tree = This(DummyName)
+ def Throw(tpe: Type,args: Tree*): Throw = Throw(EmptyTree)
+ def Try(body: Tree,cases: (Tree, Tree)*): Try = Try(EmptyTree)
+ def TypeDef(sym: Symbol): TypeDef = TypeDef(DummyModifiers, DummyName, Nil, EmptyTree)
+ def TypeDef(sym: Symbol,rhs: Tree): TypeDef = TypeDef(DummyModifiers, DummyName, Nil, EmptyTree)
+ def ValDef(sym: Symbol): ValDef = ValDef(DummyModifiers, DummyName, EmptyTree, EmptyTree)
+ def ValDef(sym: Symbol,rhs: Tree): ValDef = ValDef(DummyModifiers, DummyName, EmptyTree, EmptyTree)
+ protected def duplicateTree(tree: Tree): Tree = notSupported()
+ object emptyValDef extends ValDef(DummyModifiers, DummyName, EmptyTree, EmptyTree) { override def isEmpty = true }
+ type TreeCopier = DummyTreeCopier.type
+ def newStrictTreeCopier: TreeCopier = DummyTreeCopier
+ def newLazyTreeCopier: TreeCopier = DummyTreeCopier
+ object DummyTreeCopier extends TreeCopierOps {
+ def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef = notSupported()
+ def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef = notSupported()
+ def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef = notSupported()
+ def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef = notSupported()
+ def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef = notSupported()
+ def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef = notSupported()
+ def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef = notSupported()
+ def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import = notSupported()
+ def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template = notSupported()
+ def Block(tree: Tree, stats: List[Tree], expr: Tree): Block = notSupported()
+ def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef = notSupported()
+ def Alternative(tree: Tree, trees: List[Tree]): Alternative = notSupported()
+ def Star(tree: Tree, elem: Tree): Star = notSupported()
+ def Bind(tree: Tree, name: Name, body: Tree): Bind = notSupported()
+ def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply = notSupported()
+ def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue = notSupported()
+ def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function = notSupported()
+ def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign = notSupported()
+ def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg = notSupported()
+ def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If = notSupported()
+ def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match = notSupported()
+ def Return(tree: Tree, expr: Tree): Return = notSupported()
+ def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try = notSupported()
+ def Throw(tree: Tree, expr: Tree): Throw = notSupported()
+ def New(tree: Tree, tpt: Tree): New = notSupported()
+ def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed = notSupported()
+ def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply = notSupported()
+ def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply = notSupported()
+ def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic = notSupported()
+ def Super(tree: Tree, qual: Tree, mix: TypeName): Super = notSupported()
+ def This(tree: Tree, qual: Name): This = notSupported()
+ def Select(tree: Tree, qualifier: Tree, selector: Name): Select = notSupported()
+ def Ident(tree: Tree, name: Name): Ident = notSupported()
+ def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed = notSupported()
+ def Literal(tree: Tree, value: Constant): Literal = notSupported()
+ def TypeTree(tree: Tree): TypeTree = notSupported()
+ def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated = notSupported()
+ def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree = notSupported()
+ def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree = notSupported()
+ def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree = notSupported()
+ def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree = notSupported()
+ def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree = notSupported()
+ def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree = notSupported()
+ }
+
+ // Members declared in scala.reflect.api.Types
+ type Type = DummyType.type
+ type SingletonType = DummyType.type
+ type CompoundType = DummyType.type
+ type AnnotatedType = DummyType.type
+ val AnnotatedType: AnnotatedTypeExtractor = DummyAnnotatedTypeExtractor
+ type BoundedWildcardType = DummyType.type
+ val BoundedWildcardType: BoundedWildcardTypeExtractor = DummyBoundedWildcardTypeExtractor
+ type ClassInfoType = DummyType.type
+ val ClassInfoType: ClassInfoTypeExtractor = DummyClassInfoTypeExtractor
+ type ConstantType = DummyType.type
+ val ConstantType: ConstantTypeExtractor = DummyConstantTypeExtractor
+ type ExistentialType = DummyType.type
+ val ExistentialType: ExistentialTypeExtractor = DummyExistentialTypeExtractor
+ type MethodType = DummyType.type
+ val MethodType: MethodTypeExtractor = DummyMethodTypeExtractor
+ val NoPrefix: Type = DummyType
+ val NoType: Type = DummyType
+ type NullaryMethodType = DummyType.type
+ val NullaryMethodType: NullaryMethodTypeExtractor = DummyNullaryMethodTypeExtractor
+ type PolyType = DummyType.type
+ val PolyType: PolyTypeExtractor = DummyPolyTypeExtractor
+ type RefinedType = DummyType.type
+ val RefinedType: RefinedTypeExtractor = DummyRefinedTypeExtractor
+ type SingleType = DummyType.type
+ val SingleType: SingleTypeExtractor = DummySingleTypeExtractor
+ type SuperType = DummyType.type
+ val SuperType: SuperTypeExtractor = DummySuperTypeExtractor
+ type ThisType = DummyType.type
+ val ThisType: ThisTypeExtractor = DummyThisTypeExtractor
+ type TypeBounds = DummyType.type
+ val TypeBounds: TypeBoundsExtractor = DummyTypeBoundsExtractor
+ type TypeRef = DummyType.type
+ val TypeRef: TypeRefExtractor = DummyTypeRefExtractor
+ val WildcardType: Type = DummyType
+ def appliedType(tycon: Type,args: List[Type]): Type = DummyType
+ def existentialAbstraction(tparams: List[Symbol],tpe0: Type): Type = DummyType
+ def glb(ts: List[Type]): Type = DummyType
+ def intersectionType(tps: List[Type],owner: Symbol): Type = DummyType
+ def intersectionType(tps: List[Type]): Type = DummyType
+ def lub(xs: List[Type]): Type = DummyType
+ def polyType(tparams: List[Symbol],tpe: Type): Type = DummyType
+ def refinedType(parents: List[Type],owner: Symbol): Type = DummyType
+ def refinedType(parents: List[Type],owner: Symbol,decls: Scope,pos: Position): Type = DummyType
+ def singleType(pre: Type,sym: Symbol): Type = DummyType
+ def typeRef(pre: Type,sym: Symbol,args: List[Type]): Type = DummyType
+ object DummyType extends AbsType {
+ def =:=(that: Type): Boolean = notSupported()
+ def <:<(that: Type): Boolean = notSupported()
+ def asSeenFrom(pre: Type,clazz: Symbol): Type = notSupported()
+ def baseClasses: List[Symbol] = notSupported()
+ def baseType(clazz: Symbol): Type = notSupported()
+ def contains(sym: Symbol): Boolean = notSupported()
+ def declaration(name: Name): Symbol = notSupported()
+ def declarations: Iterable[Symbol] = notSupported()
+ def erasure: Type = notSupported()
+ def exists(p: Type => Boolean): Boolean = notSupported()
+ def find(p: Type => Boolean): Option[Type] = notSupported()
+ def foreach(f: Type => Unit): Unit = notSupported()
+ def isConcrete: Boolean = notSupported()
+ def isHigherKinded: Boolean = notSupported()
+ def isSpliceable: Boolean = notSupported()
+ def kind: String = notSupported()
+ def map(f: Type => Type): Type = notSupported()
+ def member(name: Name): Symbol = notSupported()
+ def members: Iterable[Symbol] = notSupported()
+ def nonPrivateMember(name: Name): Symbol = notSupported()
+ def nonPrivateMembers: Iterable[Symbol] = notSupported()
+ def normalize: Type = notSupported()
+ def parents: List[Type] = notSupported()
+ def substituteTypes(from: List[Symbol],to: List[Type]): Type = notSupported()
+ def typeArguments: List[Type] = notSupported()
+ def typeConstructor: Type = notSupported()
+ def typeParams: List[Symbol] = notSupported()
+ def typeSymbol: Symbol = notSupported()
+ def underlying: Type = notSupported()
+ def widen: Type = notSupported()
+ }
+ object DummyAnnotatedTypeExtractor extends AnnotatedTypeExtractor {
+ def apply(annotations: List[AnnotationInfo], underlying: Type, selfsym: Symbol): AnnotatedType = DummyType
+ def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)] = notSupported()
+ }
+ object DummyBoundedWildcardTypeExtractor extends BoundedWildcardTypeExtractor {
+ def apply(bounds: TypeBounds): BoundedWildcardType = DummyType
+ def unapply(tpe: BoundedWildcardType): Option[TypeBounds] = notSupported()
+ }
+ object DummyClassInfoTypeExtractor extends ClassInfoTypeExtractor {
+ def apply(parents: List[Type], decls: Scope, clazz: Symbol): ClassInfoType = DummyType
+ def unapply(tpe: ClassInfoType): Option[(List[Type], Scope, Symbol)] = notSupported()
+ }
+ object DummyConstantTypeExtractor extends ConstantTypeExtractor {
+ def apply(value: Constant): ConstantType = DummyType
+ def unapply(tpe: ConstantType): Option[Constant] = notSupported()
+ }
+ object DummyExistentialTypeExtractor extends ExistentialTypeExtractor {
+ def apply(quantified: List[Symbol], underlying: Type): ExistentialType = DummyType
+ def unapply(tpe: ExistentialType): Option[(List[Symbol], Type)] = notSupported()
+ }
+ object DummyMethodTypeExtractor extends MethodTypeExtractor {
+ def apply(params: List[Symbol], resultType: Type): MethodType = DummyType
+ def unapply(tpe: MethodType): Option[(List[Symbol], Type)] = notSupported()
+ }
+ object DummyNullaryMethodTypeExtractor extends NullaryMethodTypeExtractor {
+ def apply(resultType: Type): NullaryMethodType = DummyType
+ def unapply(tpe: NullaryMethodType): Option[(Type)] = notSupported()
+ }
+ object DummyPolyTypeExtractor extends PolyTypeExtractor {
+ def apply(typeParams: List[Symbol], resultType: Type): PolyType = DummyType
+ def unapply(tpe: PolyType): Option[(List[Symbol], Type)] = notSupported()
+ }
+ object DummyRefinedTypeExtractor extends RefinedTypeExtractor {
+ def apply(parents: List[Type], decls: Scope): RefinedType = DummyType
+ def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType = DummyType
+ def unapply(tpe: RefinedType): Option[(List[Type], Scope)] = notSupported()
+ }
+ object DummySingleTypeExtractor extends SingleTypeExtractor {
+ def apply(pre: Type, sym: Symbol): Type = DummyType
+ def unapply(tpe: SingleType): Option[(Type, Symbol)] = notSupported()
+ }
+ object DummySuperTypeExtractor extends SuperTypeExtractor {
+ def apply(thistpe: Type, supertpe: Type): Type = DummyType
+ def unapply(tpe: SuperType): Option[(Type, Type)] = notSupported()
+ }
+ object DummyThisTypeExtractor extends ThisTypeExtractor {
+ def apply(sym: Symbol): Type = DummyType
+ def unapply(tpe: ThisType): Option[Symbol] = notSupported()
+ }
+ object DummyTypeBoundsExtractor extends TypeBoundsExtractor {
+ def apply(lo: Type, hi: Type): TypeBounds = DummyType
+ def unapply(tpe: TypeBounds): Option[(Type, Type)] = notSupported()
+ }
+ object DummyTypeRefExtractor extends TypeRefExtractor {
+ def apply(pre: Type, sym: Symbol, args: List[Type]): Type = DummyType
+ def unapply(tpe: TypeRef): Option[(Type, Symbol, List[Type])] = notSupported()
+ }
+
+ // Utils
+ def notSupported() = {
+ throw new UnsupportedOperationException("Scala reflection not available on this platform." + mirrorDiagnostics(cl))
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/DynamicProxy.scala b/src/library/scala/reflect/DynamicProxy.scala
new file mode 100644
index 0000000000..3ed17fea41
--- /dev/null
+++ b/src/library/scala/reflect/DynamicProxy.scala
@@ -0,0 +1,74 @@
+package scala.reflect
+/**
+ * A dynamic proxy which redirects method calls and attribute access to a given
+ * target object at runtime using reflection.
+ *
+ * Usage example:
+ *
+ * object x{ def hello = "hello world" }
+ * val d = new DynamicProxy{ val dynamicProxyTarget = x }
+ * assert( d.hello == "hello world" )
+ *
+ * Not supported (yet):
+ * - implicit conversions and parameters
+ * - multiple arguments lists
+ * - explicit type arguments
+ */
+trait DynamicProxy extends Dynamic{
+ /** Method calls on DynamicProxy are redirected to this object. Needs to be defined in a subclass. */
+ val dynamicProxyTarget : AnyRef
+
+ import scala.reflect.mirror._
+ /**
+ * boxing to preserve information on primitive types for overloading resolution
+ */
+ case class DynamicReflectBoxed( class_ : Class[_], value: Any )
+ object DynamicReflectBoxed{
+ implicit def box[@specialized T]( v:T ) = DynamicReflectBoxed( v.getClass, v )
+ }
+
+ def selectDynamic( method:String ) = {
+ val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName )
+ invoke( dynamicProxyTarget, symbol )()
+ }
+
+ def updateDynamic( method:String )( value : Any ) = {
+ val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method+"_=").encodedName )
+ invoke( dynamicProxyTarget, symbol )( value )
+ }
+
+ def applyDynamic( method:String )( args:DynamicReflectBoxed* ) : Any
+ = applyDynamicNamed( method )( args.map( value => ("",value) ) :_* )
+
+ def applyDynamicNamed( method:String )( args:(String,DynamicReflectBoxed)* ) : Any = {
+ val class_ = dynamicProxyTarget.getClass
+ var i = 0
+ val toolbox = mkToolBox(mkConsoleFrontEnd(),"")
+ val symbol = classToType( dynamicProxyTarget.getClass ).member( newTermName(method).encodedName )
+ if(args.size == 0){
+ invoke( dynamicProxyTarget, symbol )()
+ } else {
+ val call =
+ Apply(
+ Select(
+ TypeApply(
+ Select(
+ Select(
+ Ident(newFreeTerm("__this", symbolForName("scala.reflect.DynamicProxy").asType, this))
+ , newTermName("dynamicProxyTarget")
+ ),
+ newTermName("asInstanceOf") )
+ , List(TypeTree().setType(classToType(class_)))
+ )
+ ,newTermName(method).encodedName
+ )
+ ,args.map{ case(name,box) =>
+ val value = Ident(newFreeTerm("__arg"+({i+=1;i}.toString), classToType(box.class_), box.value))
+ if( name == "" ) value
+ else AssignOrNamedArg( Ident(name), value )
+ }.toList
+ )
+ toolbox.runExpr( call )
+ }
+ }
+}
diff --git a/src/library/scala/reflect/ErasureTag.scala b/src/library/scala/reflect/ErasureTag.scala
new file mode 100644
index 0000000000..f95451fab2
--- /dev/null
+++ b/src/library/scala/reflect/ErasureTag.scala
@@ -0,0 +1,23 @@
+package scala.reflect
+
+import java.lang.{Class => jClass}
+
+/** An `ErasureTag[T]` is a descriptor that is requested by the compiler every time
+ * when it needs to persist an erasure of a type.
+ *
+ * Scala library provides a standard implementation of this trait,
+ * `TypeTag[T]` that carries the `java.lang.Class` erasure for arbitrary types.
+ *
+ * However other platforms may reimplement this trait as they see fit
+ * and then expose the implementation via an implicit macro.
+ *
+ * If you need to guarantee that the type does not contain
+ * references to type parameters or abstract types, use `ClassTag[T]`.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+@annotation.implicitNotFound(msg = "No ErasureTag available for ${T}")
+trait ErasureTag[T] {
+ /** Returns an erasure of type `T` */
+ def erasure: jClass[_]
+}
diff --git a/src/library/scala/reflect/Manifest.scala b/src/library/scala/reflect/Manifest.scala
index e5df487be9..da029f046d 100644
--- a/src/library/scala/reflect/Manifest.scala
+++ b/src/library/scala/reflect/Manifest.scala
@@ -40,6 +40,7 @@ import mirror._
*
*/
@annotation.implicitNotFound(msg = "No Manifest available for ${T}.")
+@deprecated("Use `@scala.reflect.ConcreteTypeTag` instead", "2.10.0")
trait Manifest[T] extends ClassManifest[T] with Equals {
override def typeArguments: List[Manifest[_]] = Nil
@@ -60,6 +61,7 @@ trait Manifest[T] extends ClassManifest[T] with Equals {
override def hashCode = this.erasure.##
}
+@deprecated("Use type tags and manually check the corresponding class or type instead", "2.10.0")
abstract class AnyValManifest[T <: AnyVal](override val toString: String) extends Manifest[T] with Equals {
override def <:<(that: ClassManifest[_]): Boolean =
(that eq this) || (that eq Manifest.Any) || (that eq Manifest.AnyVal)
@@ -75,9 +77,8 @@ abstract class AnyValManifest[T <: AnyVal](override val toString: String) extend
* It is intended for use by the compiler and should not be used
* in client code.
*/
+@deprecated("Use `@scala.reflect.ConcreteTypeTag` instead", "2.10.0")
object Manifest {
- import mirror.{ definitions => mdefs }
-
def valueManifests: List[AnyValManifest[_]] =
List(Byte, Short, Char, Int, Long, Float, Double, Boolean, Unit)
@@ -154,40 +155,33 @@ object Manifest {
}
val Any: Manifest[scala.Any] = new PhantomManifest[scala.Any]("Any") {
- override def symbol = mdefs.AnyClass
override def <:<(that: ClassManifest[_]): Boolean = (that eq this)
private def readResolve(): Any = Manifest.Any
}
val Object: Manifest[java.lang.Object] = new PhantomManifest[java.lang.Object]("Object") {
- override def symbol = mdefs.ObjectClass
override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
private def readResolve(): Any = Manifest.Object
}
val AnyVal: Manifest[scala.AnyVal] = new PhantomManifest[scala.AnyVal]("AnyVal") {
- override def symbol = mdefs.AnyValClass
override def <:<(that: ClassManifest[_]): Boolean = (that eq this) || (that eq Any)
private def readResolve(): Any = Manifest.AnyVal
}
val Null: Manifest[scala.Null] = new PhantomManifest[scala.Null]("Null") {
- override def symbol = mdefs.NullClass
override def <:<(that: ClassManifest[_]): Boolean =
(that ne null) && (that ne Nothing) && !(that <:< AnyVal)
private def readResolve(): Any = Manifest.Null
}
val Nothing: Manifest[scala.Nothing] = new PhantomManifest[scala.Nothing]("Nothing") {
- override def symbol = mdefs.NothingClass
override def <:<(that: ClassManifest[_]): Boolean = (that ne null)
private def readResolve(): Any = Manifest.Nothing
}
private class SingletonTypeManifest[T <: AnyRef](value: AnyRef) extends Manifest[T] {
lazy val erasure = value.getClass
- override lazy val symbol = InstanceRefSymbol(value) // todo: change to freevar
- override lazy val tpe = mirror.SingleType(mirror.NoPrefix, symbol)
override lazy val toString = value.toString + ".type"
}
@@ -216,12 +210,8 @@ object Manifest {
def classType[T](prefix: Manifest[_], clazz: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
new ClassTypeManifest[T](Some(prefix), clazz, args.toList)
- /** Phantom types have no runtime representation; they all erase to Object,
- * but the Symbol preserves their identity.
- */
private abstract class PhantomManifest[T](override val toString: String) extends ClassTypeManifest[T](None, classOf[java.lang.Object], Nil) {
- override lazy val tpe = namedType(mirror.NoPrefix, symbol, Nil)
- override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
+ override def equals(that: Any): Boolean = this eq that.asInstanceOf[AnyRef]
override val hashCode = System.identityHashCode(this)
}
@@ -230,15 +220,6 @@ object Manifest {
private class ClassTypeManifest[T](prefix: Option[Manifest[_]],
val erasure: Predef.Class[_],
override val typeArguments: List[Manifest[_]]) extends Manifest[T] {
-
- override lazy val tpe = {
- val pre = prefix match {
- case Some(pm) => pm.tpe
- case None => symbol.owner.thisPrefix
- }
- namedType(pre, symbol, typeArguments map (_.tpe))
- }
-
override def toString =
(if (prefix.isEmpty) "" else prefix.get.toString+"#") +
(if (erasure.isArray) "Array" else erasure.getName) +
@@ -254,7 +235,6 @@ object Manifest {
def abstractType[T](prefix: Manifest[_], name: String, upperBound: Predef.Class[_], args: Manifest[_]*): Manifest[T] =
new Manifest[T] {
def erasure = upperBound
- override lazy val tpe = namedType(prefix.tpe, prefix.tpe.member(newTypeName(name)), args map (_.tpe) toList)
override val typeArguments = args.toList
override def toString = prefix.toString+"#"+name+argString
}
@@ -264,7 +244,6 @@ object Manifest {
def wildcardType[T](lowerBound: Manifest[_], upperBound: Manifest[_]): Manifest[T] =
new Manifest[T] {
def erasure = upperBound.erasure
- override lazy val tpe = mirror.TypeBounds(lowerBound.tpe, upperBound.tpe)
override def toString =
"_" +
(if (lowerBound eq Nothing) "" else " >: "+lowerBound) +
@@ -275,28 +254,6 @@ object Manifest {
def intersectionType[T](parents: Manifest[_]*): Manifest[T] =
new Manifest[T] {
def erasure = parents.head.erasure
- override lazy val tpe = mirror.RefinedType((parents map (_.tpe)).toList, newScope)
override def toString = parents.mkString(" with ")
}
-
- /** A generic manifest factory from a reflect.Type. Except where
- * mandated by performance considerations, we should replace most
- * other manifest factories by this one. There's just one thing
- * that needs to be done first: A Manifest's type can refer
- * to type variables that are controlled by manifests. In that
- * case the reified type needs to contain the type passed in the manifest
- * instead of the reference to the manifest. Note that splicing manifests
- * into manfifests is completely analogous to splicing code blocks into
- * code blocks. Manifest[T] and Code[T] are really the same thing, only one
- * works for types, the other for trees.
- * Another complication is that once we generate manifests from types, we really
- * should have reflection as a standard component shipped with the standard library,
- * instead of in scala-compiler.jar.
- */
- def apply[T](_tpe: mirror.Type): Manifest[T] = new Manifest[T] {
- override def symbol = _tpe.typeSymbol
- override lazy val tpe = _tpe
- override def erasure = mirror.typeToClass(_tpe.erasedType)
- override def toString = _tpe.toString
- }
-}
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/NoManifest.scala b/src/library/scala/reflect/NoManifest.scala
index 191e46ae39..7b8037272c 100644
--- a/src/library/scala/reflect/NoManifest.scala
+++ b/src/library/scala/reflect/NoManifest.scala
@@ -10,6 +10,7 @@ package scala.reflect
/** One of the branches of an [[scala.reflect.OptManifest]].
*/
+@deprecated("Use `@scala.reflect.TypeTag` instead", "2.10.0")
object NoManifest extends OptManifest[Nothing] with Serializable {
override def toString = "<?>"
-}
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/OptManifest.scala b/src/library/scala/reflect/OptManifest.scala
index 2a955deb2c..46f23c4e22 100644
--- a/src/library/scala/reflect/OptManifest.scala
+++ b/src/library/scala/reflect/OptManifest.scala
@@ -14,4 +14,5 @@ package scala.reflect
*
* @author Martin Odersky
*/
-trait OptManifest[+T] extends Serializable
+@deprecated("Use `@scala.reflect.TypeTag` instead", "2.10.0")
+trait OptManifest[+T] extends Serializable \ No newline at end of file
diff --git a/src/library/scala/reflect/ReflectionUtils.scala b/src/library/scala/reflect/ReflectionUtils.scala
index 510f0819c6..6ea69cb80d 100644
--- a/src/library/scala/reflect/ReflectionUtils.scala
+++ b/src/library/scala/reflect/ReflectionUtils.scala
@@ -5,6 +5,7 @@
package scala.reflect
+import java.lang.{Class => jClass}
import java.lang.reflect.{ InvocationTargetException, UndeclaredThrowableException }
/** A few java-reflection oriented utility functions useful during reflection bootstrapping.
@@ -27,7 +28,39 @@ object ReflectionUtils {
case ex if pf isDefinedAt unwrapThrowable(ex) => pf(unwrapThrowable(ex))
}
- def singletonInstance(className: String, cl: ClassLoader = getClass.getClassLoader): AnyRef = {
+ private def systemProperties: Iterator[(String, String)] = {
+ import scala.collection.JavaConverters._
+ System.getProperties.asScala.iterator
+ }
+
+ private def searchForBootClasspath = (
+ systemProperties find (_._1 endsWith ".boot.class.path") map (_._2) getOrElse ""
+ )
+
+ def show(cl: ClassLoader) = {
+ def inferClasspath(cl: ClassLoader) = cl match {
+ case cl: java.net.URLClassLoader => "[" + (cl.getURLs mkString ",") + "]"
+ case _ => "<unknown>"
+ }
+ cl match {
+ case cl if cl != null =>
+ "%s of type %s with classpath %s".format(cl, cl.getClass, inferClasspath(cl))
+ case null =>
+ "primordial classloader with boot classpath [%s]".format(searchForBootClasspath)
+ }
+ }
+
+ def defaultReflectionClassLoader() = {
+ // say no to non-determinism of mirror classloaders
+ // default classloader will be instantiated using current system classloader
+ // if you wish so, you can rebind it by setting ``mirror.classLoader'' to whatever is necessary
+// val cl = Thread.currentThread.getContextClassLoader
+// if (cl == null) getClass.getClassLoader else cl
+// cl
+ getClass.getClassLoader
+ }
+
+ def singletonInstance(cl: ClassLoader, className: String): AnyRef = {
val name = if (className endsWith "$") className else className + "$"
val clazz = java.lang.Class.forName(name, true, cl)
val singleton = clazz getField "MODULE$" get null
@@ -35,7 +68,17 @@ object ReflectionUtils {
}
// Retrieves the MODULE$ field for the given class name.
- def singletonInstanceOpt(className: String, cl: ClassLoader = getClass.getClassLoader): Option[AnyRef] =
- try Some(singletonInstance(className, cl))
+ def singletonInstanceOpt(cl: ClassLoader, className: String): Option[AnyRef] =
+ try Some(singletonInstance(cl, className))
+ catch { case _: ClassNotFoundException => None }
+
+ def invokeFactory(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): AnyRef = {
+ val singleton = singletonInstance(cl, className)
+ val method = singleton.getClass.getMethod(methodName, classOf[ClassLoader])
+ method.invoke(singleton, args: _*)
+ }
+
+ def invokeFactoryOpt(cl: ClassLoader, className: String, methodName: String, args: AnyRef*): Option[AnyRef] =
+ try Some(invokeFactory(cl, className, methodName, args: _*))
catch { case _: ClassNotFoundException => None }
}
diff --git a/src/library/scala/reflect/TagInterop.scala b/src/library/scala/reflect/TagInterop.scala
new file mode 100644
index 0000000000..6c6bfcc2f2
--- /dev/null
+++ b/src/library/scala/reflect/TagInterop.scala
@@ -0,0 +1,34 @@
+package scala.reflect
+
+import scala.runtime.ScalaRunTime._
+import mirror._
+import definitions._
+
+object TagInterop {
+ def arrayTagToClassManifest[T](tag: ArrayTag[T]): ClassManifest[T] = {
+ val erasure = arrayElementClass(tag)
+ if (erasure.isArray) {
+ val elementClass = arrayElementClass(erasure)
+ val elementManifest = arrayTagToClassManifest(ClassTag(elementClass))
+ ClassManifest.arrayType(elementManifest).asInstanceOf[ClassManifest[T]]
+ } else {
+ ClassManifest.fromClass(erasure.asInstanceOf[Class[T]])
+ }
+ }
+
+ def concreteTypeTagToManifest[T](tag: ConcreteTypeTag[T]): Manifest[T] = {
+ // todo. reproduce manifest generation code here. toolboxes are too slow.
+ val implicitly = PredefModule.typeSignature.member(newTermName("implicitly"))
+ val taggedTpe = appliedType(staticClass("scala.reflect.Manifest").asTypeConstructor, List(tag.tpe))
+ val materializer = TypeApply(Ident(implicitly), List(TypeTree(taggedTpe)))
+ try mkToolBox().runExpr(materializer).asInstanceOf[Manifest[T]]
+ catch { case ex: Throwable => Manifest.classType(tag.erasure).asInstanceOf[Manifest[T]] }
+ }
+
+ def manifestToConcreteTypeTag[T](tag: Manifest[T]): ConcreteTypeTag[T] = {
+ val tpe =
+ if (tag.typeArguments.isEmpty) classToType(tag.erasure)
+ else appliedType(classToType(tag.erasure).typeConstructor, tag.typeArguments map (manifestToConcreteTypeTag(_)) map (_.tpe))
+ ConcreteTypeTag(tpe, tag.erasure)
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/AnnotationInfos.scala b/src/library/scala/reflect/api/AnnotationInfos.scala
index 96a65606e5..cc1c4d2b6b 100755
--- a/src/library/scala/reflect/api/AnnotationInfos.scala
+++ b/src/library/scala/reflect/api/AnnotationInfos.scala
@@ -12,7 +12,7 @@ trait AnnotationInfos { self: Universe =>
}
type ClassfileAnnotArg <: AnyRef
- implicit def classfileAnnotArgManifest: ClassManifest[ClassfileAnnotArg] // need a precise manifest to pass to UnPickle's toArray call
+ implicit def classfileAnnotArgTag: ArrayTag[ClassfileAnnotArg] // need a precise tag to pass to UnPickle's toArray call
type LiteralAnnotArg <: ClassfileAnnotArg
val LiteralAnnotArg: LiteralAnnotArgExtractor
diff --git a/src/library/scala/reflect/api/Attachment.scala b/src/library/scala/reflect/api/Attachment.scala
new file mode 100644
index 0000000000..50f55b4aa5
--- /dev/null
+++ b/src/library/scala/reflect/api/Attachment.scala
@@ -0,0 +1,29 @@
+package scala.reflect
+package api
+
+/** Attachment is a generalisation of Position.
+ * Typically it stores a Position of a tree, but this can be extended to encompass arbitrary payloads.
+ *
+ * Attachments have to carry positions, because we don't want to introduce even a single additional field in Tree
+ * imposing an unnecessary memory tax because of something that will not be used in most cases.
+ */
+trait Attachment {
+ /** Gets the underlying position */
+ def pos: Position
+
+ /** Creates a copy of this attachment with its position updated */
+ def withPos(newPos: Position): Attachment
+
+ /** Gets the underlying payload */
+ def payload: Any
+
+ /** Creates a copy of this attachment with its payload updated */
+ def withPayload(newPayload: Any): Attachment
+}
+
+// [Eugene] with the introduction of `attach` and `attachment[T]` users don't need to create custom attachments anymore
+// however, we cannot move attachments to scala.reflect.internal, because they are used in Trees, which are implemented completely in scala.reflect.api
+private[scala] case class NontrivialAttachment(pos: api.Position, payload: collection.mutable.ListBuffer[Any]) extends Attachment {
+ def withPos(newPos: api.Position) = copy(pos = newPos, payload = payload)
+ def withPayload(newPayload: Any) = copy(pos = pos, payload = newPayload.asInstanceOf[collection.mutable.ListBuffer[Any]])
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/ClassLoaders.scala b/src/library/scala/reflect/api/ClassLoaders.scala
new file mode 100644
index 0000000000..7be402d3df
--- /dev/null
+++ b/src/library/scala/reflect/api/ClassLoaders.scala
@@ -0,0 +1,16 @@
+package scala.reflect
+package api
+
+trait ClassLoaders { self: Universe =>
+
+ /** The symbol corresponding to the globally accessible class with the
+ * given fully qualified name `fullName`.
+ */
+ def staticClass(fullName: String): Symbol
+
+ /** The symbol corresponding to the globally accessible object with the
+ * given fully qualified name `fullName`.
+ */
+ def staticModule(fullName: String): Symbol
+
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/Exprs.scala b/src/library/scala/reflect/api/Exprs.scala
new file mode 100644
index 0000000000..b8db64422e
--- /dev/null
+++ b/src/library/scala/reflect/api/Exprs.scala
@@ -0,0 +1,19 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package api
+import language.implicitConversions
+
+trait Exprs { self: Universe =>
+
+ /** An expression tree tagged with its type */
+ case class Expr[+T: TypeTag](tree: Tree) {
+ def tpe: Type = implicitly[TypeTag[T]].tpe
+ def eval: T = mkToolBox().runExpr(tree).asInstanceOf[T]
+ lazy val value: T = eval
+ override def toString = "Expr["+tpe+"]("+tree+")"
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/FreeVars.scala b/src/library/scala/reflect/api/FreeVars.scala
new file mode 100644
index 0000000000..0bef099a55
--- /dev/null
+++ b/src/library/scala/reflect/api/FreeVars.scala
@@ -0,0 +1,42 @@
+package scala.reflect
+package api
+
+trait FreeVars {
+ self: Universe =>
+
+ /** Represents a free term captured by reification.
+ */
+ type FreeTerm <: Symbol
+
+ val FreeTerm: FreeTermExtractor
+
+ abstract class FreeTermExtractor {
+ def unapply(freeTerm: FreeTerm): Option[(TermName, Type, Any, String)]
+ }
+
+ /** Extracts free terms from a tree that is reified or contains reified subtrees.
+ */
+ def freeTerms(tree: Tree): List[FreeTerm]
+
+ /** Represents a free type captured by reification.
+ */
+ type FreeType <: Symbol
+
+ val FreeType: FreeTypeExtractor
+
+ abstract class FreeTypeExtractor {
+ def unapply(freeType: FreeType): Option[(TypeName, Type, String)]
+ }
+
+ /** Extracts free types from a tree that is reified or contains reified subtrees.
+ */
+ def freeTypes(tree: Tree): List[FreeType]
+
+ /** Substitutes free types in a reified tree.
+ */
+ def substituteFreeTypes(tree: Tree, subs: Map[FreeType, Type]): Tree
+
+ /** Substitutes free types in a reified type.
+ */
+ def substituteFreeTypes(tpe: Type, subs: Map[FreeType, Type]): Type
+}
diff --git a/src/library/scala/reflect/api/FrontEnds.scala b/src/library/scala/reflect/api/FrontEnds.scala
new file mode 100644
index 0000000000..2c1f3feff6
--- /dev/null
+++ b/src/library/scala/reflect/api/FrontEnds.scala
@@ -0,0 +1,68 @@
+package scala.reflect
+package api
+
+trait FrontEnds { self: Universe =>
+
+ trait FrontEnd {
+ object severity extends Enumeration
+ class Severity(val id: Int) extends severity.Value {
+ var count: Int = 0
+ override def toString() = this match {
+ case INFO => "INFO"
+ case WARNING => "WARNING"
+ case ERROR => "ERROR"
+ case _ => "<unknown>"
+ }
+ }
+ val INFO = new Severity(0)
+ val WARNING = new Severity(1)
+ val ERROR = new Severity(2)
+
+ def hasErrors = ERROR.count > 0
+ def hasWarnings = WARNING.count > 0
+
+ case class Info(val pos: Position, val msg: String, val severity: Severity)
+ val infos = new collection.mutable.LinkedHashSet[Info]
+
+ /** Handles incoming info */
+ def log(pos: Position, msg: String, severity: Severity) {
+ infos += new Info(pos, msg, severity)
+ severity.count += 1
+ display(infos.last)
+ }
+
+ /** Displays incoming info */
+ def display(info: Info): Unit
+
+ /** Services a request to drop into interactive mode */
+ def interactive(): Unit
+
+ /** Refreshes the UI */
+ def flush(): Unit = {}
+
+ /** Resets the reporter */
+ def reset(): Unit = {
+ INFO.count = 0
+ WARNING.count = 0
+ ERROR.count = 0
+ infos.clear()
+ }
+ }
+
+ class SilentFrontEnd extends FrontEnd {
+ def display(info: Info) {}
+ def interactive() {}
+ }
+
+ /** Creates a UI-less reporter that simply accumulates all the messages
+ */
+ def mkSilentFrontEnd(): FrontEnd = new SilentFrontEnd()
+
+ /** Creates a reporter that prints messages to the console according to the settings.
+ *
+ * ``minSeverity'' determines minimum severity of the messages to be printed.
+ * 0 stands for INFO, 1 stands for WARNING and 2 stands for ERROR.
+ */
+ // todo. untangle warningsAsErrors from Reporters. I don't feel like moving this flag here!
+ def mkConsoleFrontEnd(minSeverity: Int = 1): FrontEnd
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/Importers.scala b/src/library/scala/reflect/api/Importers.scala
new file mode 100644
index 0000000000..1d8890b7db
--- /dev/null
+++ b/src/library/scala/reflect/api/Importers.scala
@@ -0,0 +1,19 @@
+package scala.reflect
+package api
+
+trait Importers { self: Universe =>
+
+ def mkImporter(from0: Universe): Importer { val from: from0.type }
+
+ trait Importer {
+ val from: Universe
+
+ val reverse: from.Importer { val from: self.type }
+
+ def importSymbol(sym: from.Symbol): Symbol
+
+ def importType(tpe: from.Type): Type
+
+ def importTree(tree: from.Tree): Tree
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/Mirror.scala b/src/library/scala/reflect/api/Mirror.scala
index cea9e1a37d..ed8ead7aaf 100644
--- a/src/library/scala/reflect/api/Mirror.scala
+++ b/src/library/scala/reflect/api/Mirror.scala
@@ -5,7 +5,22 @@ package api
* runtime entities such as class names and object instances
* with a reflexive universe.
*/
-trait Mirror extends Universe with RuntimeTypes with TreeBuildUtil {
+trait Mirror extends Universe {
+
+ /** Class loader that is a mastermind behind the reflexive mirror.
+ *
+ * By default it is set to system classloader (more precisely, to the classloader that loads the `scala.reflect.package` class).
+ * However, sometimes it is useful to have a mirror services by a custom classloader.
+ *
+ * There are two ways to customize the `classLoader`:
+ * 1) Create a new mirror using the `scala.reflect.mkMirror(classLoader: ClassLoader)` method
+ * 2) Set `classLoader` to the new value
+ *
+ * The first, immutable, way should be strongly preferred in most situation.
+ * However sometimes it is necessary to migrate the default reflexive mirror (`scala.reflect.mirror`) to a new classloader.
+ * In that and only that case, use the setter, but be very careful not to introduce inconsistencies.
+ */
+ var classLoader: ClassLoader
/** The Scala class symbol that has given fully qualified name
* @param name The fully qualified name of the class to be returned
diff --git a/src/library/scala/reflect/api/Names.scala b/src/library/scala/reflect/api/Names.scala
index c72774dfc7..96651ffa88 100755
--- a/src/library/scala/reflect/api/Names.scala
+++ b/src/library/scala/reflect/api/Names.scala
@@ -33,13 +33,13 @@ trait Names {
/** Returns a type name that represents the same string as this name */
def toTypeName: TypeName
- /** Replaces all occurrences of $op_names in this name by corresponding operator symbols.
- * Example: `foo_+=` becomes `foo_$plus$eq`.
+ /** Replaces all occurrences of \$op_names in this name by corresponding operator symbols.
+ * Example: `foo_\$plus\$eq` becomes `foo_+=`
*/
def decoded: String
- /** Replaces all occurrences of operator symbols in this name by corresponding $op_names.
- * Example: `foo_$plus$eq` becomes `foo_+=`
+ /** Replaces all occurrences of operator symbols in this name by corresponding \$op_names.
+ * Example: `foo_+=` becomes `foo_\$plus\$eq`.
*/
def encoded: String
diff --git a/src/library/scala/reflect/api/Positions.scala b/src/library/scala/reflect/api/Positions.scala
index 4c8c33bec8..8f01e0ced1 100644
--- a/src/library/scala/reflect/api/Positions.scala
+++ b/src/library/scala/reflect/api/Positions.scala
@@ -1,21 +1,202 @@
package scala.reflect
package api
-trait Positions { self: Universe =>
- /** TreeAnnotation is a generalisation of Position.
- *
- * TreeAnnotation cannot be an upperbound of Position since the corresponding classes
- * must live outside of the universe for backwards compatibility (see scala.tools.nsc.util.Position).
- * Thus, represent subtyping as coercions.
- *
- * Typically, positionToAnnotation is the identity, and annotationToPosition returns annot.pos
- */
- type TreeAnnotation // <: { def pos: Position }
- val NoTreeAnnotation: TreeAnnotation
- implicit def positionToAnnotation(pos: Position): TreeAnnotation // = pos
- def annotationToPosition(annot: TreeAnnotation): Position // = annot.pos
- def _checkSetAnnotation(tree: Tree, annot: TreeAnnotation): Unit = () // check that annot may overwrite tree.annot
-
- type Position // <: TreeAnnotation, but not practical to enforce this (would require moving Position, SourceFile, Reporter,... into the universe)
+trait Positions {
+ self: Universe =>
+
+ // [Eugene] in quite a lot of situations (mostly related to error reporting) we need positions in the API
+ // however it seems that neither runtime compilation, nor macros need facilities to create positions from scratch
+ // both emit ASTs, which can be automatically transformed into synthetic sources and assigned with synthetic positions
+ // hence I added possibilities to inspect everything we can, but add any position factories
+ // this simplified a lot of things, the biggest of them is that we don't need to expose SourceFile/AbstractFile
+ type Position <: scala.reflect.api.Position
val NoPosition: Position
-} \ No newline at end of file
+
+ /** A position that wraps a set of trees.
+ * The point of the wrapping position is the point of the default position.
+ * If some of the trees are ranges, returns a range position enclosing all ranges
+ * Otherwise returns default position.
+ */
+ def wrappingPos(default: Position, trees: List[Tree]): Position
+
+ /** A position that wraps the non-empty set of trees.
+ * The point of the wrapping position is the point of the first trees' position.
+ * If all some the trees are non-synthetic, returns a range position enclosing the non-synthetic trees
+ * Otherwise returns a synthetic offset position to point.
+ */
+ def wrappingPos(trees: List[Tree]): Position
+
+ /** Ensure that given tree has no positions that overlap with
+ * any of the positions of `others`. This is done by
+ * shortening the range or assigning TransparentPositions
+ * to some of the nodes in `tree`.
+ */
+ def ensureNonOverlapping(tree: Tree, others: List[Tree])
+
+ /** Assigns a given position to all position-less nodes of a given AST.
+ */
+ def atPos[T <: Tree](pos: Position)(tree: T): T
+}
+
+/** The Position class and its subclasses represent positions of ASTs and symbols.
+ * Except for NoPosition and FakePos, every position refers to a SourceFile
+ * and to an offset in the sourcefile (its `point`). For batch compilation,
+ * that's all. For interactive IDE's there are also RangePositions
+ * and TransparentPositions. A RangePosition indicates a start and an end
+ * in addition to its point. TransparentPositions are a subclass of RangePositions.
+ * Range positions that are not transparent are called opaque.
+ * Trees with RangePositions need to satisfy the following invariants.
+ *
+ * INV1: A tree with an offset position never contains a child
+ * with a range position
+ * INV2: If the child of a tree with a range position also has a range position,
+ * then the child's range is contained in the parent's range.
+ * INV3: Opaque range positions of children of the same node are non-overlapping
+ * (this means their overlap is at most a single point).
+ *
+ * The following tests are useful on positions:
+ *
+ * pos.isDefined true if position is not a NoPosition nor a FakePosition
+ * pos.isRange true if position is a range
+ * pos.isOpaqueRange true if position is an opaque range
+ *
+ * The following accessor methods are provided:
+ *
+ * pos.source The source file of the position, which must be defined
+ * pos.point The offset of the position's point, which must be defined
+ * pos.start The start of the position, which must be a range
+ * pos.end The end of the position, which must be a range
+ *
+ * There are also convenience methods, such as
+ *
+ * pos.startOrPoint
+ * pos.endOrPoint
+ * pos.pointOrElse(default)
+ *
+ * These are less strict about the kind of position on which they can be applied.
+ *
+ * The following conversion methods are often used:
+ *
+ * pos.focus converts a range position to an offset position, keeping its point;
+ * returns all other positions unchanged.
+ * pos.makeTransparent converts an opaque range position into a transparent one.
+ * returns all other positions unchanged.
+ */
+trait Position extends Attachment {
+
+ /** Java file corresponding to the source file of this position.
+ */
+ def fileInfo: java.io.File
+
+ /** Content of the source file that contains this position.
+ */
+ def fileContent: Array[Char]
+
+ /** Is this position neither a NoPosition nor a FakePosition?
+ * If isDefined is true, offset and source are both defined.
+ */
+ def isDefined: Boolean
+
+ /** Is this position a transparent position? */
+ def isTransparent: Boolean
+
+ /** Is this position a range position? */
+ def isRange: Boolean
+
+ /** Is this position a non-transparent range position? */
+ def isOpaqueRange: Boolean
+
+ /** if opaque range, make this position transparent */
+ def makeTransparent: Position
+
+ /** The start of the position's range, error if not a range position */
+ def start: Int
+
+ /** The start of the position's range, or point if not a range position */
+ def startOrPoint: Int
+
+ /** The point (where the ^ is) of the position */
+ def point: Int
+
+ /** The point (where the ^ is) of the position, or else `default` if undefined */
+ def pointOrElse(default: Int): Int
+
+ /** The end of the position's range, error if not a range position */
+ def end: Int
+
+ /** The end of the position's range, or point if not a range position */
+ def endOrPoint: Int
+
+ /** The same position with a different start value (if a range) */
+ def withStart(off: Int): Position
+
+ /** The same position with a different end value (if a range) */
+ def withEnd(off: Int): Position
+
+ /** The same position with a different point value (if a range or offset) */
+ def withPoint(off: Int): Position
+
+ /** If this is a range, the union with the other range, with the point of this position.
+ * Otherwise, this position
+ */
+ def union(pos: Position): Position
+
+ /** If this is a range position, the offset position of its start.
+ * Otherwise the position itself
+ */
+ def focusStart: Position
+
+ /** If this is a range position, the offset position of its point.
+ * Otherwise the position itself
+ */
+ def focus: Position
+
+ /** If this is a range position, the offset position of its end.
+ * Otherwise the position itself
+ */
+ def focusEnd: Position
+
+ /** Does this position include the given position `pos`.
+ * This holds if `this` is a range position and its range [start..end]
+ * is the same or covers the range of the given position, which may or may not be a range position.
+ */
+ def includes(pos: Position): Boolean
+
+ /** Does this position properly include the given position `pos` ("properly" meaning their
+ * ranges are not the same)?
+ */
+ def properlyIncludes(pos: Position): Boolean
+
+ /** Does this position precede that position?
+ * This holds if both positions are defined and the end point of this position
+ * is not larger than the start point of the given position.
+ */
+ def precedes(pos: Position): Boolean
+
+ /** Does this position properly precede the given position `pos` ("properly" meaning their ranges
+ * do not share a common point).
+ */
+ def properlyPrecedes(pos: Position): Boolean
+
+ /** Does this position overlap with that position?
+ * This holds if both positions are ranges and there is an interval of
+ * non-zero length that is shared by both position ranges.
+ */
+ def overlaps(pos: Position): Boolean
+
+ /** Does this position cover the same range as that position?
+ * Holds only if both position are ranges
+ */
+ def sameRange(pos: Position): Boolean
+
+ def line: Int
+
+ def column: Int
+
+ /** Convert this to a position around `point` that spans a single source line */
+ def toSingleLine: Position
+
+ def lineContent: String
+
+ def show: String
+}
diff --git a/src/library/scala/reflect/api/RequiredFile.scala b/src/library/scala/reflect/api/RequiredFile.scala
new file mode 100644
index 0000000000..4a54595940
--- /dev/null
+++ b/src/library/scala/reflect/api/RequiredFile.scala
@@ -0,0 +1,7 @@
+package scala.reflect
+package api
+
+trait RequiredFile {
+ def path: String
+ def canonicalPath: String
+}
diff --git a/src/library/scala/reflect/api/RuntimeTypes.scala b/src/library/scala/reflect/api/RuntimeTypes.scala
deleted file mode 100644
index f58b328868..0000000000
--- a/src/library/scala/reflect/api/RuntimeTypes.scala
+++ /dev/null
@@ -1,20 +0,0 @@
-package scala.reflect
-package api
-
-/** A mirror establishes connections of
- * runtime entities such as class names and object instances
- * with a refexive universe.
- */
-private[reflect] trait RuntimeTypes extends Universe {
-
- type InstanceRefSymbol >: Null <: Symbol
-
- val InstanceRefSymbol: InstanceRefSymbolExtractor
-
- private[reflect] def namedType(pre: Type, sym: Symbol, args: List[Type]): Type
-
- abstract class InstanceRefSymbolExtractor {
- def apply(value: AnyRef): InstanceRefSymbol
- def unapply(tpe: InstanceRefSymbol): Option[AnyRef]
- }
-}
diff --git a/src/library/scala/reflect/api/Scopes.scala b/src/library/scala/reflect/api/Scopes.scala
index d4e4e24f29..4a5702eadc 100755
--- a/src/library/scala/reflect/api/Scopes.scala
+++ b/src/library/scala/reflect/api/Scopes.scala
@@ -5,7 +5,12 @@ trait Scopes { self: Universe =>
type Scope <: Iterable[Symbol]
- def newScope(): Scope
-}
+ /** Create a new scope */
+ def newScope: Scope
+ /** Create a new scope nested in another one with which it shares its elements */
+ def newNestedScope(outer: Scope): Scope
+ /** Create a new scope with given initial elements */
+ def newScopeWith(elems: Symbol*): Scope
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/StandardDefinitions.scala b/src/library/scala/reflect/api/StandardDefinitions.scala
index c3d989f971..21f7c9283b 100755
--- a/src/library/scala/reflect/api/StandardDefinitions.scala
+++ b/src/library/scala/reflect/api/StandardDefinitions.scala
@@ -6,55 +6,131 @@
package scala.reflect
package api
-trait StandardDefinitions { self: Universe =>
+trait StandardTypes {
+ self: Universe =>
+
+ val ByteTpe: Type
+ val ShortTpe: Type
+ val CharTpe: Type
+ val IntTpe: Type
+ val LongTpe: Type
+ val FloatTpe: Type
+ val DoubleTpe: Type
+ val BooleanTpe: Type
+ val UnitTpe: Type
+
+ val AnyTpe: Type
+ val AnyValTpe: Type
+ val AnyRefTpe: Type
+ val ObjectTpe: Type
+
+ val NothingTpe: Type
+ val NullTpe: Type
+ val StringTpe: Type
+}
+
+trait StandardDefinitions extends StandardTypes {
+ self: Universe =>
val definitions: AbsDefinitions
- abstract class AbsDefinitions {
+ // I intend to pull everything in here out of the public API.
+ trait AbsDefinitionsInternal {
+ def ArrayModule: Symbol
+ def ArrayModule_overloadedApply: Symbol
+ def Array_apply: Symbol
+ def Array_clone: Symbol
+ def Array_length: Symbol
+ def Array_update: Symbol
+ def ByNameParamClass: Symbol
+ def ClassTagModule: Symbol
+ def ConcreteTypeTagModule: Symbol
+ def ConsClass: Symbol
+ def EmptyPackageClass: Symbol
+ def FunctionClass : Array[Symbol]
+ def IterableClass: Symbol
+ def IteratorClass: Symbol
+ def IteratorModule: Symbol
+ def Iterator_apply: Symbol
+ def JavaLangPackageClass: Symbol
+ def JavaRepeatedParamClass: Symbol
+ def ListModule: Symbol
+ def List_apply: Symbol
+ def NilModule: Symbol
+ def NoneModule: Symbol
+ def OptionClass: Symbol
+ def ProductClass : Array[Symbol]
+ def RepeatedParamClass: Symbol
+ def ScalaPackageClass: Symbol
+ def SeqClass: Symbol
+ def SeqModule: Symbol
+ def SomeClass: Symbol
+ def SomeModule: Symbol
+ def StringBuilderClass: Symbol
+ def SymbolClass : Symbol
+ def TraversableClass: Symbol
+ def TupleClass : Array[Symbol]
+ def TypeTagModule: Symbol
+ def ScalaPrimitiveValueClasses: List[ClassSymbol]
+ }
+
+ trait AbsDefinitions extends AbsDefinitionsInternal {
// packages
- def RootPackage: Symbol
- def RootClass: Symbol
- def EmptyPackage: Symbol
- def ScalaPackage: Symbol
+ def RootClass: ClassSymbol
+ def RootPackage: PackageSymbol
+ def EmptyPackage: PackageSymbol
+ def ScalaPackage: PackageSymbol
+ def JavaLangPackage: PackageSymbol
// top types
- def AnyClass : Symbol
- def AnyValClass: Symbol
- def AnyRefClass: Symbol
- def ObjectClass: Symbol
+ def AnyClass : ClassSymbol
+ def AnyValClass: ClassSymbol
+ def ObjectClass: ClassSymbol
+ def AnyRefClass: TypeSymbol
// bottom types
- def NullClass : Symbol
- def NothingClass: Symbol
+ def NullClass : ClassSymbol
+ def NothingClass: ClassSymbol
// the scala value classes
- def UnitClass : Symbol
- def ByteClass : Symbol
- def ShortClass : Symbol
- def CharClass : Symbol
- def IntClass : Symbol
- def LongClass : Symbol
- def FloatClass : Symbol
- def DoubleClass : Symbol
- def BooleanClass: Symbol
-
- // fundamental reference classes
- def SymbolClass : Symbol
- def StringClass : Symbol
- def ClassClass : Symbol
+ def UnitClass : ClassSymbol
+ def ByteClass : ClassSymbol
+ def ShortClass : ClassSymbol
+ def CharClass : ClassSymbol
+ def IntClass : ClassSymbol
+ def LongClass : ClassSymbol
+ def FloatClass : ClassSymbol
+ def DoubleClass : ClassSymbol
+ def BooleanClass: ClassSymbol
- // product, tuple, function
- def TupleClass : Array[Symbol]
- def ProductClass : Array[Symbol]
- def FunctionClass : Array[Symbol]
+ // some special classes
+ def StringClass : ClassSymbol
+ def ClassClass : ClassSymbol
+ def ArrayClass: ClassSymbol
+
+ // collections classes
+ def ListClass: ClassSymbol
+ def ListModule: ModuleSymbol
+
+ // collections modules
+ def PredefModule: ModuleSymbol
- // fundamental modules
- def PredefModule: Symbol
+ // type tags
+ def ClassTagClass: ClassSymbol
+ def TypeTagClass: ClassSymbol
+ def ConcreteTypeTagClass: ClassSymbol
/** Given a type T, returns the type corresponding to the VM's
* representation: ClassClass's type constructor applied to `arg`.
*/
def vmClassType(arg: Type): Type // !!! better name?
+ // [Eugene] we already have arg.erasure, right?
+ //
+ // [Paul] You misunderstand the method (it could be better named).
+ // Given List[String], it returns java.lang.Class[List[String]]
+ // (or the .Net equivalent), not the erasure of List[String].
+ // See def ClassType in definitions - that's what it was called before,
+ // and obviously that name has to go.
/** The string representation used by the given type in the VM.
*/
diff --git a/src/library/scala/reflect/api/StandardNames.scala b/src/library/scala/reflect/api/StandardNames.scala
index 81517d2a6b..a17ea216f7 100644
--- a/src/library/scala/reflect/api/StandardNames.scala
+++ b/src/library/scala/reflect/api/StandardNames.scala
@@ -1,21 +1,163 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2011 LAMP/EPFL
- * @author Martin Odersky
- */
+* Copyright 2005-2011 LAMP/EPFL
+* @author Martin Odersky
+*/
package scala.reflect
package api
-trait StandardNames { self: Universe =>
+trait StandardNames {
+ self: Universe =>
val nme: AbsTermNames
+ val tpnme: AbsTypeNames
+
+ trait AbsNames {
+ type NameType <: Name
+
+ val ANON_CLASS_NAME: NameType
+ val ANON_FUN_NAME: NameType
+ val EMPTY: NameType
+ val EMPTY_PACKAGE_NAME: NameType
+ val ERROR: NameType
+ val IMPORT: NameType
+ val MODULE_VAR_SUFFIX: NameType
+ val NO_NAME: NameType
+ val PACKAGE: NameType
+ val ROOT: NameType
+ val SPECIALIZED_SUFFIX: NameType
+ val WILDCARD: NameType
+
+ def flattenedName(segments: Name*): NameType
+ }
+
+ trait AbsTermNames extends AbsNames {
+ val EXPAND_SEPARATOR_STRING: String
+ val IMPL_CLASS_SUFFIX: String
+ val INTERPRETER_IMPORT_WRAPPER: String
+ val INTERPRETER_LINE_PREFIX: String
+ val INTERPRETER_VAR_PREFIX: String
+ val INTERPRETER_WRAPPER_SUFFIX: String
+ val LOCALDUMMY_PREFIX: String
+ val LOCAL_SUFFIX_STRING: String
+ val MODULE_SUFFIX_NAME: TermName
+ val NAME_JOIN_NAME: TermName
+ val PROTECTED_PREFIX: String
+ val PROTECTED_SET_PREFIX: String
+ val SETTER_SUFFIX: TermName
+ val SINGLETON_SUFFIX: String
+ val SUPER_PREFIX_STRING: String
+ val TRAIT_SETTER_SEPARATOR_STRING: String
- abstract class AbsTermNames {
+ val ANYNAME: TermName
val CONSTRUCTOR: TermName
+ val FAKE_LOCAL_THIS: TermName
+ val INITIALIZER: TermName
+ val LAZY_LOCAL: TermName
+ val MIRROR_FREE_PREFIX: TermName
+ val MIRROR_FREE_THIS_SUFFIX: TermName
+ val MIRROR_FREE_VALUE_SUFFIX: TermName
+ val MIRROR_PREFIX: TermName
+ val MIRROR_SHORT: TermName
+ val MIRROR_SYMDEF_PREFIX: TermName
+ val MIXIN_CONSTRUCTOR: TermName
+ val MODULE_INSTANCE_FIELD: TermName
+ val OUTER: TermName
+ val OUTER_LOCAL: TermName
+ val OUTER_SYNTH: TermName
+ val SELECTOR_DUMMY: TermName
+ val SELF: TermName
+ val SPECIALIZED_INSTANCE: TermName
+ val STAR: TermName
+ val THIS: TermName
+
+ val BITMAP_NORMAL: TermName
+ val BITMAP_TRANSIENT: TermName
+ val BITMAP_CHECKINIT: TermName
+ val BITMAP_CHECKINIT_TRANSIENT: TermName
+
+ val ROOTPKG: TermName
+
+ val ADD: TermName
+ val AND: TermName
+ val ASR: TermName
+ val DIV: TermName
+ val EQ: TermName
+ val EQL: TermName
+ val GE: TermName
+ val GT: TermName
+ val HASHHASH: TermName
+ val LE: TermName
+ val LSL: TermName
+ val LSR: TermName
+ val LT: TermName
+ val MINUS: TermName
+ val MOD: TermName
+ val MUL: TermName
+ val NE: TermName
+ val OR: TermName
+ val PLUS : TermName
+ val SUB: TermName
+ val XOR: TermName
+ val ZAND: TermName
+ val ZOR: TermName
+
+ val UNARY_~ : TermName
+ val UNARY_+ : TermName
+ val UNARY_- : TermName
+ val UNARY_! : TermName
+
+ val ??? : TermName
+
+ def isConstructorName(name: Name): Boolean
+ def isExceptionResultName(name: Name): Boolean
+ def isImplClassName(name: Name): Boolean
+ def isLocalDummyName(name: Name): Boolean
+ def isLocalName(name: Name): Boolean
+ def isLoopHeaderLabel(name: Name): Boolean
+ def isModuleName(name: Name): Boolean
+ def isOpAssignmentName(name: Name): Boolean
+ def isProtectedAccessorName(name: Name): Boolean
+ def isReplWrapperName(name: Name): Boolean
+ def isSetterName(name: Name): Boolean
+ def isSingletonName(name: Name): Boolean
+ def isSuperAccessorName(name: Name): Boolean
+ def isTraitSetterName(name: Name): Boolean
+
+ def defaultGetterName(name: Name, pos: Int): TermName
+ def defaultGetterToMethod(name: Name): TermName
+ def expandedName(name: TermName, base: Symbol, separator: String): TermName
+ def expandedSetterName(name: TermName, base: Symbol): TermName
+ def getterName(name: TermName): TermName
+ def getterToLocal(name: TermName): TermName
+ def getterToSetter(name: TermName): TermName
+ def localDummyName(clazz: Symbol): TermName
+ def localToGetter(name: TermName): TermName
+ def protName(name: Name): TermName
+ def protSetterName(name: Name): TermName
+ def setterToGetter(name: TermName): TermName
+ def superName(name: Name): TermName
+
+ def dropLocalSuffix(name: Name): Name
+ def originalName(name: Name): Name
+ def stripModuleSuffix(name: Name): Name
+ def unspecializedName(name: Name): Name
+ def segments(name: String, assumeTerm: Boolean): List[Name]
+ def splitSpecializedName(name: Name): (Name, String, String)
}
- val tpnme: AbsTypeNames
+ trait AbsTypeNames extends AbsNames {
+ val BYNAME_PARAM_CLASS_NAME: TypeName
+ val EQUALS_PATTERN_NAME: TypeName
+ val JAVA_REPEATED_PARAM_CLASS_NAME: TypeName
+ val LOCAL_CHILD: TypeName
+ val REFINE_CLASS_NAME: TypeName
+ val REPEATED_PARAM_CLASS_NAME: TypeName
+ val WILDCARD_STAR: TypeName
- abstract class AbsTypeNames {
+ def dropSingletonName(name: Name): TypeName
+ def implClassName(name: Name): TypeName
+ def interfaceName(implname: Name): TypeName
+ def singletonName(name: Name): TypeName
}
}
diff --git a/src/library/scala/reflect/api/Symbols.scala b/src/library/scala/reflect/api/Symbols.scala
index 44dc2ce1c2..32faee2512 100755
--- a/src/library/scala/reflect/api/Symbols.scala
+++ b/src/library/scala/reflect/api/Symbols.scala
@@ -4,8 +4,105 @@ package api
trait Symbols { self: Universe =>
type Symbol >: Null <: AbsSymbol
+ type TypeSymbol <: Symbol with TypeSymbolApi
+ type TermSymbol <: Symbol with TermSymbolApi
+ type MethodSymbol <: TermSymbol with MethodSymbolApi
+ type ModuleSymbol <: TermSymbol with ModuleSymbolApi
+ type PackageSymbol <: ModuleSymbol with PackageSymbolApi
+ type ClassSymbol <: TypeSymbol with ClassSymbolApi
- abstract class AbsSymbol { this: Symbol =>
+ val NoSymbol: Symbol
+
+ trait TypeSymbolApi {
+ self: TypeSymbol =>
+
+ def name: TypeName
+ }
+ trait TermSymbolApi {
+ self: TermSymbol =>
+
+ def name: TermName
+ }
+ trait MethodSymbolApi extends TermSymbolApi {
+ self: MethodSymbol =>
+ }
+ trait ClassSymbolApi extends TypeSymbolApi {
+ self: ClassSymbol =>
+ }
+ trait ModuleSymbolApi extends TermSymbolApi {
+ self: ModuleSymbol =>
+ }
+ trait PackageSymbolApi extends ModuleSymbolApi {
+ self: PackageSymbol =>
+ }
+
+ // I intend to pull everything in here out of the public API.
+ trait AbsSymbolInternal {
+ this: Symbol =>
+
+ /** A fresh symbol with given name `name`, position `pos` and flags `flags` that has
+ * the current symbol as its owner.
+ */
+ def newNestedSymbol(name: Name, pos: Position, flags: Long, isClass: Boolean): Symbol
+ // needed by LiftCode !!! not enough reason to have in the api
+
+ /** Low-level operation to set the symbol's flags
+ * @return the symbol itself
+ */
+ def setInternalFlags(flags: Long): this.type
+ // needed by LiftCode !!! not enough reason to have in the api
+
+ /** Set symbol's type signature to given type
+ * @return the symbol itself
+ */
+ def setTypeSignature(tpe: Type): this.type
+ // needed by LiftCode !!! not enough reason to have in the api
+
+ /** Set symbol's annotations to given annotations `annots`.
+ */
+ def setAnnotations(annots: AnnotationInfo*): this.type
+ // needed by LiftCode !!! not enough reason to have in the api
+
+ /** Does this symbol represent the definition of a skolem?
+ * Skolems are used during typechecking to represent type parameters viewed from inside their scopes.
+ * If yes, `isType` is also guaranteed to be true.
+ */
+ def isSkolem : Boolean
+
+ /** Does this symbol represent a free type captured by reification?
+ */
+ // needed for ones who wish to inspect reified trees
+ def isFreeType : Boolean
+
+ /** The type signature of this symbol.
+ * Note if the symbol is a member of a class, one almost always is interested
+ * in `typeSignatureIn` with a site type instead.
+ */
+ def typeSignature: Type // !!! Since one should almost never use this, let's give it a different name.
+
+ /** A type reference that refers to this type symbol
+ * Note if symbol is a member of a class, one almost always is interested
+ * in `asTypeIn` with a site type instead.
+ *
+ * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
+ * `C`. Then `C.asType` is the type `C[T]`.
+ *
+ * By contrast, `C.typeSignature` would be a type signature of form
+ * `PolyType(ClassInfoType(...))` that describes type parameters, value
+ * parameters, parent types, and members of `C`.
+ */
+ def asType: Type // !!! Same as typeSignature.
+
+ /** The kind of this symbol; used for debugging */
+ def kind: String
+ }
+
+ trait AbsSymbol extends AbsSymbolInternal {
+ this: Symbol =>
+
+ /** The position of this symbol
+ */
+ def pos: Position
/** The modifiers of this symbol
*/
@@ -47,6 +144,18 @@ trait Symbols { self: Universe =>
/** An id number which is unique for all symbols in this universe */
def id: Int
+ /** ...
+ */
+ def orElse(alt: => Symbol): Symbol
+
+ /** ...
+ */
+ def filter(cond: Symbol => Boolean): Symbol
+
+ /** ...
+ */
+ def suchThat(cond: Symbol => Boolean): Symbol
+
/**
* Set when symbol has a modifier of the form private[X], NoSymbol otherwise.
*
@@ -112,6 +221,25 @@ trait Symbols { self: Universe =>
*/
def isTerm : Boolean
+ /** Does this symbol represent a package?
+ * If yes, `isTerm` is also guaranteed to be true.
+ */
+ def isPackage : Boolean
+
+ /** Does this symbol represent the definition of method?
+ * If yes, `isTerm` is also guaranteed to be true.
+ */
+ def isMethod : Boolean
+
+ /** Is this symbol an overloaded method?
+ */
+ def isOverloaded : Boolean
+
+ /** Does this symbol represent a free term captured by reification?
+ */
+ // needed for ones who wish to inspect reified trees
+ def isFreeTerm : Boolean
+
/** Does this symbol represent the definition of type?
* Note that every symbol is either a term or a type.
* So for every symbol `sym`, either `sym.isTerm` is true
@@ -124,6 +252,22 @@ trait Symbols { self: Universe =>
*/
def isClass : Boolean
+ /** Does this symbol represent a package class?
+ * If yes, `isClass` is also guaranteed to be true.
+ */
+ def isPackageClass : Boolean
+
+ /** Does this symbol represent the definition of a primitive class?
+ * Namely, is it one of [[scala.Double]], [[scala.Float]], [[scala.Long]], [[scala.Int]], [[scala.Char]],
+ * [[scala.Short]], [[scala.Byte]], [[scala.Unit]] or [[scala.Boolean]]?
+ */
+ def isPrimitiveValueClass: Boolean
+
+ /** Does this symbol represent the definition of a custom value class?
+ * Namely, is AnyVal among its parent classes?
+ */
+ def isDerivedValueClass: Boolean
+
/** Does this symbol represent the definition of a type alias?
* If yes, `isType` is also guaranteed to be true.
*/
@@ -134,28 +278,26 @@ trait Symbols { self: Universe =>
*/
def isAbstractType : Boolean
- /** The type signature of this symbol.
- * Note if the symbol is a member of a class, one almost always is interested
- * in `typeSignatureIn` with a site type instead.
+ /** Does this symbol represent an existentially bound type?
+ * If yes, `isType` is also guaranteed to be true.
*/
- def typeSignature: Type // !!! Since one should almost never use this, let's give it a different name.
+ def isExistential : Boolean
- /** The type signature of this symbol seen as a member of given type `site`.
+ /** Is the type parameter represented by this symbol contravariant?
*/
- def typeSignatureIn(site: Type): Type
+ def isContravariant : Boolean
- /** A type reference that refers to this type symbol
- * Note if symbol is a member of a class, one almost always is interested
- * in `asTypeIn` with a site type instead.
- *
- * Example: Given a class declaration `class C[T] { ... } `, that generates a symbol
- * `C`. Then `C.asType` is the type `C[T]`.
- *
- * By contrast, `C.typeSignature` would be a type signature of form
- * `PolyType(ClassInfoType(...))` that describes type parameters, value
- * parameters, parent types, and members of `C`.
+ /** Is the type parameter represented by this symbol contravariant?
+ */
+ def isCovariant : Boolean
+
+ /** Does this symbol or its underlying type represent a typechecking error?
+ */
+ def isErroneous : Boolean
+
+ /** The type signature of this symbol seen as a member of given type `site`.
*/
- def asType: Type // !!! Same as typeSignature.
+ def typeSignatureIn(site: Type): Type
/** A type reference that refers to this type symbol seen
* as a member of given type `site`.
@@ -180,25 +322,9 @@ trait Symbols { self: Universe =>
*/
def selfType: Type
- /** A fresh symbol with given name `name`, position `pos` and flags `flags` that has
- * the current symbol as its owner.
- */
- def newNestedSymbol(name: Name, pos: Position, flags: Long): Symbol // needed by LiftCode
+ /** The overloaded alternatives of this symbol */
+ def alternatives: List[Symbol]
- /** Low-level operation to set the symbol's flags
- * @return the symbol itself
- */
- def setInternalFlags(flags: Long): this.type // needed by LiftCode !!! not enough reason to have in the api
-
- /** Set symbol's type signature to given type
- * @return the symbol itself
- */
- def setTypeSignature(tpe: Type): this.type // needed by LiftCode !!! not enough reason to have in the api
-
- /** Set symbol's annotations to given annotations `annots`.
- */
- def setAnnotations(annots: AnnotationInfo*): this.type // needed by LiftCode !!! not enough reason to have in the api
+ def resolveOverloaded(pre: Type = NoPrefix, targs: Seq[Type] = List(), actuals: Seq[Type]): Symbol
}
-
- val NoSymbol: Symbol
}
diff --git a/src/library/scala/reflect/api/ToolBoxes.scala b/src/library/scala/reflect/api/ToolBoxes.scala
new file mode 100644
index 0000000000..aefd6b511c
--- /dev/null
+++ b/src/library/scala/reflect/api/ToolBoxes.scala
@@ -0,0 +1,90 @@
+package scala.reflect
+package api
+
+trait ToolBoxes { self: Universe =>
+
+ type ToolBox <: AbsToolBox
+
+ def mkToolBox(frontEnd: FrontEnd = mkSilentFrontEnd(), options: String = ""): AbsToolBox
+
+ // [Eugene] what do you think about the interface? namely about the ``freeTypes'' part.
+ trait AbsToolBox {
+
+ /** Front end of the toolbox.
+ *
+ * Accumulates and displays warnings and errors, can drop to interactive mode (if supported).
+ * The latter can be useful to study the typechecker or to debug complex macros.
+ */
+ def frontEnd: FrontEnd
+
+ /** Typechecks a tree using this ToolBox.
+ * This populates symbols and types of the tree and possibly transforms it to reflect certain desugarings.
+ *
+ * If the tree has unresolved type variables (represented as instances of ``FreeType'' symbols),
+ * then they might, might be partially or might not be specified in the ``freeTypes'' parameter.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Ydebug.
+ *
+ * Typechecking can be steered with the following optional parameters:
+ * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false
+ * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false
+ */
+ def typeCheck(tree: Tree, pt: Type = WildcardType, freeTypes: Map[FreeType, Type] = Map[FreeType, Type](), silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree
+
+ /** Infers an implicit value of the expected type ``pt'' in the macro callsite context.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false): Tree
+
+ /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context.
+ *
+ * Otional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported.
+ * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true): Tree
+
+ /** Recursively resets symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetAllAttrs[T <: Tree](tree: T): T
+
+ /** Recursively resets locally defined symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetLocalAttrs[T <: Tree](tree: T): T
+
+ /** Compiles and runs a tree using this ToolBox.
+ *
+ * If the tree has unresolved type variables (represented as instances of ``FreeType'' symbols),
+ * then they all have to be specified in the ``freeTypes'' parameter or an error occurs.
+ *
+ * This spawns the compiler at the Namer phase, and pipelines the tree through that compiler.
+ * Currently ``runExpr'' does not accept trees that already typechecked, because typechecking isn't idempotent.
+ * For more info, take a look at https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def runExpr(tree: Tree, freeTypes: Map[FreeType, Type] = Map[FreeType, Type]()): Any
+
+ /** Represents an error during toolboxing
+ */
+ type ToolBoxError <: Throwable
+ val ToolBoxError: ToolBoxErrorExtractor
+ abstract class ToolBoxErrorExtractor {
+ def unapply(error: ToolBoxError): Option[(ToolBox, String)]
+ }
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/api/TreeBuildUtil.scala b/src/library/scala/reflect/api/TreeBuildUtil.scala
index f28008bc21..87790b3812 100644
--- a/src/library/scala/reflect/api/TreeBuildUtil.scala
+++ b/src/library/scala/reflect/api/TreeBuildUtil.scala
@@ -1,46 +1,159 @@
-package scala.reflect.api
+package scala.reflect
+package api
-trait TreeBuildUtil extends Universe {
+trait TreeBuildUtil { self: Universe =>
- /** The symbol corresponding to the globally accessible class with the
- * given fully qualified name `fullName`.
+ /** The symbol corresponding to the globally accessible class with the given fully qualified name `fullName`.
+ * Unlike `staticClassIfDefined`, throws `MissingRequirementError` is requested class cannot be found.
*/
def staticClass(fullName: String): Symbol
- /** The symbol corresponding to the globally accessible object with the
- * given fully qualified name `fullName`.
+ /** The symbol corresponding to the globally accessible class with the given fully qualified name `fullName`.
+ * Unlike `staticClass`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested class cannot be found.
+ */
+ def staticClassIfDefined(fullName: String): Symbol
+
+ /** The symbol corresponding to the globally accessible object with the given fully qualified name `fullName`.
+ * Unlike `staticModuleIfDefined`, throws `MissingRequirementError` is requested object cannot be found.
*/
def staticModule(fullName: String): Symbol
+ /** The symbol corresponding to the globally accessible object with the given fully qualified name `fullName`.
+ * Unlike `staticModule`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested object cannot be found.
+ */
+ def staticModuleIfDefined(fullName: String): Symbol
+
/** The this-ptype of the globally accessible object with the
* given fully qualified name `fullName`.
*/
def thisModuleType(fullName: String): Type
/** Selects type symbol with given simple name `name` from the defined members of `owner`.
+ * Unlike `selectTypeIfDefined`, throws `MissingRequirementError` is requested type symbol cannot be found.
*/
def selectType(owner: Symbol, name: String): Symbol
+ /** Selects type symbol with given simple name `name` from the defined members of `owner`.
+ * Unlike `selectType`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested type symbol cannot be found.
+ */
+ def selectTypeIfDefined(owner: Symbol, name: String): Symbol
+
/** Selects term symbol with given name and type from the defined members of prefix type
- * @pre The prefix type
- * @name The name of the selected member
+ * Unlike `selectTermIfDefined`, throws `MissingRequirementError` is requested term symbol cannot be found.
*/
def selectTerm(owner: Symbol, name: String): Symbol
- def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol
+ /** Selects term symbol with given name and type from the defined members of prefix type
+ * Unlike `selectTerm`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested term symbol cannot be found.
+ */
+ def selectTermIfDefined(owner: Symbol, name: String): Symbol
- def selectParam(owner: Symbol, idx: Int): Symbol
+ /** Selects overloaded method symbol with given name and index
+ * Unlike `selectOverloadedMethodIfDefined`, throws `MissingRequirementError` is requested overloaded method cannot be found.
+ */
+ def selectOverloadedMethod(owner: Symbol, name: String, index: Int): Symbol
- def newScopeWith(decls: Symbol*): Scope
+ /** Selects overloaded method symbol with given name and index
+ * Unlike `selectOverloadedMethod`, doesn't throw `MissingRequirementError` (returns NoSymbol) is requested overloaded method cannot be found.
+ */
+ def selectOverloadedMethodIfDefined(owner: Symbol, name: String, index: Int): Symbol
- /** Create a fresh free variable symbol.
+ /** Create a fresh free term symbol.
* @param name the name of the free variable
- * @param tsig the type signature of the free variable
+ * @param info the type signature of the free variable
* @param value the value of the free variable at runtime
+ * @param flags (optional) flags of the free variable
+ * @param origin debug information that tells where this symbol comes from
+ */
+ def newFreeTerm(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol
+
+ /** Create a fresh free non-existential type symbol.
+ * @param name the name of the free variable
+ * @param info the type signature of the free variable
+ * @param value a type tag that captures the value of the free variable
+ * is completely phantom, since the captured type cannot be propagated to the runtime
+ * if it could be, we wouldn't be creating a free type to begin with
+ * the only usage for it is preserving the captured symbol for compile-time analysis
+ * @param flags (optional) flags of the free variable
+ * @param origin debug information that tells where this symbol comes from
*/
- def newFreeVar(name: String, info: Type, value: Any): Symbol
+ def newFreeType(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol
+
+ /** Create a fresh free existential type symbol.
+ * @param name the name of the free variable
+ * @param info the type signature of the free variable
+ * @param value a type tag that captures the value of the free variable
+ * is completely phantom, since the captured type cannot be propagated to the runtime
+ * if it could be, we wouldn't be creating a free type to begin with
+ * the only usage for it is preserving the captured symbol for compile-time analysis
+ * @param flags (optional) flags of the free variable
+ * @param origin (optional) debug information that tells where this symbol comes from
+ */
+ def newFreeExistential(name: String, info: Type, value: => Any, flags: Long = 0L, origin: String = null): Symbol
/** Create a Modiiers structure given internal flags, qualifier, annotations */
def modifiersFromInternalFlags(flags: Long, privateWithin: Name, annotations: List[Tree]): Modifiers
-} \ No newline at end of file
+ val gen: TreeGen { val global: TreeBuildUtil.this.type }
+
+ type TreeGen <: AbsTreeGen
+}
+
+// [Eugene to Paul] we need to expose some of the functionality provided by TreeGen
+// I added some stuff that was necessary for typetag materialization macros
+// but we should think it over and pick other generally useful stuff
+// same goes for tree traversers/transformers, type maps, etc
+// and once we expose all that, there's another question: how do we stay in sync?
+trait AbsTreeGen {
+ val global: Universe
+
+ import global._
+ import definitions._
+
+ /** Builds a reference to value whose type is given stable prefix.
+ * The type must be suitable for this. For example, it
+ * must not be a TypeRef pointing to an abstract type variable.
+ */
+ def mkAttributedQualifier(tpe: Type): Tree
+
+ /** Builds a reference to value whose type is given stable prefix.
+ * If the type is unsuitable, e.g. it is a TypeRef for an
+ * abstract type variable, then an Ident will be made using
+ * termSym as the Ident's symbol. In that case, termSym must
+ * not be NoSymbol.
+ */
+ def mkAttributedQualifier(tpe: Type, termSym: Symbol): Tree
+
+ /** Builds a typed reference to given symbol with given stable prefix. */
+ def mkAttributedRef(pre: Type, sym: Symbol): Tree
+
+ /** Builds a typed reference to given symbol. */
+ def mkAttributedRef(sym: Symbol): Tree
+
+ /** Builds a typed This reference to given symbol. */
+ def mkAttributedThis(sym: Symbol): Tree
+
+ /** Builds a typed Ident with an underlying symbol. */
+ def mkAttributedIdent(sym: Symbol): Tree
+
+ /** Builds a typed Select with an underlying symbol. */
+ def mkAttributedSelect(qual: Tree, sym: Symbol): Tree
+
+ /** A creator for method calls, e.g. fn[T1, T2, ...](v1, v2, ...)
+ * There are a number of variations.
+ *
+ * @param receiver symbol of the method receiver
+ * @param methodName name of the method to call
+ * @param targs type arguments (if Nil, no TypeApply node will be generated)
+ * @param args value arguments
+ * @return the newly created trees.
+ */
+ def mkMethodCall(receiver: Symbol, methodName: Name, targs: List[Type], args: List[Tree]): Tree
+ def mkMethodCall(method: Symbol, targs: List[Type], args: List[Tree]): Tree
+ def mkMethodCall(method: Symbol, args: List[Tree]): Tree
+ def mkMethodCall(target: Tree, args: List[Tree]): Tree
+ def mkMethodCall(receiver: Symbol, methodName: Name, args: List[Tree]): Tree
+ def mkMethodCall(receiver: Tree, method: Symbol, targs: List[Type], args: List[Tree]): Tree
+ def mkMethodCall(target: Tree, targs: List[Type], args: List[Tree]): Tree
+ def mkNullaryCall(method: Symbol, targs: List[Type]): Tree
+}
diff --git a/src/library/scala/reflect/api/TreePrinters.scala b/src/library/scala/reflect/api/TreePrinters.scala
index 43865915d3..3d64ec8e40 100644
--- a/src/library/scala/reflect/api/TreePrinters.scala
+++ b/src/library/scala/reflect/api/TreePrinters.scala
@@ -29,17 +29,21 @@ trait TreePrinters { self: Universe =>
def newTreePrinter(out: PrintWriter): TreePrinter
// emits more or less verbatim representation of the provided tree
- // todo. when LiftCode becomes a macro, throw this code away and use that macro
class RawTreePrinter(out: PrintWriter) extends TreePrinter {
+ val EmptyValDef = self.emptyValDef
def print(args: Any*): Unit = args foreach {
case EmptyTree =>
print("EmptyTree")
+ case EmptyValDef =>
+ print("emptyValDef")
case tree @ TypeTree() =>
print("TypeTree()")
if (tree.tpe != null)
print(".setType(", tree.tpe, ")")
else if (tree.original != null)
print(".setOriginal(", tree.original, ")")
+ case Literal(Constant(s: String)) =>
+ print("Literal(Constant(\"" + s + "\"))")
case tree: Tree =>
print(tree.printingPrefix+"(")
val it = tree.productIterator
diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala
index 4ee13adf52..ca4e60f3f6 100644
--- a/src/library/scala/reflect/api/Trees.scala
+++ b/src/library/scala/reflect/api/Trees.scala
@@ -14,6 +14,10 @@ trait Trees { self: Universe =>
private[scala] var nodeCount = 0
type Modifiers >: Null <: AbsModifiers
+ val NoMods: Modifiers
+
+ // TODO - Where do I put this?
+ object BackquotedIdentifier
abstract class AbsModifiers {
def modifiers: Set[Modifier]
@@ -80,24 +84,65 @@ trait Trees { self: Universe =>
*/
def printingPrefix = productPrefix
- def pos: Position = annotationToPosition(rawannot)
- def pos_=(pos: Position): Unit = annotation = pos
+ def pos: Position = rawatt.pos.asInstanceOf[Position] // [Eugene] how do we get rid of this cast?
+ def pos_=(pos: Position): Unit = rawatt = (rawatt withPos pos) // the "withPos" part is crucial to robustness
def setPos(newpos: Position): this.type = { pos = newpos; this }
- private[this] var rawannot: TreeAnnotation = NoTreeAnnotation
- def annotation: TreeAnnotation = rawannot
- def annotation_=(annot: TreeAnnotation): Unit = {
- _checkSetAnnotation(this, annot)
- rawannot = annot
- }
+ // [Eugene] can we make this more type-safe
+ private var rawatt: Attachment = NoPosition
+ def attach(att: Any): Unit =
+ rawatt match {
+ case NontrivialAttachment(pos, payload) =>
+ val index = payload.indexWhere(p => p.getClass == att.getClass)
+ if (index == -1) payload += att
+ else payload(index) = att
+ case _ =>
+ rawatt = NontrivialAttachment(pos, collection.mutable.ListBuffer[Any](att))
+ }
- def setAnnotation(annot: TreeAnnotation): this.type = { annotation = annot; this }
+ // a) why didn't this method already exist
+ // b) what is all this "Any" business?
+ // c) am I reverse-engineering this correctly? It shouldn't be hard
+ // to figure out what is attached.
+ def attachments: List[Any] = rawatt match {
+ case NoPosition => Nil
+ case NontrivialAttachment(pos, atts) => pos :: atts.toList
+ case x => List(x)
+ }
+ // Writing "Any" repeatedly to work within this structure
+ // is making my skin crawl.
+ def hasAttachment(x: Any) = attachments contains x
+
+ def withAttachment(att: Any): this.type = { attach(att); this }
+ def detach(att: Any): Unit =
+ detach(att.getClass)
+ def detach(clazz: java.lang.Class[_]): Unit =
+ rawatt match {
+ case NontrivialAttachment(pos, payload) =>
+ val index = payload.indexWhere(p => p.getClass == clazz)
+ if (index != -1) payload.remove(index)
+ case _ =>
+ // do nothing
+ }
+ def withoutAttachment(att: Any): this.type = { detach(att); this }
+ def attachment[T: ClassTag]: T = attachmentOpt[T] getOrElse { throw new Error("no attachment of type %s".format(classTag[T].erasure)) }
+ def attachmentOpt[T: ClassTag]: Option[T] =
+ firstAttachment { case attachment if attachment.getClass == classTag[T].erasure => attachment.asInstanceOf[T] }
+
+ def firstAttachment[T](p: PartialFunction[Any, T]): Option[T] =
+ rawatt match {
+ case NontrivialAttachment(pos, payload) => payload.collectFirst(p)
+ case _ => None
+ }
private[this] var rawtpe: Type = _
def tpe = rawtpe
def tpe_=(t: Type) = rawtpe = t
+ def resetType(): this.type = { tpe = null ; this }
+ def resetSymbol(): this.type = { if (hasSymbol) symbol = NoSymbol ; this }
+
/** Set tpe to give `tp` and return this.
*/
def setType(tp: Type): this.type = { rawtpe = tp; this }
@@ -108,7 +153,7 @@ trait Trees { self: Universe =>
* @PP: Attempting to elaborate on the above, I find: If defineType
* is called on a TypeTree whose type field is null or NoType,
* this is recorded as "wasEmpty = true". That value is used in
- * ResetAttrsTraverser, which nulls out the type field of TypeTrees
+ * ResetAttrs, which nulls out the type field of TypeTrees
* for which wasEmpty is true, leaving the others alone.
*
* resetAllAttrs is used in situations where some speculative
@@ -143,8 +188,14 @@ trait Trees { self: Universe =>
def hasSymbol = false
def isDef = false
def isEmpty = false
+ @inline final def orElse(alt: => Tree) = if (!isEmpty) this else alt
+ @inline final def andAlso(f: Tree => Unit): Tree = { if (!this.isEmpty) f(this) ; this }
- def hasSymbolWhich(f: Symbol => Boolean) = hasSymbol && f(symbol)
+ def hasAssignedType = (tpe ne null) && (tpe ne NoType)
+ def hasAssignedSymbol = (symbol ne null) && (symbol ne NoSymbol)
+
+ @inline final def hasSymbolWhich(f: Symbol => Boolean) = hasAssignedSymbol && f(symbol)
+ @inline final def hasTypeWhich(f: Type => Boolean) = hasAssignedType && f(tpe)
/** The canonical way to test if a Tree represents a term.
*/
@@ -179,6 +230,13 @@ trait Trees { self: Universe =>
}
def filter(f: Tree => Boolean): List[Tree] = withFilter(f)
+ /** Apply `pf' to each subtree on which the function is defined */
+ def collect[T](pf: PartialFunction[Tree, T]): List[T] = {
+ val ctt = new CollectTreeTraverser[T](pf)
+ ctt.traverse(this)
+ ctt.results.toList
+ }
+
/** Returns optionally first tree (in a preorder traversal) which satisfies predicate `p`,
* or None if none exists.
*/
@@ -188,9 +246,12 @@ trait Trees { self: Universe =>
ft.result
}
- /** Is there part of this tree which satisfies predicate `p`? */
+ /** Is there exists a part of this tree which satisfies predicate `p`? */
def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty
+ /** Do all parts of this tree satisfy predicate `p`? */
+ def forAll(p: Tree => Boolean): Boolean = find(!p(_)).isEmpty
+
def equalsStructure(that : Tree) = equalsStructure0(that)(_ eq _)
def equalsStructure0(that: Tree)(f: (Tree,Tree) => Boolean): Boolean =
f(this, that) || ((this.productArity == that.productArity) && {
@@ -230,7 +291,7 @@ trait Trees { self: Universe =>
duplicateTree(this).asInstanceOf[this.type]
private[scala] def copyAttrs(tree: Tree): this.type = {
- annotation = tree.annotation
+ rawatt = tree.rawatt
tpe = tree.tpe
if (hasSymbol) symbol = tree.symbol
this
@@ -258,18 +319,24 @@ trait Trees { self: Universe =>
override var symbol: Symbol = NoSymbol
}
+ /** A tree with a name - effectively, a DefTree or RefTree.
+ */
+ trait NameTree extends Tree {
+ def name: Name
+ }
+
/** A tree which references a symbol-carrying entity.
* References one, as opposed to defining one; definitions
* are in DefTrees.
*/
- trait RefTree extends SymTree {
+ trait RefTree extends SymTree with NameTree {
def qualifier: Tree // empty for Idents
def name: Name
}
/** A tree which defines a symbol-carrying entity.
*/
- abstract class DefTree extends SymTree {
+ abstract class DefTree extends SymTree with NameTree {
def name: Name
override def isDef = true
}
@@ -282,6 +349,7 @@ trait Trees { self: Universe =>
override def tpe_=(t: Type) =
if (t != NoType) throw new UnsupportedOperationException("tpe_=("+t+") inapplicable for <empty>")
override def isEmpty = true
+ override def resetType(): this.type = this
}
/** Common base class for all member definitions: types, classes,
@@ -298,7 +366,6 @@ trait Trees { self: Universe =>
case ValDef(mods, _, _, _) => if (mods hasModifier Modifier.mutable) "var" else "val"
case _ => ""
}
- // final def hasFlag(mask: Long): Boolean = mods hasFlag mask
}
/** A packaging, such as `package pid { stats }`
@@ -320,12 +387,23 @@ trait Trees { self: Universe =>
case class ClassDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], impl: Template)
extends ImplDef
+ /** @param sym the class symbol
+ * @return the implementation template
+ */
+ def ClassDef(sym: Symbol, impl: Template): ClassDef
+
/** An object definition, e.g. `object Foo`. Internally, objects are
* quite frequently called modules to reduce ambiguity.
*/
case class ModuleDef(mods: Modifiers, name: TermName, impl: Template)
extends ImplDef
+ /**
+ * @param sym the class symbol
+ * @param impl the implementation template
+ */
+ def ModuleDef(sym: Symbol, impl: Template): ModuleDef
+
/** A common base class for ValDefs and DefDefs.
*/
abstract class ValOrDefDef extends MemberDef {
@@ -344,17 +422,37 @@ trait Trees { self: Universe =>
*/
case class ValDef(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree) extends ValOrDefDef
+ def ValDef(sym: Symbol, rhs: Tree): ValDef
+
+ def ValDef(sym: Symbol): ValDef
+
/** A method or macro definition.
* @param name The name of the method or macro. Can be a type name in case this is a type macro
*/
case class DefDef(mods: Modifiers, name: Name, tparams: List[TypeDef],
vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree) extends ValOrDefDef
+ def DefDef(sym: Symbol, mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, vparamss: List[List[ValDef]], rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, mods: Modifiers, rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, rhs: Tree): DefDef
+
+ def DefDef(sym: Symbol, rhs: List[List[Symbol]] => Tree): DefDef
+
/** An abstract type, a type parameter, or a type alias.
*/
case class TypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree)
extends MemberDef
+ /** A TypeDef node which defines given `sym` with given tight hand side `rhs`. */
+ def TypeDef(sym: Symbol, rhs: Tree): TypeDef
+
+ /** A TypeDef node which defines abstract type or type parameter for given `sym` */
+ def TypeDef(sym: Symbol): TypeDef
+
/** A labelled expression. Not expressible in language syntax, but
* generated by the compiler to simulate while/do-while loops, and
* also by the pattern matcher.
@@ -372,6 +470,8 @@ trait Trees { self: Universe =>
case class LabelDef(name: TermName, params: List[Ident], rhs: Tree)
extends DefTree with TermTree
+ def LabelDef(sym: Symbol, params: List[Symbol], rhs: Tree): LabelDef
+
/** Import selector
*
* Representation of an imported name its optional rename and their optional positions
@@ -416,12 +516,19 @@ trait Trees { self: Universe =>
case class Block(stats: List[Tree], expr: Tree)
extends TermTree
+ /** Block factory that flattens directly nested blocks.
+ */
+ def Block(stats: Tree*): Block
+
/** Case clause in a pattern match, eliminated during explicitouter
* (except for occurrences in switch statements)
*/
case class CaseDef(pat: Tree, guard: Tree, body: Tree)
extends Tree
+ /** casedef shorthand */
+ def CaseDef(pat: Tree, body: Tree): CaseDef
+
/** Alternatives of patterns, eliminated by explicitouter, except for
* occurrences in encoded Switch stmt (=remaining Match(CaseDef(...))
*/
@@ -440,6 +547,8 @@ trait Trees { self: Universe =>
case class Bind(name: Name, body: Tree)
extends DefTree
+ def Bind(sym: Symbol, body: Tree): Bind
+
case class UnApply(fun: Tree, args: List[Tree])
extends TermTree
@@ -490,10 +599,14 @@ trait Trees { self: Universe =>
case class Try(block: Tree, catches: List[CaseDef], finalizer: Tree)
extends TermTree
+ def Try(body: Tree, cases: (Tree, Tree)*): Try
+
/** Throw expression */
case class Throw(expr: Tree)
extends TermTree
+ def Throw(tpe: Type, args: Tree*): Throw
+
/** Object instantiation
* One should always use factory method below to build a user level new.
*
@@ -504,14 +617,13 @@ trait Trees { self: Universe =>
/** Factory method for object creation `new tpt(args_1)...(args_n)`
* A `New(t, as)` is expanded to: `(new t).<init>(as)`
*/
- def New(tpt: Tree, argss: List[List[Tree]]): Tree = argss match {
- case Nil => new ApplyConstructor(tpt, Nil)
- case xs :: rest => rest.foldLeft(new ApplyConstructor(tpt, xs): Tree)(Apply)
- }
+ def New(tpt: Tree, argss: List[List[Tree]]): Tree
+
/** 0-1 argument list new, based on a type.
*/
- def New(tpe: Type, args: Tree*): Tree =
- new ApplyConstructor(TypeTree(tpe), args.toList)
+ def New(tpe: Type, args: Tree*): Tree
+
+ def New(sym: Symbol, args: Tree*): Tree
/** Type annotation, eliminated by explicit outer */
case class Typed(expr: Tree, tpt: Tree)
@@ -535,6 +647,9 @@ trait Trees { self: Universe =>
*/
case class TypeApply(fun: Tree, args: List[Tree])
extends GenericApply {
+
+ // Testing the above theory re: args.nonEmpty.
+ require(args.nonEmpty, this)
override def symbol: Symbol = fun.symbol
override def symbol_=(sym: Symbol) { fun.symbol = sym }
}
@@ -546,10 +661,19 @@ trait Trees { self: Universe =>
override def symbol_=(sym: Symbol) { fun.symbol = sym }
}
+ def Apply(sym: Symbol, args: Tree*): Tree
+
+ // TODO remove this class, add a tree attachment to Apply to track whether implicits were involved
+ // copying trees will all too easily forget to distinguish subclasses
class ApplyToImplicitArgs(fun: Tree, args: List[Tree]) extends Apply(fun, args)
+ // TODO remove this class, add a tree attachment to Apply to track whether implicits were involved
+ // copying trees will all too easily forget to distinguish subclasses
class ApplyImplicitView(fun: Tree, args: List[Tree]) extends Apply(fun, args)
+ // TODO: use a factory method, not a class (???)
+ // as a case in point of the comment that should go here by similarity to ApplyToImplicitArgs,
+ // this tree is considered in importers, but not in treecopier
class ApplyConstructor(tpt: Tree, args: List[Tree]) extends Apply(Select(New(tpt), nme.CONSTRUCTOR), args) {
override def printingPrefix = "ApplyConstructor"
}
@@ -564,7 +688,9 @@ trait Trees { self: Universe =>
extends TermTree with SymTree
// The symbol of an ApplyDynamic is the function symbol of `qual`, or NoSymbol, if there is none.
- /** Super reference, qual = corresponding this reference */
+ /** Super reference, qual = corresponding this reference
+ * A super reference C.super[M] is represented as Super(This(C), M).
+ */
case class Super(qual: Tree, mix: TypeName) extends TermTree {
// The symbol of a Super is the class _from_ which the super reference is made.
// For instance in C.super(...), it would be C.
@@ -572,37 +698,45 @@ trait Trees { self: Universe =>
override def symbol_=(sym: Symbol) { qual.symbol = sym }
}
+ def Super(sym: Symbol, mix: TypeName): Tree
+
/** Self reference */
case class This(qual: TypeName)
extends TermTree with SymTree
// The symbol of a This is the class to which the this refers.
// For instance in C.this, it would be C.
- def This(sym: Symbol): Tree =
- This(sym.name.toTypeName) setSymbol sym
+ def This(sym: Symbol): Tree
/** Designator <qualifier> . <name> */
case class Select(qualifier: Tree, name: Name)
extends RefTree
- def Select(qualifier: Tree, name: String): Select =
- Select(qualifier, newTermName(name))
+ def Select(qualifier: Tree, name: String): Select
- def Select(qualifier: Tree, sym: Symbol): Select =
- Select(qualifier, sym.name) setSymbol sym
+ def Select(qualifier: Tree, sym: Symbol): Select
/** Identifier <name> */
case class Ident(name: Name) extends RefTree {
def qualifier: Tree = EmptyTree
+ def isBackquoted = this hasAttachment BackquotedIdentifier
}
- def Ident(name: String): Ident =
- Ident(newTermName(name))
+ def Ident(name: String): Ident
- def Ident(sym: Symbol): Ident =
- Ident(sym.name) setSymbol sym
+ def Ident(sym: Symbol): Ident
- class BackQuotedIdent(name: Name) extends Ident(name)
+ /** Marks underlying reference to id as boxed.
+ * @pre: id must refer to a captured variable
+ * A reference such marked will refer to the boxed entity, no dereferencing
+ * with `.elem` is done on it.
+ * This tree node can be emitted by macros such as reify that call referenceCapturedVariable.
+ * It is eliminated in LambdaLift, where the boxing conversion takes place.
+ */
+ case class ReferenceToBoxed(ident: Ident) extends TermTree {
+ override def symbol: Symbol = ident.symbol
+ override def symbol_=(sym: Symbol) { ident.symbol = sym }
+ }
/** Literal */
case class Literal(value: Constant)
@@ -664,8 +798,8 @@ trait Trees { self: Universe =>
case t => t
}
- orig = followOriginal(tree); setPos(tree.pos);
- this
+ orig = followOriginal(tree)
+ this setPos tree.pos
}
override def defineType(tp: Type): this.type = {
@@ -874,6 +1008,8 @@ trait Trees { self: Universe =>
traverse(qualifier)
case Ident(_) =>
;
+ case ReferenceToBoxed(idt) =>
+ traverse(idt)
case Literal(_) =>
;
case TypeTree() =>
@@ -959,6 +1095,7 @@ trait Trees { self: Universe =>
def This(tree: Tree, qual: Name): This
def Select(tree: Tree, qualifier: Tree, selector: Name): Select
def Ident(tree: Tree, name: Name): Ident
+ def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed
def Literal(tree: Tree, value: Constant): Literal
def TypeTree(tree: Tree): TypeTree
def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated
@@ -1026,9 +1163,10 @@ trait Trees { self: Universe =>
def TypeApply(tree: Tree, fun: Tree, args: List[Tree]) =
new TypeApply(fun, args).copyAttrs(tree)
def Apply(tree: Tree, fun: Tree, args: List[Tree]) =
- (tree match {
+ (tree match { // TODO: use a tree attachment to track whether this is an apply to implicit args or a view
case _: ApplyToImplicitArgs => new ApplyToImplicitArgs(fun, args)
case _: ApplyImplicitView => new ApplyImplicitView(fun, args)
+ // TODO: ApplyConstructor ???
case _ => new Apply(fun, args)
}).copyAttrs(tree)
def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]) =
@@ -1039,8 +1177,13 @@ trait Trees { self: Universe =>
new This(qual.toTypeName).copyAttrs(tree)
def Select(tree: Tree, qualifier: Tree, selector: Name) =
new Select(qualifier, selector).copyAttrs(tree)
- def Ident(tree: Tree, name: Name) =
- new Ident(name).copyAttrs(tree)
+ def Ident(tree: Tree, name: Name) = {
+ val t = new Ident(name) copyAttrs tree
+ if (tree hasAttachment BackquotedIdentifier) t withAttachment BackquotedIdentifier
+ else t
+ }
+ def ReferenceToBoxed(tree: Tree, idt: Ident) =
+ new ReferenceToBoxed(idt).copyAttrs(tree)
def Literal(tree: Tree, value: Constant) =
new Literal(value).copyAttrs(tree)
def TypeTree(tree: Tree) =
@@ -1229,6 +1372,11 @@ trait Trees { self: Universe =>
if name0 == name => t
case _ => treeCopy.Ident(tree, name)
}
+ def ReferenceToBoxed(tree: Tree, idt: Ident) = tree match {
+ case t @ ReferenceToBoxed(idt0)
+ if (idt0 == idt) => t
+ case _ => this.treeCopy.ReferenceToBoxed(tree, idt)
+ }
def Literal(tree: Tree, value: Constant) = tree match {
case t @ Literal(value0)
if value0 == value => t
@@ -1373,6 +1521,8 @@ trait Trees { self: Universe =>
treeCopy.Select(tree, transform(qualifier), selector)
case Ident(name) =>
treeCopy.Ident(tree, name)
+ case ReferenceToBoxed(idt) =>
+ treeCopy.ReferenceToBoxed(tree, transform(idt) match { case idt1: Ident => idt1 })
case Literal(value) =>
treeCopy.Literal(tree, value)
case TypeTree() =>
@@ -1414,7 +1564,7 @@ trait Trees { self: Universe =>
def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
stats mapConserve (stat =>
if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
- else transform(stat)) filter (EmptyTree !=)
+ else transform(stat)) filter (EmptyTree != _)
def transformModifiers(mods: Modifiers): Modifiers =
mods.mapAnnotations(transformTrees)
@@ -1444,6 +1594,14 @@ trait Trees { self: Universe =>
}
}
+ class CollectTreeTraverser[T](pf: PartialFunction[Tree, T]) extends Traverser {
+ val results = new ListBuffer[T]
+ override def traverse(t: Tree) {
+ if (pf.isDefinedAt(t)) results += pf(t)
+ super.traverse(t)
+ }
+ }
+
class FindTreeTraverser(p: Tree => Boolean) extends Traverser {
var result: Option[Tree] = None
override def traverse(t: Tree) {
@@ -1536,7 +1694,7 @@ trait Trees { self: Universe =>
case ApplyDynamic(qual, args) (introduced by erasure, eliminated by cleanup)
// fun(args)
case Super(qual, mix) =>
- // qual.super[mix] if qual and/or mix is empty, ther are tpnme.EMPTY
+ // qual.super[mix] qual is always This(something), if mix is empty, it is tpnme.EMPTY
case This(qual) =>
// qual.this
case Select(qualifier, selector) =>
@@ -1545,6 +1703,10 @@ trait Trees { self: Universe =>
// name
// note: type checker converts idents that refer to enclosing fields or methods
// to selects; name ==> this.name
+ case ReferenceToBoxed(ident) => (created by typer, eliminated by lambdalift)
+ // synthetic node emitted by macros to reference capture vars directly without going through ``elem''
+ // var x = ...; fun { x } will emit Ident(x), which gets transformed to Select(Ident(x), "elem")
+ // if ReferenceToBoxed were used instead of Ident, no transformation would be performed
case Literal(value) =>
// value
case TypeTree() => (introduced by refcheck)
diff --git a/src/library/scala/reflect/api/TypeTags.scala b/src/library/scala/reflect/api/TypeTags.scala
new file mode 100644
index 0000000000..c58b0fcec2
--- /dev/null
+++ b/src/library/scala/reflect/api/TypeTags.scala
@@ -0,0 +1,254 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+package scala.reflect
+package api
+
+import java.lang.{ Class => jClass }
+import language.implicitConversions
+
+/**
+ * Type tags encapsulate a representation of type T.
+ * They are supposed to replace the pre-2.10 concept of a [[scala.reflect.Manifest]].
+ * TypeTags are much better integrated with reflection than manifests are, and are consequently much simpler.
+ *
+ * === Overview ===
+ *
+ * Type tags are organized in a hierarchy of five classes:
+ * [[scala.reflect.ArrayTag]], [[scala.reflect.ErasureTag]], [[scala.reflect.ClassTag]],
+ * [[scala.reflect.api.Universe#TypeTag]] and [[scala.reflect.api.Universe#ConcreteTypeTag]].
+ *
+ * An [[scala.reflect.ArrayTag]] value carries knowledge about how to build an array of elements of type T.
+ * Typically such operation is performed by storing an erasure and instantiating arrays via Java reflection,
+ * but [[scala.reflect.ArrayTag]] only defines an interface, not an implementation, hence it only contains the factory methods
+ * `newArray` and `wrap` that can be used to build, correspondingly, single-dimensional and multi-dimensional arrays.
+ *
+ * An [[scala.reflect.ErasureTag]] value wraps a Java class, which can be accessed via the `erasure` method.
+ * This notion, previously embodied in a [[scala.reflect.ClassManifest]] together with the notion of array creation,
+ * deserves a concept of itself. Quite often (e.g. for serialization or classloader introspection) it's useful to
+ * know an erasure, and only it, so we've implemented this notion in [[scala.reflect.ErasureTag]].
+ *
+ * A [[scala.reflect.ClassTag]] is a standard implementation of both [[scala.reflect.ArrayTag]] and [[scala.reflect.ErasureTag]].
+ * It guarantees that the source type T did not to contain any references to type parameters or abstract types.
+ * [[scala.reflect.ClassTag]] corresponds to a previous notion of [[scala.reflect.ClassManifest]].
+ *
+ * A [[scala.reflect.api.Universe#TypeTag]] value wraps a full Scala type in its tpe field.
+ * A [[scala.reflect.api.Universe#ConcreteTypeTag]] value is a [[scala.reflect.api.Universe#TypeTag]]
+ * that is guaranteed not to contain any references to type parameters or abstract types.
+ * Both flavors of TypeTags also carry an erasure, so [[scala.reflect.api.Universe#TypeTag]] is also an [[scala.reflect.ErasureTag]],
+ * and [[scala.reflect.api.Universe#ConcreteTypeTag]] is additionally an [[scala.reflect.ArrayTag]] and a [[scala.reflect.ClassTag]]
+ *
+ * It is recommended to use the tag supertypes of to precisely express your intent, i.e.:
+ * use ArrayTag when you want to construct arrays,
+ * use ErasureTag when you need an erasure and don't mind it being generated for untagged abstract types,
+ * use ClassTag only when you need an erasure of a type that doesn't refer to untagged abstract types.
+ *
+ * === Splicing ===
+ *
+ * Tags can be spliced, i.e. if compiler generates a tag for a type that contains references to tagged
+ * type parameters or abstract type members, it will retrieve the corresponding tag and embed it into the result.
+ * An example that illustrates the TypeTag embedding, consider the following function:
+ *
+ * import reflect.mirror._
+ * def f[T: TypeTag, U] = {
+ * type L = T => U
+ * implicitly[TypeTag[L]]
+ * }
+ *
+ * Then a call of f[String, Int] will yield a result of the form
+ *
+ * TypeTag(<[ String => U ]>).
+ *
+ * Note that T has been replaced by String, because it comes with a TypeTag in f, whereas U was left as a type parameter.
+ *
+ * === ErasureTag vs ClassTag and TypeTag vs ConcreteTypeTag ===
+ *
+ * Be careful with ErasureTag and TypeTag, because they will reify types even if these types are abstract.
+ * This makes it easy to forget to tag one of the methods in the call chain and discover it much later in the runtime
+ * by getting cryptic errors far away from their source. For example, consider the following snippet:
+ *
+ * def bind[T: TypeTag](name: String, value: T): IR.Result = bind((name, value))
+ * def bind(p: NamedParam): IR.Result = bind(p.name, p.tpe, p.value)
+ * object NamedParam {
+ * implicit def namedValue[T: TypeTag](name: String, x: T): NamedParam = apply(name, x)
+ * def apply[T: TypeTag](name: String, x: T): NamedParam = new Typed[T](name, x)
+ * }
+ *
+ * This fragment of Scala REPL implementation defines a `bind` function that carries a named value along with its type
+ * into the heart of the REPL. Using a [[scala.reflect.api.Universe#TypeTag]] here is reasonable, because it is desirable
+ * to work with all types, even if they are type parameters or abstract type members.
+ *
+ * However if any of the three `TypeTag` context bounds is omitted, the resulting code will be incorrect,
+ * because the missing `TypeTag` will be transparently generated by the compiler, carrying meaningless information.
+ * Most likely, this problem will manifest itself elsewhere, making debugging complicated.
+ * If `TypeTag` context bounds were replaced with `ConcreteTypeTag`, then such errors would be reported statically.
+ * But in that case we wouldn't be able to use `bind` in arbitrary contexts.
+ *
+ * === Backward compatibility ===
+ *
+ * TypeTags correspond loosely to Manifests. More precisely:
+ * The previous notion of a [[scala.reflect.ClassManifest]] corresponds to a scala.reflect.ClassTag,
+ * The previous notion of a [[scala.reflect.Manifest]] corresponds to scala.reflect.mirror.ConcreteTypeTag,
+ * Whereas scala.reflect.mirror.TypeTag is approximated by the previous notion of [[scala.reflect.OptManifest]].
+ *
+ * In Scala 2.10, manifests are deprecated, so it's adviseable to migrate them to tags,
+ * because manifests might be removed in the next major release.
+ *
+ * In most cases it will be enough to replace ClassManifests with ClassTags and Manifests with ConcreteTypeTags,
+ * however there are a few caveats:
+ *
+ * 1) The notion of OptManifest is no longer supported. Tags can reify arbitrary types, so they are always available.
+ * // [Eugene] it might be useful, though, to guard against abstractness of the incoming type.
+ *
+ * 2) There's no equivalent for AnyValManifest. Consider comparing your tag with one of the core tags
+ * (defined in the corresponding companion objects) to find out whether it represents a primitive value class.
+ *
+ * 3) There's no replacement for factory methods defined in `ClassManifest` and `Manifest` companion objects.
+ * Consider assembling corresponding types using reflection API provided by Java (for classes) and Scala (for types).
+ *
+ * 4) Certain manifest functions (such as `<:<`, `>:>` and `typeArguments`) weren't included in the tag API.
+ * Consider using reflection API provided by Java (for classes) and Scala (for types) instead.
+ */
+trait TypeTags { self: Universe =>
+
+ /**
+ * If an implicit value of type u.TypeTag[T] is required, the compiler will make one up on demand.
+ * The implicitly created value contains in its tpe field a value of type u.Type that is a reflective representation of T.
+ * In that value, any occurrences of type parameters or abstract types U
+ * which come themselves with a TypeTag are represented by the type referenced by that TypeTag.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+ @annotation.implicitNotFound(msg = "No TypeTag available for ${T}")
+ trait TypeTag[T] extends ErasureTag[T] with Equals with Serializable {
+
+ def tpe: Type
+ def sym: Symbol = tpe.typeSymbol
+
+ def isConcrete: Boolean = tpe.isConcrete
+ def notConcrete: Boolean = !isConcrete
+ def toConcrete: ConcreteTypeTag[T] = ConcreteTypeTag[T](tpe, erasure)
+
+ /** case class accessories */
+ override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]]
+ override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.tpe == x.asInstanceOf[TypeTag[_]].tpe
+ override def hashCode = scala.runtime.ScalaRunTime.hash(tpe)
+ override def toString = if (!self.isInstanceOf[DummyMirror]) (if (isConcrete) "*ConcreteTypeTag" else "TypeTag") + "[" + tpe + "]" else "TypeTag[?]"
+ }
+
+ object TypeTag {
+ val Byte : TypeTag[scala.Byte] = ConcreteTypeTag.Byte
+ val Short : TypeTag[scala.Short] = ConcreteTypeTag.Short
+ val Char : TypeTag[scala.Char] = ConcreteTypeTag.Char
+ val Int : TypeTag[scala.Int] = ConcreteTypeTag.Int
+ val Long : TypeTag[scala.Long] = ConcreteTypeTag.Long
+ val Float : TypeTag[scala.Float] = ConcreteTypeTag.Float
+ val Double : TypeTag[scala.Double] = ConcreteTypeTag.Double
+ val Boolean : TypeTag[scala.Boolean] = ConcreteTypeTag.Boolean
+ val Unit : TypeTag[scala.Unit] = ConcreteTypeTag.Unit
+ val Any : TypeTag[scala.Any] = ConcreteTypeTag.Any
+ val Object : TypeTag[java.lang.Object] = ConcreteTypeTag.Object
+ val AnyVal : TypeTag[scala.AnyVal] = ConcreteTypeTag.AnyVal
+ val AnyRef : TypeTag[scala.AnyRef] = ConcreteTypeTag.AnyRef
+ val Nothing : TypeTag[scala.Nothing] = ConcreteTypeTag.Nothing
+ val Null : TypeTag[scala.Null] = ConcreteTypeTag.Null
+ val String : TypeTag[java.lang.String] = ConcreteTypeTag.String
+
+ // todo. uncomment after I redo the starr
+ // def apply[T](tpe1: Type, erasure1: jClass[_]): TypeTag[T] =
+ def apply[T](tpe1: Type, erasure1: jClass[_]): TypeTag[T] =
+ tpe1 match {
+ case ByteTpe => TypeTag.Byte.asInstanceOf[TypeTag[T]]
+ case ShortTpe => TypeTag.Short.asInstanceOf[TypeTag[T]]
+ case CharTpe => TypeTag.Char.asInstanceOf[TypeTag[T]]
+ case IntTpe => TypeTag.Int.asInstanceOf[TypeTag[T]]
+ case LongTpe => TypeTag.Long.asInstanceOf[TypeTag[T]]
+ case FloatTpe => TypeTag.Float.asInstanceOf[TypeTag[T]]
+ case DoubleTpe => TypeTag.Double.asInstanceOf[TypeTag[T]]
+ case BooleanTpe => TypeTag.Boolean.asInstanceOf[TypeTag[T]]
+ case UnitTpe => TypeTag.Unit.asInstanceOf[TypeTag[T]]
+ case AnyTpe => TypeTag.Any.asInstanceOf[TypeTag[T]]
+ case ObjectTpe => TypeTag.Object.asInstanceOf[TypeTag[T]]
+ case AnyValTpe => TypeTag.AnyVal.asInstanceOf[TypeTag[T]]
+ case AnyRefTpe => TypeTag.AnyRef.asInstanceOf[TypeTag[T]]
+ case NothingTpe => TypeTag.Nothing.asInstanceOf[TypeTag[T]]
+ case NullTpe => TypeTag.Null.asInstanceOf[TypeTag[T]]
+ case StringTpe => TypeTag.String.asInstanceOf[TypeTag[T]]
+ case _ => new TypeTag[T]{ def tpe = tpe1; def erasure = erasure1 }
+ }
+
+ def unapply[T](ttag: TypeTag[T]): Option[Type] = Some(ttag.tpe)
+ }
+
+ /**
+ * If an implicit value of type u.ConcreteTypeTag[T] is required, the compiler will make one up on demand following the same procedure as for TypeTags.
+ * However, if the resulting type still contains references to type parameters or abstract types, a static error results.
+ *
+ * @see [[scala.reflect.api.TypeTags]]
+ */
+ @annotation.implicitNotFound(msg = "No ConcreteTypeTag available for ${T}")
+ trait ConcreteTypeTag[T] extends TypeTag[T] with ClassTag[T] with Equals with Serializable {
+ if (!self.isInstanceOf[DummyMirror]) {
+ if (notConcrete) throw new Error("%s (%s) is not concrete and cannot be used to construct a concrete type tag".format(tpe, tpe.kind))
+ }
+
+ /** case class accessories */
+ override def canEqual(x: Any) = x.isInstanceOf[TypeTag[_]] // this is done on purpose. TypeTag(tpe) and ConcreteTypeTag(tpe) should be equal if tpe's are equal
+ override def equals(x: Any) = x.isInstanceOf[TypeTag[_]] && this.tpe == x.asInstanceOf[TypeTag[_]].tpe
+ override def hashCode = scala.runtime.ScalaRunTime.hash(tpe)
+ override def toString = if (!self.isInstanceOf[DummyMirror]) "ConcreteTypeTag[" + tpe + "]" else "ConcreteTypeTag[?]"
+ }
+
+ object ConcreteTypeTag {
+ val Byte : ConcreteTypeTag[scala.Byte] = new ConcreteTypeTag[scala.Byte]{ def tpe = ByteTpe; def erasure = ClassTag.Byte.erasure; private def readResolve() = ConcreteTypeTag.Byte }
+ val Short : ConcreteTypeTag[scala.Short] = new ConcreteTypeTag[scala.Short]{ def tpe = ShortTpe; def erasure = ClassTag.Short.erasure; private def readResolve() = ConcreteTypeTag.Short }
+ val Char : ConcreteTypeTag[scala.Char] = new ConcreteTypeTag[scala.Char]{ def tpe = CharTpe; def erasure = ClassTag.Char.erasure; private def readResolve() = ConcreteTypeTag.Char }
+ val Int : ConcreteTypeTag[scala.Int] = new ConcreteTypeTag[scala.Int]{ def tpe = IntTpe; def erasure = ClassTag.Int.erasure; private def readResolve() = ConcreteTypeTag.Int }
+ val Long : ConcreteTypeTag[scala.Long] = new ConcreteTypeTag[scala.Long]{ def tpe = LongTpe; def erasure = ClassTag.Long.erasure; private def readResolve() = ConcreteTypeTag.Long }
+ val Float : ConcreteTypeTag[scala.Float] = new ConcreteTypeTag[scala.Float]{ def tpe = FloatTpe; def erasure = ClassTag.Float.erasure; private def readResolve() = ConcreteTypeTag.Float }
+ val Double : ConcreteTypeTag[scala.Double] = new ConcreteTypeTag[scala.Double]{ def tpe = DoubleTpe; def erasure = ClassTag.Double.erasure; private def readResolve() = ConcreteTypeTag.Double }
+ val Boolean : ConcreteTypeTag[scala.Boolean] = new ConcreteTypeTag[scala.Boolean]{ def tpe = BooleanTpe; def erasure = ClassTag.Boolean.erasure; private def readResolve() = ConcreteTypeTag.Boolean }
+ val Unit : ConcreteTypeTag[scala.Unit] = new ConcreteTypeTag[scala.Unit]{ def tpe = UnitTpe; def erasure = ClassTag.Unit.erasure; private def readResolve() = ConcreteTypeTag.Unit }
+ val Any : ConcreteTypeTag[scala.Any] = new ConcreteTypeTag[scala.Any]{ def tpe = AnyTpe; def erasure = ClassTag.Any.erasure; private def readResolve() = ConcreteTypeTag.Any }
+ val Object : ConcreteTypeTag[java.lang.Object] = new ConcreteTypeTag[java.lang.Object]{ def tpe = ObjectTpe; def erasure = ClassTag.Object.erasure; private def readResolve() = ConcreteTypeTag.Object }
+ val AnyVal : ConcreteTypeTag[scala.AnyVal] = new ConcreteTypeTag[scala.AnyVal]{ def tpe = AnyValTpe; def erasure = ClassTag.AnyVal.erasure; private def readResolve() = ConcreteTypeTag.AnyVal }
+ val AnyRef : ConcreteTypeTag[scala.AnyRef] = new ConcreteTypeTag[scala.AnyRef]{ def tpe = AnyRefTpe; def erasure = ClassTag.AnyRef.erasure; private def readResolve() = ConcreteTypeTag.AnyRef }
+ val Nothing : ConcreteTypeTag[scala.Nothing] = new ConcreteTypeTag[scala.Nothing]{ def tpe = NothingTpe; def erasure = ClassTag.Nothing.erasure; private def readResolve() = ConcreteTypeTag.Nothing }
+ val Null : ConcreteTypeTag[scala.Null] = new ConcreteTypeTag[scala.Null]{ def tpe = NullTpe; def erasure = ClassTag.Null.erasure; private def readResolve() = ConcreteTypeTag.Null }
+ val String : ConcreteTypeTag[java.lang.String] = new ConcreteTypeTag[java.lang.String]{ def tpe = StringTpe; def erasure = ClassTag.String.erasure; private def readResolve() = ConcreteTypeTag.String }
+
+ // todo. uncomment after I redo the starr
+ // def apply[T](tpe1: Type, erasure1: jClass[_]): ConcreteTypeTag[T] =
+ def apply[T](tpe1: Type, erasure1: jClass[_] = null): ConcreteTypeTag[T] =
+ tpe1 match {
+ case ByteTpe => ConcreteTypeTag.Byte.asInstanceOf[ConcreteTypeTag[T]]
+ case ShortTpe => ConcreteTypeTag.Short.asInstanceOf[ConcreteTypeTag[T]]
+ case CharTpe => ConcreteTypeTag.Char.asInstanceOf[ConcreteTypeTag[T]]
+ case IntTpe => ConcreteTypeTag.Int.asInstanceOf[ConcreteTypeTag[T]]
+ case LongTpe => ConcreteTypeTag.Long.asInstanceOf[ConcreteTypeTag[T]]
+ case FloatTpe => ConcreteTypeTag.Float.asInstanceOf[ConcreteTypeTag[T]]
+ case DoubleTpe => ConcreteTypeTag.Double.asInstanceOf[ConcreteTypeTag[T]]
+ case BooleanTpe => ConcreteTypeTag.Boolean.asInstanceOf[ConcreteTypeTag[T]]
+ case UnitTpe => ConcreteTypeTag.Unit.asInstanceOf[ConcreteTypeTag[T]]
+ case AnyTpe => ConcreteTypeTag.Any.asInstanceOf[ConcreteTypeTag[T]]
+ case ObjectTpe => ConcreteTypeTag.Object.asInstanceOf[ConcreteTypeTag[T]]
+ case AnyValTpe => ConcreteTypeTag.AnyVal.asInstanceOf[ConcreteTypeTag[T]]
+ case AnyRefTpe => ConcreteTypeTag.AnyRef.asInstanceOf[ConcreteTypeTag[T]]
+ case NothingTpe => ConcreteTypeTag.Nothing.asInstanceOf[ConcreteTypeTag[T]]
+ case NullTpe => ConcreteTypeTag.Null.asInstanceOf[ConcreteTypeTag[T]]
+ case StringTpe => ConcreteTypeTag.String.asInstanceOf[ConcreteTypeTag[T]]
+ case _ => new ConcreteTypeTag[T]{ def tpe = tpe1; def erasure = erasure1 }
+ }
+
+ def unapply[T](ttag: TypeTag[T]): Option[Type] = if (ttag.isConcrete) Some(ttag.tpe) else None
+ }
+
+ // incantations for summoning
+ // moved to Context, since rm.tags have their own incantations in Predef, and these guys are only useful in macros
+// def tag[T](implicit ttag: TypeTag[T]) = ttag
+// def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+// def concreteTag[T](implicit gttag: ConcreteTypeTag[T]) = cttag
+// def concreteTypeTag[T](implicit gttag: ConcreteTypeTag[T]) = cttag
+}
diff --git a/src/library/scala/reflect/api/Types.scala b/src/library/scala/reflect/api/Types.scala
index 0371e2c5df..5c7563c2c5 100755
--- a/src/library/scala/reflect/api/Types.scala
+++ b/src/library/scala/reflect/api/Types.scala
@@ -53,10 +53,26 @@ trait Types { self: Universe =>
*/
def typeArguments: List[Type]
+ /** For a (potentially wrapped) poly type, its type parameters,
+ * the empty list for all other types */
+ def typeParams: List[Symbol]
+
/** Is this type a type constructor that is missing its type arguments?
*/
def isHigherKinded: Boolean // !!! This should be called "isTypeConstructor", no?
+ /** Returns the corresponding type constructor (e.g. List for List[T] or List[String])
+ */
+ def typeConstructor: Type
+
+ /** Does this type refer to spliceable types or is a spliceable type?
+ */
+ def isConcrete: Boolean
+
+ /** Is this type an abstract type that needs to be resolved?
+ */
+ def isSpliceable: Boolean
+
/**
* Expands type aliases and converts higher-kinded TypeRefs to PolyTypes.
* Functions on types are also implemented as PolyTypes.
@@ -105,7 +121,8 @@ trait Types { self: Universe =>
/** The erased type corresponding to this type after
* all transformations from Scala to Java have been performed.
*/
- def erasedType: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased")
+ def erasure: Type // !!! "erasedType", compare with "widen" (so "erase") or "underlying" (so "erased")
+ // why not name it "erasure"?
/** Apply `f` to each part of this type, returning
* a new type. children get mapped before their parents */
@@ -146,6 +163,33 @@ trait Types { self: Universe =>
* <o.x.type>.widen = o.C
*/
def widen: Type
+
+ /** The kind of this type; used for debugging */
+ def kind: String
+ }
+
+ /** An object representing an unknown type, used during type inference.
+ * If you see WildcardType outside of inference it is almost certainly a bug.
+ */
+ val WildcardType: Type
+
+ /** BoundedWildcardTypes, used only during type inference, are created in
+ * two places that I can find:
+ *
+ * 1. If the expected type of an expression is an existential type,
+ * its hidden symbols are replaced with bounded wildcards.
+ * 2. When an implicit conversion is being sought based in part on
+ * the name of a method in the converted type, a HasMethodMatching
+ * type is created: a MethodType with parameters typed as
+ * BoundedWildcardTypes.
+ */
+ type BoundedWildcardType >: Null <: Type
+
+ val BoundedWildcardType: BoundedWildcardTypeExtractor
+
+ abstract class BoundedWildcardTypeExtractor {
+ def apply(bounds: TypeBounds): BoundedWildcardType
+ def unapply(tpe: BoundedWildcardType): Option[TypeBounds]
}
/** The type of Scala types, and also Scala type signatures.
@@ -225,6 +269,7 @@ trait Types { self: Universe =>
* (T # x).type SingleType(T, x)
* p.x.type SingleType(p.type, x)
* x.type SingleType(NoPrefix, x)
+ * }}}
*/
type SingleType <: SingletonType
@@ -419,10 +464,73 @@ trait Types { self: Universe =>
def unapply(tpe: AnnotatedType): Option[(List[AnnotationInfo], Type, Symbol)]
}
- /** The least upper bound wrt <:< of a list of types */
+ /** The least upper bound of a list of types, as determined by `<:<`. */
def lub(xs: List[Type]): Type
- /** The greatest lower bound wrt <:< of a list of types */
+ /** The greatest lower bound of a list of types, as determined by `<:<`. */
def glb(ts: List[Type]): Type
+
+ // Creators ---------------------------------------------------------------
+ // too useful and too non-trivial to be left out of public API
+ // [Eugene to Paul] needs review!
+
+ /** The canonical creator for single-types */
+ def singleType(pre: Type, sym: Symbol): Type
+
+ /** the canonical creator for a refined type with a given scope */
+ def refinedType(parents: List[Type], owner: Symbol, decls: Scope, pos: Position): Type
+
+ /** The canonical creator for a refined type with an initially empty scope.
+ *
+ * @param parents ...
+ * @param owner ...
+ * @return ...
+ */
+ def refinedType(parents: List[Type], owner: Symbol): Type
+
+ /** The canonical creator for typerefs
+ */
+ def typeRef(pre: Type, sym: Symbol, args: List[Type]): Type
+
+ /** A creator for intersection type where intersections of a single type are
+ * replaced by the type itself. */
+ def intersectionType(tps: List[Type]): Type
+
+ /** A creator for intersection type where intersections of a single type are
+ * replaced by the type itself, and repeated parent classes are merged.
+ *
+ * !!! Repeated parent classes are not merged - is this a bug in the
+ * comment or in the code?
+ */
+ def intersectionType(tps: List[Type], owner: Symbol): Type
+
+ /** A creator for type applications */
+ def appliedType(tycon: Type, args: List[Type]): Type
+
+ /** A creator for type parameterizations that strips empty type parameter lists.
+ * Use this factory method to indicate the type has kind * (it's a polymorphic value)
+ * until we start tracking explicit kinds equivalent to typeFun (except that the latter requires tparams nonEmpty).
+ */
+ def polyType(tparams: List[Symbol], tpe: Type): Type
+
+ /** A creator for existential types. This generates:
+ *
+ * {{{
+ * tpe1 where { tparams }
+ * }}}
+ *
+ * where `tpe1` is the result of extrapolating `tpe` with regard to `tparams`.
+ * Extrapolating means that type variables in `tparams` occurring
+ * in covariant positions are replaced by upper bounds, (minus any
+ * SingletonClass markers), type variables in `tparams` occurring in
+ * contravariant positions are replaced by upper bounds, provided the
+ * resulting type is legal with regard to stability, and does not contain
+ * any type variable in `tparams`.
+ *
+ * The abstraction drops all type parameters that are not directly or
+ * indirectly referenced by type `tpe1`. If there are no remaining type
+ * parameters, simply returns result type `tpe`.
+ */
+ def existentialAbstraction(tparams: List[Symbol], tpe0: Type): Type
}
diff --git a/src/library/scala/reflect/api/Universe.scala b/src/library/scala/reflect/api/Universe.scala
index a3cec3271b..9670780522 100755
--- a/src/library/scala/reflect/api/Universe.scala
+++ b/src/library/scala/reflect/api/Universe.scala
@@ -1,19 +1,71 @@
package scala.reflect
package api
+import language.experimental.macros
+
abstract class Universe extends Symbols
+ with FreeVars
with Types
with Constants
with Scopes
with Names
with Trees
- with Positions
- with TreePrinters
with AnnotationInfos
+ with Positions
+ with Exprs
with StandardDefinitions
- with StandardNames {
- type Position
- val NoPosition: Position
+ with TypeTags
+ with TreePrinters
+ with StandardNames
+ with ClassLoaders
+ with TreeBuildUtil
+ with ToolBoxes
+ with FrontEnds
+ with Importers {
+ /** Given an expression, generate a tree that when compiled and executed produces the original tree.
+ * The produced tree will be bound to the Universe it was called from.
+ *
+ * For instance, given the abstract syntax tree representation of the <[ x + 1 ]> expression:
+ *
+ * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
+ *
+ * The reifier transforms it to the following expression:
+ *
+ * <[
+ * val $mr: scala.reflect.api.Universe = <reference to the Universe that calls the reify>
+ * $mr.Expr[Int]($mr.Apply($mr.Select($mr.Ident($mr.newFreeVar("x", <Int>, x), "+"), List($mr.Literal($mr.Constant(1))))))
+ * ]>
+ *
+ * Reification performs expression splicing (when processing Expr.eval and Expr.value)
+ * and type splicing (for every type T that has a TypeTag[T] implicit in scope):
+ *
+ * val two = mirror.reify(2) // Literal(Constant(2))
+ * val four = mirror.reify(two.eval + two.eval) // Apply(Select(two.tree, newTermName("$plus")), List(two.tree))
+ *
+ * def macroImpl[T](c: Context) = {
+ * ...
+ * // T here is just a type parameter, so the tree produced by reify won't be of much use in a macro expansion
+ * // however, if T were annotated with c.TypeTag (which would declare an implicit parameter for macroImpl)
+ * // then reification would subtitute T with the TypeTree that was used in a TypeApply of this particular macro invocation
+ * val factory = c.reify{ new Queryable[T] }
+ * ...
+ * }
+ *
+ * The transformation looks mostly straightforward, but it has its tricky parts:
+ * * Reifier retains symbols and types defined outside the reified tree, however
+ * locally defined entities get erased and replaced with their original trees
+ * * Free variables are detected and wrapped in symbols of the type FreeVar
+ * * Mutable variables that are accessed from a local function are wrapped in refs
+ * * Since reified trees can be compiled outside of the scope they've been created in,
+ * special measures are taken to ensure that all members accessed in the reifee remain visible
+ */
+ def reify[T](expr: T): Expr[T] = macro Universe.reify[T]
}
+object Universe {
+ def reify[T](cc: scala.reflect.makro.Context{ type PrefixType = Universe })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = {
+ import scala.reflect.makro.internal._
+ cc.Expr(cc.materializeExpr(cc.prefix.tree, expr.tree))
+ }
+}
diff --git a/src/library/scala/reflect/macro/Context.scala b/src/library/scala/reflect/macro/Context.scala
deleted file mode 100644
index 2fd9bb6484..0000000000
--- a/src/library/scala/reflect/macro/Context.scala
+++ /dev/null
@@ -1,36 +0,0 @@
-package scala.reflect
-package macro
-
-trait Context extends api.Universe {
-
- /** Mark a variable as captured; i.e. force boxing in a *Ref type.
- */
- def captureVariable(vble: Symbol): Unit
-
- /** Mark given identifier as a reference to a captured variable itself
- * suppressing dereferencing with the `elem` field.
- */
- def referenceCapturedVariable(id: Ident): Tree
-
- /** Given a tree or type, generate a tree that when executed at runtime produces the original tree or type.
- * For instance, given the abstract syntax tree representation of the `x + 1` expression:
- *
- * Apply(Select(Ident("x"), "+"), List(Literal(Constant(1))))
- *
- * The reifier transforms it to the following tree:
- *
- * $mr.Apply($mr.Select($mr.Ident($mr.newFreeVar("x", <Int>, x), "+"), List($mr.Literal($mr.Constant(1))))))
- *
- * The transformation looks mostly straightforward, but it has its tricky parts:
- * * Reifier retains symbols and types defined outside the reified tree, however
- * locally defined entities get erased and replaced with their original trees
- * * Free variables are detected and wrapped in symbols of the type FreeVar
- * * Mutable variables that are accessed from a local function are wrapped in refs
- * * Since reified trees can be compiled outside of the scope they've been created in,
- * special measures are taken to ensure that all freeVars remain visible
- *
- * Typical usage of this function is to retain some of the trees received/created by a macro
- * into the form that can be inspected (via pattern matching) or compiled/run (by a reflective ToolBox) during the runtime.
- */
- def reify(tree: Tree): Tree
-}
diff --git a/src/library/scala/reflect/makro/Aliases.scala b/src/library/scala/reflect/makro/Aliases.scala
new file mode 100644
index 0000000000..38b1065a40
--- /dev/null
+++ b/src/library/scala/reflect/makro/Aliases.scala
@@ -0,0 +1,26 @@
+package scala.reflect.makro
+
+trait Aliases {
+ self: Context =>
+
+ /** Aliases of mirror types */
+ type Symbol = mirror.Symbol
+ type Type = mirror.Type
+ type Name = mirror.Name
+ type Tree = mirror.Tree
+ type Position = mirror.Position
+ type Scope = mirror.Scope
+ type Modifiers = mirror.Modifiers
+ type Expr[+T] = mirror.Expr[T]
+ type TypeTag[T] = mirror.TypeTag[T]
+
+ /** Creator/extractor objects for Expr and TypeTag values */
+ val TypeTag = mirror.TypeTag
+ val Expr = mirror.Expr
+
+ /** incantations for summoning tags */
+ def tag[T](implicit ttag: TypeTag[T]) = ttag
+ def typeTag[T](implicit ttag: TypeTag[T]) = ttag
+ def concreteTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
+ def concreteTypeTag[T](implicit cttag: ConcreteTypeTag[T]) = cttag
+}
diff --git a/src/library/scala/reflect/makro/CapturedVariables.scala b/src/library/scala/reflect/makro/CapturedVariables.scala
new file mode 100644
index 0000000000..6ce832b2b3
--- /dev/null
+++ b/src/library/scala/reflect/makro/CapturedVariables.scala
@@ -0,0 +1,20 @@
+package scala.reflect.makro
+
+trait CapturedVariables {
+ self: Context =>
+
+ import mirror._
+
+ /** Mark a variable as captured; i.e. force boxing in a *Ref type.
+ */
+ def captureVariable(vble: Symbol): Unit
+
+ /** Mark given identifier as a reference to a captured variable itself
+ * suppressing dereferencing with the `elem` field.
+ */
+ def referenceCapturedVariable(vble: Symbol): Tree
+
+ /** Convert type of a captured variable to *Ref type.
+ */
+ def capturedVariableType(vble: Symbol): Type
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Context.scala b/src/library/scala/reflect/makro/Context.scala
new file mode 100644
index 0000000000..b8fb0dcce5
--- /dev/null
+++ b/src/library/scala/reflect/makro/Context.scala
@@ -0,0 +1,44 @@
+package scala.reflect.makro
+
+import language.experimental.macros
+
+// todo. introduce context hierarchy
+// the most lightweight context should just expose the stuff from the SIP
+// the full context should include all traits from scala.reflect.makro (and probably reside in scala-compiler.jar)
+
+trait Context extends Aliases
+ with CapturedVariables
+ with Enclosures
+ with Infrastructure
+ with Names
+ with Reifiers
+ with FrontEnds
+ with Settings
+ with Symbols
+ with Typers
+ with Util {
+
+ /** The mirror that corresponds to the compile-time universe */
+ val mirror: scala.reflect.api.Universe
+
+ /** The type of the prefix tree from which the macro is selected */
+ type PrefixType
+
+ /** The prefix tree from which the macro is selected */
+ val prefix: Expr[PrefixType]
+
+ /** Alias to the underlying mirror's reify */
+ def reify[T](expr: T): Expr[T] = macro Context.reify[T]
+}
+
+object Context {
+ def reify[T](cc: Context{ type PrefixType = Context })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = {
+ import cc.mirror._
+ import scala.reflect.makro.internal._
+ // [Eugene] how do I typecheck this without undergoing this tiresome (and, in general, incorrect) procedure?
+ val prefix: Tree = Select(cc.prefix.tree, newTermName("mirror"))
+ val prefixTpe = cc.typeCheck(TypeApply(Select(prefix, newTermName("asInstanceOf")), List(SingletonTypeTree(prefix)))).tpe
+ prefix setType prefixTpe
+ cc.Expr(cc.materializeExpr(prefix, expr.tree))
+ }
+}
diff --git a/src/library/scala/reflect/makro/Enclosures.scala b/src/library/scala/reflect/makro/Enclosures.scala
new file mode 100644
index 0000000000..136d39498e
--- /dev/null
+++ b/src/library/scala/reflect/makro/Enclosures.scala
@@ -0,0 +1,53 @@
+package scala.reflect.makro
+
+trait Enclosures {
+ self: Context =>
+
+ /** The tree that undergoes macro expansion.
+ * Can be useful to get an offset or a range position of the entire tree being processed.
+ */
+ val macroApplication: Tree
+
+ /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only.
+ * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion.
+ *
+ * Is also priceless for emitting sane error messages for macros that are called by other macros on synthetic (i.e. position-less) trees.
+ * In that dire case navigate the ``enclosingMacros'' stack, and it will most likely contain at least one macro with a position-ful macro application.
+ * See ``enclosingPosition'' for a default implementation of this logic.
+ *
+ * Unlike `openMacros`, this is a val, which means that it gets initialized when the context is created
+ * and always stays the same regardless of whatever happens during macro expansion.
+ */
+ val enclosingMacros: List[Context]
+
+ /** Types along with corresponding trees for which implicit arguments are currently searched.
+ * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
+ *
+ * Unlike `openImplicits`, this is a val, which means that it gets initialized when the context is created
+ * and always stays the same regardless of whatever happens during macro expansion.
+ */
+ val enclosingImplicits: List[(Type, Tree)]
+
+ /** Tries to guess a position for the enclosing application.
+ * But that is simple, right? Just dereference ``pos'' of ``macroApplication''? Not really.
+ * If we're in a synthetic macro expansion (no positions), we must do our best to infer the position of something that triggerd this expansion.
+ * Surprisingly, quite often we can do this by navigation the ``enclosingMacros'' stack.
+ */
+ val enclosingPosition: Position
+
+ /** Tree that corresponds to the enclosing application, or EmptyTree if not applicable.
+ */
+ val enclosingApplication: Tree
+
+ /** Tree that corresponds to the enclosing method, or EmptyTree if not applicable.
+ */
+ val enclosingMethod: Tree
+
+ /** Tree that corresponds to the enclosing class, or EmptyTree if not applicable.
+ */
+ val enclosingClass: Tree
+
+ /** Compilation unit that contains this macro application.
+ */
+ val enclosingUnit: CompilationUnit
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/FrontEnds.scala b/src/library/scala/reflect/makro/FrontEnds.scala
new file mode 100644
index 0000000000..a1e24dcea3
--- /dev/null
+++ b/src/library/scala/reflect/makro/FrontEnds.scala
@@ -0,0 +1,39 @@
+package scala.reflect.makro
+
+trait FrontEnds {
+ self: Context =>
+
+ import mirror._
+
+ /** Exposes means to control the compiler UI */
+ def frontEnd: FrontEnd
+ def setFrontEnd(frontEnd: FrontEnd): this.type
+ def withFrontEnd[T](frontEnd: FrontEnd)(op: => T): T
+
+ /** For sending a message which should not be labeled as a warning/error,
+ * but also shouldn't require -verbose to be visible.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def echo(pos: Position, msg: String): Unit
+
+ /** Informational messages, suppressed unless -verbose or force=true.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def info(pos: Position, msg: String, force: Boolean): Unit
+
+ /** Warnings and errors.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def hasWarnings: Boolean
+ def hasErrors: Boolean
+ def warning(pos: Position, msg: String): Unit
+ def error(pos: Position, msg: String): Unit
+
+ /** Abruptly terminates current macro expansion leaving a note about what happened.
+ * Use ``enclosingPosition'' if you're in doubt what position to pass to ``pos''.
+ */
+ def abort(pos: Position, msg: String): Nothing
+
+ /** Drops into interactive mode if supported by the compiler UI */
+ def interactive(): Unit
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Infrastructure.scala b/src/library/scala/reflect/makro/Infrastructure.scala
new file mode 100644
index 0000000000..2bf49dca77
--- /dev/null
+++ b/src/library/scala/reflect/makro/Infrastructure.scala
@@ -0,0 +1,73 @@
+package scala.reflect.makro
+
+trait Infrastructure {
+ self: Context =>
+
+ /** Determines whether the compiler expanding a macro targets JVM.
+ */
+ val forJVM: Boolean
+
+ /** Determines whether the compiler expanding a macro targets CLR.
+ */
+ val forMSIL: Boolean
+
+ /** Determines whether the compiler expanding a macro is a presentation compiler.
+ */
+ val forInteractive: Boolean
+
+ /** Determines whether the compiler expanding a macro is a Scaladoc compiler.
+ */
+ val forScaladoc: Boolean
+
+ /** Exposes current compilation run.
+ */
+ val currentRun: Run
+
+ /** As seen by macro API, compilation run is an opaque type that can be deconstructed into:
+ * 1) Current compilation unit
+ * 2) List of all compilation units that comprise the run
+ */
+ type Run
+
+ val Run: RunExtractor
+
+ abstract class RunExtractor {
+ def unapply(run: Run): Option[(CompilationUnit, List[CompilationUnit])]
+ }
+
+ /** As seen by macro API, compilation unit is an opaque type that can be deconstructed into:
+ * 1) File that corresponds to the unit (if not applicable, null)
+ * 2) Content of the file (if not applicable, empty array)
+ * 3) Body, i.e. the AST that represents the compilation unit
+ */
+ type CompilationUnit
+
+ val CompilationUnit: CompilationUnitExtractor
+
+ abstract class CompilationUnitExtractor {
+ def unapply(compilationUnit: CompilationUnit): Option[(java.io.File, Array[Char], Tree)]
+ }
+
+ /** Returns a macro definition which triggered this macro expansion.
+ */
+ val currentMacro: Symbol
+
+ // todo. redo caches as discussed on Reflecting Meeting 2012/03/29
+ // https://docs.google.com/document/d/1oUZGQpdt2qwioTlJcSt8ZFQwVLTvpxn8xa67P8OGVpU/edit
+
+ /** A cache shared by all invocations of all macros across all compilation runs.
+ *
+ * Needs to be used with extreme care, since memory leaks here will swiftly crash the presentation compiler.
+ * For example, Scala IDE typically launches a compiler run on every edit action so there might be hundreds of runs per minute.
+ */
+ val globalCache: collection.mutable.Map[Any, Any]
+
+ /** A cache shared by all invocations of the same macro within a single compilation run.
+ *
+ * This cache is cleared automatically after a compilation run is completed or abandoned.
+ * It is also specific to a particular macro definition.
+ *
+ * To share data between different macros and/or different compilation runs, use ``globalCache''.
+ */
+ val cache: collection.mutable.Map[Any, Any]
+}
diff --git a/src/library/scala/reflect/makro/Names.scala b/src/library/scala/reflect/makro/Names.scala
new file mode 100644
index 0000000000..8a823d19cb
--- /dev/null
+++ b/src/library/scala/reflect/makro/Names.scala
@@ -0,0 +1,14 @@
+package scala.reflect.makro
+
+trait Names {
+ self: Context =>
+
+ /** Creates a fresh string */
+ def fresh(): String
+
+ /** Creates a fresh string from the provided string */
+ def fresh(name: String): String
+
+ /** Creates a fresh name from the provided name */
+ def fresh(name: Name): Name
+}
diff --git a/src/library/scala/reflect/makro/Reifiers.scala b/src/library/scala/reflect/makro/Reifiers.scala
new file mode 100644
index 0000000000..b1de8d9957
--- /dev/null
+++ b/src/library/scala/reflect/makro/Reifiers.scala
@@ -0,0 +1,77 @@
+package scala.reflect.makro
+
+trait Reifiers {
+ self: Context =>
+
+ /** Reification prefix that refers to the standard reflexive mirror, ``scala.reflect.mirror''.
+ * Providing it for the ``prefix'' parameter of ``reifyTree'' or ``reifyType'' will create a tree that can be inspected at runtime.
+ */
+ val reflectMirrorPrefix: Tree
+
+ /** Given a tree, generate a tree that when compiled and executed produces the original tree.
+ * The produced tree will be bound to the mirror specified by ``prefix'' (also see ``reflectMirrorPrefix'').
+ * For more information and examples see the documentation for ``Universe.reify''.
+ *
+ * This function is deeply connected to ``Universe.reify'', a macro that reifies arbitrary expressions into runtime trees.
+ * They do very similar things (``Universe.reify'' calls ``Context.reifyTree'' to implement itself), but they operate on different metalevels (see below).
+ *
+ * Let's study the differences between ``Context.reifyTree'' and ``Universe.reify'' on an example of using them inside a ``fooMacro'' macro:
+ *
+ * * Since reify itself is a macro, it will be executed when fooMacro is being compiled (metalevel -1)
+ * and will produce a tree that when evaluated during macro expansion of fooMacro (metalevel 0) will recreate the input tree.
+ *
+ * This provides a facility analogous to quasi-quoting. Writing "reify{ expr }" will generate an AST that represents expr.
+ * Afterwards this AST (or its parts) can be used to construct the return value of fooMacro.
+ *
+ * * reifyTree is evaluated during macro expansion (metalevel 0)
+ * and will produce a tree that when evaluated during the runtime of the program (metalevel 1) will recreate the input tree.
+ *
+ * This provides a way to retain certain trees from macro expansion time to be inspected later, in the runtime.
+ * For example, DSL authors may find it useful to capture DSL snippets into ASTs that are then processed at runtime in a domain-specific way.
+ *
+ * Also note the difference between universes of the runtime trees produced by two reifies:
+ *
+ * * The result of compiling and running the result of reify will be bound to the Universe that called reify.
+ * This is possible because it's a macro, so it can generate whatever code it wishes.
+ *
+ * * The result of compiling and running the result of reifyTree will be the ``prefix'' that needs to be passed explicitly.
+ * This happens because the Universe of the evaluated result is from a different metalevel than the Context the called reify.
+ *
+ * Typical usage of this function is to retain some of the trees received/created by a macro
+ * into the form that can be inspected (via pattern matching) or compiled/run (by a reflective ToolBox) during the runtime.
+ */
+ def reifyTree(prefix: Tree, tree: Tree): Tree
+
+ /** Given a type, generate a tree that when compiled and executed produces the original type.
+ * The produced tree will be bound to the mirror specified by ``prefix'' (also see ``reflectMirrorPrefix'').
+ * For more information and examples see the documentation for ``Context.reifyTree'' and ``Universe.reify''.
+ */
+ def reifyType(prefix: Tree, tpe: Type, dontSpliceAtTopLevel: Boolean = false, concrete: Boolean = false): Tree
+
+ /** Given a type, generate a tree that when compiled and executed produces the erasure of the original type.
+ * If ``concrete'' is true, then this function will bail on types, whose erasure includes abstract types (like `ClassTag` does).
+ */
+ def reifyErasure(tpe: Type, concrete: Boolean = true): Tree
+
+ /** Undoes reification of a tree.
+ *
+ * This reversion doesn't simply restore the original tree (that would lose the context of reification),
+ * but does something more involved that conforms to the following laws:
+ *
+ * 1) unreifyTree(reifyTree(tree)) != tree // unreified tree is tree + saved context
+ * // in current implementation, the result of unreify is opaque
+ * // i.e. there's no possibility to inspect underlying tree/context
+ *
+ * 2) reifyTree(unreifyTree(reifyTree(tree))) == reifyTree(tree) // the result of reifying a tree in its original context equals to
+ * // the result of reifying a tree along with its saved context
+ *
+ * 3) compileAndEval(unreifyTree(reifyTree(tree))) ~ compileAndEval(tree) // at runtime original and unreified trees are behaviorally equivalent
+ */
+ def unreifyTree(tree: Tree): Tree
+}
+
+// made these guys non path-dependent, otherwise exception handling quickly becomes a mess
+
+case class ReificationError(var pos: reflect.api.Position, val msg: String) extends Throwable(msg)
+
+case class UnexpectedReificationError(val pos: reflect.api.Position, val msg: String, val cause: Throwable = null) extends Throwable(msg, cause) \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Settings.scala b/src/library/scala/reflect/makro/Settings.scala
new file mode 100644
index 0000000000..c4a8ebd1b5
--- /dev/null
+++ b/src/library/scala/reflect/makro/Settings.scala
@@ -0,0 +1,38 @@
+package scala.reflect.makro
+
+trait Settings {
+ self: Context =>
+
+ /** Exposes macro-specific settings as a list of strings.
+ * These settings are passed to the compiler via the "-Xmacro-settings:setting1,setting2...,settingN" command-line option.
+ */
+ def settings: List[String]
+
+ /** Exposes current compiler settings as a list of options.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ // [Eugene] ugly? yes, but I don't really fancy copy/pasting all our settings here and keep it synchronized at all times
+ // why all settings? because macros need to be in full control of the stuff going on
+ // maybe later we can implement a gettable/settable list of important settings, but for now let's leave it like that
+ def compilerSettings: List[String]
+
+ /** Updates current compiler settings with an option string.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def setCompilerSettings(options: String): this.type
+
+ /** Updates current compiler settings with a list of options.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def setCompilerSettings(options: List[String]): this.type
+
+ /** Temporary sets compiler settings to a given option string and executes a given closure.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def withCompilerSettings[T](options: String)(op: => T): T
+
+ /** Temporary sets compiler settings to a given list of options and executes a given closure.
+ * Use `scalac -help`, `scalac -X` and `scalac -Y` to learn about currently supported options.
+ */
+ def withCompilerSettings[T](options: List[String])(op: => T): T
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Symbols.scala b/src/library/scala/reflect/makro/Symbols.scala
new file mode 100644
index 0000000000..ca1c17534c
--- /dev/null
+++ b/src/library/scala/reflect/makro/Symbols.scala
@@ -0,0 +1,24 @@
+package scala.reflect.makro
+
+trait Symbols {
+ self: Context =>
+
+ /** Can this symbol be loaded by a reflective mirror?
+ *
+ * Scalac relies on `ScalaSignature' annotation to retain symbols across compilation runs.
+ * Such annotations (also called "pickles") are applied on top-level classes and include information
+ * about all symbols reachable from the annotee. However, local symbols (e.g. classes or definitions local to a block)
+ * are typically unreachable and information about them gets lost.
+ *
+ * This method is useful for macro writers who wish to save certain ASTs to be used at runtime.
+ * With `isLocatable' it's possible to check whether a tree can be retained as is, or it needs special treatment.
+ */
+ def isLocatable(sym: Symbol): Boolean
+
+ /** Is this symbol static (i.e. with no outer instance)?
+ * Q: When exactly is a sym marked as STATIC?
+ * A: If it's a member of a toplevel object, or of an object contained in a toplevel object, or any number of levels deep.
+ * http://groups.google.com/group/scala-internals/browse_thread/thread/d385bcd60b08faf6
+ */
+ def isStatic(sym: Symbol): Boolean
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Typers.scala b/src/library/scala/reflect/makro/Typers.scala
new file mode 100644
index 0000000000..c62c5f254c
--- /dev/null
+++ b/src/library/scala/reflect/makro/Typers.scala
@@ -0,0 +1,85 @@
+package scala.reflect.makro
+
+trait Typers {
+ self: Context =>
+
+ import mirror._
+
+ /** Contexts that represent macros in-flight, including the current one. Very much like a stack trace, but for macros only.
+ * Can be useful for interoperating with other macros and for imposing compiler-friendly limits on macro expansion.
+ *
+ * Is also priceless for emitting sane error messages for macros that are called by other macros on synthetic (i.e. position-less) trees.
+ * In that dire case navigate the ``openMacros'' stack, and it will most likely contain at least one macro with a position-ful macro application.
+ * See ``enclosingPosition'' for a default implementation of this logic.
+ *
+ * Unlike `enclosingMacros`, this is a def, which means that it gets recalculated on every invocation,
+ * so it might change depending on what is going on during macro expansion.
+ */
+ def openMacros: List[Context]
+
+ /** Types along with corresponding trees for which implicit arguments are currently searched.
+ * Can be useful to get information about an application with an implicit parameter that is materialized during current macro expansion.
+ *
+ * Unlike `enclosingImplicits`, this is a def, which means that it gets recalculated on every invocation,
+ * so it might change depending on what is going on during macro expansion.
+ */
+ def openImplicits: List[(Type, Tree)]
+
+ /** Typechecks the provided tree against the expected type ``pt'' in the macro callsite context.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of a typecheck error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Ymacro-debug-verbose.
+ * Unlike in ``inferImplicitValue'' and ``inferImplicitView'', ``silent'' is false by default.
+ *
+ * Typechecking can be steered with the following optional parameters:
+ * ``withImplicitViewsDisabled'' recursively prohibits implicit views (though, implicit vals will still be looked up and filled in), default value is false
+ * ``withMacrosDisabled'' recursively prohibits macro expansions and macro-based implicits, default value is false
+ */
+ def typeCheck(tree: Tree, pt: Type = WildcardType, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): Tree
+
+ /** Infers an implicit value of the expected type ``pt'' in the macro callsite context.
+ * Optional ``pos'' parameter provides a position that will be associated with the implicit search.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitValue(pt: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: Position = enclosingPosition): Tree
+
+ /** Infers an implicit view from the provided tree ``tree'' from the type ``from'' to the type ``to'' in the macro callsite context.
+ *
+ * Optional ``pos'' parameter provides a position that will be associated with the implicit search.
+ * Another optional parameter, ``reportAmbiguous`` controls whether ambiguous implicit errors should be reported.
+ * If we search for a view simply to find out whether one type is coercible to another, it might be desirable to set this flag to ``false''.
+ *
+ * If ``silent'' is false, ``TypeError'' will be thrown in case of an inference error.
+ * If ``silent'' is true, the typecheck is silent and will return ``EmptyTree'' if an error occurs.
+ * Such errors don't vanish and can be inspected by turning on -Xlog-implicits.
+ * Unlike in ``typeCheck'', ``silent'' is true by default.
+ */
+ def inferImplicitView(tree: Tree, from: Type, to: Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, reportAmbiguous: Boolean = true, pos: Position = enclosingPosition): Tree
+
+ /** Recursively resets symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetAllAttrs[T <: Tree](tree: T): T
+
+ /** Recursively resets locally defined symbols and types in a given tree.
+ *
+ * Note that this does not revert the tree to its pre-typer shape.
+ * For more info, read up https://issues.scala-lang.org/browse/SI-5464.
+ */
+ def resetLocalAttrs[T <: Tree](tree: T): T
+
+ /** Represents an error during typechecking
+ */
+ type TypeError <: Throwable
+ val TypeError: TypeErrorExtractor
+ abstract class TypeErrorExtractor {
+ def unapply(error: TypeError): Option[(Position, String)]
+ }
+} \ No newline at end of file
diff --git a/src/library/scala/reflect/makro/Util.scala b/src/library/scala/reflect/makro/Util.scala
new file mode 100644
index 0000000000..16eb2395a9
--- /dev/null
+++ b/src/library/scala/reflect/makro/Util.scala
@@ -0,0 +1,31 @@
+package scala.reflect.makro
+
+trait Util {
+ self: Context =>
+
+ def literalNull: Expr[Null]
+
+ def literalUnit: Expr[Unit]
+
+ def literalTrue: Expr[Boolean]
+
+ def literalFalse: Expr[Boolean]
+
+ def literal(x: Boolean): Expr[Boolean]
+
+ def literal(x: Byte): Expr[Byte]
+
+ def literal(x: Short): Expr[Short]
+
+ def literal(x: Int): Expr[Int]
+
+ def literal(x: Long): Expr[Long]
+
+ def literal(x: Float): Expr[Float]
+
+ def literal(x: Double): Expr[Double]
+
+ def literal(x: String): Expr[String]
+
+ def literal(x: Char): Expr[Char]
+}
diff --git a/src/library/scala/reflect/makro/internal/Utils.scala b/src/library/scala/reflect/makro/internal/Utils.scala
new file mode 100644
index 0000000000..3af58e1c88
--- /dev/null
+++ b/src/library/scala/reflect/makro/internal/Utils.scala
@@ -0,0 +1,146 @@
+package scala.reflect.makro
+
+import scala.reflect.api.Universe
+import language.implicitConversions
+import language.experimental.macros
+
+/** This package is required by the compiler and <b>should not be used in client code</b>. */
+package object internal {
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeArrayTag[T](u: Universe): ArrayTag[T] = macro materializeArrayTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeArrayTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ArrayTag[T]] =
+ c.Expr[Nothing](c.materializeArrayTag(u.tree, implicitly[c.TypeTag[T]].tpe))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeErasureTag[T](u: Universe): ErasureTag[T] = macro materializeErasureTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeErasureTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ErasureTag[T]] =
+ c.Expr[Nothing](c.materializeErasureTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = false))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeClassTag[T](u: Universe): ClassTag[T] = macro materializeClassTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeClassTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[ClassTag[T]] =
+ c.Expr[Nothing](c.materializeClassTag(u.tree, implicitly[c.TypeTag[T]].tpe))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeTypeTag[T](u: Universe): u.TypeTag[T] = macro materializeTypeTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.TypeTag[T]] =
+ c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = false))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeConcreteTypeTag[T](u: Universe): u.ConcreteTypeTag[T] = macro materializeConcreteTypeTag_impl[T]
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ def materializeConcreteTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe]): c.Expr[u.value.ConcreteTypeTag[T]] =
+ c.Expr[Nothing](c.materializeTypeTag(u.tree, implicitly[c.TypeTag[T]].tpe, concrete = true))(c.TypeTag.Nothing)
+
+ /** This method is required by the compiler and <b>should not be used in client code</b>. */
+ private[scala] implicit def context2utils(c0: Context) : Utils { val c: c0.type } = new { val c: c0.type = c0 } with Utils
+}
+
+package internal {
+ private[scala] abstract class Utils {
+ val c: Context
+
+ import c.mirror._
+ import definitions._
+
+ val coreTags = Map(
+ ByteClass.asType -> newTermName("Byte"),
+ ShortClass.asType -> newTermName("Short"),
+ CharClass.asType -> newTermName("Char"),
+ IntClass.asType -> newTermName("Int"),
+ LongClass.asType -> newTermName("Long"),
+ FloatClass.asType -> newTermName("Float"),
+ DoubleClass.asType -> newTermName("Double"),
+ BooleanClass.asType -> newTermName("Boolean"),
+ UnitClass.asType -> newTermName("Unit"),
+ AnyClass.asType -> newTermName("Any"),
+ ObjectClass.asType -> newTermName("Object"),
+ AnyValClass.asType -> newTermName("AnyVal"),
+ AnyRefClass.asType -> newTermName("AnyRef"),
+ NothingClass.asType -> newTermName("Nothing"),
+ NullClass.asType -> newTermName("Null"),
+ StringClass.asType -> newTermName("String"))
+
+ // todo. the following two methods won't be necessary once we implement implicit macro generators for tags
+
+ def materializeArrayTag(prefix: Tree, tpe: Type): Tree =
+ materializeClassTag(prefix, tpe)
+
+ def materializeErasureTag(prefix: Tree, tpe: Type, concrete: Boolean): Tree =
+ if (concrete) materializeClassTag(prefix, tpe) else materializeTypeTag(prefix, tpe, concrete = false)
+
+ def materializeClassTag(prefix: Tree, tpe: Type): Tree =
+ materializeTag(prefix, tpe, ClassTagModule, {
+ val erasure = c.reifyErasure(tpe, concrete = true)
+ val factory = TypeApply(Select(Ident(ClassTagModule), "apply"), List(TypeTree(tpe)))
+ Apply(factory, List(erasure))
+ })
+
+ def materializeTypeTag(prefix: Tree, tpe: Type, concrete: Boolean): Tree = {
+ val tagModule = if (concrete) ConcreteTypeTagModule else TypeTagModule
+ materializeTag(prefix, tpe, tagModule, c.reifyType(prefix, tpe, dontSpliceAtTopLevel = true, concrete = concrete))
+ }
+
+ private def materializeTag(prefix: Tree, tpe: Type, tagModule: Symbol, materializer: => Tree): Tree = {
+ val result =
+ tpe match {
+ case coreTpe if coreTags contains coreTpe =>
+ val ref = if (tagModule.owner.isPackageClass) Ident(tagModule) else Select(prefix, tagModule.name)
+ Select(ref, coreTags(coreTpe))
+ case _ =>
+ val manifestInScope = nonSyntheticManifestInScope(tpe)
+ if (manifestInScope.isEmpty) translatingReificationErrors(materializer)
+ else gen.mkMethodCall(staticModule("scala.reflect.package"), newTermName("manifestToConcreteTypeTag"), List(tpe), List(manifestInScope))
+ }
+ try c.typeCheck(result)
+ catch { case terr @ c.TypeError(pos, msg) => failTag(terr) }
+ }
+
+ private def nonSyntheticManifestInScope(tpe: Type) = {
+ val ManifestClass = staticClass("scala.reflect.Manifest")
+ val ManifestModule = staticModule("scala.reflect.Manifest")
+ val manifest = c.inferImplicitValue(appliedType(ManifestClass.asTypeConstructor, List(tpe)))
+ val notOk = manifest.isEmpty || (manifest exists (sub => sub.symbol != null && (sub.symbol == ManifestModule || sub.symbol.owner == ManifestModule)))
+ if (notOk) EmptyTree else manifest
+ }
+
+ def materializeExpr(prefix: Tree, expr: Tree): Tree = {
+ val result = translatingReificationErrors(c.reifyTree(prefix, expr))
+ try c.typeCheck(result)
+ catch { case terr @ c.TypeError(pos, msg) => failExpr(terr) }
+ }
+
+ private def translatingReificationErrors(materializer: => Tree): Tree = {
+ try materializer
+ catch {
+ case ReificationError(pos, msg) =>
+ c.error(pos.asInstanceOf[c.Position], msg) // this cast is a very small price for the sanity of exception handling
+ EmptyTree
+ case UnexpectedReificationError(pos, err, cause) if cause != null =>
+ throw cause
+ }
+ }
+
+ private def failTag(reason: Any): Nothing = {
+ val Apply(TypeApply(fun, List(tpeTree)), _) = c.macroApplication
+ val tpe = tpeTree.tpe
+ val PolyType(_, MethodType(_, tagTpe)) = fun.tpe
+ val tagModule = tagTpe.typeSymbol.companionSymbol
+ if (c.compilerSettings.contains("-Xlog-implicits"))
+ c.echo(c.enclosingPosition, "cannot materialize " + tagModule.name + "[" + tpe + "] because:\n" + reason)
+ c.abort(c.enclosingPosition, "No %s available for %s".format(tagModule.name, tpe))
+ }
+
+ private def failExpr(reason: Any): Nothing =
+ c.abort(c.enclosingPosition, "Cannot materialize Expr because:\n" + reason)
+ }
+}
diff --git a/src/library/scala/reflect/makro/internal/macroImpl.scala b/src/library/scala/reflect/makro/internal/macroImpl.scala
new file mode 100644
index 0000000000..9cf4d23072
--- /dev/null
+++ b/src/library/scala/reflect/makro/internal/macroImpl.scala
@@ -0,0 +1,5 @@
+package scala.reflect.makro
+package internal
+
+/** This type is required by the compiler and <b>should not be used in client code</b>. */
+class macroImpl(val referenceToMacroImpl: Any) extends annotation.StaticAnnotation
diff --git a/src/library/scala/reflect/package.scala b/src/library/scala/reflect/package.scala
index 1c3e618520..38a144cd49 100644
--- a/src/library/scala/reflect/package.scala
+++ b/src/library/scala/reflect/package.scala
@@ -2,20 +2,41 @@ package scala
package object reflect {
+ import ReflectionUtils._
+ import scala.compat.Platform.EOL
+
// !!! This was a val; we can't throw exceptions that aggressively without breaking
// non-standard environments, e.g. google app engine. I made it a lazy val, but
// I think it would be better yet to throw the exception somewhere else - not during
// initialization, but in response to a doomed attempt to utilize it.
- lazy val mirror: api.Mirror = {
- // we use (Java) reflection here so that we can keep reflect.runtime and reflect.internals in a seperate jar
- ReflectionUtils.singletonInstanceOpt("scala.reflect.runtime.Mirror") collect { case x: api.Mirror => x } getOrElse {
- throw new UnsupportedOperationException("Scala reflection not available on this platform")
+
+ // todo. default mirror (a static object) might become a source for memory leaks (because it holds a strong reference to a classloader)!
+ lazy val mirror: api.Mirror =
+ try mkMirror(defaultReflectionClassLoader)
+ catch {
+ case ex: UnsupportedOperationException =>
+ new DummyMirror(defaultReflectionClassLoader)
}
- }
- type Symbol = mirror.Symbol
- type Type = mirror.Type
- type Tree = mirror.Tree
+ private[scala] def mirrorDiagnostics(cl: ClassLoader): String = """
+ |
+ | This error has happened because `scala.reflect.runtime.package` located in
+ | scala-compiler.jar cannot be loaded. Classloader you are using is:
+ | %s.
+ |
+ | For the instructions for some of the situations that might be relevant
+ | visit our knowledge base at https://gist.github.com/2391081.
+ """.stripMargin('|').format(show(cl))
+
+ def mkMirror(classLoader: ClassLoader): api.Mirror = {
+ val coreClassLoader = getClass.getClassLoader
+ val instance = invokeFactoryOpt(coreClassLoader, "scala.reflect.runtime.package", "mkMirror", classLoader)
+ instance match {
+ case Some(x: api.Mirror) => x
+ case Some(_) => throw new UnsupportedOperationException("Available scala reflection implementation is incompatible with this interface." + mirrorDiagnostics(coreClassLoader))
+ case None => throw new UnsupportedOperationException("Scala reflection not available on this platform." + mirrorDiagnostics(coreClassLoader))
+ }
+ }
@deprecated("Use `@scala.beans.BeanDescription` instead", "2.10.0")
type BeanDescription = scala.beans.BeanDescription
@@ -31,4 +52,19 @@ package object reflect {
type BooleanBeanProperty = scala.beans.BooleanBeanProperty
@deprecated("Use `@scala.beans.ScalaBeanInfo` instead", "2.10.0")
type ScalaBeanInfo = scala.beans.ScalaBeanInfo
+
+ // ArrayTag trait is defined separately from the mirror
+ // ErasureTag trait is defined separately from the mirror
+ // ConcreteErasureTag trait is defined separately from the mirror
+ // ClassTag class is defined separately from the mirror
+ type TypeTag[T] = scala.reflect.mirror.TypeTag[T]
+ type ConcreteTypeTag[T] = scala.reflect.mirror.ConcreteTypeTag[T]
+
+ // ClassTag object is defined separately from the mirror
+ lazy val TypeTag = scala.reflect.mirror.TypeTag
+ lazy val ConcreteTypeTag = scala.reflect.mirror.ConcreteTypeTag
+
+ def arrayTagToClassManifest[T](tag: ArrayTag[T]): ClassManifest[T] = TagInterop.arrayTagToClassManifest[T](tag)
+ def concreteTypeTagToManifest[T](tag: ConcreteTypeTag[T]): Manifest[T] = TagInterop.concreteTypeTagToManifest[T](tag)
+ def manifestToConcreteTypeTag[T](tag: Manifest[T]): ConcreteTypeTag[T] = TagInterop.manifestToConcreteTypeTag[T](tag)
}
diff --git a/src/library/scala/runtime/AbstractPartialFunction.scala b/src/library/scala/runtime/AbstractPartialFunction.scala
index 2e435d8a7e..f499350ce9 100644
--- a/src/library/scala/runtime/AbstractPartialFunction.scala
+++ b/src/library/scala/runtime/AbstractPartialFunction.scala
@@ -36,7 +36,7 @@ abstract class AbstractPartialFunction[@specialized(scala.Int, scala.Long, scala
// let's not make it final so as not to confuse anyone
/*final*/ def apply(x: T1): R = applyOrElse(x, PartialFunction.empty)
- override final def andThen[C](k: R => C) : PartialFunction[T1, C] =
+ @annotation.unspecialized override final def andThen[C](k: R => C) : PartialFunction[T1, C] =
new AbstractPartialFunction[T1, C] {
def isDefinedAt(x: T1): Boolean = self.isDefinedAt(x)
override def applyOrElse[A1 <: T1, C1 >: C](x: A1, default: A1 => C1): C1 =
@@ -61,8 +61,8 @@ abstract class AbstractPartialFunction[@specialized(scala.Int, scala.Long, scala
*/
abstract class AbstractTotalFunction[@specialized(scala.Int, scala.Long, scala.Float, scala.Double, scala.AnyRef) -T1, @specialized(scala.Unit, scala.Boolean, scala.Int, scala.Float, scala.Long, scala.Double, scala.AnyRef) +R] extends Function1[T1, R] with PartialFunction[T1, R] {
final def isDefinedAt(x: T1): Boolean = true
- override final def applyOrElse[A1 <: T1, B1 >: R](x: A1, default: A1 => B1): B1 = apply(x)
- override final def orElse[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = this
+ @annotation.unspecialized override final def applyOrElse[A1 <: T1, B1 >: R](x: A1, default: A1 => B1): B1 = apply(x)
+ @annotation.unspecialized override final def orElse[A1 <: T1, B1 >: R](that: PartialFunction[A1, B1]): PartialFunction[A1, B1] = this
//TODO: check generated code for PF literal here
- override final def andThen[C](k: R => C): PartialFunction[T1, C] = { case x => k(apply(x)) }
+ @annotation.unspecialized override final def andThen[C](k: R => C): PartialFunction[T1, C] = { case x => k(apply(x)) }
}
diff --git a/src/library/scala/runtime/BoxesRunTime.java b/src/library/scala/runtime/BoxesRunTime.java
index b19c8d086c..258a176671 100644
--- a/src/library/scala/runtime/BoxesRunTime.java
+++ b/src/library/scala/runtime/BoxesRunTime.java
@@ -31,14 +31,16 @@ public final class BoxesRunTime
{
private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7;
+ /** We don't need to return BYTE and SHORT, as everything which might
+ * care widens to INT.
+ */
private static int typeCode(Object a) {
if (a instanceof java.lang.Integer) return INT;
- if (a instanceof java.lang.Byte) return BYTE;
- if (a instanceof java.lang.Character) return CHAR;
- if (a instanceof java.lang.Long) return LONG;
if (a instanceof java.lang.Double) return DOUBLE;
- if (a instanceof java.lang.Short) return SHORT;
+ if (a instanceof java.lang.Long) return LONG;
+ if (a instanceof java.lang.Character) return CHAR;
if (a instanceof java.lang.Float) return FLOAT;
+ if ((a instanceof java.lang.Byte) || (a instanceof java.lang.Short)) return INT;
return OTHER;
}
@@ -119,15 +121,6 @@ public final class BoxesRunTime
/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */
- private static int eqTypeCode(Number a) {
- if ((a instanceof java.lang.Integer) || (a instanceof java.lang.Byte)) return INT;
- if (a instanceof java.lang.Long) return LONG;
- if (a instanceof java.lang.Double) return DOUBLE;
- if (a instanceof java.lang.Short) return INT;
- if (a instanceof java.lang.Float) return FLOAT;
- return OTHER;
- }
-
public static boolean equals(Object x, Object y) {
if (x == y) return true;
return equals2(x, y);
@@ -159,8 +152,8 @@ public final class BoxesRunTime
}
public static boolean equalsNumNum(java.lang.Number xn, java.lang.Number yn) {
- int xcode = eqTypeCode(xn);
- int ycode = eqTypeCode(yn);
+ int xcode = typeCode(xn);
+ int ycode = typeCode(yn);
switch (ycode > xcode ? ycode : xcode) {
case INT:
return xn.intValue() == yn.intValue();
@@ -192,8 +185,11 @@ public final class BoxesRunTime
}
private static boolean equalsNumChar(java.lang.Number xn, java.lang.Character yc) {
+ if (yc == null)
+ return xn == null;
+
char ch = yc.charValue();
- switch (eqTypeCode(xn)) {
+ switch (typeCode(xn)) {
case INT:
return xn.intValue() == ch;
case LONG:
@@ -203,9 +199,6 @@ public final class BoxesRunTime
case DOUBLE:
return xn.doubleValue() == ch;
default:
- if (xn == null)
- return yc == null;
-
return xn.equals(yc);
}
}
@@ -271,6 +264,31 @@ public final class BoxesRunTime
else return a.hashCode();
}
+ private static int unboxCharOrInt(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).intValue();
+ }
+ private static long unboxCharOrLong(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).longValue();
+ }
+ private static float unboxCharOrFloat(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).floatValue();
+ }
+ private static double unboxCharOrDouble(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).doubleValue();
+ }
+
/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */
/** arg1 + arg2 */
@@ -279,24 +297,16 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 + val2);
+ return boxToInteger(unboxCharOrInt(arg1, code1) + unboxCharOrInt(arg2, code2));
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 + val2);
+ return boxToLong(unboxCharOrLong(arg1, code1) + unboxCharOrLong(arg2, code2));
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 + val2);
+ return boxToFloat(unboxCharOrFloat(arg1, code1) + unboxCharOrFloat(arg2, code2));
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 + val2);
+ return boxToDouble(unboxCharOrDouble(arg1, code1) + unboxCharOrDouble(arg2, code2));
}
throw new NoSuchMethodException();
}
@@ -307,24 +317,16 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 - val2);
+ return boxToInteger(unboxCharOrInt(arg1, code1) - unboxCharOrInt(arg2, code2));
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 - val2);
+ return boxToLong(unboxCharOrLong(arg1, code1) - unboxCharOrLong(arg2, code2));
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 - val2);
+ return boxToFloat(unboxCharOrFloat(arg1, code1) - unboxCharOrFloat(arg2, code2));
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 - val2);
+ return boxToDouble(unboxCharOrDouble(arg1, code1) - unboxCharOrDouble(arg2, code2));
}
throw new NoSuchMethodException();
}
@@ -335,24 +337,16 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 * val2);
+ return boxToInteger(unboxCharOrInt(arg1, code1) * unboxCharOrInt(arg2, code2));
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 * val2);
+ return boxToLong(unboxCharOrLong(arg1, code1) * unboxCharOrLong(arg2, code2));
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 * val2);
+ return boxToFloat(unboxCharOrFloat(arg1, code1) * unboxCharOrFloat(arg2, code2));
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 * val2);
+ return boxToDouble(unboxCharOrDouble(arg1, code1) * unboxCharOrDouble(arg2, code2));
}
throw new NoSuchMethodException();
}
@@ -362,26 +356,16 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 / val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 / val2);
- }
- if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 / val2);
- }
- if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 / val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) / unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) / unboxCharOrLong(arg2, code2));
+ if (maxcode <= FLOAT)
+ return boxToFloat(unboxCharOrFloat(arg1, code1) / unboxCharOrFloat(arg2, code2));
+ if (maxcode <= DOUBLE)
+ return boxToDouble(unboxCharOrDouble(arg1, code1) / unboxCharOrDouble(arg2, code2));
+
throw new NoSuchMethodException();
}
@@ -390,26 +374,16 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 % val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 % val2);
- }
- if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 % val2);
- }
- if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 % val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) % unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) % unboxCharOrLong(arg2, code2));
+ if (maxcode <= FLOAT)
+ return boxToFloat(unboxCharOrFloat(arg1, code1) % unboxCharOrFloat(arg2, code2));
+ if (maxcode <= DOUBLE)
+ return boxToDouble(unboxCharOrDouble(arg1, code1) % unboxCharOrDouble(arg2, code2));
+
throw new NoSuchMethodException();
}
@@ -418,24 +392,24 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
if (code1 <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToInteger(val1 >> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToInteger(val1 >> val2);
}
}
if (code1 <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToLong(val1 >> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToLong(val1 >> val2);
}
}
@@ -447,24 +421,24 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
if (code1 <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToInteger(val1 << val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToInteger(val1 << val2);
}
}
if (code1 <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToLong(val1 << val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToLong(val1 << val2);
}
}
@@ -476,24 +450,24 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
if (code1 <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToInteger(val1 >>> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToInteger(val1 >>> val2);
}
}
if (code1 <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToLong(val1 >>> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToLong(val1 >>> val2);
}
}
@@ -504,19 +478,19 @@ public final class BoxesRunTime
public static Object negate(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
if (code <= INT) {
- int val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).intValue();
+ int val = unboxCharOrInt(arg, code);
return boxToInteger(-val);
}
if (code <= LONG) {
- long val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).longValue();
+ long val = unboxCharOrLong(arg, code);
return boxToLong(-val);
}
if (code <= FLOAT) {
- float val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).floatValue();
+ float val = unboxCharOrFloat(arg, code);
return boxToFloat(-val);
}
if (code <= DOUBLE) {
- double val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).doubleValue();
+ double val = unboxCharOrDouble(arg, code);
return boxToDouble(-val);
}
throw new NoSuchMethodException();
@@ -526,20 +500,16 @@ public final class BoxesRunTime
public static Object positive(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
if (code <= INT) {
- int val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).intValue();
- return boxToInteger(+val);
+ return boxToInteger(+unboxCharOrInt(arg, code));
}
if (code <= LONG) {
- long val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).longValue();
- return boxToLong(+val);
+ return boxToLong(+unboxCharOrLong(arg, code));
}
if (code <= FLOAT) {
- float val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).floatValue();
- return boxToFloat(+val);
+ return boxToFloat(+unboxCharOrFloat(arg, code));
}
if (code <= DOUBLE) {
- double val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).doubleValue();
- return boxToDouble(+val);
+ return boxToDouble(+unboxCharOrDouble(arg, code));
}
throw new NoSuchMethodException();
}
@@ -547,72 +517,60 @@ public final class BoxesRunTime
/** arg1 & arg2 */
public static Object takeAnd(Object arg1, Object arg2) throws NoSuchMethodException {
if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
- if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue());
+ else
throw new NoSuchMethodException();
- }
- return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue());
}
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 & val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 & val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) & unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) & unboxCharOrLong(arg2, code2));
+
throw new NoSuchMethodException();
}
/** arg1 | arg2 */
public static Object takeOr(Object arg1, Object arg2) throws NoSuchMethodException {
if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
- if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() | ((java.lang.Boolean) arg2).booleanValue());
+ else
throw new NoSuchMethodException();
- }
- return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() | ((java.lang.Boolean) arg2).booleanValue());
}
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 | val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 | val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) | unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) | unboxCharOrLong(arg2, code2));
+
throw new NoSuchMethodException();
}
/** arg1 ^ arg2 */
public static Object takeXor(Object arg1, Object arg2) throws NoSuchMethodException {
if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
- if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() ^ ((java.lang.Boolean) arg2).booleanValue());
+ else
throw new NoSuchMethodException();
- }
- return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() ^ ((java.lang.Boolean) arg2).booleanValue());
}
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 ^ val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 ^ val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) ^ unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) ^ unboxCharOrLong(arg2, code2));
+
throw new NoSuchMethodException();
}
@@ -636,12 +594,10 @@ public final class BoxesRunTime
public static Object complement(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
if (code <= INT) {
- int val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).intValue();
- return boxToInteger(~val);
+ return boxToInteger(~unboxCharOrInt(arg, code));
}
if (code <= LONG) {
- long val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).longValue();
- return boxToLong(~val);
+ return boxToLong(~unboxCharOrLong(arg, code));
}
throw new NoSuchMethodException();
}
@@ -667,23 +623,23 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 < val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 < val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 < val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 < val2);
}
throw new NoSuchMethodException();
@@ -694,23 +650,23 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 <= val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 <= val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 <= val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 <= val2);
}
throw new NoSuchMethodException();
@@ -721,23 +677,23 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 >= val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 >= val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 >= val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 >= val2);
}
throw new NoSuchMethodException();
@@ -748,33 +704,30 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 > val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 > val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 > val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 > val2);
}
throw new NoSuchMethodException();
}
-
+
public static boolean isBoxedNumberOrBoolean(Object arg) {
- if (arg instanceof java.lang.Boolean)
- return true;
- else
- return isBoxedNumber(arg);
+ return (arg instanceof java.lang.Boolean) || isBoxedNumber(arg);
}
public static boolean isBoxedNumber(Object arg) {
return (
diff --git a/src/library/scala/runtime/RichDouble.scala b/src/library/scala/runtime/RichDouble.scala
index 0a9cda40ec..f702b9e3da 100644
--- a/src/library/scala/runtime/RichDouble.scala
+++ b/src/library/scala/runtime/RichDouble.scala
@@ -35,4 +35,16 @@ final class RichDouble(val self: Double) extends FractionalProxy[Double] {
def isInfinity: Boolean = java.lang.Double.isInfinite(self)
def isPosInfinity: Boolean = isInfinity && self > 0.0
def isNegInfinity: Boolean = isInfinity && self < 0.0
+
+ override def isValidByte = self.toByte.toDouble == self
+ override def isValidShort = self.toShort.toDouble == self
+ override def isValidChar = self.toChar.toDouble == self
+ override def isValidInt = self.toInt.toDouble == self
+ // override def isValidLong = { val l = self.toLong; l.toDouble == self && l != Long.MaxValue }
+ // override def isValidFloat = self.toFloat.toDouble == self
+ // override def isValidDouble = !java.lang.Double.isNaN(self)
+ override def isWhole = {
+ val l = self.toLong
+ l.toDouble == self || l == Long.MaxValue && self < Double.PositiveInfinity || l == Long.MinValue && self > Double.NegativeInfinity
+ }
}
diff --git a/src/library/scala/runtime/RichFloat.scala b/src/library/scala/runtime/RichFloat.scala
index c6478ec0c9..6b72a9dd55 100644
--- a/src/library/scala/runtime/RichFloat.scala
+++ b/src/library/scala/runtime/RichFloat.scala
@@ -36,4 +36,16 @@ final class RichFloat(val self: Float) extends FractionalProxy[Float] {
def isInfinity: Boolean = java.lang.Float.isInfinite(self)
def isPosInfinity: Boolean = isInfinity && self > 0.0f
def isNegInfinity: Boolean = isInfinity && self < 0.0f
+
+ override def isValidByte = self.toByte.toFloat == self
+ override def isValidShort = self.toShort.toFloat == self
+ override def isValidChar = self.toChar.toFloat == self
+ override def isValidInt = { val i = self.toInt; i.toFloat == self && i != Int.MaxValue }
+ // override def isValidLong = { val l = self.toLong; l.toFloat == self && l != Long.MaxValue }
+ // override def isValidFloat = !java.lang.Float.isNaN(self)
+ // override def isValidDouble = !java.lang.Float.isNaN(self)
+ override def isWhole = {
+ val l = self.toLong
+ l.toFloat == self || l == Long.MaxValue && self < Float.PositiveInfinity || l == Long.MinValue && self > Float.NegativeInfinity
+ }
}
diff --git a/src/library/scala/runtime/RichInt.scala b/src/library/scala/runtime/RichInt.scala
index cf5aab0be4..d03968212f 100644
--- a/src/library/scala/runtime/RichInt.scala
+++ b/src/library/scala/runtime/RichInt.scala
@@ -9,7 +9,6 @@
package scala.runtime
import scala.collection.immutable.Range
-import annotation.bridge
// Note that this does not implement IntegralProxy[Int] so that it can return
// the Int-specific Range class from until/to.
@@ -37,9 +36,6 @@ final class RichInt(val self: Int) extends ScalaNumberProxy[Int] with RangedProx
*/
def until(end: Int, step: Int): Range = Range(self, end, step)
-// @bridge
-// def until(end: Int): Range with Range.ByOne = new Range(self, end, 1) with Range.ByOne
-
/** like `until`, but includes the last index */
/**
* @param end The final bound of the range to make.
@@ -56,9 +52,6 @@ final class RichInt(val self: Int) extends ScalaNumberProxy[Int] with RangedProx
*/
def to(end: Int, step: Int): Range.Inclusive = Range.inclusive(self, end, step)
-// @bridge
-// def to(end: Int): Range with Range.ByOne = new Range.Inclusive(self, end, 1) with Range.ByOne
-
/**
* @return `'''this'''` if `'''this''' < that` or `that` otherwise
*/
diff --git a/src/library/scala/runtime/RichLong.scala b/src/library/scala/runtime/RichLong.scala
index f93d9459d1..5784934ffd 100644
--- a/src/library/scala/runtime/RichLong.scala
+++ b/src/library/scala/runtime/RichLong.scala
@@ -12,4 +12,12 @@ final class RichLong(val self: Long) extends IntegralProxy[Long] {
def toBinaryString: String = java.lang.Long.toBinaryString(self)
def toHexString: String = java.lang.Long.toHexString(self)
def toOctalString: String = java.lang.Long.toOctalString(self)
+
+ override def isValidByte = self.toByte.toLong == self
+ override def isValidShort = self.toShort.toLong == self
+ override def isValidChar = self.toChar.toLong == self
+ override def isValidInt = self.toInt.toLong == self
+ // override def isValidLong = true
+ // override def isValidFloat = self.toFloat.toLong == self && self != Long.MaxValue
+ // override def isValidDouble = self.toDouble.toLong == self && self != Long.MaxValue
}
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala
index 8bc63ae3a0..a04fd23710 100644
--- a/src/library/scala/runtime/ScalaRunTime.scala
+++ b/src/library/scala/runtime/ScalaRunTime.scala
@@ -31,7 +31,7 @@ object ScalaRunTime {
clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))
def isValueClass(clazz: Class[_]) = clazz.isPrimitive()
- def isTuple(x: Any) = tupleNames(x.getClass.getName)
+ def isTuple(x: Any) = x != null && tupleNames(x.getClass.getName)
def isAnyVal(x: Any) = x match {
case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true
case _ => false
@@ -47,21 +47,29 @@ object ScalaRunTime {
names.toSet
}
+ /** Return the class object representing an array with element class `clazz`.
+ */
+ def arrayClass(clazz: Class[_]): Class[_] = {
+ // newInstance throws an exception if the erasure is Void.TYPE. see SI-5680
+ if (clazz == java.lang.Void.TYPE) classOf[Array[Unit]]
+ else java.lang.reflect.Array.newInstance(clazz, 0).getClass
+ }
+
+ /** Return the class object representing elements in arrays described by a given schematic.
+ */
+ def arrayElementClass(schematic: Any): Class[_] = schematic match {
+ case cls: Class[_] => cls.getComponentType
+ case tag: ClassTag[_] => tag.erasure
+ case tag: ArrayTag[_] => tag.newArray(0).getClass.getComponentType
+ case _ => throw new UnsupportedOperationException("unsupported schematic %s (%s)".format(schematic, if (schematic == null) "null" else schematic.getClass))
+ }
+
/** Return the class object representing an unboxed value type,
* e.g. classOf[int], not classOf[java.lang.Integer]. The compiler
* rewrites expressions like 5.getClass to come here.
*/
- def anyValClass[T <: AnyVal](value: T): Class[T] = (value match {
- case x: Byte => java.lang.Byte.TYPE
- case x: Short => java.lang.Short.TYPE
- case x: Char => java.lang.Character.TYPE
- case x: Int => java.lang.Integer.TYPE
- case x: Long => java.lang.Long.TYPE
- case x: Float => java.lang.Float.TYPE
- case x: Double => java.lang.Double.TYPE
- case x: Boolean => java.lang.Boolean.TYPE
- case x: Unit => java.lang.Void.TYPE
- }).asInstanceOf[Class[T]]
+ def anyValClass[T <: AnyVal : ClassTag](value: T): Class[T] =
+ classTag[T].erasure.asInstanceOf[Class[T]]
/** Retrieve generic array element */
def array_apply(xs: AnyRef, idx: Int): Any = xs match {
@@ -122,16 +130,18 @@ object ScalaRunTime {
case null => throw new NullPointerException
}
- /** Convert a numeric value array to an object array.
+ /** Convert an array to an object array.
* Needed to deal with vararg arguments of primitive types that are passed
* to a generic Java vararg parameter T ...
*/
- def toObjectArray(src: AnyRef): Array[Object] = {
- val length = array_length(src)
- val dest = new Array[Object](length)
- for (i <- 0 until length)
- array_update(dest, i, array_apply(src, i))
- dest
+ def toObjectArray(src: AnyRef): Array[Object] = src match {
+ case x: Array[AnyRef] => x
+ case _ =>
+ val length = array_length(src)
+ val dest = new Array[Object](length)
+ for (i <- 0 until length)
+ array_update(dest, i, array_apply(src, i))
+ dest
}
def toArray[T](xs: collection.Seq[T]) = {
@@ -224,10 +234,13 @@ object ScalaRunTime {
// Note that these are the implementations called by ##, so they
// must not call ## themselves.
- @inline def hash(x: Any): Int =
- if (x == null) 0
- else if (x.isInstanceOf[java.lang.Number]) BoxesRunTime.hashFromNumber(x.asInstanceOf[java.lang.Number])
- else x.hashCode
+ @inline def hash(x: Any): Int = x match {
+ case null => 0
+ case x: Double => hash(x)
+ case x: Float => hash(x)
+ case x: java.lang.Number => hash(x)
+ case _ => x.hashCode
+ }
@inline def hash(dv: Double): Int = {
val iv = dv.toInt
@@ -285,8 +298,12 @@ object ScalaRunTime {
*/
def stringOf(arg: Any): String = stringOf(arg, scala.Int.MaxValue)
def stringOf(arg: Any, maxElements: Int): String = {
- def isScalaClass(x: AnyRef) =
- Option(x.getClass.getPackage) exists (_.getName startsWith "scala.")
+ def packageOf(x: AnyRef) = x.getClass.getPackage match {
+ case null => ""
+ case p => p.getName
+ }
+ def isScalaClass(x: AnyRef) = packageOf(x) startsWith "scala."
+ def isScalaCompilerClass(x: AnyRef) = packageOf(x) startsWith "scala.tools.nsc."
// When doing our own iteration is dangerous
def useOwnToString(x: Any) = x match {
@@ -302,7 +319,8 @@ object ScalaRunTime {
case _: TraversableView[_, _] => true
// Don't want to a) traverse infinity or b) be overly helpful with peoples' custom
// collections which may have useful toString methods - ticket #3710
- case x: Traversable[_] => !x.hasDefiniteSize || !isScalaClass(x)
+ // or c) print AbstractFiles which are somehow also Iterable[AbstractFile]s.
+ case x: Traversable[_] => !x.hasDefiniteSize || !isScalaClass(x) || isScalaCompilerClass(x)
// Otherwise, nothing could possibly go wrong
case _ => false
}
@@ -329,14 +347,14 @@ object ScalaRunTime {
case null => "null"
case "" => "\"\""
case x: String => if (x.head.isWhitespace || x.last.isWhitespace) "\"" + x + "\"" else x
- case x if useOwnToString(x) => x toString
+ case x if useOwnToString(x) => x.toString
case x: AnyRef if isArray(x) => arrayToString(x)
case x: collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.stringPrefix + "(", ", ", ")")
case x: Iterable[_] => x.iterator take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
case x: Traversable[_] => x take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
case x: Product1[_] if isTuple(x) => "(" + inner(x._1) + ",)" // that special trailing comma
case x: Product if isTuple(x) => x.productIterator map inner mkString ("(", ",", ")")
- case x => x toString
+ case x => x.toString
}
// The try/catch is defense against iterables which aren't actually designed
diff --git a/src/library/scala/runtime/SeqCharSequence.scala b/src/library/scala/runtime/SeqCharSequence.scala
new file mode 100644
index 0000000000..8ef1a9a33e
--- /dev/null
+++ b/src/library/scala/runtime/SeqCharSequence.scala
@@ -0,0 +1,44 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.runtime
+
+import java.util.Arrays.copyOfRange
+
+final class SeqCharSequence(val xs: collection.IndexedSeq[Char]) extends CharSequence {
+ def length: Int = xs.length
+ def charAt(index: Int): Char = xs(index)
+ def subSequence(start: Int, end: Int): CharSequence = new SeqCharSequence(xs.slice(start, end))
+ override def toString = xs.mkString("")
+}
+
+final class ArrayCharSequence(val xs: Array[Char], start: Int, end: Int) extends CharSequence {
+ // yikes
+ // java.lang.VerifyError: (class: scala/runtime/ArrayCharSequence, method: <init> signature: ([C)V)
+ // Constructor must call super() or this()
+ //
+ // def this(xs: Array[Char]) = this(xs, 0, xs.length)
+
+ def length: Int = math.max(0, end - start)
+ def charAt(index: Int): Char = {
+ if (0 <= index && index < length)
+ xs(start + index)
+ else throw new ArrayIndexOutOfBoundsException(index)
+ }
+ def subSequence(start0: Int, end0: Int): CharSequence = {
+ if (start0 < 0) throw new ArrayIndexOutOfBoundsException(start0)
+ else if (end0 > length) throw new ArrayIndexOutOfBoundsException(end0)
+ else if (end0 <= start0) new ArrayCharSequence(xs, 0, 0)
+ else {
+ val newlen = end0 - start0
+ val start1 = start + start0
+ new ArrayCharSequence(xs, start1, start1 + newlen)
+ }
+ }
+ override def toString = xs drop start take length mkString ""
+}
diff --git a/src/library/scala/runtime/Tuple2Zipped.scala b/src/library/scala/runtime/Tuple2Zipped.scala
new file mode 100644
index 0000000000..5ad364c8a5
--- /dev/null
+++ b/src/library/scala/runtime/Tuple2Zipped.scala
@@ -0,0 +1,130 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.runtime
+
+import scala.collection.{ TraversableLike, IterableLike }
+import scala.collection.generic.{ CanBuildFrom => CBF }
+
+/** This interface is intended as a minimal interface, not complicated
+ * by the requirement to resolve type constructors, for implicit search (which only
+ * needs to find an implicit conversion to Traversable for our purposes.)
+ */
+trait ZippedTraversable2[+El1, +El2] {
+ def foreach[U](f: (El1, El2) => U): Unit
+}
+object ZippedTraversable2 {
+ implicit def zippedTraversable2ToTraversable[El1, El2](zz: ZippedTraversable2[El1, El2]): Traversable[(El1, El2)] = {
+ new collection.AbstractTraversable[(El1, El2)] {
+ def foreach[U](f: ((El1, El2)) => U): Unit = zz foreach Function.untupled(f)
+ }
+ }
+}
+
+class Tuple2Zipped[El1, Repr1, El2, Repr2](
+ coll1: TraversableLike[El1, Repr1],
+ coll2: IterableLike[El2, Repr2]
+) extends ZippedTraversable2[El1, El2] {
+ def map[B, To](f: (El1, El2) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
+ val b = cbf(coll1.repr)
+ b.sizeHint(coll1)
+ val elems2 = coll2.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext)
+ b += f(el1, elems2.next)
+ else
+ return b.result
+ }
+
+ b.result
+ }
+
+ def flatMap[B, To](f: (El1, El2) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
+ val b = cbf(coll1.repr)
+ val elems2 = coll2.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext)
+ b ++= f(el1, elems2.next)
+ else
+ return b.result
+ }
+
+ b.result
+ }
+
+ def filter[To1, To2](f: (El1, El2) => Boolean)(implicit cbf1: CBF[Repr1, El1, To1], cbf2: CBF[Repr2, El2, To2]): (To1, To2) = {
+ val b1 = cbf1(coll1.repr)
+ val b2 = cbf2(coll2.repr)
+ val elems2 = coll2.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext) {
+ val el2 = elems2.next
+ if (f(el1, el2)) {
+ b1 += el1
+ b2 += el2
+ }
+ }
+ else return (b1.result, b2.result)
+ }
+
+ (b1.result, b2.result)
+ }
+
+ def exists(f: (El1, El2) => Boolean): Boolean = {
+ val elems2 = coll2.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext) {
+ if (f(el1, elems2.next))
+ return true
+ }
+ else return false
+ }
+ false
+ }
+
+ def forall(f: (El1, El2) => Boolean): Boolean =
+ !exists((x, y) => !f(x, y))
+
+ def foreach[U](f: (El1, El2) => U): Unit = {
+ val elems2 = coll2.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext)
+ f(el1, elems2.next)
+ else
+ return
+ }
+ }
+}
+
+object Tuple2Zipped {
+ class Ops[T1, T2](x: (T1, T2)) {
+ def invert[El1, CC1[X] <: TraversableOnce[X], El2, CC2[X] <: TraversableOnce[X], That]
+ (implicit w1: T1 <:< CC1[El1],
+ w2: T2 <:< CC2[El2],
+ bf: collection.generic.CanBuildFrom[CC1[_], (El1, El2), That]
+ ): That = {
+ val buf = bf(x._1)
+ val it1 = x._1.toIterator
+ val it2 = x._2.toIterator
+ while (it1.hasNext && it2.hasNext)
+ buf += ((it1.next, it2.next))
+
+ buf.result
+ }
+
+ def zipped[El1, Repr1, El2, Repr2]
+ (implicit w1: T1 => TraversableLike[El1, Repr1],
+ w2: T2 => IterableLike[El2, Repr2]
+ ): Tuple2Zipped[El1, Repr1, El2, Repr2] = new Tuple2Zipped(x._1, x._2)
+ }
+}
diff --git a/src/library/scala/runtime/Tuple3Zipped.scala b/src/library/scala/runtime/Tuple3Zipped.scala
new file mode 100644
index 0000000000..4e9c542c58
--- /dev/null
+++ b/src/library/scala/runtime/Tuple3Zipped.scala
@@ -0,0 +1,141 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+package scala.runtime
+
+import scala.collection.{ TraversableLike, IterableLike }
+import scala.collection.generic.{ CanBuildFrom => CBF }
+
+/** See comment on ZippedTraversable2. */
+trait ZippedTraversable3[+El1, +El2, +El3] {
+ def foreach[U](f: (El1, El2, El3) => U): Unit
+}
+object ZippedTraversable3 {
+ implicit def zippedTraversable3ToTraversable[El1, El2, El3](zz: ZippedTraversable3[El1, El2, El3]): Traversable[(El1, El2, El3)] = {
+ new collection.AbstractTraversable[(El1, El2, El3)] {
+ def foreach[U](f: ((El1, El2, El3)) => U): Unit = zz foreach Function.untupled(f)
+ }
+ }
+}
+
+class Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3](
+ coll1: TraversableLike[El1, Repr1],
+ coll2: IterableLike[El2, Repr2],
+ coll3: IterableLike[El3, Repr3]
+) extends ZippedTraversable3[El1, El2, El3] {
+ def map[B, To](f: (El1, El2, El3) => B)(implicit cbf: CBF[Repr1, B, To]): To = {
+ val b = cbf(coll1.repr)
+ val elems2 = coll2.iterator
+ val elems3 = coll3.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext && elems3.hasNext)
+ b += f(el1, elems2.next, elems3.next)
+ else
+ return b.result
+ }
+ b.result
+ }
+
+ def flatMap[B, To](f: (El1, El2, El3) => TraversableOnce[B])(implicit cbf: CBF[Repr1, B, To]): To = {
+ val b = cbf(coll1.repr)
+ val elems2 = coll2.iterator
+ val elems3 = coll3.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext && elems3.hasNext)
+ b ++= f(el1, elems2.next, elems3.next)
+ else
+ return b.result
+ }
+ b.result
+ }
+
+ def filter[To1, To2, To3](f: (El1, El2, El3) => Boolean)(
+ implicit cbf1: CBF[Repr1, El1, To1],
+ cbf2: CBF[Repr2, El2, To2],
+ cbf3: CBF[Repr3, El3, To3]): (To1, To2, To3) = {
+ val b1 = cbf1(coll1.repr)
+ val b2 = cbf2(coll2.repr)
+ val b3 = cbf3(coll3.repr)
+ val elems2 = coll2.iterator
+ val elems3 = coll3.iterator
+ def result = (b1.result, b2.result, b3.result)
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext && elems3.hasNext) {
+ val el2 = elems2.next
+ val el3 = elems3.next
+
+ if (f(el1, el2, el3)) {
+ b1 += el1
+ b2 += el2
+ b3 += el3
+ }
+ }
+ else return result
+ }
+
+ result
+ }
+
+ def exists(f: (El1, El2, El3) => Boolean): Boolean = {
+ val elems2 = coll2.iterator
+ val elems3 = coll3.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext && elems3.hasNext) {
+ if (f(el1, elems2.next, elems3.next))
+ return true
+ }
+ else return false
+ }
+ false
+ }
+
+ def forall(f: (El1, El2, El3) => Boolean): Boolean =
+ !exists((x, y, z) => !f(x, y, z))
+
+ def foreach[U](f: (El1, El2, El3) => U): Unit = {
+ val elems2 = coll2.iterator
+ val elems3 = coll3.iterator
+
+ for (el1 <- coll1) {
+ if (elems2.hasNext && elems3.hasNext)
+ f(el1, elems2.next, elems3.next)
+ else
+ return
+ }
+ }
+}
+
+object Tuple3Zipped {
+ class Ops[T1, T2, T3](x: (T1, T2, T3)) {
+ def invert[El1, CC1[X] <: TraversableOnce[X], El2, CC2[X] <: TraversableOnce[X], El3, CC3[X] <: TraversableOnce[X], That]
+ (implicit w1: T1 <:< CC1[El1],
+ w2: T2 <:< CC2[El2],
+ w3: T3 <:< CC3[El3],
+ bf: collection.generic.CanBuildFrom[CC1[_], (El1, El2, El3), That]
+ ): That = {
+ val buf = bf(x._1)
+ val it1 = x._1.toIterator
+ val it2 = x._2.toIterator
+ val it3 = x._3.toIterator
+ while (it1.hasNext && it2.hasNext && it3.hasNext)
+ buf += ((it1.next, it2.next, it3.next))
+
+ buf.result
+ }
+
+ def zipped[El1, Repr1, El2, Repr2, El3, Repr3]
+ (implicit w1: T1 => TraversableLike[El1, Repr1],
+ w2: T2 => IterableLike[El2, Repr2],
+ w3: T3 => IterableLike[El3, Repr3]
+ ): Tuple3Zipped[El1, Repr1, El2, Repr2, El3, Repr3] = new Tuple3Zipped(x._1, x._2, x._3)
+ }
+}
diff --git a/src/library/scala/runtime/package.scala b/src/library/scala/runtime/package.scala
index 9c87baf6a7..e4472b3ea1 100644
--- a/src/library/scala/runtime/package.scala
+++ b/src/library/scala/runtime/package.scala
@@ -1,13 +1,3 @@
package scala
-package object runtime {
- @deprecated("Use `scala.Unit` instead.", "2.9.0") val Unit = scala.Unit
- @deprecated("Use `scala.Boolean` instead.", "2.9.0") val Boolean = scala.Boolean
- @deprecated("Use `scala.Byte` instead.", "2.9.0") val Byte = scala.Byte
- @deprecated("Use `scala.Short` instead.", "2.9.0") val Short = scala.Short
- @deprecated("Use `scala.Char` instead.", "2.9.0") val Char = scala.Char
- @deprecated("Use `scala.Int` instead.", "2.9.0") val Int = scala.Int
- @deprecated("Use `scala.Long` instead.", "2.9.0") val Long = scala.Long
- @deprecated("Use `scala.Float` instead.", "2.9.0") val Float = scala.Float
- @deprecated("Use `scala.Double` instead.", "2.9.0") val Double = scala.Double
-}
+package object runtime { }
diff --git a/src/library/scala/sys/BooleanProp.scala b/src/library/scala/sys/BooleanProp.scala
index e940990785..45fc6f5897 100644
--- a/src/library/scala/sys/BooleanProp.scala
+++ b/src/library/scala/sys/BooleanProp.scala
@@ -8,6 +8,8 @@
package scala.sys
+import language.implicitConversions
+
/** A few additional conveniences for Boolean properties.
*/
trait BooleanProp extends Prop[Boolean] {
diff --git a/src/library/scala/sys/SystemProperties.scala b/src/library/scala/sys/SystemProperties.scala
index 52e0ac230b..4853da3495 100644
--- a/src/library/scala/sys/SystemProperties.scala
+++ b/src/library/scala/sys/SystemProperties.scala
@@ -11,6 +11,8 @@ package scala.sys
import scala.collection.{ mutable, Iterator }
import scala.collection.JavaConverters._
import java.security.AccessControlException
+import language.implicitConversions
+
/** A bidirectional map wrapping the java System properties.
* Changes to System properties will be immediately visible in the map,
diff --git a/src/library/scala/sys/process/Process.scala b/src/library/scala/sys/process/Process.scala
index c2a61af936..d56c6f2c9d 100644
--- a/src/library/scala/sys/process/Process.scala
+++ b/src/library/scala/sys/process/Process.scala
@@ -11,6 +11,7 @@ package process
import processInternal._
import ProcessBuilder._
+import language.implicitConversions
/** Represents a process that is running or has finished running.
* It may be a compound process with several underlying native processes (such as `a #&& b`).
diff --git a/src/library/scala/testing/Show.scala b/src/library/scala/testing/Show.scala
index 7570bf705c..5ab46b8985 100644
--- a/src/library/scala/testing/Show.scala
+++ b/src/library/scala/testing/Show.scala
@@ -27,17 +27,17 @@ package scala.testing
*/
trait Show {
- /** The result class of wrapper `symApply`.
+ /** An implicit definition that adds an apply method to Symbol which forwards to `test`.
* Prints out diagnostics of method applications.
*/
- class SymApply(f: Symbol) {
+ implicit class SymApply(f: Symbol) {
def apply[A](args: A*) {
println(test(f, args: _*))
}
}
- /** An implicit definition that adds an apply method to Symbol which forwards to `test`. */
- implicit def symApply(sym: Symbol) = new SymApply(sym)
+ @deprecated("use SymApply instead", "2.10")
+ def symApply(sym: Symbol): SymApply = new SymApply(sym)
/** Apply method with name of given symbol `f` to given arguments and return
* a result diagnostics.
diff --git a/src/library/scala/util/Marshal.scala b/src/library/scala/util/Marshal.scala
index daeaf4c53b..e2ebe7851c 100644
--- a/src/library/scala/util/Marshal.scala
+++ b/src/library/scala/util/Marshal.scala
@@ -11,19 +11,19 @@
package scala.util
/**
- * Marshalling of Scala objects using Scala manifests.
+ * Marshalling of Scala objects using Scala tags.
*
* @author Stephane Micheloud
* @version 1.0
*/
object Marshal {
import java.io._
- import scala.reflect.ClassManifest
+ import scala.reflect.ClassTag
- def dump[A](o: A)(implicit m: ClassManifest[A]): Array[Byte] = {
+ def dump[A](o: A)(implicit t: ClassTag[A]): Array[Byte] = {
val ba = new ByteArrayOutputStream(512)
val out = new ObjectOutputStream(ba)
- out.writeObject(m)
+ out.writeObject(t)
out.writeObject(o)
out.close()
ba.toByteArray()
@@ -32,19 +32,20 @@ object Marshal {
@throws(classOf[IOException])
@throws(classOf[ClassCastException])
@throws(classOf[ClassNotFoundException])
- def load[A](buffer: Array[Byte])(implicit expected: ClassManifest[A]): A = {
+ def load[A](buffer: Array[Byte])(implicit expected: ClassTag[A]): A = {
val in = new ObjectInputStream(new ByteArrayInputStream(buffer))
- val found = in.readObject.asInstanceOf[ClassManifest[_]]
- if (found <:< expected) {
- val o = in.readObject.asInstanceOf[A]
- in.close()
- o
- } else {
- in.close()
- throw new ClassCastException("type mismatch;"+
- "\n found : "+found+
- "\n required: "+expected)
+ val found = in.readObject.asInstanceOf[ClassTag[_]]
+ try {
+ // [Eugene] needs review
+ // previously was: found <:< expected
+ found.erasure.asSubclass(expected.erasure)
+ in.readObject.asInstanceOf[A]
+ } catch {
+ case _: ClassCastException =>
+ in.close()
+ throw new ClassCastException("type mismatch;"+
+ "\n found : "+found+
+ "\n required: "+expected)
}
}
-
}
diff --git a/src/library/scala/util/Random.scala b/src/library/scala/util/Random.scala
index 791582c9ec..17c356801b 100644
--- a/src/library/scala/util/Random.scala
+++ b/src/library/scala/util/Random.scala
@@ -11,6 +11,7 @@ package scala.util
import collection.mutable.ArrayBuffer
import collection.generic.CanBuildFrom
import scala.collection.immutable.{ List, Stream }
+import language.{implicitConversions, higherKinds}
/**
* @author Stephane Micheloud
@@ -117,18 +118,9 @@ class Random(val self: java.util.Random) {
swap(n - 1, k)
}
- bf(xs) ++= buf result
+ (bf(xs) ++= buf).result
}
-}
-
-/** The object `Random` offers a default implementation
- * of scala.util.Random and random-related convenience methods.
- *
- * @since 2.8
- */
-object Random extends Random {
-
/** Returns a Stream of pseudorandomly chosen alphanumeric characters,
* equally chosen from A-Z, a-z, and 0-9.
*
@@ -141,3 +133,14 @@ object Random extends Random {
}
}
+
+/** The object `Random` offers a default implementation
+ * of scala.util.Random and random-related convenience methods.
+ *
+ * @since 2.8
+ */
+object Random extends Random {
+
+ implicit def javaRandomToRandom(r: java.util.Random): Random = new Random(r)
+
+}
diff --git a/src/library/scala/util/Sorting.scala b/src/library/scala/util/Sorting.scala
index bf460a118f..7d98e57741 100644
--- a/src/library/scala/util/Sorting.scala
+++ b/src/library/scala/util/Sorting.scala
@@ -8,7 +8,7 @@
package scala.util
-import scala.reflect.ClassManifest
+import scala.reflect.ClassTag
import scala.math.Ordering
/** The Sorting object provides functions that can sort various kinds of
@@ -39,14 +39,14 @@ object Sorting {
/** Sort an array of K where K is Ordered, preserving the existing order
* where the values are equal. */
- def stableSort[K: ClassManifest: Ordering](a: Array[K]) {
+ def stableSort[K: ArrayTag: Ordering](a: Array[K]) {
stableSort(a, 0, a.length-1, new Array[K](a.length), Ordering[K].lt _)
}
/** Sorts an array of `K` given an ordering function `f`.
* `f` should return `true` iff its first parameter is strictly less than its second parameter.
*/
- def stableSort[K: ClassManifest](a: Array[K], f: (K, K) => Boolean) {
+ def stableSort[K: ArrayTag](a: Array[K], f: (K, K) => Boolean) {
stableSort(a, 0, a.length-1, new Array[K](a.length), f)
}
@@ -57,14 +57,14 @@ object Sorting {
* @param f the comparison function.
* @return the sorted sequence of items.
*/
- def stableSort[K: ClassManifest](a: Seq[K], f: (K, K) => Boolean): Array[K] = {
+ def stableSort[K: ArrayTag](a: Seq[K], f: (K, K) => Boolean): Array[K] = {
val ret = a.toArray
stableSort(ret, f)
ret
}
/** Sorts an arbitrary sequence of items that are viewable as ordered. */
- def stableSort[K: ClassManifest: Ordering](a: Seq[K]): Array[K] =
+ def stableSort[K: ArrayTag: Ordering](a: Seq[K]): Array[K] =
stableSort(a, Ordering[K].lt _)
/** Stably sorts a sequence of items given an extraction function that will
@@ -74,8 +74,8 @@ object Sorting {
* @param f the comparison function.
* @return the sorted sequence of items.
*/
- def stableSort[K: ClassManifest, M: Ordering](a: Seq[K], f: K => M): Array[K] =
- stableSort(a)(implicitly[ClassManifest[K]], Ordering[M] on f)
+ def stableSort[K: ArrayTag, M: Ordering](a: Seq[K], f: K => M): Array[K] =
+ stableSort(a)(implicitly[ArrayTag[K]], Ordering[M] on f)
private def sort1[K: Ordering](x: Array[K], off: Int, len: Int) {
val ord = Ordering[K]
@@ -498,7 +498,7 @@ object Sorting {
sort2(off, len)
}
- private def stableSort[K : ClassManifest](a: Array[K], lo: Int, hi: Int, scratch: Array[K], f: (K,K) => Boolean) {
+ private def stableSort[K : ArrayTag](a: Array[K], lo: Int, hi: Int, scratch: Array[K], f: (K,K) => Boolean) {
if (lo < hi) {
val mid = (lo+hi) / 2
stableSort(a, lo, mid, scratch, f)
diff --git a/src/library/scala/util/automata/BaseBerrySethi.scala b/src/library/scala/util/automata/BaseBerrySethi.scala
index 18f36f9496..c78b2d0790 100644
--- a/src/library/scala/util/automata/BaseBerrySethi.scala
+++ b/src/library/scala/util/automata/BaseBerrySethi.scala
@@ -78,7 +78,7 @@ abstract class BaseBerrySethi {
* @return ...
*/
protected def compFollow1(fol1: Set[Int], r: RegExp): Set[Int] = r match {
- case x: Alt => Set(x.rs reverseMap (compFollow1(fol1, _)) flatten: _*)
+ case x: Alt => Set((x.rs reverseMap (compFollow1(fol1, _))).flatten: _*)
case x: Meta => compFollow1(fol1, x.r)
case x: Star => compFollow1(fol1 ++ compFirst(x.r), x.r)
case x: Sequ =>
diff --git a/src/library/scala/util/automata/NondetWordAutom.scala b/src/library/scala/util/automata/NondetWordAutom.scala
index fbc05de7fd..b09e82ca11 100644
--- a/src/library/scala/util/automata/NondetWordAutom.scala
+++ b/src/library/scala/util/automata/NondetWordAutom.scala
@@ -50,8 +50,8 @@ abstract class NondetWordAutom[T <: AnyRef] {
override def toString = {
val finalString = Map(finalStates map (j => j -> finals(j)) : _*).toString
- val deltaString = (0 until nstates) .
- map (i => " %d->%s\n _>%s\n".format(i, delta(i), default(i))) mkString
+ val deltaString = (0 until nstates)
+ .map(i => " %d->%s\n _>%s\n".format(i, delta(i), default(i))).mkString
"[NondetWordAutom nstates=%d finals=%s delta=\n%s".format(nstates, finalString, deltaString)
}
diff --git a/src/library/scala/util/automata/SubsetConstruction.scala b/src/library/scala/util/automata/SubsetConstruction.scala
index 8049d10d88..81805fce2f 100644
--- a/src/library/scala/util/automata/SubsetConstruction.scala
+++ b/src/library/scala/util/automata/SubsetConstruction.scala
@@ -14,7 +14,7 @@ class SubsetConstruction[T <: AnyRef](val nfa: NondetWordAutom[T]) {
import nfa.labels
def selectTag(Q: immutable.BitSet, finals: Array[Int]) =
- Q map finals filter (_ > 0) min
+ (Q map finals filter (_ > 0)).min
def determinize: DetWordAutom[T] = {
// for assigning numbers to bitsets
diff --git a/src/library/scala/util/automata/WordBerrySethi.scala b/src/library/scala/util/automata/WordBerrySethi.scala
index 84b78d8dd8..a7ad92e648 100644
--- a/src/library/scala/util/automata/WordBerrySethi.scala
+++ b/src/library/scala/util/automata/WordBerrySethi.scala
@@ -139,7 +139,7 @@ abstract class WordBerrySethi extends BaseBerrySethi {
finals = finals.updated(0, finalTag)
val delta1 = immutable.Map(deltaq.zipWithIndex map (_.swap): _*)
- val finalsArr = 0 until pos map (k => finals.getOrElse(k, 0)) toArray // 0 == not final
+ val finalsArr = (0 until pos map (k => finals.getOrElse(k, 0))).toArray // 0 == not final
val initialsArr = initials.toArray
val deltaArr: Array[mutable.Map[_labelT, immutable.BitSet]] =
@@ -147,7 +147,7 @@ abstract class WordBerrySethi extends BaseBerrySethi {
mutable.HashMap(delta1(x).toSeq map { case (k, v) => k -> immutable.BitSet(v: _*) } : _*)
}).toArray
- val defaultArr = 0 until pos map (k => immutable.BitSet(defaultq(k): _*)) toArray
+ val defaultArr = (0 until pos map (k => immutable.BitSet(defaultq(k): _*))).toArray
new NondetWordAutom[_labelT] {
val nstates = pos
@@ -161,4 +161,4 @@ abstract class WordBerrySethi extends BaseBerrySethi {
automatonFrom(Sequ(z.asInstanceOf[this.lang._regexpT]), finalTag)
}
}
-} \ No newline at end of file
+}
diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala
index 20a179a884..38f4abb20a 100644
--- a/src/library/scala/util/control/Exception.scala
+++ b/src/library/scala/util/control/Exception.scala
@@ -10,6 +10,8 @@ package scala.util.control
import collection.immutable.List
import java.lang.reflect.InvocationTargetException
+import language.implicitConversions
+
/** Classes representing the components of exception handling.
* Each class is independently composable. Some example usages:
@@ -28,9 +30,9 @@ import java.lang.reflect.InvocationTargetException
object Exception {
type Catcher[+T] = PartialFunction[Throwable, T]
- def mkCatcher[Ex <: Throwable: ClassManifest, T](isDef: Ex => Boolean, f: Ex => T) = new Catcher[T] {
+ def mkCatcher[Ex <: Throwable: ClassTag, T](isDef: Ex => Boolean, f: Ex => T) = new Catcher[T] {
private def downcast(x: Throwable): Option[Ex] =
- if (classManifest[Ex].erasure.isAssignableFrom(x.getClass)) Some(x.asInstanceOf[Ex])
+ if (classTag[Ex].erasure.isAssignableFrom(x.getClass)) Some(x.asInstanceOf[Ex])
else None
def isDefinedAt(x: Throwable) = downcast(x) exists isDef
@@ -39,7 +41,7 @@ object Exception {
def mkThrowableCatcher[T](isDef: Throwable => Boolean, f: Throwable => T) = mkCatcher(isDef, f)
- implicit def throwableSubtypeToCatcher[Ex <: Throwable: ClassManifest, T](pf: PartialFunction[Ex, T]) =
+ implicit def throwableSubtypeToCatcher[Ex <: Throwable: ClassTag, T](pf: PartialFunction[Ex, T]) =
mkCatcher(pf.isDefinedAt _, pf.apply _)
/** !!! Not at all sure of every factor which goes into this,
diff --git a/src/library/scala/util/control/NoStackTrace.scala b/src/library/scala/util/control/NoStackTrace.scala
index dff29c86b4..c2b5dbca22 100644
--- a/src/library/scala/util/control/NoStackTrace.scala
+++ b/src/library/scala/util/control/NoStackTrace.scala
@@ -23,5 +23,9 @@ trait NoStackTrace extends Throwable {
}
object NoStackTrace {
- final val noSuppression = sys.SystemProperties.noTraceSupression.value
+ final def noSuppression = _noSuppression
+
+ // two-stage init to make checkinit happy, since sys.SystemProperties.noTraceSupression.value calls back into NoStackTrace.noSuppression
+ final private var _noSuppression = false
+ _noSuppression = sys.SystemProperties.noTraceSupression.value
}
diff --git a/src/library/scala/util/matching/Regex.scala b/src/library/scala/util/matching/Regex.scala
index 3f21cc9724..3655a0a019 100644
--- a/src/library/scala/util/matching/Regex.scala
+++ b/src/library/scala/util/matching/Regex.scala
@@ -145,6 +145,7 @@ import java.util.regex.{ Pattern, Matcher }
*/
@SerialVersionUID(-2094783597747625537L)
class Regex(regex: String, groupNames: String*) extends Serializable {
+ outer =>
import Regex._
@@ -179,15 +180,14 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
* @return The matches
*/
def unapplySeq(target: Any): Option[List[String]] = target match {
- case s: java.lang.CharSequence =>
- val m = pattern.matcher(s)
- if (m.matches) Some((1 to m.groupCount).toList map m.group)
+ case s: CharSequence =>
+ val m = pattern matcher s
+ if (runMatcher(m)) Some((1 to m.groupCount).toList map m.group)
else None
- case Match(s) =>
- unapplySeq(s)
- case _ =>
- None
+ case m: Match => unapplySeq(m.matched)
+ case _ => None
}
+ protected def runMatcher(m: Matcher) = m.matches()
/** Return all matches of this regexp in given character sequence as a [[scala.util.matching.Regex.MatchIterator]],
* which is a special [[scala.collection.Iterator]] that returns the
@@ -204,7 +204,7 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
/** Return all matches of this regexp in given character sequence as a
- * [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match].
+ * [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match]].
*
* @param source The text to match against.
* @return A [[scala.collection.Iterator]] of [[scala.util.matching.Regex.Match]] for all matches.
@@ -373,10 +373,35 @@ class Regex(regex: String, groupNames: String*) extends Serializable {
def split(toSplit: java.lang.CharSequence): Array[String] =
pattern.split(toSplit)
+ /** Create a new Regex with the same pattern, but no requirement that
+ * the entire String matches in extractor patterns. For instance, the strings
+ * shown below lead to successful matches, where they would not otherwise.
+ *
+ * {{{
+ * val dateP1 = """(\d\d\d\d)-(\d\d)-(\d\d)""".r.unanchored
+ *
+ * val dateP1(year, month, day) = "Date 2011-07-15"
+ *
+ * val copyright: String = "Date of this document: 2011-07-15" match {
+ * case dateP1(year, month, day) => "Copyright "+year
+ * case _ => "No copyright"
+ * }
+ * }}}
+ *
+ * @return The new unanchored regex
+ */
+ def unanchored: UnanchoredRegex = new Regex(regex, groupNames: _*) with UnanchoredRegex { override def anchored = outer }
+ def anchored: Regex = this
+
/** The string defining the regular expression */
override def toString = regex
}
+trait UnanchoredRegex extends Regex {
+ override protected def runMatcher(m: Matcher) = m.find()
+ override def unanchored = this
+}
+
/** This object defines inner classes that describe
* regex matches and helper objects. The class hierarchy
* is as follows:
diff --git a/src/library/scala/util/parsing/ast/Binders.scala b/src/library/scala/util/parsing/ast/Binders.scala
index 0646f57064..09ad5ce2ab 100644
--- a/src/library/scala/util/parsing/ast/Binders.scala
+++ b/src/library/scala/util/parsing/ast/Binders.scala
@@ -10,6 +10,7 @@ package scala.util.parsing.ast
import scala.collection.AbstractIterable
import scala.collection.mutable
+import language.implicitConversions
//DISCLAIMER: this code is highly experimental!
diff --git a/src/library/scala/util/parsing/combinator/ImplicitConversions.scala b/src/library/scala/util/parsing/combinator/ImplicitConversions.scala
index e993628e88..270ac680a9 100644
--- a/src/library/scala/util/parsing/combinator/ImplicitConversions.scala
+++ b/src/library/scala/util/parsing/combinator/ImplicitConversions.scala
@@ -9,6 +9,8 @@
package scala.util.parsing.combinator
+import language.implicitConversions
+
/** This object contains implicit conversions that come in handy when using the `^^` combinator.
*
* Refer to [[scala.util.parsing.combinator.Parsers]] to construct an AST from the concrete syntax.
diff --git a/src/library/scala/util/parsing/combinator/PackratParsers.scala b/src/library/scala/util/parsing/combinator/PackratParsers.scala
index ea856efc3a..9516df0093 100644
--- a/src/library/scala/util/parsing/combinator/PackratParsers.scala
+++ b/src/library/scala/util/parsing/combinator/PackratParsers.scala
@@ -11,6 +11,7 @@ package scala.util.parsing.combinator
import scala.util.parsing.combinator._
import scala.util.parsing.input.{ Reader, Position }
import scala.collection.mutable
+import language.implicitConversions
/**
* `PackratParsers` is a component that extends the parser combinators
diff --git a/src/library/scala/util/parsing/combinator/Parsers.scala b/src/library/scala/util/parsing/combinator/Parsers.scala
index 9aaf0aeb54..66e0a496d8 100644
--- a/src/library/scala/util/parsing/combinator/Parsers.scala
+++ b/src/library/scala/util/parsing/combinator/Parsers.scala
@@ -12,6 +12,8 @@ import scala.util.parsing.input._
import scala.collection.mutable.ListBuffer
import scala.annotation.tailrec
import annotation.migration
+import language.implicitConversions
+import scala.util.DynamicVariable
// TODO: better error handling (labelling like parsec's <?>)
@@ -153,13 +155,14 @@ trait Parsers {
val successful = true
}
- var lastNoSuccess: NoSuccess = null
+ private lazy val lastNoSuccess = new DynamicVariable[Option[NoSuccess]](None)
/** A common super-class for unsuccessful parse results. */
sealed abstract class NoSuccess(val msg: String, override val next: Input) extends ParseResult[Nothing] { // when we don't care about the difference between Failure and Error
val successful = false
- if (!(lastNoSuccess != null && next.pos < lastNoSuccess.next.pos))
- lastNoSuccess = this
+
+ if (lastNoSuccess.value map { v => !(next.pos < v.next.pos) } getOrElse true)
+ lastNoSuccess.value = Some(this)
def map[U](f: Nothing => U) = this
def mapPartial[U](f: PartialFunction[Nothing, U], error: Nothing => String): ParseResult[U] = this
@@ -595,7 +598,8 @@ trait Parsers {
* @return A parser for elements satisfying p(e).
*/
def acceptIf(p: Elem => Boolean)(err: Elem => String): Parser[Elem] = Parser { in =>
- if (p(in.first)) Success(in.first, in.rest)
+ if (in.atEnd) Failure("end of input", in)
+ else if (p(in.first)) Success(in.first, in.rest)
else Failure(err(in.first), in)
}
@@ -613,7 +617,8 @@ trait Parsers {
* applying `f` to it to produce the result.
*/
def acceptMatch[U](expected: String, f: PartialFunction[Elem, U]): Parser[U] = Parser{ in =>
- if (f.isDefinedAt(in.first)) Success(f(in.first), in.rest)
+ if (in.atEnd) Failure("end of input", in)
+ else if (f.isDefinedAt(in.first)) Success(f(in.first), in.rest)
else Failure(expected+" expected", in)
}
@@ -876,16 +881,15 @@ trait Parsers {
* if `p` consumed all the input.
*/
def phrase[T](p: Parser[T]) = new Parser[T] {
- lastNoSuccess = null
- def apply(in: Input) = p(in) match {
+ def apply(in: Input) = lastNoSuccess.withValue(None) {
+ p(in) match {
case s @ Success(out, in1) =>
if (in1.atEnd)
s
- else if (lastNoSuccess == null || lastNoSuccess.next.pos < in1.pos)
- Failure("end of input expected", in1)
else
- lastNoSuccess
- case _ => lastNoSuccess
+ lastNoSuccess.value filterNot { _.next.pos < in1.pos } getOrElse Failure("end of input expected", in1)
+ case ns => lastNoSuccess.value.getOrElse(ns)
+ }
}
}
diff --git a/src/library/scala/util/parsing/combinator/RegexParsers.scala b/src/library/scala/util/parsing/combinator/RegexParsers.scala
index 86eecd03c4..d685329ef1 100644
--- a/src/library/scala/util/parsing/combinator/RegexParsers.scala
+++ b/src/library/scala/util/parsing/combinator/RegexParsers.scala
@@ -13,6 +13,7 @@ import java.util.regex.Pattern
import scala.util.matching.Regex
import scala.util.parsing.input._
import scala.collection.immutable.PagedSeq
+import language.implicitConversions
/** The ''most important'' differences between `RegexParsers` and
* [[scala.util.parsing.combinator.Parsers]] are:
diff --git a/src/library/scala/util/parsing/combinator/lexical/Lexical.scala b/src/library/scala/util/parsing/combinator/lexical/Lexical.scala
index 9979a420d6..6c3bc52c1a 100644
--- a/src/library/scala/util/parsing/combinator/lexical/Lexical.scala
+++ b/src/library/scala/util/parsing/combinator/lexical/Lexical.scala
@@ -32,7 +32,7 @@ abstract class Lexical extends Scanners with Tokens {
def digit = elem("digit", _.isDigit)
/** A character-parser that matches any character except the ones given in `cs` (and returns it).*/
- def chrExcept(cs: Char*) = elem("", ch => (cs forall (ch !=)))
+ def chrExcept(cs: Char*) = elem("", ch => (cs forall (ch != _)))
/** A character-parser that matches a white-space character (and returns it).*/
def whitespaceChar = elem("space char", ch => ch <= ' ' && ch != EofCh)
diff --git a/src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala b/src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala
index e494a69cf0..215b8b792f 100644
--- a/src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala
+++ b/src/library/scala/util/parsing/combinator/syntactical/StandardTokenParsers.scala
@@ -13,6 +13,7 @@ package syntactical
import token._
import lexical.StdLexical
+import language.implicitConversions
/** This component provides primitive parsers for the standard tokens defined in `StdTokens`.
*
diff --git a/src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala b/src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala
index 0901f9bbd0..7aa6178df9 100644
--- a/src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala
+++ b/src/library/scala/util/parsing/combinator/syntactical/StdTokenParsers.scala
@@ -14,6 +14,7 @@ package syntactical
import token._
import scala.collection.mutable
+import language.implicitConversions
/** This component provides primitive parsers for the standard tokens defined in `StdTokens`.
*
diff --git a/src/library/scala/util/parsing/combinator/testing/RegexTest.scala b/src/library/scala/util/parsing/combinator/testing/RegexTest.scala
index 299736046e..255730e5db 100644
--- a/src/library/scala/util/parsing/combinator/testing/RegexTest.scala
+++ b/src/library/scala/util/parsing/combinator/testing/RegexTest.scala
@@ -3,6 +3,7 @@ package scala.util.parsing.combinator.testing
import scala.util.parsing.combinator._
import scala.util.parsing.input._
+import language.postfixOps
case class Ident(s: String)
case class Number(n: Int)
diff --git a/src/library/scala/xml/Elem.scala b/src/library/scala/xml/Elem.scala
index 5b6b9f2bb9..f140fd1e07 100755
--- a/src/library/scala/xml/Elem.scala
+++ b/src/library/scala/xml/Elem.scala
@@ -107,5 +107,5 @@ extends Node with Serializable
/** Returns concatenation of `text(n)` for each child `n`.
*/
- override def text = child map (_.text) mkString
+ override def text = (child map (_.text)).mkString
}
diff --git a/src/library/scala/xml/MetaData.scala b/src/library/scala/xml/MetaData.scala
index c516747bae..b44a817499 100644
--- a/src/library/scala/xml/MetaData.scala
+++ b/src/library/scala/xml/MetaData.scala
@@ -167,7 +167,7 @@ extends AbstractIterable[MetaData]
/** Returns a Map containing the attributes stored as key/value pairs.
*/
def asAttrMap: Map[String, String] =
- iterator map (x => (x.prefixedKey, x.value.text)) toMap
+ (iterator map (x => (x.prefixedKey, x.value.text))).toMap
/** returns Null or the next MetaData item */
def next: MetaData
diff --git a/src/library/scala/xml/NodeSeq.scala b/src/library/scala/xml/NodeSeq.scala
index ff5618645f..f0be338fcf 100644
--- a/src/library/scala/xml/NodeSeq.scala
+++ b/src/library/scala/xml/NodeSeq.scala
@@ -11,6 +11,7 @@ package scala.xml
import collection.{ mutable, immutable, generic, SeqLike, AbstractSeq }
import mutable.{ Builder, ListBuffer }
import generic.{ CanBuildFrom }
+import language.implicitConversions
/** This object ...
*
@@ -152,5 +153,5 @@ abstract class NodeSeq extends AbstractSeq[Node] with immutable.Seq[Node] with S
override def toString(): String = theSeq.mkString
- def text: String = this map (_.text) mkString
+ def text: String = (this map (_.text)).mkString
}
diff --git a/src/library/scala/xml/Utility.scala b/src/library/scala/xml/Utility.scala
index 9f944c0e92..062a62e240 100755
--- a/src/library/scala/xml/Utility.scala
+++ b/src/library/scala/xml/Utility.scala
@@ -10,6 +10,7 @@ package scala.xml
import scala.collection.mutable
import parsing.XhtmlEntities
+import language.implicitConversions
/**
* The `Utility` object provides utility functions for processing instances
@@ -20,6 +21,8 @@ import parsing.XhtmlEntities
object Utility extends AnyRef with parsing.TokenTests {
final val SU = '\u001A'
+ // [Martin] This looks dubious. We don't convert StringBuilders to
+ // Strings anywhere else, why do it here?
implicit def implicitSbToString(sb: StringBuilder) = sb.toString()
// helper for the extremely oft-repeated sequence of creating a
@@ -137,7 +140,7 @@ object Utility extends AnyRef with parsing.TokenTests {
* @return `'''null'''` if `ref` was not a predefined entity.
*/
final def unescape(ref: String, s: StringBuilder): StringBuilder =
- (unescMap get ref) map (s append _) orNull
+ ((unescMap get ref) map (s append _)).orNull
/**
* Returns a set of all namespaces used in a sequence of nodes
diff --git a/src/library/scala/xml/dtd/ContentModel.scala b/src/library/scala/xml/dtd/ContentModel.scala
index 1e9a3a4b58..a5d2a6bd7e 100644
--- a/src/library/scala/xml/dtd/ContentModel.scala
+++ b/src/library/scala/xml/dtd/ContentModel.scala
@@ -36,8 +36,8 @@ object ContentModel extends WordExp {
def traverse(r: RegExp): Set[String] = r match { // !!! check for match translation problem
case Letter(ElemName(name)) => Set(name)
case Star( x @ _ ) => traverse( x ) // bug if x@_*
- case Sequ( xs @ _* ) => Set(xs map traverse flatten: _*)
- case Alt( xs @ _* ) => Set(xs map traverse flatten: _*)
+ case Sequ( xs @ _* ) => Set(xs flatMap traverse: _*)
+ case Alt( xs @ _* ) => Set(xs flatMap traverse: _*)
}
traverse(r)
diff --git a/src/library/scala/xml/factory/LoggedNodeFactory.scala b/src/library/scala/xml/factory/LoggedNodeFactory.scala
index abf8f97f03..45ba9530e1 100644
--- a/src/library/scala/xml/factory/LoggedNodeFactory.scala
+++ b/src/library/scala/xml/factory/LoggedNodeFactory.scala
@@ -12,7 +12,7 @@ package factory
/** This class logs what the nodefactory is actually doing.
* If you want to see what happens during loading, use it like this:
{{{
-object testLogged extends Application {
+object testLogged extends App {
val x = new scala.xml.parsing.NoBindingFactoryAdapter
with scala.xml.factory.LoggedNodeFactory[scala.xml.Elem]
with scala.util.logging.ConsoleLogger
diff --git a/src/library/scala/xml/parsing/ConstructingParser.scala b/src/library/scala/xml/parsing/ConstructingParser.scala
index 5571c9844d..471cde056e 100644
--- a/src/library/scala/xml/parsing/ConstructingParser.scala
+++ b/src/library/scala/xml/parsing/ConstructingParser.scala
@@ -16,10 +16,10 @@ import scala.io.Source
object ConstructingParser {
def fromFile(inp: File, preserveWS: Boolean) =
- new ConstructingParser(Source.fromFile(inp), preserveWS) initialize
+ new ConstructingParser(Source.fromFile(inp), preserveWS).initialize
def fromSource(inp: Source, preserveWS: Boolean) =
- new ConstructingParser(inp, preserveWS) initialize
+ new ConstructingParser(inp, preserveWS).initialize
}
/** An xml parser. parses XML and invokes callback methods of a MarkupHandler.
diff --git a/src/partest/scala/tools/partest/CompilerTest.scala b/src/partest/scala/tools/partest/CompilerTest.scala
index 994928c0f6..86678760be 100644
--- a/src/partest/scala/tools/partest/CompilerTest.scala
+++ b/src/partest/scala/tools/partest/CompilerTest.scala
@@ -5,6 +5,7 @@
package scala.tools.partest
+import scala.reflect.{mirror => rm}
import scala.tools.nsc._
/** For testing compiler internals directly.
@@ -29,13 +30,13 @@ abstract class CompilerTest extends DirectTest {
// Override at least one of these...
def code = ""
def sources: List[String] = List(code)
-
+
// Utility functions
-
+
class MkType(sym: Symbol) {
- def apply[M](implicit m1: Manifest[M]): Type =
+ def apply[M](implicit t: rm.TypeTag[M]): Type =
if (sym eq NoSymbol) NoType
- else appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x)))
+ else appliedType(sym, compilerTypeFromTag(t))
}
implicit def mkMkType(sym: Symbol) = new MkType(sym)
@@ -47,7 +48,7 @@ abstract class CompilerTest extends DirectTest {
}
loop(Set(), List(root))
}
-
+
class SymsInPackage(pkgName: String) {
def pkg = getRequiredModule(pkgName)
def classes = allMembers(pkg) filter (_.isClass)
diff --git a/src/partest/scala/tools/partest/ScaladocModelTest.scala b/src/partest/scala/tools/partest/ScaladocModelTest.scala
index 2eb026ceee..142f2baea5 100644
--- a/src/partest/scala/tools/partest/ScaladocModelTest.scala
+++ b/src/partest/scala/tools/partest/ScaladocModelTest.scala
@@ -21,10 +21,10 @@ import scala.tools.nsc.reporters.ConsoleReporter
import scala.tools.nsc.doc.model._
import scala.tools.partest.ScaladocModelTest
- object Test extends ScaladocModelTest {
+ object Test extends ScaladocModelTest {
- def code = """ ... """
- def scaladocSettings = ""
+ override def code = """ ... """ // or override def resourceFile = "<file>.scala" (from test/scaladoc/resources)
+ def scaladocSettings = " ... "
def testModel(rootPackage: Package) = {
// get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
import access._
@@ -39,10 +39,22 @@ abstract class ScaladocModelTest extends DirectTest {
/** Override this to give scaladoc command line parameters */
def scaladocSettings: String
-
+
/** Override this to test the model */
def testModel(root: Package): Unit
+ /** Override to feed a file in resources to scaladoc*/
+ def resourceFile: String = null
+
+ /** Override to feed code into scaladoc */
+ override def code =
+ if (resourceFile ne null)
+ io.File(resourcePath + "/" + resourceFile).slurp()
+ else
+ sys.error("Scaladoc Model Test: You need to give a file or some code to feed to scaladoc!")
+
+ def resourcePath = io.Directory(sys.props("partest.cwd") + "/../resources")
+
// Implementation follows:
override def extraSettings: String = "-usejavacp"
@@ -50,15 +62,15 @@ abstract class ScaladocModelTest extends DirectTest {
// redirect err to out, for logging
val prevErr = System.err
System.setErr(System.out)
-
+
try {
// 1 - compile with scaladoc and get the model out
- val args = scaladocSettings.split(" ")
- val universe = model(args:_*).getOrElse({sys.error("Scaladoc Model Test ERROR: No universe generated!")})
+ val universe = model.getOrElse({sys.error("Scaladoc Model Test ERROR: No universe generated!")})
// 2 - check the model generated
testModel(universe.rootPackage)
+ println("Done.")
} catch {
- case e =>
+ case e =>
println(e)
e.printStackTrace
}
@@ -66,51 +78,46 @@ abstract class ScaladocModelTest extends DirectTest {
System.setErr(prevErr)
}
+ private[this] var settings: Settings = null
+
// create a new scaladoc compiler
- def newDocFactory(args: String*): DocFactory = {
- val settings = new Settings(_ => ())
- val command = new ScalaDoc.Command((CommandLineParser tokenize extraSettings) ++ args.toList, settings)
+ def newDocFactory: DocFactory = {
+ settings = new Settings(_ => ())
+ settings.reportModel = false // yaay, no more "model contains X documentable templates"!
+ val args = extraSettings + " " + scaladocSettings
+ val command = new ScalaDoc.Command((CommandLineParser tokenize (args)), settings)
val docFact = new DocFactory(new ConsoleReporter(settings), settings)
docFact
}
// compile with scaladoc and output the result
- def model(args: String*): Option[Universe] = newDocFactory(args: _*).makeUniverse(Right(code))
+ def model: Option[Universe] = newDocFactory.makeUniverse(Right(code))
// so we don't get the newSettings warning
- override def isDebug = false
+ override def isDebug = false
// finally, enable easy navigation inside the entities
object access {
- // Make it easy to access things
class TemplateAccess(tpl: DocTemplateEntity) {
-
def _class(name: String): DocTemplateEntity = getTheFirst(_classes(name), tpl.qualifiedName + ".class(" + name + ")")
- def _classes(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).flatMap({ case c: Class => List(c)})
+ def _classes(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case c: Class => c})
def _trait(name: String): DocTemplateEntity = getTheFirst(_traits(name), tpl.qualifiedName + ".trait(" + name + ")")
- def _traits(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).flatMap({ case t: Trait => List(t)})
+ def _traits(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case t: Trait => t})
def _object(name: String): DocTemplateEntity = getTheFirst(_objects(name), tpl.qualifiedName + ".object(" + name + ")")
- def _objects(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).flatMap({ case o: Object => List(o)})
+ def _objects(name: String): List[DocTemplateEntity] = tpl.templates.filter(_.name == name).collect({ case o: Object => o})
def _method(name: String): Def = getTheFirst(_methods(name), tpl.qualifiedName + ".method(" + name + ")")
def _methods(name: String): List[Def] = tpl.methods.filter(_.name == name)
-
+
def _value(name: String): Val = getTheFirst(_values(name), tpl.qualifiedName + ".value(" + name + ")")
def _values(name: String): List[Val] = tpl.values.filter(_.name == name)
- def getTheFirst[T](list: List[T], expl: String): T = {
- if (list.length == 1)
- list.head
- else if (list.length == 0)
- sys.error("Error getting " + expl + ": No such element. All elements in list: [" + list.mkString(", ") + "]")
- else
- sys.error("Error getting " + expl + ": " + list.length + " elements with this name. " +
- "All elements in list: [" + list.mkString(", ") + "]")
- }
+ def _conversion(name: String): ImplicitConversion = getTheFirst(_conversions(name), tpl.qualifiedName + ".conversion(" + name + ")")
+ def _conversions(name: String): List[ImplicitConversion] = tpl.conversions.filter(_.conversionQualifiedName == name)
}
class PackageAccess(pack: Package) extends TemplateAccess(pack) {
@@ -118,7 +125,22 @@ abstract class ScaladocModelTest extends DirectTest {
def _packages(name: String): List[Package] = pack.packages.filter(_.name == name)
}
+ class MemberAccess(mbrs: WithMembers) {
+ def _member(name: String): MemberEntity = getTheFirst(_members(name), mbrs.toString + ".member(" + name + ")")
+ def _members(name: String): List[MemberEntity] = mbrs.members.filter(_.name == name)
+ }
+
+ type WithMembers = { def members: List[MemberEntity]; def toString: String } /* DocTemplates and ImplicitConversions */
+
implicit def templateAccess(tpl: DocTemplateEntity) = new TemplateAccess(tpl)
implicit def packageAccess(pack: Package) = new PackageAccess(pack)
+ implicit def membersAccess(mbrs: WithMembers) = new MemberAccess(mbrs)
+
+ def getTheFirst[T](list: List[T], expl: String): T = list.length match {
+ case 1 => list.head
+ case 0 => sys.error("Error getting " + expl + ": No such element.")
+ case _ => sys.error("Error getting " + expl + ": " + list.length + " elements with this name. " +
+ "All elements in list: [" + list.mkString(", ") + "]")
+ }
}
}
diff --git a/src/partest/scala/tools/partest/SigTest.scala b/src/partest/scala/tools/partest/SigTest.scala
index 072ec006f9..999d901d21 100644
--- a/src/partest/scala/tools/partest/SigTest.scala
+++ b/src/partest/scala/tools/partest/SigTest.scala
@@ -20,31 +20,31 @@ trait SigTest {
def isObjectMethodName(name: String) = classOf[Object].getMethods exists (_.getName == name)
- def fields[T: ClassManifest](p: JField => Boolean) = {
- val cl = classManifest[T].erasure
+ def fields[T: ClassTag](p: JField => Boolean) = {
+ val cl = classTag[T].erasure
val fs = (cl.getFields ++ cl.getDeclaredFields).distinct sortBy (_.getName)
fs filter p
}
- def methods[T: ClassManifest](p: JMethod => Boolean) = {
- val cl = classManifest[T].erasure
+ def methods[T: ClassTag](p: JMethod => Boolean) = {
+ val cl = classTag[T].erasure
val ms = (cl.getMethods ++ cl.getDeclaredMethods).distinct sortBy (x => (x.getName, x.isBridge))
ms filter p
}
- def allFields[T: ClassManifest]() = fields[T](_ => true)
- def allMethods[T: ClassManifest]() = methods[T](m => !isObjectMethodName(m.getName))
- def fieldsNamed[T: ClassManifest](name: String) = fields[T](_.getName == name)
- def methodsNamed[T: ClassManifest](name: String) = methods[T](_.getName == name)
+ def allFields[T: ClassTag]() = fields[T](_ => true)
+ def allMethods[T: ClassTag]() = methods[T](m => !isObjectMethodName(m.getName))
+ def fieldsNamed[T: ClassTag](name: String) = fields[T](_.getName == name)
+ def methodsNamed[T: ClassTag](name: String) = methods[T](_.getName == name)
- def allGenericStrings[T: ClassManifest]() =
+ def allGenericStrings[T: ClassTag]() =
(allMethods[T]() map mstr) ++ (allFields[T]() map fstr)
- def genericStrings[T: ClassManifest](name: String) =
+ def genericStrings[T: ClassTag](name: String) =
(methodsNamed[T](name) map mstr) ++ (fieldsNamed[T](name) map fstr)
- def show[T: ClassManifest](name: String = "") = {
- println(classManifest[T].erasure.getName)
+ def show[T: ClassTag](name: String = "") = {
+ println(classTag[T].erasure.getName)
if (name == "") allGenericStrings[T]() foreach println
else genericStrings[T](name) foreach println
}
diff --git a/src/partest/scala/tools/partest/nest/CompileManager.scala b/src/partest/scala/tools/partest/nest/CompileManager.scala
index 7aaa7bab00..c674e21482 100644
--- a/src/partest/scala/tools/partest/nest/CompileManager.scala
+++ b/src/partest/scala/tools/partest/nest/CompileManager.scala
@@ -18,6 +18,21 @@ import io.Path
import java.io.{ File, BufferedReader, PrintWriter, FileReader, Writer, FileWriter, StringWriter }
import File.pathSeparator
+sealed abstract class CompilationOutcome {
+ def merge(other: CompilationOutcome): CompilationOutcome
+ def isPositive = this eq CompileSuccess
+ def isNegative = this eq CompileFailed
+}
+case object CompileSuccess extends CompilationOutcome {
+ def merge(other: CompilationOutcome) = other
+}
+case object CompileFailed extends CompilationOutcome {
+ def merge(other: CompilationOutcome) = if (other eq CompileSuccess) this else other
+}
+case object CompilerCrashed extends CompilationOutcome {
+ def merge(other: CompilationOutcome) = this
+}
+
class ExtConsoleReporter(settings: Settings, val writer: PrintWriter) extends ConsoleReporter(settings, Console.in, writer) {
shortname = true
}
@@ -32,7 +47,7 @@ class TestSettings(cp: String, error: String => Unit) extends Settings(error) {
}
abstract class SimpleCompiler {
- def compile(out: Option[File], files: List[File], kind: String, log: File): Boolean
+ def compile(out: Option[File], files: List[File], kind: String, log: File): CompilationOutcome
}
class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
@@ -68,7 +83,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
(opt2 ::: pluginOption) mkString " "
}
- def compile(out: Option[File], files: List[File], kind: String, log: File): Boolean = {
+ def compile(out: Option[File], files: List[File], kind: String, log: File): CompilationOutcome = {
val testSettings = out match {
case Some(f) => newSettings(f.getAbsolutePath)
case _ => newSettings()
@@ -118,6 +133,7 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
catch {
case FatalError(msg) =>
testRep.error(null, "fatal error: " + msg)
+ return CompilerCrashed
}
testRep.printSummary()
@@ -125,81 +141,13 @@ class DirectCompiler(val fileManager: FileManager) extends SimpleCompiler {
}
finally logWriter.close()
- !testRep.hasErrors
+ if (testRep.hasErrors) CompileFailed
+ else CompileSuccess
}
}
-// class ReflectiveCompiler(val fileManager: ConsoleFileManager) extends SimpleCompiler {
-// import fileManager.{latestCompFile, latestPartestFile}
-//
-// val sepUrls = Array(latestCompFile.toURI.toURL, latestPartestFile.toURI.toURL)
-// //NestUI.verbose("constructing URLClassLoader from URLs "+latestCompFile+" and "+latestPartestFile)
-//
-// val sepLoader = new java.net.URLClassLoader(sepUrls, null)
-//
-// val sepCompilerClass =
-// sepLoader.loadClass("scala.tools.partest.nest.DirectCompiler")
-// val sepCompiler = sepCompilerClass.newInstance()
-//
-// // needed for reflective invocation
-// val fileClass = Class.forName("java.io.File")
-// val stringClass = Class.forName("java.lang.String")
-// val sepCompileMethod =
-// sepCompilerClass.getMethod("compile", fileClass, stringClass)
-// val sepCompileMethod2 =
-// sepCompilerClass.getMethod("compile", fileClass, stringClass, fileClass)
-//
-// /* This method throws java.lang.reflect.InvocationTargetException
-// * if the compiler crashes.
-// * This exception is handled in the shouldCompile and shouldFailCompile
-// * methods of class CompileManager.
-// */
-// def compile(out: Option[File], files: List[File], kind: String, log: File): Boolean = {
-// val res = sepCompileMethod2.invoke(sepCompiler, out, files, kind, log).asInstanceOf[java.lang.Boolean]
-// res.booleanValue()
-// }
-// }
-
class CompileManager(val fileManager: FileManager) {
- var compiler: SimpleCompiler = new DirectCompiler(fileManager)
-
- var numSeparateCompilers = 1
- def createSeparateCompiler() = {
- numSeparateCompilers += 1
- compiler = new /*ReflectiveCompiler*/ DirectCompiler(fileManager)
- }
-
- /* This method returns true iff compilation succeeds.
- */
- def shouldCompile(files: List[File], kind: String, log: File): Boolean = {
- createSeparateCompiler()
- compiler.compile(None, files, kind, log)
- }
-
- /* This method returns true iff compilation succeeds.
- */
- def shouldCompile(out: File, files: List[File], kind: String, log: File): Boolean = {
- createSeparateCompiler()
- compiler.compile(Some(out), files, kind, log)
- }
-
- /* This method returns true iff compilation fails
- * _and_ the compiler does _not_ crash or loop.
- *
- * If the compiler crashes, this method returns false.
- */
- def shouldFailCompile(files: List[File], kind: String, log: File): Boolean = {
- createSeparateCompiler()
- !compiler.compile(None, files, kind, log)
- }
-
- /* This method returns true iff compilation fails
- * _and_ the compiler does _not_ crash or loop.
- *
- * If the compiler crashes, this method returns false.
- */
- def shouldFailCompile(out: File, files: List[File], kind: String, log: File): Boolean = {
- createSeparateCompiler()
- !compiler.compile(Some(out), files, kind, log)
- }
+ private def newCompiler = new DirectCompiler(fileManager)
+ def attemptCompile(outdir: Option[File], sources: List[File], kind: String, log: File): CompilationOutcome =
+ newCompiler.compile(outdir, sources, kind, log)
}
diff --git a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
index fa533eeb10..8d239a84bd 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleFileManager.scala
@@ -96,6 +96,7 @@ class ConsoleFileManager extends FileManager {
latestActorsFile = dir / "lib/scala-actors.jar"
latestCompFile = dir / "lib/scala-compiler.jar"
latestPartestFile = dir / "lib/scala-partest.jar"
+ latestFjbgFile = testParent / "lib" / "fjbg.jar"
}
else {
def setupQuick() {
diff --git a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
index 85060ad633..fb3cab52c4 100644
--- a/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
+++ b/src/partest/scala/tools/partest/nest/ConsoleRunner.scala
@@ -213,7 +213,12 @@ class ConsoleRunner extends DirectRunner {
* @return (success count, failure count)
*/
def testCheckAll(enabledSets: List[TestSet]): (Int, Int) = {
- def kindOf(f: File) = (srcDir relativize Path(f).toCanonical).segments.head
+ def kindOf(f: File) = {
+ (srcDir relativize Path(f).toCanonical).segments match {
+ case (".." :: "scaladoc" :: xs) => xs.head
+ case xs => xs.head
+ }
+ }
val (valid, invalid) = testFiles partition (x => testSetKinds contains kindOf(x))
invalid foreach (x => NestUI.failure(
diff --git a/src/partest/scala/tools/partest/nest/TestFile.scala b/src/partest/scala/tools/partest/nest/TestFile.scala
index fc5792e886..1aa0a7baf6 100644
--- a/src/partest/scala/tools/partest/nest/TestFile.scala
+++ b/src/partest/scala/tools/partest/nest/TestFile.scala
@@ -35,7 +35,9 @@ abstract class TestFile(val kind: String) extends TestFileCommon {
if (setOutDir)
settings.outputDirs setSingleOutput setOutDirTo.path
- // adding code.jar to the classpath (to provide Code.lift services for reification tests)
+ // adding codelib.jar to the classpath
+ // codelib provides the possibility to override standard reify
+ // this shields the massive amount of reification tests from changes in the API
settings.classpath prepend PathSettings.srcCodeLib.toString
if (propIsSet("java.class.path")) setProp("java.class.path", PathSettings.srcCodeLib.toString + ";" + propOrElse("java.class.path", ""))
diff --git a/src/partest/scala/tools/partest/nest/Worker.scala b/src/partest/scala/tools/partest/nest/Worker.scala
index cb6f2a0edc..9326a8b232 100644
--- a/src/partest/scala/tools/partest/nest/Worker.scala
+++ b/src/partest/scala/tools/partest/nest/Worker.scala
@@ -181,7 +181,9 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
//
private def replaceSlashes(dir: File, s: String): String = {
val base = (dir.getAbsolutePath + File.separator).replace('\\', '/')
- s.replace('\\', '/').replaceAll("""\Q%s\E""" format base, "")
+ var regex = """\Q%s\E""" format base
+ if (isWin) regex = "(?i)" + regex
+ s.replace('\\', '/').replaceAll(regex, "")
}
private def currentFileString = {
@@ -267,7 +269,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
outDir.jfile
}
- private def javac(outDir: File, files: List[File], output: File): Boolean = {
+ private def javac(outDir: File, files: List[File], output: File): CompilationOutcome = {
// compile using command-line javac compiler
val args = Seq(
javacCmd,
@@ -277,8 +279,8 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
join(outDir.toString, CLASSPATH)
) ++ files.map("" + _)
- try runCommand(args, output)
- catch exHandler(output, "javac command failed:\n" + args.map(" " + _ + "\n").mkString + "\n")
+ try if (runCommand(args, output)) CompileSuccess else CompileFailed
+ catch exHandler(output, "javac command failed:\n" + args.map(" " + _ + "\n").mkString + "\n", CompilerCrashed)
}
/** Runs command redirecting standard out and
@@ -355,13 +357,13 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
private def compareOutput(dir: File, logFile: File): String = {
val checkFile = getCheckFilePath(dir, kind)
- // if check file exists, compare with log file
val diff =
if (checkFile.canRead) compareFiles(logFile, checkFile.jfile)
else file2String(logFile)
+ // if check file exists, compare with log file
if (diff != "" && fileManager.updateCheck) {
- NestUI.verbose("output differs from log file: updating checkfile\n")
+ NestUI.verbose("Updating checkfile " + checkFile.jfile)
val toWrite = if (checkFile.exists) checkFile else getCheckFilePath(dir, "")
toWrite writeAll file2String(logFile)
""
@@ -386,10 +388,8 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
false
}
- private def exHandler(logFile: File): PartialFunction[Throwable, Boolean] =
- exHandler(logFile, "")
- private def exHandler(logFile: File, msg: String): PartialFunction[Throwable, Boolean] = {
- case e: Exception => logStackTrace(logFile, e, msg)
+ private def exHandler[T](logFile: File, msg: String, value: T): PartialFunction[Throwable, T] = {
+ case e: Exception => logStackTrace(logFile, e, msg) ; value
}
/** Runs a list of tests.
@@ -462,39 +462,38 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
}
else script(logFile, outDir)
}
- catch exHandler(logFile)
+ catch exHandler(logFile, "", false)
LogContext(logFile, swr, wr)
}
}
- def compileFilesIn(dir: File, logFile: File, outDir: File): Boolean = {
+ def groupedFiles(dir: File): List[List[File]] = {
val testFiles = dir.listFiles.toList filter isJavaOrScala
def isInGroup(f: File, num: Int) = SFile(f).stripExtension endsWith ("_" + num)
val groups = (0 to 9).toList map (num => testFiles filter (f => isInGroup(f, num)))
val noGroupSuffix = testFiles filterNot (groups.flatten contains)
- def compileGroup(g: List[File]): Boolean = {
+ noGroupSuffix :: groups filterNot (_.isEmpty)
+ }
+
+ def compileFilesIn(dir: File, logFile: File, outDir: File): CompilationOutcome = {
+ def compileGroup(g: List[File]): CompilationOutcome = {
val (scalaFiles, javaFiles) = g partition isScala
val allFiles = javaFiles ++ scalaFiles
- // scala+java, then java, then scala
- (scalaFiles.isEmpty || compileMgr.shouldCompile(outDir, allFiles, kind, logFile) || fail(g)) && {
- (javaFiles.isEmpty || javac(outDir, javaFiles, logFile)) && {
- (scalaFiles.isEmpty || compileMgr.shouldCompile(outDir, scalaFiles, kind, logFile) || fail(scalaFiles))
- }
+ List(1, 2, 3).foldLeft(CompileSuccess: CompilationOutcome) {
+ case (CompileSuccess, 1) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), allFiles, kind, logFile) // java + scala
+ case (CompileSuccess, 2) if javaFiles.nonEmpty => javac(outDir, javaFiles, logFile) // java
+ case (CompileSuccess, 3) if scalaFiles.nonEmpty => compileMgr.attemptCompile(Some(outDir), scalaFiles, kind, logFile) // scala
+ case (outcome, _) => outcome
}
}
-
- (noGroupSuffix.isEmpty || compileGroup(noGroupSuffix)) && (groups forall compileGroup)
- }
-
- def failCompileFilesIn(dir: File, logFile: File, outDir: File): Boolean = {
- val testFiles = dir.listFiles.toList
- val sourceFiles = testFiles filter isJavaOrScala
-
- sourceFiles.isEmpty || compileMgr.shouldFailCompile(outDir, sourceFiles, kind, logFile) || fail(testFiles filter isScala)
+ groupedFiles(dir).foldLeft(CompileSuccess: CompilationOutcome) {
+ case (CompileSuccess, files) => compileGroup(files)
+ case (outcome, _) => outcome
+ }
}
def runTestCommon(file: File, expectFailure: Boolean)(
@@ -502,15 +501,14 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
onFail: (File, File) => Unit = (_, _) => ()): LogContext =
{
runInContext(file, (logFile: File, outDir: File) => {
- val result =
- if (file.isDirectory) {
- if (expectFailure) failCompileFilesIn(file, logFile, outDir)
- else compileFilesIn(file, logFile, outDir)
- }
- else {
- if (expectFailure) compileMgr.shouldFailCompile(List(file), kind, logFile)
- else compileMgr.shouldCompile(List(file), kind, logFile)
- }
+ val outcome = (
+ if (file.isDirectory) compileFilesIn(file, logFile, outDir)
+ else compileMgr.attemptCompile(None, List(file), kind, logFile)
+ )
+ val result = (
+ if (expectFailure) outcome.isNegative
+ else outcome.isPositive
+ )
if (result) onSuccess(logFile, outDir)
else { onFail(logFile, outDir) ; false }
@@ -521,9 +519,15 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
runTestCommon(file, expectFailure = false)((logFile, outDir) => {
val dir = file.getParentFile
- // adding code.jar to the classpath (to provide Code.lift services for reification tests)
- execTest(outDir, logFile, PathSettings.srcCodeLib.toString) &&
- diffCheck(compareOutput(dir, logFile))
+ // adding codelib.jar to the classpath
+ // codelib provides the possibility to override standard reify
+ // this shields the massive amount of reification tests from changes in the API
+ execTest(outDir, logFile, PathSettings.srcCodeLib.toString) && {
+ // cannot replace paths here since this also inverts slashes
+ // which affects a bunch of tests
+ //fileManager.mapFile(logFile, replaceSlashes(dir, _))
+ diffCheck(compareOutput(dir, logFile))
+ }
})
// Apache Ant 1.6 or newer
@@ -543,7 +547,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
)
try runCommand(cmd, output)
- catch exHandler(output, "ant command '" + cmd + "' failed:\n")
+ catch exHandler(output, "ant command '" + cmd + "' failed:\n", false)
}
def runAntTest(file: File): LogContext = {
@@ -876,7 +880,7 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
)
// 4. compile testFile
- val ok = compileMgr.shouldCompile(List(testFile), kind, logFile)
+ val ok = compileMgr.attemptCompile(None, List(testFile), kind, logFile) eq CompileSuccess
NestUI.verbose("compilation of " + testFile + (if (ok) "succeeded" else "failed"))
if (ok) {
execTest(outDir, logFile) && {
@@ -903,7 +907,8 @@ class Worker(val fileManager: FileManager, params: TestRunParams) extends Actor
else {
val resFile = results.head
// 2. Compile source file
- if (!compileMgr.shouldCompile(outDir, sources, kind, logFile)) {
+
+ if (!compileMgr.attemptCompile(Some(outDir), sources, kind, logFile).isPositive) {
NestUI.normal("compilerMgr failed to compile %s to %s".format(sources mkString ", ", outDir))
false
}
diff --git a/src/scalacheck/org/scalacheck/Arbitrary.scala b/src/scalacheck/org/scalacheck/Arbitrary.scala
index 91d56b0aec..9bb235f917 100644
--- a/src/scalacheck/org/scalacheck/Arbitrary.scala
+++ b/src/scalacheck/org/scalacheck/Arbitrary.scala
@@ -263,7 +263,7 @@ object Arbitrary {
): Arbitrary[C[T]] = Arbitrary(containerOf[C,T](arbitrary[T]))
/** Arbitrary instance of any array. */
- implicit def arbArray[T](implicit a: Arbitrary[T], c: ClassManifest[T]
+ implicit def arbArray[T](implicit a: Arbitrary[T], c: ClassTag[T]
): Arbitrary[Array[T]] = Arbitrary(containerOf[Array,T](arbitrary[T]))
diff --git a/src/scalacheck/org/scalacheck/util/Buildable.scala b/src/scalacheck/org/scalacheck/util/Buildable.scala
index 6378e72d4f..662bc6146b 100644
--- a/src/scalacheck/org/scalacheck/util/Buildable.scala
+++ b/src/scalacheck/org/scalacheck/util/Buildable.scala
@@ -30,7 +30,7 @@ object Buildable {
def builder = (new mutable.ListBuffer[T]).mapResult(_.toStream)
}
- implicit def buildableArray[T](implicit cm: ClassManifest[T]) =
+ implicit def buildableArray[T](implicit t: ClassTag[T]) =
new Buildable[T,Array] {
def builder = mutable.ArrayBuilder.make[T]
}
diff --git a/src/scalap/scala/tools/scalap/JavaWriter.scala b/src/scalap/scala/tools/scalap/JavaWriter.scala
index 02b940ab16..9b0748509f 100644
--- a/src/scalap/scala/tools/scalap/JavaWriter.scala
+++ b/src/scalap/scala/tools/scalap/JavaWriter.scala
@@ -128,33 +128,12 @@ class JavaWriter(classfile: Classfile, writer: Writer) extends CodeWriter(writer
def printMethod(flags: Int, name: Int, tpe: Int, attribs: List[cf.Attribute]) {
if (getName(name) == "<init>")
print(flagsToStr(false, flags))
- attribs find {
- case cf.Attribute(name, _) => getName(name) == "JacoMeta"
- } match {
- case Some(cf.Attribute(_, data)) =>
- val mp = new MetaParser(getName(
- ((data(0) & 0xff) << 8) + (data(1) & 0xff)).trim())
- mp.parse match {
- case None =>
- if (getName(name) == "<init>") {
- print("def this" + getType(tpe) + ";").newline
- } else {
- print("def " + NameTransformer.decode(getName(name)))
- print(getType(tpe) + ";").newline
- }
- case Some(str) =>
- if (getName(name) == "<init>")
- print("def this" + str + ";").newline
- else
- print("def " + NameTransformer.decode(getName(name)) + str + ";").newline
- }
- case None =>
- if (getName(name) == "<init>") {
- print("def this" + getType(tpe) + ";").newline
- } else {
- print("def " + NameTransformer.decode(getName(name)))
- print(getType(tpe) + ";").newline
- }
+ if (getName(name) == "<init>") {
+ print("def this" + getType(tpe) + ";").newline
+ }
+ else {
+ print("def " + NameTransformer.decode(getName(name)))
+ print(getType(tpe) + ";").newline
}
attribs find {
case cf.Attribute(name, _) => getName(name) == "Exceptions"
diff --git a/src/swing/scala/swing/Font.scala.disabled b/src/swing/scala/swing/Font.scala.disabled
index 6eebd667bd..9e21eb859c 100644
--- a/src/swing/scala/swing/Font.scala.disabled
+++ b/src/swing/scala/swing/Font.scala.disabled
@@ -1,36 +1,36 @@
package scala.swing
-/*object Font {
- def apply(fontFormat: Int, fontFile: java.io.File) = java.awt.Font.createFont(fontFormat, fontFile)
- def apply(fontFormat: Int, fontStream: java.io.InputStream) = java.awt.Font.createFont(fontFormat, fontStream)
+/*object Font {
+ def apply(fontFormat: Int, fontFile: java.io.File) = java.awt.Font.createFont(fontFormat, fontFile)
+ def apply(fontFormat: Int, fontStream: java.io.InputStream) = java.awt.Font.createFont(fontFormat, fontStream)
def decode(str: String) = java.awt.Font.decode(str)
-
+
/* TODO: finish implementation
/**
* See [java.awt.Font.getFont].
*/
- def get(attributes: Map[_ <: java.text.AttributedCharacterIterator.Attribute, _]) =
+ def get(attributes: Map[_ <: java.text.AttributedCharacterIterator.Attribute, _]) =
java.awt.Font.getFont(ImmutableMapWrapper(attributes))
-
+
import java.{util => ju}
- private case class ImmutableMapWrapper[A, B](underlying : Map[A, B])(m : ClassManifest[A]) extends ju.AbstractMap[A, B] {
+ private case class ImmutableMapWrapper[A, B](underlying : Map[A, B])(t : ClassTag[A]) extends ju.AbstractMap[A, B] {
self =>
override def size = underlying.size
- override def put(k : A, v : B) =
+ override def put(k : A, v : B) =
throw new UnsupportedOperationException("This is a wrapper that does not support mutation")
- override def remove(k : AnyRef) =
+ override def remove(k : AnyRef) =
throw new UnsupportedOperationException("This is a wrapper that does not support mutation")
-
+
override def entrySet : ju.Set[ju.Map.Entry[A, B]] = new ju.AbstractSet[ju.Map.Entry[A, B]] {
def size = self.size
def iterator = new ju.Iterator[ju.Map.Entry[A, B]] {
val ui = underlying.iterator
var prev : Option[A] = None
-
+
def hasNext = ui.hasNext
-
+
def next = {
val (k, v) = ui.next
prev = Some(k)
@@ -44,7 +44,7 @@ package scala.swing
}
}
}
-
+
def remove = prev match {
case Some(k) => val v = self.remove(k.asInstanceOf[AnyRef]) ; prev = None ; v
case _ => throw new IllegalStateException("next must be called at least once before remove")
@@ -53,7 +53,7 @@ package scala.swing
}
}
*/
-
+
/**
* See [java.awt.Font.getFont].
*/
@@ -62,9 +62,9 @@ package scala.swing
* See [java.awt.Font.getFont].
*/
def get(nm: String, font: Font) = java.awt.Font.getFont(nm, font)
-
+
def Insets(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height)
def Rectangle(x: Int, y: Int, width: Int, height: Int) = new Insets(x, y, width, height)
def Point(x: Int, y: Int) = new Point(x, y)
- def Dimension(x: Int, y: Int) = new Dimension(x, y)
+ def Dimension(x: Int, y: Int) = new Dimension(x, y)
}*/ \ No newline at end of file
diff --git a/test/benchmarks/src/scala/collection/parallel/benchmarks/arrays/Resetting.scala b/test/benchmarks/src/scala/collection/parallel/benchmarks/arrays/Resetting.scala
index e6feb59fcd..22d2107f62 100644
--- a/test/benchmarks/src/scala/collection/parallel/benchmarks/arrays/Resetting.scala
+++ b/test/benchmarks/src/scala/collection/parallel/benchmarks/arrays/Resetting.scala
@@ -4,19 +4,19 @@ package scala.collection.parallel.benchmarks.arrays
import scala.collection.parallel.benchmarks._
-abstract class Resetting[T: Manifest](elemcreate: Int => T, sz: Int, p: Int, what: String)
+abstract class Resetting[T: ClassTag](elemcreate: Int => T, sz: Int, p: Int, what: String)
extends Bench {
val size = sz
val parallelism = p
val runWhat = what
-
+
var anyarray: Array[Any] = null
var castarray: AnyRef = null
var gencastarray: Array[T] = null
var manifarray: Array[T] = null
-
+
reset
-
+
def reset = what match {
case "any" =>
anyarray = new Array[Any](sz)
diff --git a/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/MatrixMultiplication.scala b/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/MatrixMultiplication.scala
index 5f902ff483..6d5b189c3a 100644
--- a/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/MatrixMultiplication.scala
+++ b/test/benchmarks/src/scala/collection/parallel/benchmarks/parallel_array/MatrixMultiplication.scala
@@ -16,54 +16,54 @@ class MatrixMultiplication(sz: Int, p: Int, what: String)
extends Resettable(sz, p, what, new Cont(_), new Array[Any](_), classOf[Cont]) {
def companion = MatrixMultiplication
collection.parallel.tasksupport.environment = forkjoinpool
-
+
val a = Matrix.unit[Int](sz)
val b = Matrix.unit[Int](sz)
var c = new Matrix[Int](sz)
-
+
def runpar = c = a * b //{ c.assignProduct(a, b) } //; println("--------"); c.output }
def runseq = throw new UnsupportedOperationException
def comparisonMap = collection.Map()
-
- class Matrix[T](n: Int)(implicit num: Numeric[T], man: Manifest[T]) {
+
+ class Matrix[T](n: Int)(implicit num: Numeric[T], tag: ClassTag[T]) {
val array = new Array[T](n * n)
-
+
def apply(y: Int, x: Int) = array(y * n + x)
-
+
def update(y: Int, x: Int, elem: T) = array(y * n + x) = elem
-
+
def *(b: Matrix[T]) = {
val m = new Matrix[T](n)
m.assignProduct(this, b)
m
}
-
+
def assignProduct(a: Matrix[T], b: Matrix[T]) = {
val range = ParRange(0, n * n, 1, false)
for (i <- range) this(i / n, i % n) = calcProduct(a, b, i / n, i % n);
}
-
+
private def calcProduct(a: Matrix[T], b: Matrix[T], y: Int, x: Int): T = {
import num._
var sum = zero
for (i <- 0 until n) sum += a(y, i) * b(i, x)
sum
}
-
+
def output = for (y <- 0 until n) {
for (x <- 0 until n) print(this(y, x))
println
}
}
-
+
object Matrix {
- def unit[T](n: Int)(implicit num: Numeric[T], man: Manifest[T]) = {
+ def unit[T](n: Int)(implicit num: Numeric[T], tag: ClassTag[T]) = {
val m = new Matrix[T](n)
for (i <- 0 until n) m(i, i) = num.one
m
}
}
-
+
}
diff --git a/test/files/continuations-neg/infer0.check b/test/disabled/continuations-neg/infer0.check
index 1dd072ef09..1dd072ef09 100644
--- a/test/files/continuations-neg/infer0.check
+++ b/test/disabled/continuations-neg/infer0.check
diff --git a/test/files/continuations-neg/infer0.scala b/test/disabled/continuations-neg/infer0.scala
index 9cf69c5d35..6d97d7504d 100644
--- a/test/files/continuations-neg/infer0.scala
+++ b/test/disabled/continuations-neg/infer0.scala
@@ -4,11 +4,9 @@ import scala.util.continuations._
object Test {
-
def test(x: => Int @cpsParam[String,Int]) = 7
-
- def main(args: Array[String]): Any = {
+
+ def main(args: Array[String]) {
test(8)
}
-
-} \ No newline at end of file
+}
diff --git a/test/files/jvm/concurrent-future.check b/test/disabled/jvm/concurrent-future.check
index c55e824818..715ac90ce7 100644
--- a/test/files/jvm/concurrent-future.check
+++ b/test/disabled/jvm/concurrent-future.check
@@ -12,5 +12,3 @@ test6: hai world
test6: kthxbye
test7: hai world
test7: kthxbye
-test8: hai world
-test8: im in yr loop
diff --git a/test/files/jvm/concurrent-future.scala b/test/disabled/jvm/concurrent-future.scala
index b44d054219..eda05428c8 100644
--- a/test/files/jvm/concurrent-future.scala
+++ b/test/disabled/jvm/concurrent-future.scala
@@ -90,25 +90,25 @@ object Test extends App {
}
}
- def testOnFailureWhenFutureTimeoutException(): Unit = once {
- done =>
- val f = future[Unit] {
- output(8, "hai world")
- throw new FutureTimeoutException(null)
- }
- f onSuccess { case _ =>
- output(8, "onoes")
- done()
- }
- f onFailure {
- case e: FutureTimeoutException =>
- output(8, "im in yr loop")
- done()
- case other =>
- output(8, "onoes: " + other)
- done()
- }
- }
+ // def testOnFailureWhenFutureTimeoutException(): Unit = once {
+ // done =>
+ // val f = future[Unit] {
+ // output(8, "hai world")
+ // throw new FutureTimeoutException(null)
+ // }
+ // f onSuccess { case _ =>
+ // output(8, "onoes")
+ // done()
+ // }
+ // f onFailure {
+ // case e: FutureTimeoutException =>
+ // output(8, "im in yr loop")
+ // done()
+ // case other =>
+ // output(8, "onoes: " + other)
+ // done()
+ // }
+ // }
testOnSuccess()
testOnSuccessWhenCompleted()
@@ -117,6 +117,6 @@ object Test extends App {
testOnFailureWhenSpecialThrowable(5, new Error)
testOnFailureWhenSpecialThrowable(6, new scala.util.control.ControlThrowable { })
testOnFailureWhenSpecialThrowable(7, new InterruptedException)
- testOnFailureWhenFutureTimeoutException()
+ // testOnFailureWhenFutureTimeoutException()
}
diff --git a/test/disabled/presentation/akka.check b/test/disabled/presentation/akka.check
index 9cd20ffb1c..5105d85a00 100644
--- a/test/disabled/presentation/akka.check
+++ b/test/disabled/presentation/akka.check
@@ -153,11 +153,11 @@ retrieved 131 members
`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef`
`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef`
`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef`
-`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef`
-`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef`
+`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: ClassTag[T])akka.actor.ActorRef`
+`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: ClassTag[T])akka.actor.ActorRef`
`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef`
-`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef`
-`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef`
+`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: ClassTag[T])akka.actor.ActorRef`
+`method spawn[T <: akka.actor.Actor](implicit evidence$1: ClassTag[T])akka.actor.ActorRef`
`method start()akka.actor.ActorRef`
`method startLink(actorRef: akka.actor.ActorRef)Unit`
`method stop()Unit`
@@ -286,11 +286,11 @@ retrieved 131 members
`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef`
`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef`
`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef`
-`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef`
-`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef`
+`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: ClassTag[T])akka.actor.ActorRef`
+`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: ClassTag[T])akka.actor.ActorRef`
`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef`
-`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef`
-`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef`
+`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: ClassTag[T])akka.actor.ActorRef`
+`method spawn[T <: akka.actor.Actor](implicit evidence$1: ClassTag[T])akka.actor.ActorRef`
`method start()akka.actor.ActorRef`
`method startLink(actorRef: akka.actor.ActorRef)Unit`
`method stop()Unit`
@@ -419,11 +419,11 @@ retrieved 131 members
`method spawn(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef`
`method spawnLink(clazz: Class[_ <: akka.actor.Actor])akka.actor.ActorRef`
`method spawnLinkRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef`
-`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: Manifest[T])akka.actor.ActorRef`
-`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: Manifest[T])akka.actor.ActorRef`
+`method spawnLinkRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$4: ClassTag[T])akka.actor.ActorRef`
+`method spawnLink[T <: akka.actor.Actor](implicit evidence$3: ClassTag[T])akka.actor.ActorRef`
`method spawnRemote(clazz: Class[_ <: akka.actor.Actor], hostname: String, port: Int, timeout: Long)akka.actor.ActorRef`
-`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: Manifest[T])akka.actor.ActorRef`
-`method spawn[T <: akka.actor.Actor](implicit evidence$1: Manifest[T])akka.actor.ActorRef`
+`method spawnRemote[T <: akka.actor.Actor](hostname: String, port: Int, timeout: Long)(implicit evidence$2: ClassTag[T])akka.actor.ActorRef`
+`method spawn[T <: akka.actor.Actor](implicit evidence$1: ClassTag[T])akka.actor.ActorRef`
`method start()akka.actor.ActorRef`
`method startLink(actorRef: akka.actor.ActorRef)Unit`
`method stop()Unit`
diff --git a/test/disabled/presentation/akka/src/akka/actor/Actor.scala b/test/disabled/presentation/akka/src/akka/actor/Actor.scala
index b955c4c38b..b9bc51b635 100644
--- a/test/disabled/presentation/akka/src/akka/actor/Actor.scala
+++ b/test/disabled/presentation/akka/src/akka/actor/Actor.scala
@@ -135,7 +135,7 @@ object Actor extends ListenerManagement {
* val actor = actorOf[MyActor].start()
* </pre>
*/
- def actorOf[T <: Actor: Manifest]: ActorRef = actorOf(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]])
+ def actorOf[T <: Actor: ClassTag]: ActorRef = actorOf(classTag[T].erasure.asInstanceOf[Class[_ <: Actor]])
/** Creates an ActorRef out of the Actor of the specified Class.
* <pre>
@@ -481,7 +481,7 @@ private[actor] class AnyOptionAsTypedOption(anyOption: Option[Any]) {
/** Convenience helper to cast the given Option of Any to an Option of the given type. Will swallow a possible
* ClassCastException and return None in that case.
*/
- def asSilently[T: Manifest]: Option[T] = narrowSilently[T](anyOption)
+ def asSilently[T: ClassTag]: Option[T] = narrowSilently[T](anyOption)
}
/** Marker interface for proxyable actors (such as typed actor).
diff --git a/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala b/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala
index ff67c9468e..da0b63006a 100644
--- a/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala
+++ b/test/disabled/presentation/akka/src/akka/actor/ActorRef.scala
@@ -1406,28 +1406,28 @@ trait ScalaActorRef extends ActorRefShared { ref: ActorRef =>
/**
* Atomically create (from actor class) and start an actor.
*/
- def spawn[T <: Actor: Manifest]: ActorRef =
- spawn(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]])
+ def spawn[T <: Actor: ClassTag]: ActorRef =
+ spawn(classTag[T].erasure.asInstanceOf[Class[_ <: Actor]])
/**
* Atomically create (from actor class), start and make an actor remote.
*/
- def spawnRemote[T <: Actor: Manifest](hostname: String, port: Int, timeout: Long): ActorRef = {
+ def spawnRemote[T <: Actor: ClassTag](hostname: String, port: Int, timeout: Long): ActorRef = {
ensureRemotingEnabled
- spawnRemote(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout)
+ spawnRemote(classTag[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout)
}
/**
* Atomically create (from actor class), start and link an actor.
*/
- def spawnLink[T <: Actor: Manifest]: ActorRef =
- spawnLink(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]])
+ def spawnLink[T <: Actor: ClassTag]: ActorRef =
+ spawnLink(classTag[T].erasure.asInstanceOf[Class[_ <: Actor]])
/**
* Atomically create (from actor class), start, link and make an actor remote.
*/
- def spawnLinkRemote[T <: Actor: Manifest](hostname: String, port: Int, timeout: Long): ActorRef = {
+ def spawnLinkRemote[T <: Actor: ClassTag](hostname: String, port: Int, timeout: Long): ActorRef = {
ensureRemotingEnabled
- spawnLinkRemote(manifest[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout)
+ spawnLinkRemote(classTag[T].erasure.asInstanceOf[Class[_ <: Actor]], hostname, port, timeout)
}
}
diff --git a/test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala b/test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala
index df335dc8b4..5d649fcd36 100644
--- a/test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala
+++ b/test/disabled/presentation/akka/src/akka/actor/ActorRegistry.scala
@@ -5,7 +5,7 @@
package akka.actor
import scala.collection.mutable.{ ListBuffer, Map }
-import scala.reflect.Manifest
+import scala.reflect.ArrayTag
import java.util.concurrent.{ ConcurrentSkipListSet, ConcurrentHashMap }
import java.util.{ Set => JSet }
@@ -74,10 +74,10 @@ final class ActorRegistry private[actor] () extends ListenerManagement {
}
/**
- * Finds all actors that are subtypes of the class passed in as the Manifest argument and supporting passed message.
+ * Finds all actors that are subtypes of the class passed in as the ClassTag argument and supporting passed message.
*/
- def actorsFor[T <: Actor](message: Any)(implicit manifest: Manifest[T]): Array[ActorRef] =
- filter(a => manifest.erasure.isAssignableFrom(a.actor.getClass) && a.isDefinedAt(message))
+ def actorsFor[T <: Actor](message: Any)(implicit classTag: ClassTag[T]): Array[ActorRef] =
+ filter(a => classTag.erasure.isAssignableFrom(a.actor.getClass) && a.isDefinedAt(message))
/**
* Finds all actors that satisfy a predicate.
@@ -93,16 +93,16 @@ final class ActorRegistry private[actor] () extends ListenerManagement {
}
/**
- * Finds all actors that are subtypes of the class passed in as the Manifest argument.
+ * Finds all actors that are subtypes of the class passed in as the ClassTag argument.
*/
- def actorsFor[T <: Actor](implicit manifest: Manifest[T]): Array[ActorRef] =
- actorsFor[T](manifest.erasure.asInstanceOf[Class[T]])
+ def actorsFor[T <: Actor](implicit classTag: ClassTag[T]): Array[ActorRef] =
+ actorsFor[T](classTag.erasure.asInstanceOf[Class[T]])
/**
* Finds any actor that matches T. Very expensive, traverses ALL alive actors.
*/
- def actorFor[T <: Actor](implicit manifest: Manifest[T]): Option[ActorRef] =
- find({ case a: ActorRef if manifest.erasure.isAssignableFrom(a.actor.getClass) => a })
+ def actorFor[T <: Actor](implicit classTag: ClassTag[T]): Option[ActorRef] =
+ find({ case a: ActorRef if classTag.erasure.isAssignableFrom(a.actor.getClass) => a })
/**
* Finds all actors of type or sub-type specified by the class passed in as the Class argument.
@@ -166,21 +166,21 @@ final class ActorRegistry private[actor] () extends ListenerManagement {
}
/**
- * Finds all typed actors that are subtypes of the class passed in as the Manifest argument.
+ * Finds all typed actors that are subtypes of the class passed in as the ClassTag argument.
*/
- def typedActorsFor[T <: AnyRef](implicit manifest: Manifest[T]): Array[AnyRef] = {
+ def typedActorsFor[T <: AnyRef](implicit classTag: ClassTag[T]): Array[AnyRef] = {
TypedActorModule.ensureEnabled
- typedActorsFor[T](manifest.erasure.asInstanceOf[Class[T]])
+ typedActorsFor[T](classTag.erasure.asInstanceOf[Class[T]])
}
/**
* Finds any typed actor that matches T.
*/
- def typedActorFor[T <: AnyRef](implicit manifest: Manifest[T]): Option[AnyRef] = {
+ def typedActorFor[T <: AnyRef](implicit classTag: ClassTag[T]): Option[AnyRef] = {
TypedActorModule.ensureEnabled
def predicate(proxy: AnyRef): Boolean = {
val actorRef = TypedActorModule.typedActorObjectInstance.get.actorFor(proxy)
- actorRef.isDefined && manifest.erasure.isAssignableFrom(actorRef.get.actor.getClass)
+ actorRef.isDefined && classTag.erasure.isAssignableFrom(actorRef.get.actor.getClass)
}
findTypedActor({ case a: Some[AnyRef] if predicate(a.get) => a })
}
@@ -279,7 +279,7 @@ final class ActorRegistry private[actor] () extends ListenerManagement {
*
* @author Viktor Klang
*/
-class Index[K <: AnyRef, V <: AnyRef: Manifest] {
+class Index[K <: AnyRef, V <: AnyRef: ArrayTag] {
private val Naught = Array[V]() //Nil for Arrays
private val container = new ConcurrentHashMap[K, JSet[V]]
private val emptySet = new ConcurrentSkipListSet[V]
diff --git a/test/disabled/presentation/akka/src/akka/event/EventHandler.scala b/test/disabled/presentation/akka/src/akka/event/EventHandler.scala
index f3176b7c21..af2fee6c47 100644
--- a/test/disabled/presentation/akka/src/akka/event/EventHandler.scala
+++ b/test/disabled/presentation/akka/src/akka/event/EventHandler.scala
@@ -115,8 +115,8 @@ object EventHandler extends ListenerManagement {
notifyListeners(event)
}
- def notify[T <: Event: ClassManifest](event: => T) {
- if (level >= levelFor(classManifest[T].erasure.asInstanceOf[Class[_ <: Event]])) notifyListeners(event)
+ def notify[T <: Event: ClassTag](event: => T) {
+ if (level >= levelFor(classTag[T].erasure.asInstanceOf[Class[_ <: Event]])) notifyListeners(event)
}
def error(cause: Throwable, instance: AnyRef, message: => String) {
diff --git a/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala b/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala
index 0c5da82294..5219c49dcb 100644
--- a/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala
+++ b/test/disabled/presentation/akka/src/akka/remoteinterface/RemoteInterface.scala
@@ -206,8 +206,8 @@ abstract class RemoteSupport extends ListenerManagement with RemoteServerModule
* </pre>
*/
@deprecated("Will be removed after 1.1", "1.1")
- def actorOf[T <: Actor: Manifest](host: String, port: Int): ActorRef =
- clientManagedActorOf(() => createActorFromClass(manifest.erasure), host, port)
+ def actorOf[T <: Actor: ClassTag](host: String, port: Int): ActorRef =
+ clientManagedActorOf(() => createActorFromClass(classTag[T].erasure), host, port)
protected def createActorFromClass(clazz: Class[_]): Actor = {
import ReflectiveAccess.{ createInstance, noParams, noArgs }
diff --git a/test/disabled/presentation/akka/src/akka/util/Helpers.scala b/test/disabled/presentation/akka/src/akka/util/Helpers.scala
index 48477426c9..0ff45408d0 100644
--- a/test/disabled/presentation/akka/src/akka/util/Helpers.scala
+++ b/test/disabled/presentation/akka/src/akka/util/Helpers.scala
@@ -37,7 +37,7 @@ object Helpers {
* Convenience helper to cast the given Option of Any to an Option of the given type. Will swallow a possible
* ClassCastException and return None in that case.
*/
- def narrowSilently[T: Manifest](o: Option[Any]): Option[T] =
+ def narrowSilently[T: ClassTag](o: Option[Any]): Option[T] =
try {
narrow(o)
} catch {
diff --git a/test/files/presentation/shutdown-deadlock.check b/test/disabled/presentation/shutdown-deadlock.check
index ddcb4ff59b..ddcb4ff59b 100644
--- a/test/files/presentation/shutdown-deadlock.check
+++ b/test/disabled/presentation/shutdown-deadlock.check
diff --git a/test/files/presentation/shutdown-deadlock/ShutdownDeadlockTest.scala b/test/disabled/presentation/shutdown-deadlock/ShutdownDeadlockTest.scala
index cef9d2a5ed..cef9d2a5ed 100644
--- a/test/files/presentation/shutdown-deadlock/ShutdownDeadlockTest.scala
+++ b/test/disabled/presentation/shutdown-deadlock/ShutdownDeadlockTest.scala
diff --git a/test/files/presentation/shutdown-deadlock/src/arrays.scala b/test/disabled/presentation/shutdown-deadlock/src/arrays.scala
index ecebc78a6f..ecebc78a6f 100644
--- a/test/files/presentation/shutdown-deadlock/src/arrays.scala
+++ b/test/disabled/presentation/shutdown-deadlock/src/arrays.scala
diff --git a/test/disabled/presentation/simple-tests.check b/test/disabled/presentation/simple-tests.check
index b90dfce77c..cdb80ed987 100644
--- a/test/disabled/presentation/simple-tests.check
+++ b/test/disabled/presentation/simple-tests.check
@@ -244,7 +244,7 @@ TypeMember(method disable,(s: Tester.this.settings.Setting)scala.collection.muta
TypeMember(value disable,Tester.this.settings.MultiStringSetting,false,true,<none>)
TypeMember(value elidebelow,Tester.this.settings.IntSetting,false,true,<none>)
TypeMember(method embeddedDefaults,(loader: java.lang.ClassLoader)Unit,true,true,<none>)
-TypeMember(method embeddedDefaults,[T](implicit evidence$1: Manifest[T])Unit,true,true,<none>)
+TypeMember(method embeddedDefaults,[T](implicit evidence$1: ClassTag[T])Unit,true,true,<none>)
TypeMember(value encoding,Tester.this.settings.StringSetting,false,true,<none>)
TypeMember(method ensuring,(cond: (scala.tools.nsc.Settings) => Boolean,msg: => Any)scala.tools.nsc.Settings,true,false,method any2Ensuring)
TypeMember(method ensuring,(cond: (scala.tools.nsc.Settings) => Boolean)scala.tools.nsc.Settings,true,false,method any2Ensuring)
diff --git a/test/files/buildmanager/t2556_3/t2556_3.check b/test/files/buildmanager/t2556_3/t2556_3.check
index 37808d2b31..34f90f7f9b 100644
--- a/test/files/buildmanager/t2556_3/t2556_3.check
+++ b/test/files/buildmanager/t2556_3/t2556_3.check
@@ -9,10 +9,10 @@ invalidate B.scala because it references invalid (no longer inherited) definitio
compiling Set(B.scala, C.scala)
B.scala:3: error: type mismatch;
found : C
- required: ?{val x: ?}
+ required: ?{def x: ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method any2Ensuring in object Predef of type [A](x: A)Ensuring[A]
and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
- are possible conversion functions from C to ?{val x: ?}
+ are possible conversion functions from C to ?{def x: ?}
println( (new C).x )
^
diff --git a/test/files/buildmanager/t2559/D.scala b/test/files/buildmanager/t2559/D.scala
index 906b69a3e7..62dc5427f9 100644
--- a/test/files/buildmanager/t2559/D.scala
+++ b/test/files/buildmanager/t2559/D.scala
@@ -1,8 +1,4 @@
object D {
- def x(a: A) =
- a match {
- case _: B => ()
- case _: C => ()
- }
+ def x(a: A) = if (a.isInstanceOf[B] || a.isInstanceOf[C]) ()
}
diff --git a/test/files/buildmanager/t2559/t2559.check b/test/files/buildmanager/t2559/t2559.check
index 752278fbe8..4d43838cf5 100644
--- a/test/files/buildmanager/t2559/t2559.check
+++ b/test/files/buildmanager/t2559/t2559.check
@@ -6,9 +6,4 @@ compiling Set(A.scala)
Changes: Map(class B -> List(), class C -> List(), class E -> List(Changed(Class(A))[class E extends a sealed trait A]), trait A -> List())
invalidate D.scala because it references changed class [Changed(Class(A))[class E extends a sealed trait A]]
compiling Set(D.scala)
-D.scala:3: warning: match is not exhaustive!
-missing combination E
-
- a match {
- ^
Changes: Map(object D -> List())
diff --git a/test/files/buildmanager/t2650_1/t2650_1.check b/test/files/buildmanager/t2650_1/t2650_1.check
index ecddb33620..f1e4b1b8bc 100644
--- a/test/files/buildmanager/t2650_1/t2650_1.check
+++ b/test/files/buildmanager/t2650_1/t2650_1.check
@@ -1,5 +1,6 @@
builder > A.scala B.scala
compiling Set(A.scala, B.scala)
+warning: there were 1 feature warnings; re-run with -feature for details
Changes: Map()
builder > A.scala
compiling Set(A.scala)
diff --git a/test/files/buildmanager/t2657/t2657.check b/test/files/buildmanager/t2657/t2657.check
index 74ba87a21d..cd0357599c 100644
--- a/test/files/buildmanager/t2657/t2657.check
+++ b/test/files/buildmanager/t2657/t2657.check
@@ -1,5 +1,6 @@
builder > A.scala B.scala
compiling Set(A.scala, B.scala)
+warning: there were 1 feature warnings; re-run with -feature for details
Changes: Map()
builder > A.scala
compiling Set(A.scala)
diff --git a/test/files/codelib/code.jar.desired.sha1 b/test/files/codelib/code.jar.desired.sha1
index 8dabf404b9..21c4dccb30 100644
--- a/test/files/codelib/code.jar.desired.sha1
+++ b/test/files/codelib/code.jar.desired.sha1
@@ -1 +1 @@
-e76a8883d275ca4870f745b505fb0a1cb9cbe446 ?code.jar
+3ddb9fded6e19ca591a78b8a294284c9e945da30 ?code.jar
diff --git a/test/files/continuations-neg/t3718.check b/test/files/continuations-neg/t3718.check
new file mode 100644
index 0000000000..659104c1c6
--- /dev/null
+++ b/test/files/continuations-neg/t3718.check
@@ -0,0 +1,4 @@
+t3718.scala:2: error: cannot cps-transform malformed (possibly in shift/reset placement) expression
+ scala.util.continuations.reset((_: Any).##)
+ ^
+one error found
diff --git a/test/files/continuations-neg/t3718.scala b/test/files/continuations-neg/t3718.scala
new file mode 100644
index 0000000000..a0fcb9d869
--- /dev/null
+++ b/test/files/continuations-neg/t3718.scala
@@ -0,0 +1,3 @@
+object Test {
+ scala.util.continuations.reset((_: Any).##)
+}
diff --git a/test/files/continuations-run/match2.scala b/test/files/continuations-run/match2.scala
index 8b0fb946df..5092ce3abe 100644
--- a/test/files/continuations-run/match2.scala
+++ b/test/files/continuations-run/match2.scala
@@ -18,7 +18,7 @@ object Test {
}
- def main(args: Array[String]): Any = {
+ def main(args: Array[String]): Unit = {
println(reset(test1()))
println(reset(test2()))
}
diff --git a/test/files/continuations-run/shift-pct.check b/test/files/continuations-run/shift-pct.check
new file mode 100644
index 0000000000..fb190e770a
--- /dev/null
+++ b/test/files/continuations-run/shift-pct.check
@@ -0,0 +1,25 @@
+d = 1, d2 = 1.0, pct = 1.000
+d = 2, d2 = 4.0, pct = 0.500
+d = 3, d2 = 9.0, pct = 0.333
+d = 4, d2 = 16.0, pct = 0.250
+d = 5, d2 = 25.0, pct = 0.200
+d = 6, d2 = 36.0, pct = 0.167
+d = 7, d2 = 49.0, pct = 0.143
+d = 8, d2 = 64.0, pct = 0.125
+d = 9, d2 = 81.0, pct = 0.111
+d = 10, d2 = 100.0, pct = 0.100
+d = 11, d2 = 121.0, pct = 0.091
+d = 12, d2 = 144.0, pct = 0.083
+d = 13, d2 = 169.0, pct = 0.077
+d = 14, d2 = 196.0, pct = 0.071
+d = 15, d2 = 225.0, pct = 0.067
+d = 16, d2 = 256.0, pct = 0.063
+d = 17, d2 = 289.0, pct = 0.059
+d = 18, d2 = 324.0, pct = 0.056
+d = 19, d2 = 361.0, pct = 0.053
+d = 20, d2 = 400.0, pct = 0.050
+d = 21, d2 = 441.0, pct = 0.048
+d = 22, d2 = 484.0, pct = 0.045
+d = 23, d2 = 529.0, pct = 0.043
+d = 24, d2 = 576.0, pct = 0.042
+d = 25, d2 = 625.0, pct = 0.040
diff --git a/test/files/continuations-run/shift-pct.scala b/test/files/continuations-run/shift-pct.scala
new file mode 100644
index 0000000000..7ef9922168
--- /dev/null
+++ b/test/files/continuations-run/shift-pct.scala
@@ -0,0 +1,30 @@
+import scala.util.continuations._
+
+object Test {
+ abstract class IfReturnRepro {
+ def s1: Double @cpsParam[Any, Unit]
+ def s2: Double @cpsParam[Any, Unit]
+
+ def p(i: Int): Double @cpsParam[Unit, Any] = {
+ val px = s1
+ val pct = if (px > 100) px else px / s2
+ println("pct = %.3f".format(pct))
+ pct
+ }
+ }
+
+ def main(args: Array[String]) : Unit = {
+ var d: Double = 0d
+ def d2 = d * d
+
+ val irr = new IfReturnRepro {
+ def s1 = shift(f => f(d))
+ def s2 = shift(f => f(d2))
+ }
+ 1 to 25 foreach { i =>
+ d = i
+ print("d = " + i + ", d2 = " + d2 + ", ")
+ run(irr p i)
+ }
+ }
+}
diff --git a/test/files/continuations-run/t5472.check b/test/files/continuations-run/t5472.check
new file mode 100644
index 0000000000..d42e80c18e
--- /dev/null
+++ b/test/files/continuations-run/t5472.check
@@ -0,0 +1 @@
+List(23, 23)
diff --git a/test/files/continuations-run/t5472.scala b/test/files/continuations-run/t5472.scala
new file mode 100644
index 0000000000..3e3c76b32a
--- /dev/null
+++ b/test/files/continuations-run/t5472.scala
@@ -0,0 +1,90 @@
+import scala.annotation._
+import scala.util.continuations._
+import java.util.concurrent.atomic._
+
+object Test {
+ def main(args: Array[String]) {
+ val map = Map("foo" -> 1, "bar" -> 2)
+ reset {
+ val mapped =
+ for {
+ (location, accessors) <- new ContinuationizedParallelIterable(map)
+ } yield {
+ shiftUnit0[Int, Unit](23)
+ }
+ println(mapped.toList)
+ }
+ }
+}
+
+final class ContinuationizedParallelIterable[+A](protected val underline: Iterable[A]) {
+ def toList = underline.toList.sortBy(_.toString)
+
+ final def filter(p: A => Boolean @suspendable): ContinuationizedParallelIterable[A] @suspendable =
+ shift(
+ new AtomicInteger(1) with ((ContinuationizedParallelIterable[A] => Unit) => Unit) {
+ private val results = new AtomicReference[List[A]](Nil)
+
+ @tailrec
+ private def add(element: A) {
+ val old = results.get
+ if (!results.compareAndSet(old, element :: old)) {
+ add(element)
+ }
+ }
+
+ override final def apply(continue: ContinuationizedParallelIterable[A] => Unit) {
+ for (element <- underline) {
+ super.incrementAndGet()
+ reset {
+ val pass = p(element)
+ if (pass) {
+ add(element)
+ }
+ if (super.decrementAndGet() == 0) {
+ continue(new ContinuationizedParallelIterable(results.get))
+ }
+ }
+ }
+ if (super.decrementAndGet() == 0) {
+ continue(new ContinuationizedParallelIterable(results.get))
+ }
+ }
+ })
+
+ final def foreach[U](f: A => U @suspendable): Unit @suspendable =
+ shift(
+ new AtomicInteger(1) with ((Unit => Unit) => Unit) {
+ override final def apply(continue: Unit => Unit) {
+ for (element <- underline) {
+ super.incrementAndGet()
+ reset {
+ f(element)
+ if (super.decrementAndGet() == 0) {
+ continue()
+ }
+ }
+ }
+ if (super.decrementAndGet() == 0) {
+ continue()
+ }
+ }
+ })
+
+ final def map[B: Manifest](f: A => B @suspendable): ContinuationizedParallelIterable[B] @suspendable =
+ shift(
+ new AtomicInteger(underline.size) with ((ContinuationizedParallelIterable[B] => Unit) => Unit) {
+ override final def apply(continue: ContinuationizedParallelIterable[B] => Unit) {
+ val results = new Array[B](super.get)
+ for ((element, i) <- underline.view zipWithIndex) {
+ reset {
+ val result = f(element)
+ results(i) = result
+ if (super.decrementAndGet() == 0) {
+ continue(new ContinuationizedParallelIterable(results))
+ }
+ }
+ }
+ }
+ })
+}
diff --git a/test/pending/run/reify_classfileann_b.check b/test/files/continuations-run/z1673.check
index e69de29bb2..e69de29bb2 100644
--- a/test/pending/run/reify_classfileann_b.check
+++ b/test/files/continuations-run/z1673.check
diff --git a/test/files/continuations-run/z1673.scala b/test/files/continuations-run/z1673.scala
new file mode 100644
index 0000000000..716b374860
--- /dev/null
+++ b/test/files/continuations-run/z1673.scala
@@ -0,0 +1,31 @@
+import scala.util.continuations._
+
+class MatchRepro {
+ def s: String @cps[Any] = shift { k => k("foo") }
+
+ def p = {
+ val k = s
+ s match { case lit0 => }
+ }
+
+ def q = {
+ val k = s
+ k match { case lit1 => }
+ }
+
+ def r = {
+ s match { case "FOO" => }
+ }
+
+ def t = {
+ val k = s
+ k match { case "FOO" => }
+ }
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val m = new MatchRepro
+ ()
+ }
+}
diff --git a/test/files/jvm/annotations.scala b/test/files/jvm/annotations.scala
index b1c3c8ba40..66ebde592b 100644
--- a/test/files/jvm/annotations.scala
+++ b/test/files/jvm/annotations.scala
@@ -193,7 +193,9 @@ object Test6 {
val c = new C("bob")
c.setText("dylan")
println(c.getText())
- if (new D(true).isProp()) {
+ val d = new D(true)
+ d.setProp(false)
+ if (!d.isProp()) {
println(new D(false).getM())
}
}
diff --git a/test/files/jvm/future-spec/FutureTests.scala b/test/files/jvm/future-spec/FutureTests.scala
new file mode 100644
index 0000000000..9a9cf951bb
--- /dev/null
+++ b/test/files/jvm/future-spec/FutureTests.scala
@@ -0,0 +1,511 @@
+
+
+
+import scala.concurrent._
+import scala.concurrent.util.duration._
+import scala.concurrent.util.Duration.Inf
+import scala.collection._
+import scala.runtime.NonLocalReturnControl
+
+
+
+object FutureTests extends MinimalScalaTest {
+
+ /* some utils */
+
+ def testAsync(s: String): Future[String] = s match {
+ case "Hello" => future { "World" }
+ case "Failure" => Promise.failed(new RuntimeException("Expected exception; to test fault-tolerance")).future
+ case "NoReply" => Promise[String]().future
+ }
+
+ val defaultTimeout = Inf
+
+ /* future specification */
+
+ "A future" should {
+
+ "compose with for-comprehensions" in {
+ def async(x: Int) = future { (x * 2).toString }
+ val future0 = future[Any] {
+ "five!".length
+ }
+
+ val future1 = for {
+ a <- future0.mapTo[Int] // returns 5
+ b <- async(a) // returns "10"
+ c <- async(7) // returns "14"
+ } yield b + "-" + c
+
+ val future2 = for {
+ a <- future0.mapTo[Int]
+ b <- (future { (a * 2).toString }).mapTo[Int]
+ c <- future { (7 * 2).toString }
+ } yield b + "-" + c
+
+ Await.result(future1, defaultTimeout) mustBe ("10-14")
+ assert(checkType(future1, manifest[String]))
+ intercept[ClassCastException] { Await.result(future2, defaultTimeout) }
+ }
+
+ "support pattern matching within a for-comprehension" in {
+ case class Req[T](req: T)
+ case class Res[T](res: T)
+ def async[T](req: Req[T]) = req match {
+ case Req(s: String) => future { Res(s.length) }
+ case Req(i: Int) => future { Res((i * 2).toString) }
+ }
+
+ val future1 = for {
+ Res(a: Int) <- async(Req("Hello"))
+ Res(b: String) <- async(Req(a))
+ Res(c: String) <- async(Req(7))
+ } yield b + "-" + c
+
+ val future2 = for {
+ Res(a: Int) <- async(Req("Hello"))
+ Res(b: Int) <- async(Req(a))
+ Res(c: Int) <- async(Req(7))
+ } yield b + "-" + c
+
+ Await.result(future1, defaultTimeout) mustBe ("10-14")
+ intercept[NoSuchElementException] { Await.result(future2, defaultTimeout) }
+ }
+
+ "recover from exceptions" in {
+ val future1 = Future(5)
+ val future2 = future1 map (_ / 0)
+ val future3 = future2 map (_.toString)
+
+ val future4 = future1 recover {
+ case e: ArithmeticException => 0
+ } map (_.toString)
+
+ val future5 = future2 recover {
+ case e: ArithmeticException => 0
+ } map (_.toString)
+
+ val future6 = future2 recover {
+ case e: MatchError => 0
+ } map (_.toString)
+
+ val future7 = future3 recover {
+ case e: ArithmeticException => "You got ERROR"
+ }
+
+ val future8 = testAsync("Failure")
+ val future9 = testAsync("Failure") recover {
+ case e: RuntimeException => "FAIL!"
+ }
+ val future10 = testAsync("Hello") recover {
+ case e: RuntimeException => "FAIL!"
+ }
+ val future11 = testAsync("Failure") recover {
+ case _ => "Oops!"
+ }
+
+ Await.result(future1, defaultTimeout) mustBe (5)
+ intercept[ArithmeticException] { Await.result(future2, defaultTimeout) }
+ intercept[ArithmeticException] { Await.result(future3, defaultTimeout) }
+ Await.result(future4, defaultTimeout) mustBe ("5")
+ Await.result(future5, defaultTimeout) mustBe ("0")
+ intercept[ArithmeticException] { Await.result(future6, defaultTimeout) }
+ Await.result(future7, defaultTimeout) mustBe ("You got ERROR")
+ intercept[RuntimeException] { Await.result(future8, defaultTimeout) }
+ Await.result(future9, defaultTimeout) mustBe ("FAIL!")
+ Await.result(future10, defaultTimeout) mustBe ("World")
+ Await.result(future11, defaultTimeout) mustBe ("Oops!")
+ }
+
+ "recoverWith from exceptions" in {
+ val o = new IllegalStateException("original")
+ val r = new IllegalStateException("recovered")
+
+ intercept[IllegalStateException] {
+ val failed = Promise.failed[String](o).future recoverWith {
+ case _ if false == true => Promise.successful("yay!").future
+ }
+ Await.result(failed, defaultTimeout)
+ } mustBe (o)
+
+ val recovered = Promise.failed[String](o).future recoverWith {
+ case _ => Promise.successful("yay!").future
+ }
+ Await.result(recovered, defaultTimeout) mustBe ("yay!")
+
+ intercept[IllegalStateException] {
+ val refailed = Promise.failed[String](o).future recoverWith {
+ case _ => Promise.failed[String](r).future
+ }
+ Await.result(refailed, defaultTimeout)
+ } mustBe (r)
+ }
+
+ "andThen like a boss" in {
+ val q = new java.util.concurrent.LinkedBlockingQueue[Int]
+ for (i <- 1 to 1000) {
+ val chained = future {
+ q.add(1); 3
+ } andThen {
+ case _ => q.add(2)
+ } andThen {
+ case Right(0) => q.add(Int.MaxValue)
+ } andThen {
+ case _ => q.add(3);
+ }
+ Await.result(chained, defaultTimeout) mustBe (3)
+ q.poll() mustBe (1)
+ q.poll() mustBe (2)
+ q.poll() mustBe (3)
+ q.clear()
+ }
+ }
+
+ "firstCompletedOf" in {
+ def futures = Vector.fill[Future[Int]](10) {
+ Promise[Int]().future
+ } :+ Promise.successful[Int](5).future
+
+ Await.result(Future.firstCompletedOf(futures), defaultTimeout) mustBe (5)
+ Await.result(Future.firstCompletedOf(futures.iterator), defaultTimeout) mustBe (5)
+ }
+
+ "find" in {
+ val futures = for (i <- 1 to 10) yield future {
+ i
+ }
+
+ val result = Future.find[Int](futures)(_ == 3)
+ Await.result(result, defaultTimeout) mustBe (Some(3))
+
+ val notFound = Future.find[Int](futures.iterator)(_ == 11)
+ Await.result(notFound, defaultTimeout) mustBe (None)
+ }
+
+ "zip" in {
+ val timeout = 10000 millis
+ val f = new IllegalStateException("test")
+ intercept[IllegalStateException] {
+ val failed = Promise.failed[String](f).future zip Promise.successful("foo").future
+ Await.result(failed, timeout)
+ } mustBe (f)
+
+ intercept[IllegalStateException] {
+ val failed = Promise.successful("foo").future zip Promise.failed[String](f).future
+ Await.result(failed, timeout)
+ } mustBe (f)
+
+ intercept[IllegalStateException] {
+ val failed = Promise.failed[String](f).future zip Promise.failed[String](f).future
+ Await.result(failed, timeout)
+ } mustBe (f)
+
+ val successful = Promise.successful("foo").future zip Promise.successful("foo").future
+ Await.result(successful, timeout) mustBe (("foo", "foo"))
+ }
+
+ "fold" in {
+ val timeout = 10000 millis
+ def async(add: Int, wait: Int) = future {
+ Thread.sleep(wait)
+ add
+ }
+
+ val futures = (0 to 9) map {
+ idx => async(idx, idx * 200)
+ }
+ val folded = Future.fold(futures)(0)(_ + _)
+ Await.result(folded, timeout) mustBe (45)
+
+ val futuresit = (0 to 9) map {
+ idx => async(idx, idx * 200)
+ }
+ val foldedit = Future.fold(futures)(0)(_ + _)
+ Await.result(foldedit, timeout) mustBe (45)
+ }
+
+ "fold by composing" in {
+ val timeout = 10000 millis
+ def async(add: Int, wait: Int) = future {
+ Thread.sleep(wait)
+ add
+ }
+ def futures = (0 to 9) map {
+ idx => async(idx, idx * 200)
+ }
+ val folded = futures.foldLeft(Future(0)) {
+ case (fr, fa) => for (r <- fr; a <- fa) yield (r + a)
+ }
+ Await.result(folded, timeout) mustBe (45)
+ }
+
+ "fold with an exception" in {
+ val timeout = 10000 millis
+ def async(add: Int, wait: Int) = future {
+ Thread.sleep(wait)
+ if (add == 6) throw new IllegalArgumentException("shouldFoldResultsWithException: expected")
+ add
+ }
+ def futures = (0 to 9) map {
+ idx => async(idx, idx * 100)
+ }
+ val folded = Future.fold(futures)(0)(_ + _)
+ intercept[IllegalArgumentException] {
+ Await.result(folded, timeout)
+ }.getMessage mustBe ("shouldFoldResultsWithException: expected")
+ }
+
+ "fold mutable zeroes safely" in {
+ import scala.collection.mutable.ArrayBuffer
+ def test(testNumber: Int) {
+ val fs = (0 to 1000) map (i => Future(i))
+ val f = Future.fold(fs)(ArrayBuffer.empty[AnyRef]) {
+ case (l, i) if i % 2 == 0 => l += i.asInstanceOf[AnyRef]
+ case (l, _) => l
+ }
+ val result = Await.result(f.mapTo[ArrayBuffer[Int]], 10000 millis).sum
+
+ assert(result == 250500)
+ }
+
+ (1 to 100) foreach test //Make sure it tries to provoke the problem
+ }
+
+ "return zero value if folding empty list" in {
+ val zero = Future.fold(List[Future[Int]]())(0)(_ + _)
+ Await.result(zero, defaultTimeout) mustBe (0)
+ }
+
+ "shouldReduceResults" in {
+ def async(idx: Int) = future {
+ Thread.sleep(idx * 200)
+ idx
+ }
+ val timeout = 10000 millis
+
+ val futures = (0 to 9) map { async }
+ val reduced = Future.reduce(futures)(_ + _)
+ Await.result(reduced, timeout) mustBe (45)
+
+ val futuresit = (0 to 9) map { async }
+ val reducedit = Future.reduce(futuresit)(_ + _)
+ Await.result(reducedit, timeout) mustBe (45)
+ }
+
+ "shouldReduceResultsWithException" in {
+ def async(add: Int, wait: Int) = future {
+ Thread.sleep(wait)
+ if (add == 6) throw new IllegalArgumentException("shouldFoldResultsWithException: expected")
+ else add
+ }
+ val timeout = 10000 millis
+ def futures = (1 to 10) map {
+ idx => async(idx, idx * 100)
+ }
+ val failed = Future.reduce(futures)(_ + _)
+ intercept[IllegalArgumentException] {
+ Await.result(failed, timeout)
+ }.getMessage mustBe ("shouldFoldResultsWithException: expected")
+ }
+
+ "shouldReduceThrowNSEEOnEmptyInput" in {
+ intercept[java.util.NoSuchElementException] {
+ val emptyreduced = Future.reduce(List[Future[Int]]())(_ + _)
+ Await.result(emptyreduced, defaultTimeout)
+ }
+ }
+
+ "shouldTraverseFutures" in {
+ object counter {
+ var count = -1
+ def incAndGet() = counter.synchronized {
+ count += 2
+ count
+ }
+ }
+
+ val oddFutures = List.fill(100)(future { counter.incAndGet() }).iterator
+ val traversed = Future.sequence(oddFutures)
+ Await.result(traversed, defaultTimeout).sum mustBe (10000)
+
+ val list = (1 to 100).toList
+ val traversedList = Future.traverse(list)(x => Future(x * 2 - 1))
+ Await.result(traversedList, defaultTimeout).sum mustBe (10000)
+
+ val iterator = (1 to 100).toList.iterator
+ val traversedIterator = Future.traverse(iterator)(x => Future(x * 2 - 1))
+ Await.result(traversedIterator, defaultTimeout).sum mustBe (10000)
+ }
+
+ "shouldHandleThrowables" in {
+ val ms = new mutable.HashSet[Throwable] with mutable.SynchronizedSet[Throwable]
+ implicit val ec = scala.concurrent.ExecutionContext.fromExecutor(new scala.concurrent.forkjoin.ForkJoinPool(), {
+ t =>
+ ms += t
+ })
+
+ class ThrowableTest(m: String) extends Throwable(m)
+
+ val f1 = future[Any] {
+ throw new ThrowableTest("test")
+ }
+
+ intercept[ThrowableTest] {
+ Await.result(f1, defaultTimeout)
+ }
+
+ val latch = new TestLatch
+ val f2 = future {
+ Await.ready(latch, 5 seconds)
+ "success"
+ }
+ val f3 = f2 map { s => s.toUpperCase }
+
+ f2 foreach { _ => throw new ThrowableTest("dispatcher foreach") }
+ f2 onSuccess { case _ => throw new ThrowableTest("dispatcher receive") }
+
+ latch.open()
+
+ Await.result(f2, defaultTimeout) mustBe ("success")
+
+ f2 foreach { _ => throw new ThrowableTest("current thread foreach") }
+ f2 onSuccess { case _ => throw new ThrowableTest("current thread receive") }
+
+ Await.result(f3, defaultTimeout) mustBe ("SUCCESS")
+
+ val waiting = future {
+ Thread.sleep(1000)
+ }
+ Await.ready(waiting, 2000 millis)
+
+ ms.size mustBe (4)
+ }
+
+ "shouldBlockUntilResult" in {
+ val latch = new TestLatch
+
+ val f = future {
+ Await.ready(latch, 5 seconds)
+ 5
+ }
+ val f2 = future {
+ val res = Await.result(f, Inf)
+ res + 9
+ }
+
+ intercept[TimeoutException] {
+ Await.ready(f2, 100 millis)
+ }
+
+ latch.open()
+
+ Await.result(f2, defaultTimeout) mustBe (14)
+
+ val f3 = future {
+ Thread.sleep(100)
+ 5
+ }
+
+ intercept[TimeoutException] {
+ Await.ready(f3, 0 millis)
+ }
+ }
+
+ "run callbacks async" in {
+ val latch = Vector.fill(10)(new TestLatch)
+
+ val f1 = future {
+ latch(0).open()
+ Await.ready(latch(1), TestLatch.DefaultTimeout)
+ "Hello"
+ }
+ val f2 = f1 map {
+ s =>
+ latch(2).open()
+ Await.ready(latch(3), TestLatch.DefaultTimeout)
+ s.length
+ }
+ for (_ <- f2) latch(4).open()
+
+ Await.ready(latch(0), TestLatch.DefaultTimeout)
+
+ f1.isCompleted mustBe (false)
+ f2.isCompleted mustBe (false)
+
+ latch(1).open()
+ Await.ready(latch(2), TestLatch.DefaultTimeout)
+
+ f1.isCompleted mustBe (true)
+ f2.isCompleted mustBe (false)
+
+ val f3 = f1 map {
+ s =>
+ latch(5).open()
+ Await.ready(latch(6), TestLatch.DefaultTimeout)
+ s.length * 2
+ }
+ for (_ <- f3) latch(3).open()
+
+ Await.ready(latch(5), TestLatch.DefaultTimeout)
+
+ f3.isCompleted mustBe (false)
+
+ latch(6).open()
+ Await.ready(latch(4), TestLatch.DefaultTimeout)
+
+ f2.isCompleted mustBe (true)
+ f3.isCompleted mustBe (true)
+
+ val p1 = Promise[String]()
+ val f4 = p1.future map {
+ s =>
+ latch(7).open()
+ Await.ready(latch(8), TestLatch.DefaultTimeout)
+ s.length
+ }
+ for (_ <- f4) latch(9).open()
+
+ p1.future.isCompleted mustBe (false)
+ f4.isCompleted mustBe (false)
+
+ p1 complete Right("Hello")
+
+ Await.ready(latch(7), TestLatch.DefaultTimeout)
+
+ p1.future.isCompleted mustBe (true)
+ f4.isCompleted mustBe (false)
+
+ latch(8).open()
+ Await.ready(latch(9), TestLatch.DefaultTimeout)
+
+ Await.ready(f4, defaultTimeout).isCompleted mustBe (true)
+ }
+
+ "should not deadlock with nested await (ticket 1313)" in {
+ val simple = Future() map {
+ _ =>
+ val unit = Future(())
+ val umap = unit map { _ => () }
+ Await.result(umap, Inf)
+ }
+ Await.ready(simple, Inf).isCompleted mustBe (true)
+
+ val l1, l2 = new TestLatch
+ val complex = Future() map {
+ _ =>
+ blocking {
+ val nested = Future(())
+ for (_ <- nested) l1.open()
+ Await.ready(l1, TestLatch.DefaultTimeout) // make sure nested is completed
+ for (_ <- nested) l2.open()
+ Await.ready(l2, TestLatch.DefaultTimeout)
+ }
+ }
+ Await.ready(complex, defaultTimeout).isCompleted mustBe (true)
+ }
+
+ }
+
+}
+
+
diff --git a/test/files/jvm/future-spec/PromiseTests.scala b/test/files/jvm/future-spec/PromiseTests.scala
new file mode 100644
index 0000000000..6016746a23
--- /dev/null
+++ b/test/files/jvm/future-spec/PromiseTests.scala
@@ -0,0 +1,244 @@
+
+
+
+import scala.concurrent._
+import scala.concurrent.util.duration._
+import scala.concurrent.util.Duration.Inf
+import scala.collection._
+import scala.runtime.NonLocalReturnControl
+
+
+
+object PromiseTests extends MinimalScalaTest {
+
+ val defaultTimeout = Inf
+
+ /* promise specification */
+
+ "An empty Promise" should {
+
+ "not be completed" in {
+ val p = Promise()
+ p.future.isCompleted mustBe (false)
+ }
+
+ "have no value" in {
+ val p = Promise()
+ p.future.value mustBe (None)
+ }
+
+ "return supplied value on timeout" in {
+ val failure = Promise.failed[String](new RuntimeException("br0ken")).future
+ val otherFailure = Promise.failed[String](new RuntimeException("last")).future
+ val empty = Promise[String]().future
+ val timedOut = Promise.successful[String]("Timedout").future
+
+ Await.result(failure fallbackTo timedOut, defaultTimeout) mustBe ("Timedout")
+ Await.result(timedOut fallbackTo empty, defaultTimeout) mustBe ("Timedout")
+ Await.result(failure fallbackTo failure fallbackTo timedOut, defaultTimeout) mustBe ("Timedout")
+ intercept[RuntimeException] {
+ Await.result(failure fallbackTo otherFailure, defaultTimeout)
+ }.getMessage mustBe ("last")
+ }
+
+ }
+
+ "A successful Promise" should {
+ val result = "test value"
+ val future = Promise[String]().complete(Right(result)).future
+ futureWithResult(_(future, result))
+ }
+
+ "A failed Promise" should {
+ val message = "Expected Exception"
+ val future = Promise[String]().complete(Left(new RuntimeException(message))).future
+ futureWithException[RuntimeException](_(future, message))
+ }
+
+ "An interrupted Promise" should {
+ val message = "Boxed InterruptedException"
+ val future = Promise[String]().complete(Left(new InterruptedException(message))).future
+ futureWithException[ExecutionException](_(future, message))
+ }
+
+ "A NonLocalReturnControl failed Promise" should {
+ val result = "test value"
+ val future = Promise[String]().complete(Left(new NonLocalReturnControl[String]("test", result))).future
+ futureWithResult(_(future, result))
+ }
+
+ def futureWithResult(f: ((Future[Any], Any) => Unit) => Unit) {
+
+ "be completed" in { f((future, _) => future.isCompleted mustBe (true)) }
+
+ "contain a value" in { f((future, result) => future.value mustBe (Some(Right(result)))) }
+
+ "return result with 'blocking'" in { f((future, result) => blocking(future, defaultTimeout) mustBe (result)) }
+
+ "return result with 'Await.result'" in { f((future, result) => Await.result(future, defaultTimeout) mustBe (result)) }
+
+ "not timeout" in { f((future, _) => Await.ready(future, 0 millis)) }
+
+ "filter result" in {
+ f {
+ (future, result) =>
+ Await.result((future filter (_ => true)), defaultTimeout) mustBe (result)
+ intercept[NoSuchElementException] {
+ Await.result((future filter (_ => false)), defaultTimeout)
+ }
+ }
+ }
+
+ "transform result with map" in { f((future, result) => Await.result((future map (_.toString.length)), defaultTimeout) mustBe (result.toString.length)) }
+
+ "compose result with flatMap" in {
+ f { (future, result) =>
+ val r = for (r <- future; p <- Promise.successful("foo").future) yield r.toString + p
+ Await.result(r, defaultTimeout) mustBe (result.toString + "foo")
+ }
+ }
+
+ "perform action with foreach" in {
+ f {
+ (future, result) =>
+ val p = Promise[Any]()
+ future foreach p.success
+ Await.result(p.future, defaultTimeout) mustBe (result)
+ }
+ }
+
+ "zip properly" in {
+ f {
+ (future, result) =>
+ Await.result(future zip Promise.successful("foo").future, defaultTimeout) mustBe ((result, "foo"))
+ intercept[RuntimeException] {
+ Await.result(future zip Promise.failed(new RuntimeException("ohnoes")).future, defaultTimeout)
+ }.getMessage mustBe ("ohnoes")
+ }
+ }
+
+ "not recover from exception" in { f((future, result) => Await.result(future.recover({ case _ => "pigdog" }), defaultTimeout) mustBe (result)) }
+
+ "perform action on result" in {
+ f {
+ (future, result) =>
+ val p = Promise[Any]()
+ future.onSuccess { case x => p.success(x) }
+ Await.result(p.future, defaultTimeout) mustBe (result)
+ }
+ }
+
+ "not project a failure" in {
+ f {
+ (future, result) =>
+ intercept[NoSuchElementException] {
+ Await.result(future.failed, defaultTimeout)
+ }.getMessage mustBe ("Future.failed not completed with a throwable. Instead completed with: " + result)
+ }
+ }
+
+ "cast using mapTo" in {
+ f {
+ (future, result) =>
+ Await.result(future.mapTo[Boolean].recover({ case _: ClassCastException ⇒ false }), defaultTimeout) mustBe (false)
+ }
+ }
+
+ }
+
+ def futureWithException[E <: Throwable: Manifest](f: ((Future[Any], String) => Unit) => Unit) {
+
+ "be completed" in {
+ f((future, _) => future.isCompleted mustBe (true))
+ }
+
+ "contain a value" in {
+ f((future, message) => {
+ future.value.get.left.get.getMessage mustBe (message)
+ })
+ }
+
+ "throw exception with 'blocking'" in {
+ f {
+ (future, message) =>
+ intercept[E] {
+ blocking(future, defaultTimeout)
+ }.getMessage mustBe (message)
+ }
+ }
+
+ "throw exception with 'Await.result'" in {
+ f {
+ (future, message) =>
+ intercept[E] {
+ Await.result(future, defaultTimeout)
+ }.getMessage mustBe (message)
+ }
+ }
+
+ "retain exception with filter" in {
+ f {
+ (future, message) =>
+ intercept[E] { Await.result(future filter (_ => true), defaultTimeout) }.getMessage mustBe (message)
+ intercept[E] { Await.result(future filter (_ => false), defaultTimeout) }.getMessage mustBe (message)
+ }
+ }
+
+ "retain exception with map" in {
+ f {
+ (future, message) =>
+ intercept[E] { Await.result(future map (_.toString.length), defaultTimeout) }.getMessage mustBe (message)
+ }
+ }
+
+ "retain exception with flatMap" in {
+ f {
+ (future, message) =>
+ intercept[E] { Await.result(future flatMap (_ => Promise.successful("foo").future), defaultTimeout) }.getMessage mustBe (message)
+ }
+ }
+
+ "zip properly" in {
+ f {
+ (future, message) =>
+ intercept[E] {
+ Await.result(future zip Promise.successful("foo").future, defaultTimeout)
+ }.getMessage mustBe (message)
+ }
+ }
+
+ "recover from exception" in {
+ f {
+ (future, message) =>
+ Await.result(future.recover({ case e if e.getMessage == message ⇒ "pigdog" }), defaultTimeout) mustBe ("pigdog")
+ }
+ }
+
+ "project a failure" in {
+ f((future, message) => Await.result(future.failed, defaultTimeout).getMessage mustBe (message))
+ }
+
+ "perform action on exception" in {
+ f {
+ (future, message) =>
+ val p = Promise[Any]()
+ future.onFailure { case _ => p.success(message) }
+ Await.result(p.future, defaultTimeout) mustBe (message)
+ }
+ }
+
+ "always cast successfully using mapTo" in {
+ f {
+ (future, message) =>
+ intercept[E] { Await.result(future.mapTo[java.lang.Thread], defaultTimeout) }.getMessage mustBe (message)
+ }
+ }
+ }
+}
+
+
+
+
+
+
+
diff --git a/test/files/jvm/future-spec/main.scala b/test/files/jvm/future-spec/main.scala
new file mode 100644
index 0000000000..45b59d5d20
--- /dev/null
+++ b/test/files/jvm/future-spec/main.scala
@@ -0,0 +1,108 @@
+
+
+
+import scala.collection._
+import scala.concurrent._
+import scala.concurrent.util.Duration
+import java.util.concurrent.{ TimeoutException, CountDownLatch, TimeUnit }
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ FutureTests.check()
+ PromiseTests.check()
+ }
+
+}
+
+
+trait Output {
+ val buffer = new StringBuilder
+
+ def bufferPrintln(a: Any) = buffer.synchronized {
+ buffer.append(a.toString + "\n")
+ }
+}
+
+
+trait MinimalScalaTest extends Output {
+
+ val throwables = mutable.ArrayBuffer[Throwable]()
+
+ def check() {
+ if (throwables.nonEmpty) println(buffer.toString)
+ }
+
+ implicit def stringops(s: String) = new {
+
+ def should[U](snippets: =>U) = {
+ bufferPrintln(s + " should:")
+ snippets
+ }
+
+ def in[U](snippet: =>U) = {
+ try {
+ bufferPrintln("- " + s)
+ snippet
+ bufferPrintln("[OK] Test passed.")
+ } catch {
+ case e =>
+ bufferPrintln("[FAILED] " + e)
+ bufferPrintln(e.getStackTrace().mkString("\n"))
+ throwables += e
+ }
+ }
+
+ }
+
+ implicit def objectops(obj: Any) = new {
+
+ def mustBe(other: Any) = assert(obj == other, obj + " is not " + other)
+
+ }
+
+ def intercept[T <: Throwable: Manifest](body: =>Any): T = {
+ try {
+ body
+ throw new Exception("Exception of type %s was not thrown".format(manifest[T]))
+ } catch {
+ case t: Throwable =>
+ if (manifest[T].erasure != t.getClass) throw t
+ else t.asInstanceOf[T]
+ }
+ }
+
+ def checkType[T: Manifest, S](in: Future[T], refmanifest: Manifest[S]): Boolean = manifest[T] == refmanifest
+}
+
+
+object TestLatch {
+ val DefaultTimeout = Duration(5, TimeUnit.SECONDS)
+
+ def apply(count: Int = 1) = new TestLatch(count)
+}
+
+
+class TestLatch(count: Int = 1) extends Awaitable[Unit] {
+ private var latch = new CountDownLatch(count)
+
+ def countDown() = latch.countDown()
+ def isOpen: Boolean = latch.getCount == 0
+ def open() = while (!isOpen) countDown()
+ def reset() = latch = new CountDownLatch(count)
+
+ @throws(classOf[TimeoutException])
+ def ready(atMost: Duration)(implicit permit: CanAwait) = {
+ val opened = latch.await(atMost.toNanos, TimeUnit.NANOSECONDS)
+ if (!opened) throw new TimeoutException("Timeout of %s." format (atMost.toString))
+ this
+ }
+
+ @throws(classOf[Exception])
+ def result(atMost: Duration)(implicit permit: CanAwait): Unit = {
+ ready(atMost)
+ }
+
+}
+
diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check
index 243c9aa3be..dc835bf8b6 100755..100644
--- a/test/files/jvm/interpreter.check
+++ b/test/files/jvm/interpreter.check
@@ -1,372 +1,374 @@
-Type in expressions to have them evaluated.
-Type :help for more information.
-
-scala>
-
-scala> // basics
-
-scala> 3+4
-res0: Int = 7
-
-scala> def gcd(x: Int, y: Int): Int = {
- if (x == 0) y
- else if (y == 0) x
- else gcd(y%x, x)
-}
-gcd: (x: Int, y: Int)Int
-
-scala> val five = gcd(15,35)
-five: Int = 5
-
-scala> var x = 1
-x: Int = 1
-
-scala> x = 2
-x: Int = 2
-
-scala> val three = x+1
-three: Int = 3
-
-scala> type anotherint = Int
-defined type alias anotherint
-
-scala> val four: anotherint = 4
-four: anotherint = 4
-
-scala> val bogus: anotherint = "hello"
-<console>:8: error: type mismatch;
- found : String("hello")
- required: anotherint
- (which expands to) Int
- val bogus: anotherint = "hello"
- ^
-
-scala> trait PointlessTrait
-defined trait PointlessTrait
-
-scala> val (x,y) = (2,3)
-x: Int = 2
-y: Int = 3
-
-scala> println("hello")
-hello
-
-scala>
-
-scala> // ticket #1513
-
-scala> val t1513 = Array(null)
-t1513: Array[Null] = Array(null)
-
-scala> // ambiguous toString problem from #547
-
-scala> val atom = new scala.xml.Atom()
-atom: scala.xml.Atom[Unit] = ()
-
-scala> // overriding toString problem from #1404
-
-scala> class S(override val toString : String)
-defined class S
-
-scala> val fish = new S("fish")
-fish: S = fish
-
-scala> // Test that arrays pretty print nicely.
-
-scala> val arr = Array("What's", "up", "doc?")
-arr: Array[String] = Array(What's, up, doc?)
-
-scala> // Test that arrays pretty print nicely, even when we give them type Any
-
-scala> val arrInt : Any = Array(1,2,3)
-arrInt: Any = Array(1, 2, 3)
-
-scala> // Test that nested arrays are pretty-printed correctly
-
-scala> val arrArrInt : Any = Array(Array(1, 2), Array(3, 4))
-arrArrInt: Any = Array(Array(1, 2), Array(3, 4))
-
-scala>
-
-scala> // implicit conversions
-
-scala> case class Foo(n: Int)
-defined class Foo
-
-scala> case class Bar(n: Int)
-defined class Bar
-
-scala> implicit def foo2bar(foo: Foo) = Bar(foo.n)
-foo2bar: (foo: Foo)Bar
-
-scala> val bar: Bar = Foo(3)
-bar: Bar = Bar(3)
-
-scala>
-
-scala> // importing from a previous result
-
-scala> import bar._
-import bar._
-
-scala> val m = n
-m: Int = 3
-
-scala>
-
-scala> // stressing the imports mechanism
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala> val one = 1
-one: Int = 1
-
-scala>
-
-scala>
-
-scala> val x1 = 1
-x1: Int = 1
-
-scala> val x2 = 1
-x2: Int = 1
-
-scala> val x3 = 1
-x3: Int = 1
-
-scala> val x4 = 1
-x4: Int = 1
-
-scala> val x5 = 1
-x5: Int = 1
-
-scala> val x6 = 1
-x6: Int = 1
-
-scala> val x7 = 1
-x7: Int = 1
-
-scala> val x8 = 1
-x8: Int = 1
-
-scala> val x9 = 1
-x9: Int = 1
-
-scala> val x10 = 1
-x10: Int = 1
-
-scala> val x11 = 1
-x11: Int = 1
-
-scala> val x12 = 1
-x12: Int = 1
-
-scala> val x13 = 1
-x13: Int = 1
-
-scala> val x14 = 1
-x14: Int = 1
-
-scala> val x15 = 1
-x15: Int = 1
-
-scala> val x16 = 1
-x16: Int = 1
-
-scala> val x17 = 1
-x17: Int = 1
-
-scala> val x18 = 1
-x18: Int = 1
-
-scala> val x19 = 1
-x19: Int = 1
-
-scala> val x20 = 1
-x20: Int = 1
-
-scala>
-
-scala> val two = one + x5
-two: Int = 2
-
-scala>
-
-scala> // handling generic wildcard arrays (#2386)
-
-scala> // It's put here because type feedback is an important part of it.
-
-scala> val xs: Array[_] = Array(1, 2)
-xs: Array[_] = Array(1, 2)
-
-scala> xs.size
-res2: Int = 2
-
-scala> xs.head
-res3: Any = 1
-
-scala> xs filter (_ == 2)
-res4: Array[_] = Array(2)
-
-scala> xs map (_ => "abc")
-res5: Array[String] = Array(abc, abc)
-
-scala> xs map (x => x)
-res6: scala.collection.mutable.ArraySeq[_] = ArraySeq(1, 2)
-
-scala> xs map (x => (x, x))
-res7: Array[(_$1, _$1)] forSome { type _$1 } = Array((1,1), (2,2))
-
-scala>
-
-scala> // interior syntax errors should *not* go into multi-line input mode.
-
-scala> // both of the following should abort immediately:
-
-scala> def x => y => z
-<console>:1: error: '=' expected but '=>' found.
- def x => y => z
- ^
-
-scala> [1,2,3]
-<console>:1: error: illegal start of definition
- [1,2,3]
- ^
-
-scala>
-
-scala>
-
-scala> // multi-line XML
-
-scala> <a>
-<b
- c="c"
- d="dd"
-/></a>
-res8: scala.xml.Elem =
-<a>
-<b c="c" d="dd"/></a>
-
-scala>
-
-scala>
-
-scala> /*
- /*
- multi-line comment
- */
-*/
-
-scala>
-
-scala>
-
-scala> // multi-line string
-
-scala> """
-hello
-there
-"""
-res9: String =
-"
-hello
-there
-"
-
-scala>
-
-scala> (1 + // give up early by typing two blank lines
-
-
-You typed two blank lines. Starting a new command.
-
-scala> // defining and using quoted names should work (ticket #323)
-
-scala> def `match` = 1
-match: Int
-
-scala> val x = `match`
-x: Int = 1
-
-scala>
-
-scala> // multiple classes defined on one line
-
-scala> sealed class Exp; class Fact extends Exp; class Term extends Exp
-defined class Exp
-defined class Fact
-defined class Term
-
-scala> def f(e: Exp) = e match { // non-exhaustive warning here
- case _:Fact => 3
-}
-<console>:18: warning: match is not exhaustive!
-missing combination Exp
-missing combination Term
-
- def f(e: Exp) = e match { // non-exhaustive warning here
- ^
-f: (e: Exp)Int
-
-scala>
-
-scala>
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> // basics
+
+scala> 3+4
+res0: Int = 7
+
+scala> def gcd(x: Int, y: Int): Int = {
+ if (x == 0) y
+ else if (y == 0) x
+ else gcd(y%x, x)
+}
+gcd: (x: Int, y: Int)Int
+
+scala> val five = gcd(15,35)
+five: Int = 5
+
+scala> var x = 1
+x: Int = 1
+
+scala> x = 2
+x: Int = 2
+
+scala> val three = x+1
+three: Int = 3
+
+scala> type anotherint = Int
+defined type alias anotherint
+
+scala> val four: anotherint = 4
+four: anotherint = 4
+
+scala> val bogus: anotherint = "hello"
+<console>:8: error: type mismatch;
+ found : String("hello")
+ required: anotherint
+ (which expands to) Int
+ val bogus: anotherint = "hello"
+ ^
+
+scala> trait PointlessTrait
+defined trait PointlessTrait
+
+scala> val (x,y) = (2,3)
+x: Int = 2
+y: Int = 3
+
+scala> println("hello")
+hello
+
+scala>
+
+scala> // ticket #1513
+
+scala> val t1513 = Array(null)
+t1513: Array[Null] = Array(null)
+
+scala> // ambiguous toString problem from #547
+
+scala> val atom = new scala.xml.Atom()
+atom: scala.xml.Atom[Unit] = ()
+
+scala> // overriding toString problem from #1404
+
+scala> class S(override val toString : String)
+defined class S
+
+scala> val fish = new S("fish")
+fish: S = fish
+
+scala> // Test that arrays pretty print nicely.
+
+scala> val arr = Array("What's", "up", "doc?")
+arr: Array[String] = Array(What's, up, doc?)
+
+scala> // Test that arrays pretty print nicely, even when we give them type Any
+
+scala> val arrInt : Any = Array(1,2,3)
+arrInt: Any = Array(1, 2, 3)
+
+scala> // Test that nested arrays are pretty-printed correctly
+
+scala> val arrArrInt : Any = Array(Array(1, 2), Array(3, 4))
+arrArrInt: Any = Array(Array(1, 2), Array(3, 4))
+
+scala>
+
+scala> // implicit conversions
+
+scala> case class Foo(n: Int)
+defined class Foo
+
+scala> case class Bar(n: Int)
+defined class Bar
+
+scala> implicit def foo2bar(foo: Foo) = Bar(foo.n)
+warning: there were 1 feature warnings; re-run with -feature for details
+foo2bar: (foo: Foo)Bar
+
+scala> val bar: Bar = Foo(3)
+bar: Bar = Bar(3)
+
+scala>
+
+scala> // importing from a previous result
+
+scala> import bar._
+import bar._
+
+scala> val m = n
+m: Int = 3
+
+scala>
+
+scala> // stressing the imports mechanism
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala>
+
+scala>
+
+scala> val x1 = 1
+x1: Int = 1
+
+scala> val x2 = 1
+x2: Int = 1
+
+scala> val x3 = 1
+x3: Int = 1
+
+scala> val x4 = 1
+x4: Int = 1
+
+scala> val x5 = 1
+x5: Int = 1
+
+scala> val x6 = 1
+x6: Int = 1
+
+scala> val x7 = 1
+x7: Int = 1
+
+scala> val x8 = 1
+x8: Int = 1
+
+scala> val x9 = 1
+x9: Int = 1
+
+scala> val x10 = 1
+x10: Int = 1
+
+scala> val x11 = 1
+x11: Int = 1
+
+scala> val x12 = 1
+x12: Int = 1
+
+scala> val x13 = 1
+x13: Int = 1
+
+scala> val x14 = 1
+x14: Int = 1
+
+scala> val x15 = 1
+x15: Int = 1
+
+scala> val x16 = 1
+x16: Int = 1
+
+scala> val x17 = 1
+x17: Int = 1
+
+scala> val x18 = 1
+x18: Int = 1
+
+scala> val x19 = 1
+x19: Int = 1
+
+scala> val x20 = 1
+x20: Int = 1
+
+scala>
+
+scala> val two = one + x5
+two: Int = 2
+
+scala>
+
+scala> // handling generic wildcard arrays (#2386)
+
+scala> // It's put here because type feedback is an important part of it.
+
+scala> val xs: Array[_] = Array(1, 2)
+xs: Array[_] = Array(1, 2)
+
+scala> xs.size
+res2: Int = 2
+
+scala> xs.head
+res3: Any = 1
+
+scala> xs filter (_ == 2)
+res4: Array[_] = Array(2)
+
+scala> xs map (_ => "abc")
+res5: Array[String] = Array(abc, abc)
+
+scala> xs map (x => x)
+res6: Array[_] = Array(1, 2)
+
+scala> xs map (x => (x, x))
+warning: there were 1 feature warnings; re-run with -feature for details
+warning: there were 1 feature warnings; re-run with -feature for details
+res7: Array[(_$1, _$1)] forSome { type _$1 } = Array((1,1), (2,2))
+
+scala>
+
+scala> // interior syntax errors should *not* go into multi-line input mode.
+
+scala> // both of the following should abort immediately:
+
+scala> def x => y => z
+<console>:1: error: '=' expected but '=>' found.
+ def x => y => z
+ ^
+
+scala> [1,2,3]
+<console>:1: error: illegal start of definition
+ [1,2,3]
+ ^
+
+scala>
+
+scala>
+
+scala> // multi-line XML
+
+scala> <a>
+<b
+ c="c"
+ d="dd"
+/></a>
+res8: scala.xml.Elem =
+<a>
+<b c="c" d="dd"/></a>
+
+scala>
+
+scala>
+
+scala> /*
+ /*
+ multi-line comment
+ */
+*/
+
+
+You typed two blank lines. Starting a new command.
+
+scala> // multi-line string
+
+scala> """
+hello
+there
+"""
+res12: String =
+"
+hello
+there
+"
+
+scala>
+
+scala> (1 + // give up early by typing two blank lines
+
+
+You typed two blank lines. Starting a new command.
+
+scala> // defining and using quoted names should work (ticket #323)
+
+scala> def `match` = 1
+match: Int
+
+scala> val x = `match`
+x: Int = 1
+
+scala>
+
+scala> // multiple classes defined on one line
+
+scala> sealed class Exp; class Fact extends Exp; class Term extends Exp
+defined class Exp
+defined class Fact
+defined class Term
+
+scala> def f(e: Exp) = e match { // non-exhaustive warning here
+ case _:Fact => 3
+}
+<console>:18: warning: match is not exhaustive!
+missing combination Exp
+missing combination Term
+
+ def f(e: Exp) = e match { // non-exhaustive warning here
+ ^
+f: (e: Exp)Int
+
+scala>
+
+scala>
plusOne: (x: Int)Int
res0: Int = 6
res0: String = after reset
diff --git a/test/files/jvm/interpreter.scala b/test/files/jvm/interpreter.scala
index f0bc8b5818..755b2ac9ae 100644
--- a/test/files/jvm/interpreter.scala
+++ b/test/files/jvm/interpreter.scala
@@ -2,6 +2,7 @@ import scala.tools.nsc._
import scala.tools.partest.ReplTest
object Test extends ReplTest {
+ override def extraSettings = "-deprecation -Xoldpatmat"
def code = <code>
// basics
3+4
@@ -29,7 +30,7 @@ val atom = new scala.xml.Atom()
class S(override val toString : String)
val fish = new S("fish")
// Test that arrays pretty print nicely.
-val arr = Array("What's", "up", "doc?")
+val arr = Array("What's", "up", "doc?")
// Test that arrays pretty print nicely, even when we give them type Any
val arrInt : Any = Array(1,2,3)
// Test that nested arrays are pretty-printed correctly
@@ -132,8 +133,8 @@ there
// defining and using quoted names should work (ticket #323)
-def `match` = 1
-val x = `match`
+def `match` = 1
+val x = `match`
// multiple classes defined on one line
sealed class Exp; class Fact extends Exp; class Term extends Exp
@@ -153,6 +154,6 @@ def f(e: Exp) = e match {{ // non-exhaustive warning here
interp.interpret("\"after reset\"")
interp.interpret("plusOne(5) // should be undefined now")
}
-
+
appendix()
}
diff --git a/test/files/jvm/manifests-new.check b/test/files/jvm/manifests-new.check
new file mode 100644
index 0000000000..9fca856970
--- /dev/null
+++ b/test/files/jvm/manifests-new.check
@@ -0,0 +1,58 @@
+x=(), t=ConcreteTypeTag[Unit], k=TypeRef, s=class Unit
+x=true, t=ConcreteTypeTag[Boolean], k=TypeRef, s=class Boolean
+x=a, t=ConcreteTypeTag[Char], k=TypeRef, s=class Char
+x=1, t=ConcreteTypeTag[Int], k=TypeRef, s=class Int
+x=abc, t=ConcreteTypeTag[String], k=TypeRef, s=class String
+x='abc, t=ConcreteTypeTag[Symbol], k=TypeRef, s=class Symbol
+
+x=List(()), t=ConcreteTypeTag[List[Unit]], k=TypeRef, s=class List
+x=List(true), t=ConcreteTypeTag[List[Boolean]], k=TypeRef, s=class List
+x=List(1), t=ConcreteTypeTag[List[Int]], k=TypeRef, s=class List
+x=List(abc), t=ConcreteTypeTag[List[String]], k=TypeRef, s=class List
+x=List('abc), t=ConcreteTypeTag[List[Symbol]], k=TypeRef, s=class List
+
+x=[Z, t=ConcreteTypeTag[Array[Boolean]], k=TypeRef, s=class Array
+x=[C, t=ConcreteTypeTag[Array[Char]], k=TypeRef, s=class Array
+x=[I, t=ConcreteTypeTag[Array[Int]], k=TypeRef, s=class Array
+x=[Ljava.lang.String;, t=ConcreteTypeTag[Array[String]], k=TypeRef, s=class Array
+x=[Lscala.Symbol;, t=ConcreteTypeTag[Array[Symbol]], k=TypeRef, s=class Array
+
+x=((),()), t=ConcreteTypeTag[(Unit, Unit)], k=TypeRef, s=class Tuple2
+x=(true,false), t=ConcreteTypeTag[(Boolean, Boolean)], k=TypeRef, s=class Tuple2
+x=(1,2), t=ConcreteTypeTag[(Int, Int)], k=TypeRef, s=class Tuple2
+x=(abc,xyz), t=ConcreteTypeTag[(String, String)], k=TypeRef, s=class Tuple2
+x=('abc,'xyz), t=ConcreteTypeTag[(Symbol, Symbol)], k=TypeRef, s=class Tuple2
+
+x=Test$, t=ConcreteTypeTag[Test.type], k=TypeRef, s=object Test
+x=scala.collection.immutable.List$, t=ConcreteTypeTag[scala.collection.immutable.List.type], k=TypeRef, s=object List
+
+x=Foo, t=ConcreteTypeTag[Foo[Int]], k=TypeRef, s=class Foo
+x=Foo, t=ConcreteTypeTag[Foo[List[Int]]], k=TypeRef, s=class Foo
+x=Foo, t=ConcreteTypeTag[Foo[Foo[Int]]], k=TypeRef, s=class Foo
+x=Foo, t=ConcreteTypeTag[Foo[List[Foo[Int]]]], k=TypeRef, s=class Foo
+
+x=Test1$$anon$1, t=ConcreteTypeTag[Bar[String]], k=RefinedType, s=<local Test1>
+x=Test1$$anon$2, t=ConcreteTypeTag[Bar[String]], k=RefinedType, s=<local Test1>
+
+()=()
+true=true
+a=a
+1=1
+'abc='abc
+
+List(())=List(())
+List(true)=List(true)
+List('abc)=List('abc)
+
+Array()=Array()
+Array(true)=Array(true)
+Array(a)=Array(a)
+Array(1)=Array(1)
+
+((),())=((),())
+(true,false)=(true,false)
+
+List(List(1), List(2))=List(List(1), List(2))
+
+Array(Array(1), Array(2))=Array(Array(1), Array(2))
+
diff --git a/test/files/jvm/manifests-new.scala b/test/files/jvm/manifests-new.scala
new file mode 100644
index 0000000000..d02f6ee608
--- /dev/null
+++ b/test/files/jvm/manifests-new.scala
@@ -0,0 +1,109 @@
+object Test extends App {
+ Test1
+ Test2
+}
+
+class Foo[T](x: T)
+trait Bar[T] { def f: T }
+
+object Test1 extends TestUtil {
+ print(())
+ print(true)
+ print('a')
+ print(1)
+ print("abc")
+ print('abc)
+ println()
+
+ print(List(()))
+ print(List(true))
+ print(List(1))
+ print(List("abc"))
+ print(List('abc))
+ println()
+
+ //print(Array(())) //Illegal class name "[V" in class file Test$
+ print(Array(true))
+ print(Array('a'))
+ print(Array(1))
+ print(Array("abc"))
+ print(Array('abc))
+ println()
+
+ print(((), ()))
+ print((true, false))
+ print((1, 2))
+ print(("abc", "xyz"))
+ print(('abc, 'xyz))
+ println()
+
+ print(Test)
+ print(List)
+ println()
+
+ print(new Foo(2))
+ print(new Foo(List(2)))
+ print(new Foo(new Foo(2)))
+ print(new Foo(List(new Foo(2))))
+ println()
+
+ print(new Bar[String] { def f = "abc" });
+ {print(new Bar[String] { def f = "abc" })}
+ println()
+}
+
+object Test2 {
+ import scala.util.Marshal._
+ println("()="+load[Unit](dump(())))
+ println("true="+load[Boolean](dump(true)))
+ println("a="+load[Char](dump('a')))
+ println("1="+load[Int](dump(1)))
+ println("'abc="+load[Symbol](dump('abc)))
+ println()
+
+ println("List(())="+load[List[Unit]](dump(List(()))))
+ println("List(true)="+load[List[Boolean]](dump(List(true))))
+ println("List('abc)="+load[List[Symbol]](dump(List('abc))))
+ println()
+
+ def loadArray[T](x: Array[Byte])(implicit t: reflect.ClassTag[Array[T]]) =
+ load[Array[T]](x)(t).deep.toString
+ println("Array()="+loadArray[Int](dump(Array(): Array[Int])))
+ println("Array(true)="+loadArray[Boolean](dump(Array(true))))
+ println("Array(a)="+loadArray[Char](dump(Array('a'))))
+ println("Array(1)="+loadArray[Int](dump(Array(1))))
+ println()
+
+ println("((),())="+load[(Unit, Unit)](dump(((), ()))))
+ println("(true,false)="+load[(Boolean, Boolean)](dump((true, false))))
+ println()
+
+ println("List(List(1), List(2))="+load[List[List[Int]]](dump(List(List(1), List(2)))))
+ println()
+
+ println("Array(Array(1), Array(2))="+loadArray[Array[Int]](dump(Array(Array(1), Array(2)))))
+ println()
+}
+
+trait TestUtil {
+ import java.io._
+ def write[A](o: A): Array[Byte] = {
+ val ba = new ByteArrayOutputStream(512)
+ val out = new ObjectOutputStream(ba)
+ out.writeObject(o)
+ out.close()
+ ba.toByteArray()
+ }
+ def read[A](buffer: Array[Byte]): A = {
+ val in = new ObjectInputStream(new ByteArrayInputStream(buffer))
+ in.readObject().asInstanceOf[A]
+ }
+ import scala.reflect._
+ def print[T](x: T)(implicit t: ConcreteTypeTag[T]) {
+ // todo. type tags are not yet serializable
+// val t1: ConcreteTypeTag[T] = read(write(t))
+ val t1: ConcreteTypeTag[T] = t
+ val x1 = x.toString.replaceAll("@[0-9a-z]+$", "")
+ println("x="+x1+", t="+t1+", k="+t1.tpe.kind+", s="+t1.sym.toString)
+ }
+}
diff --git a/test/files/jvm/manifests.check b/test/files/jvm/manifests-old.check
index 54f504b929..54f504b929 100644
--- a/test/files/jvm/manifests.check
+++ b/test/files/jvm/manifests-old.check
diff --git a/test/files/jvm/manifests.scala b/test/files/jvm/manifests-old.scala
index 6bbea4d052..241966fd9d 100644
--- a/test/files/jvm/manifests.scala
+++ b/test/files/jvm/manifests-old.scala
@@ -1,7 +1,6 @@
object Test extends App {
Test1
Test2
- //Test3 // Java 1.5+ only
}
class Foo[T](x: T)
@@ -88,15 +87,6 @@ object Test2 {
println()
}
-object Test3 extends TestUtil {
- import scala.reflect.Manifest._
- val ct1 = classType(classOf[Char])
- val ct2 = classType(classOf[List[_]], ct1)
- print(ct1)
- //print(ct2) // ??? x=scala.List[char], m=scala.reflect.Manifest[scala.runtime.Nothing$]
- println()
-}
-
trait TestUtil {
import java.io._
def write[A](o: A): Array[Byte] = {
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index b3470d275d..fce1a25bb6 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -64,7 +64,7 @@ trait FutureCallbacks extends TestBase {
}
}
}
-
+
def testOnSuccessWhenFailed(): Unit = once {
done =>
val f = future[Unit] {
@@ -94,7 +94,7 @@ trait FutureCallbacks extends TestBase {
assert(x == 1)
}
}
-
+
def testOnFailureWhenSpecialThrowable(num: Int, cause: Throwable): Unit = once {
done =>
val f = future[Unit] {
@@ -139,7 +139,8 @@ trait FutureCallbacks extends TestBase {
testOnFailure()
testOnFailureWhenSpecialThrowable(5, new Error)
testOnFailureWhenSpecialThrowable(6, new scala.util.control.ControlThrowable { })
- testOnFailureWhenSpecialThrowable(7, new InterruptedException)
+ //TODO: this test is currently problematic, because NonFatal does not match InterruptedException
+ //testOnFailureWhenSpecialThrowable(7, new InterruptedException)
testOnFailureWhenTimeoutException()
}
@@ -147,59 +148,188 @@ trait FutureCallbacks extends TestBase {
trait FutureCombinators extends TestBase {
- // map: stub
def testMapSuccess(): Unit = once {
done =>
- done()
+ val f = future { 5 }
+ val g = f map { x => "result: " + x }
+ g onSuccess {
+ case s =>
+ done()
+ assert(s == "result: 5")
+ }
+ g onFailure {
+ case _ =>
+ done()
+ assert(false)
+ }
}
def testMapFailure(): Unit = once {
done =>
- done()
+ val f = future {
+ throw new Exception("exception message")
+ }
+ val g = f map { x => "result: " + x }
+ g onSuccess {
+ case _ =>
+ done()
+ assert(false)
+ }
+ g onFailure {
+ case t =>
+ done()
+ assert(t.getMessage() == "exception message")
+ }
}
- // flatMap: stub
def testFlatMapSuccess(): Unit = once {
done =>
- done()
+ val f = future { 5 }
+ val g = f flatMap { _ => future { 10 } }
+ g onSuccess {
+ case x =>
+ done()
+ assert(x == 10)
+ }
+ g onFailure {
+ case _ =>
+ done()
+ assert(false)
+ }
}
def testFlatMapFailure(): Unit = once {
done =>
- done()
+ val f = future {
+ throw new Exception("exception message")
+ }
+ val g = f flatMap { _ => future { 10 } }
+ g onSuccess {
+ case _ =>
+ done()
+ assert(false)
+ }
+ g onFailure {
+ case t =>
+ done()
+ assert(t.getMessage() == "exception message")
+ }
}
- // filter: stub
def testFilterSuccess(): Unit = once {
done =>
- done()
+ val f = future { 4 }
+ val g = f filter { _ % 2 == 0 }
+ g onSuccess {
+ case x: Int =>
+ done()
+ assert(x == 4)
+ }
+ g onFailure {
+ case _ =>
+ done()
+ assert(false)
+ }
}
def testFilterFailure(): Unit = once {
done =>
- done()
+ val f = future { 4 }
+ val g = f filter { _ % 2 == 1 }
+ g onSuccess {
+ case x: Int =>
+ done()
+ assert(false)
+ }
+ g onFailure {
+ case e: NoSuchElementException =>
+ done()
+ assert(true)
+ case _ =>
+ done()
+ assert(false)
+ }
}
- // collect: stub
def testCollectSuccess(): Unit = once {
done =>
- done()
+ val f = future { -5 }
+ val g = f collect {
+ case x if x < 0 => -x
+ }
+ g onSuccess {
+ case x: Int =>
+ done()
+ assert(x == 5)
+ }
+ g onFailure {
+ case _ =>
+ done()
+ assert(false)
+ }
}
def testCollectFailure(): Unit = once {
done =>
- done()
+ val f = future { -5 }
+ val g = f collect {
+ case x if x > 0 => x * 2
+ }
+ g onSuccess {
+ case _ =>
+ done()
+ assert(false)
+ }
+ g onFailure {
+ case e: NoSuchElementException =>
+ done()
+ assert(true)
+ case _ =>
+ done()
+ assert(false)
+ }
}
- // foreach: stub
+ /* TODO: Test for NonFatal in collect (more of a regression test at this point).
+ */
+
def testForeachSuccess(): Unit = once {
done =>
- done()
+ val p = promise[Int]()
+ val f = future[Int] { 5 }
+ f foreach { x => p.success(x * 2) }
+ val g = p.future
+
+ g.onSuccess {
+ case res: Int =>
+ done()
+ assert(res == 10)
+ }
+ g.onFailure {
+ case _ =>
+ done()
+ assert(false)
+ }
}
def testForeachFailure(): Unit = once {
done =>
- done()
+ val p = promise[Int]()
+ val f = future[Int] { throw new Exception }
+ f foreach { x => p.success(x * 2) }
+ f onFailure { case _ => p.failure(new Exception) }
+ val g = p.future
+
+ g.onSuccess {
+ case _ =>
+ done()
+ assert(false)
+ }
+ g.onFailure {
+ case _ =>
+ done()
+ assert(true)
+ }
}
def testRecoverSuccess(): Unit = once {
@@ -237,6 +367,132 @@ trait FutureCombinators extends TestBase {
}
}
+ def testRecoverWithSuccess(): Unit = once {
+ done =>
+ val cause = new RuntimeException
+ val f = future {
+ throw cause
+ } recoverWith {
+ case re: RuntimeException =>
+ future { "recovered" }
+ } onSuccess {
+ case x =>
+ done()
+ assert(x == "recovered")
+ } onFailure { case any =>
+ done()
+ assert(false)
+ }
+ }
+
+ def testRecoverWithFailure(): Unit = once {
+ done =>
+ val cause = new RuntimeException
+ val f = future {
+ throw cause
+ } recoverWith {
+ case te: TimeoutException =>
+ future { "timeout" }
+ } onSuccess {
+ case x =>
+ done()
+ assert(false)
+ } onFailure { case any =>
+ done()
+ assert(any == cause)
+ }
+ }
+
+ def testZipSuccess(): Unit = once {
+ done =>
+ val f = future { 5 }
+ val g = future { 6 }
+ val h = f zip g
+ h onSuccess {
+ case (l: Int, r: Int) =>
+ done()
+ assert(l+r == 11)
+ }
+ h onFailure {
+ case _ =>
+ done()
+ assert(false)
+ }
+ }
+
+ def testZipFailureLeft(): Unit = once {
+ done =>
+ val cause = new Exception("exception message")
+ val f = future { throw cause }
+ val g = future { 6 }
+ val h = f zip g
+ h onSuccess {
+ case _ =>
+ done()
+ assert(false)
+ }
+ h onFailure {
+ case e: Exception =>
+ done()
+ assert(e.getMessage == "exception message")
+ }
+ }
+
+ def testZipFailureRight(): Unit = once {
+ done =>
+ val cause = new Exception("exception message")
+ val f = future { 5 }
+ val g = future { throw cause }
+ val h = f zip g
+ h onSuccess {
+ case _ =>
+ done()
+ assert(false)
+ }
+ h onFailure {
+ case e: Exception =>
+ done()
+ assert(e.getMessage == "exception message")
+ }
+ }
+
+ def testFallbackTo(): Unit = once {
+ done =>
+ val f = future { sys.error("failed") }
+ val g = future { 5 }
+ val h = f fallbackTo g
+
+ h onSuccess {
+ case x: Int =>
+ done()
+ assert(x == 5)
+ }
+ h onFailure {
+ case _ =>
+ done()
+ assert(false)
+ }
+ }
+
+ def testFallbackToFailure(): Unit = once {
+ done =>
+ val cause = new Exception
+ val f = future { sys.error("failed") }
+ val g = future { throw cause }
+ val h = f fallbackTo g
+
+ h onSuccess {
+ case _ =>
+ done()
+ assert(false)
+ }
+ h onFailure {
+ case e: Exception =>
+ done()
+ assert(e == cause)
+ }
+ }
+
testMapSuccess()
testMapFailure()
testFlatMapSuccess()
@@ -249,7 +505,13 @@ trait FutureCombinators extends TestBase {
testForeachFailure()
testRecoverSuccess()
testRecoverFailure()
-
+ testRecoverWithSuccess()
+ testRecoverWithFailure()
+ testZipSuccess()
+ testZipFailureLeft()
+ testZipFailureRight()
+ testFallbackTo()
+ testFallbackToFailure()
}
diff --git a/test/files/jvm/serialization-new.check b/test/files/jvm/serialization-new.check
new file mode 100644
index 0000000000..fa51c6a879
--- /dev/null
+++ b/test/files/jvm/serialization-new.check
@@ -0,0 +1,313 @@
+a1 = Array[1,2,3]
+_a1 = Array[1,2,3]
+arrayEquals(a1, _a1): true
+
+e1 = Left(1)
+_e1 = Left(1)
+e1 eq _e1: false, _e1 eq e1: false
+e1 equals _e1: true, _e1 equals e1: true
+
+x7 = RoundingMode
+y7 = RoundingMode
+x7 eq y7: true, y7 eq x7: true
+x7 equals y7: true, y7 equals x7: true
+
+x8 = WeekDay
+y8 = WeekDay
+x8 eq y8: true, y8 eq x8: true
+x8 equals y8: true, y8 equals x8: true
+
+x9 = UP
+y9 = UP
+x9 eq y9: true, y9 eq x9: true
+x9 equals y9: true, y9 equals x9: true
+
+x10 = Monday
+y10 = Monday
+x10 eq y10: true, y10 eq x10: true
+x10 equals y10: true, y10 equals x10: true
+
+x9 eq x10: false, x10 eq x9: false
+x9 equals x10: false, x10 equals x9: false
+x9 eq y10: false, y10 eq x9: false
+x9 equals y10: false, y10 equals x9: false
+
+f1 = <na>
+_f1 = <na>
+f1(2): 4, _f1(2): 4
+
+xs0 = List(1, 2, 3)
+_xs0 = List(1, 2, 3)
+xs0 eq _xs0: false, _xs0 eq xs0: false
+xs0 equals _xs0: true, _xs0 equals xs0: true
+
+xs1 = List()
+_xs1 = List()
+xs1 eq _xs1: true, _xs1 eq xs1: true
+
+o1 = None
+_o1 = None
+o1 eq _o1: true, _o1 eq o1: true
+
+o2 = Some(1)
+_o2 = Some(1)
+o2 eq _o2: false, _o2 eq o2: false
+o2 equals _o2: true, _o2 equals o2: true
+
+s1 = 'hello
+_s1 = 'hello
+s1 eq _s1: true, _s1 eq s1: true
+s1 equals _s1: true, _s1 equals s1: true
+
+t1 = (BannerLimit,12345)
+_t1 = (BannerLimit,12345)
+t1 eq _t1: false, _t1 eq t1: false
+t1 equals _t1: true, _t1 equals t1: true
+
+x = BitSet(1, 2)
+y = BitSet(1, 2)
+x equals y: true, y equals x: true
+
+x = BitSet(2, 3)
+y = BitSet(2, 3)
+x equals y: true, y equals x: true
+
+x = Map(1 -> A, 2 -> B, 3 -> C)
+y = Map(1 -> A, 2 -> B, 3 -> C)
+x equals y: true, y equals x: true
+
+x = Set(1, 2)
+y = Set(1, 2)
+x equals y: true, y equals x: true
+
+x = List((buffers,20), (layers,2), (title,3))
+y = List((buffers,20), (layers,2), (title,3))
+x equals y: true, y equals x: true
+
+x = Map(buffers -> 20, layers -> 2, title -> 3)
+y = Map(buffers -> 20, layers -> 2, title -> 3)
+x equals y: true, y equals x: true
+
+x = ListSet(5, 3)
+y = ListSet(5, 3)
+x equals y: true, y equals x: true
+
+x = Queue(a, b, c)
+y = Queue(a, b, c)
+x equals y: true, y equals x: true
+
+x = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+y = Range(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+x equals y: true, y equals x: true
+
+x = NumericRange(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+y = NumericRange(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
+x equals y: true, y equals x: true
+
+x = Map(1 -> A, 2 -> B, 3 -> C)
+y = Map(1 -> A, 2 -> B, 3 -> C)
+x equals y: true, y equals x: true
+
+x = TreeSet(1, 2, 3)
+y = TreeSet(1, 2, 3)
+x equals y: true, y equals x: true
+
+x = Stack(c, b, a)
+y = Stack(c, b, a)
+x equals y: true, y equals x: true
+
+x = Stream(0, ?)
+y = Stream(0, ?)
+x equals y: true, y equals x: true
+
+x = Map(42 -> FortyTwo)
+y = Map(42 -> FortyTwo)
+x equals y: true, y equals x: true
+
+x = TreeSet(0, 2)
+y = TreeSet(0, 2)
+x equals y: true, y equals x: true
+
+x = Vector('a, 'b, 'c)
+y = Vector('a, 'b, 'c)
+x equals y: true, y equals x: true
+
+x = ArrayBuffer(one, two)
+y = ArrayBuffer(one, two)
+x equals y: true, y equals x: true
+
+x = ArrayBuilder.ofLong
+y = ArrayBuilder.ofLong
+x equals y: true, y equals x: true
+
+x = ArrayBuilder.ofFloat
+y = ArrayBuilder.ofFloat
+x equals y: true, y equals x: true
+
+x = ArraySeq(1, 2, 3)
+y = ArraySeq(1, 2, 3)
+x equals y: true, y equals x: true
+
+x = ArrayStack(3, 2, 20)
+y = ArrayStack(3, 2, 20)
+x equals y: true, y equals x: true
+
+x = BitSet(0, 8, 9)
+y = BitSet(0, 8, 9)
+x equals y: true, y equals x: true
+
+x = Map(A -> 1, C -> 3, B -> 2)
+y = Map(A -> 1, C -> 3, B -> 2)
+x equals y: true, y equals x: true
+
+x = Set(buffers, title, layers)
+y = Set(buffers, title, layers)
+x equals y: true, y equals x: true
+
+x = History()
+y = History()
+x equals y: true, y equals x: true
+
+x = ListBuffer(white, black)
+y = ListBuffer(white, black)
+x equals y: true, y equals x: true
+
+x = Queue(20, 2, 3)
+y = Queue(20, 2, 3)
+x equals y: true, y equals x: true
+
+x = Stack(3, 2, 20)
+y = Stack(3, 2, 20)
+x equals y: true, y equals x: true
+
+x = abc
+y = abc
+x equals y: true, y equals x: true
+
+x = WrappedArray(1, 2, 3)
+y = WrappedArray(1, 2, 3)
+x equals y: true, y equals x: true
+
+x = TreeSet(1, 2, 3)
+y = TreeSet(1, 2, 3)
+x equals y: true, y equals x: true
+
+x = TrieMap(1 -> one, 2 -> two, 3 -> three)
+y = TrieMap(1 -> one, 2 -> two, 3 -> three)
+x equals y: true, y equals x: true
+
+x = xml:src="hello"
+y = xml:src="hello"
+x equals y: true, y equals x: true
+
+x = <title></title>
+y = <title></title>
+x equals y: true, y equals x: true
+
+x = <html><title>title</title><body></body></html>
+y = <html><title>title</title><body></body></html>
+x equals y: true, y equals x: true
+
+x = <html>
+ <body>
+ <table cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Last Name</th>
+ <th>First Name</th>
+ </tr>
+ <tr>
+ <td> Tom </td>
+ <td> 20 </td>
+ </tr><tr>
+ <td> Bob </td>
+ <td> 22 </td>
+ </tr><tr>
+ <td> James </td>
+ <td> 19 </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+y = <html>
+ <body>
+ <table cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Last Name</th>
+ <th>First Name</th>
+ </tr>
+ <tr>
+ <td> Tom </td>
+ <td> 20 </td>
+ </tr><tr>
+ <td> Bob </td>
+ <td> 22 </td>
+ </tr><tr>
+ <td> James </td>
+ <td> 19 </td>
+ </tr>
+ </table>
+ </body>
+ </html>
+x equals y: true, y equals x: true
+
+x = Tim
+y = Tim
+x equals y: true, y equals x: true
+
+x = Bob
+y = Bob
+x equals y: true, y equals x: true
+
+x = John
+y = John
+x equals y: true, y equals x: true
+
+x = Bill
+y = Bill
+x equals y: true, y equals x: true
+
+x = Paul
+y = Paul
+x equals y: true, y equals x: true
+
+1
+2
+1
+2
+
+x = UnrolledBuffer(one, two)
+y = UnrolledBuffer(one, two)
+x equals y: true, y equals x: true
+
+x = ParArray(abc, def, etc)
+y = ParArray(abc, def, etc)
+x equals y: true, y equals x: true
+
+x = ParHashMap(2 -> 4, 1 -> 2)
+y = ParHashMap(2 -> 4, 1 -> 2)
+x equals y: true, y equals x: true
+
+x = ParTrieMap(1 -> 2, 2 -> 4)
+y = ParTrieMap(1 -> 2, 2 -> 4)
+x equals y: true, y equals x: true
+
+x = ParHashSet(1, 2, 3)
+y = ParHashSet(1, 2, 3)
+x equals y: true, y equals x: true
+
+x = ParRange(0, 1, 2, 3, 4)
+y = ParRange(0, 1, 2, 3, 4)
+x equals y: true, y equals x: true
+
+x = ParRange(0, 1, 2, 3)
+y = ParRange(0, 1, 2, 3)
+x equals y: true, y equals x: true
+
+x = ParMap(5 -> 1, 10 -> 2)
+y = ParMap(5 -> 1, 10 -> 2)
+x equals y: true, y equals x: true
+
+x = ParSet(two, one)
+y = ParSet(two, one)
+x equals y: true, y equals x: true
+
diff --git a/test/files/jvm/serialization-new.scala b/test/files/jvm/serialization-new.scala
new file mode 100644
index 0000000000..bb971fdf36
--- /dev/null
+++ b/test/files/jvm/serialization-new.scala
@@ -0,0 +1,651 @@
+//############################################################################
+// Serialization
+//############################################################################
+
+object Serialize {
+ @throws(classOf[java.io.IOException])
+ def write[A](o: A): Array[Byte] = {
+ val ba = new java.io.ByteArrayOutputStream(512)
+ val out = new java.io.ObjectOutputStream(ba)
+ out.writeObject(o)
+ out.close()
+ ba.toByteArray()
+ }
+ @throws(classOf[java.io.IOException])
+ @throws(classOf[ClassNotFoundException])
+ def read[A](buffer: Array[Byte]): A = {
+ val in =
+ new java.io.ObjectInputStream(new java.io.ByteArrayInputStream(buffer))
+ in.readObject().asInstanceOf[A]
+ }
+ def check[A, B](x: A, y: B) {
+ println("x = " + x)
+ println("y = " + y)
+ println("x equals y: " + (x equals y) + ", y equals x: " + (y equals x))
+ assert((x equals y) && (y equals x))
+ println()
+ }
+}
+import Serialize._
+
+//############################################################################
+// Test classes in package "scala"
+
+object Test1_scala {
+
+ private def arrayToString[A](arr: Array[A]): String =
+ arr.mkString("Array[",",","]")
+
+ private def arrayEquals[A, B](a1: Array[A], a2: Array[B]): Boolean =
+ (a1.length == a2.length) &&
+ (Iterator.range(0, a1.length) forall { i => a1(i) == a2(i) })
+
+ object WeekDay extends Enumeration {
+ type WeekDay = Value
+ val Monday, Tuesday, Wednesday, Thusday, Friday, Saturday, Sunday = Value
+ }
+ import WeekDay._, BigDecimal._, RoundingMode._
+
+ // in alphabetic order
+ try {
+ // Array
+ val a1 = Array(1, 2, 3)
+ val _a1: Array[Int] = read(write(a1))
+ println("a1 = " + arrayToString(a1))
+ println("_a1 = " + arrayToString(_a1))
+ println("arrayEquals(a1, _a1): " + arrayEquals(a1, _a1))
+ println()
+
+ // Either
+ val e1 = Left(1)
+ val _e1: Either[Int, String] = read(write(e1))
+ println("e1 = " + e1)
+ println("_e1 = " + _e1)
+ println("e1 eq _e1: " + (e1 eq _e1) + ", _e1 eq e1: " + (_e1 eq e1))
+ println("e1 equals _e1: " + (e1 equals _e1) + ", _e1 equals e1: " + (_e1 equals e1))
+ println()
+
+ // Enumeration
+ val x7 = BigDecimal.RoundingMode
+ val y7: RoundingMode.type = read(write(x7))
+ println("x7 = " + x7)
+ println("y7 = " + y7)
+ println("x7 eq y7: " + (x7 eq y7) + ", y7 eq x7: " + (y7 eq x7))
+ println("x7 equals y7: " + (x7 equals y7) + ", y7 equals x7: " + (y7 equals x7))
+ println()
+
+ val x8 = WeekDay
+ val y8: WeekDay.type = read(write(x8))
+ println("x8 = " + x8)
+ println("y8 = " + y8)
+ println("x8 eq y8: " + (x8 eq y8) + ", y8 eq x8: " + (y8 eq x8))
+ println("x8 equals y8: " + (x8 equals y8) + ", y8 equals x8: " + (y8 equals x8))
+ println()
+
+ val x9 = UP
+ val y9: RoundingMode = read(write(x9))
+ println("x9 = " + x9)
+ println("y9 = " + y9)
+ println("x9 eq y9: " + (x9 eq y9) + ", y9 eq x9: " + (y9 eq x9))
+ println("x9 equals y9: " + (x9 equals y9) + ", y9 equals x9: " + (y9 equals x9))
+ println()
+
+ val x10 = Monday
+ val y10: WeekDay = read(write(x10))
+ println("x10 = " + x10)
+ println("y10 = " + y10)
+ println("x10 eq y10: " + (x10 eq y10) + ", y10 eq x10: " + (y10 eq x10))
+ println("x10 equals y10: " + (x10 equals y10) + ", y10 equals x10: " + (y10 equals x10))
+ println()
+
+ println("x9 eq x10: " + (x9 eq x10) + ", x10 eq x9: " + (x10 eq x9))
+ println("x9 equals x10: " + (x9 equals x10) + ", x10 equals x9: " + (x10 equals x9))
+ println("x9 eq y10: " + (x9 eq y10) + ", y10 eq x9: " + (y10 eq x9))
+ println("x9 equals y10: " + (x9 equals y10) + ", y10 equals x9: " + (y10 equals x9))
+ println()
+
+ // Function
+ val f1 = { x: Int => 2 * x }
+ val _f1: Function[Int, Int] = read(write(f1))
+ println("f1 = <na>")
+ println("_f1 = <na>")
+ println("f1(2): " + f1(2) + ", _f1(2): " + _f1(2))
+ println()
+
+ // List
+ val xs0 = List(1, 2, 3)
+ val _xs0: List[Int] = read(write(xs0))
+ println("xs0 = " + xs0)
+ println("_xs0 = " + _xs0)
+ println("xs0 eq _xs0: " + (xs0 eq _xs0) + ", _xs0 eq xs0: " + (_xs0 eq xs0))
+ println("xs0 equals _xs0: " + (xs0 equals _xs0) + ", _xs0 equals xs0: " + (_xs0 equals xs0))
+ println()
+
+ val xs1 = Nil
+ val _xs1: List[Nothing] = read(write(xs1))
+ println("xs1 = " + xs1)
+ println("_xs1 = " + _xs1)
+ println("xs1 eq _xs1: " + (xs1 eq _xs1) + ", _xs1 eq xs1: " + (_xs1 eq xs1))
+ println()
+
+ // Option
+ val o1 = None
+ val _o1: Option[Nothing] = read(write(o1))
+ println("o1 = " + o1)
+ println("_o1 = " + _o1)
+ println("o1 eq _o1: " + (o1 eq _o1) + ", _o1 eq o1: " + (_o1 eq o1))
+ println()
+
+ val o2 = Some(1)
+ val _o2: Option[Int] = read(write(o2))
+ println("o2 = " + o2)
+ println("_o2 = " + _o2)
+ println("o2 eq _o2: " + (o2 eq _o2) + ", _o2 eq o2: " + (_o2 eq o2))
+ println("o2 equals _o2: " + (o2 equals _o2) + ", _o2 equals o2: " + (_o2 equals o2))
+ println()
+/*
+ // Responder
+ val r1 = Responder.constant("xyz")
+ val _r1: Responder[String] = read(write(r1))
+ check(r1, _r1)
+*/
+ // Symbol
+ val s1 = 'hello
+ val _s1: Symbol = read(write(s1))
+ println("s1 = " + s1)
+ println("_s1 = " + _s1)
+ println("s1 eq _s1: " + (s1 eq _s1) + ", _s1 eq s1: " + (_s1 eq s1))
+ println("s1 equals _s1: " + (s1 equals _s1) + ", _s1 equals s1: " + (_s1 equals s1))
+ println()
+
+ // Tuple
+ val t1 = ("BannerLimit", 12345)
+ val _t1: (String, Int) = read(write(t1))
+ println("t1 = " + t1)
+ println("_t1 = " + _t1)
+ println("t1 eq _t1: " + (t1 eq _t1) + ", _t1 eq t1: " + (_t1 eq t1))
+ println("t1 equals _t1: " + (t1 equals _t1) + ", _t1 equals t1: " + (_t1 equals t1))
+ println()
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test1_scala: " + e)
+ throw e
+ }
+}
+
+//############################################################################
+// Test classes in package "scala.collection.immutable"
+
+object Test2_immutable {
+ import scala.collection.immutable.{
+ BitSet, HashMap, HashSet, ListMap, ListSet, Queue, Range, SortedMap,
+ SortedSet, Stack, Stream, TreeMap, TreeSet, Vector}
+
+ // in alphabetic order
+ try {
+ // BitSet
+ val bs1 = BitSet.empty + 1 + 2
+ val _bs1: BitSet = read(write(bs1))
+ check(bs1, _bs1)
+
+ val bs2 = {
+ val bs = new collection.mutable.BitSet()
+ bs += 2; bs += 3
+ bs.toImmutable
+ }
+ val _bs2: BitSet = read(write(bs2))
+ check(bs2, _bs2)
+
+ // HashMap
+ val hm1 = new HashMap[Int, String] + (1 -> "A", 2 -> "B", 3 -> "C")
+ val _hm1: HashMap[Int, String] = read(write(hm1))
+ check(hm1, _hm1)
+
+ // HashSet
+ val hs1 = new HashSet[Int] + 1 + 2
+ val _hs1: HashSet[Int] = read(write(hs1))
+ check(hs1, _hs1)
+
+ // List
+ val xs1 = List(("buffers", 20), ("layers", 2), ("title", 3))
+ val _xs1: List[(String, Int)] = read(write(xs1))
+ check(xs1, _xs1)
+
+ // ListMap
+ val lm1 = new ListMap[String, Int] + ("buffers" -> 20, "layers" -> 2, "title" -> 3)
+ val _lm1: ListMap[String, Int] = read(write(lm1))
+ check(lm1, _lm1)
+
+ // ListSet
+ val ls1 = new ListSet[Int] + 3 + 5
+ val _ls1: ListSet[Int] = read(write(ls1))
+ check(ls1, _ls1)
+
+ // Queue
+ val q1 = Queue("a", "b", "c")
+ val _q1: Queue[String] = read(write(q1))
+ check(q1, _q1)
+
+ // Range
+ val r1 = 0 until 10
+ val _r1: Range = read(write(r1))
+ check(r1, _r1)
+
+ val r2 = Range.Long(0L, 10L, 1)
+ val _r2: r2.type = read(write(r2))
+ check(r2, _r2)
+
+ // SortedMap
+ val sm1 = SortedMap.empty[Int, String] + (2 -> "B", 3 -> "C", 1 -> "A")
+ val _sm1: SortedMap[Int, String] = read(write(sm1))
+ check(sm1, _sm1)
+
+ // SortedSet
+ val ss1 = SortedSet.empty[Int] + 2 + 3 + 1
+ val _ss1: SortedSet[Int] = read(write(ss1))
+ check(ss1, _ss1)
+
+ // Stack
+ val s1 = new Stack().push("a", "b", "c")
+ val _s1: Stack[String] = read(write(s1))
+ check(s1, _s1)
+
+ // Stream
+ val st1 = Stream.range(0, 10)
+ val _st1: Stream[Int] = read(write(st1))
+ check(st1, _st1)
+
+ // TreeMap
+ val tm1 = new TreeMap[Int, String] + (42 -> "FortyTwo")
+ val _tm1: TreeMap[Int, String] = read(write(tm1))
+ check(tm1, _tm1)
+
+ // TreeSet
+ val ts1 = new TreeSet[Int]() + 2 + 0
+ val _ts1: TreeSet[Int] = read(write(ts1))
+ check(ts1, _ts1)
+
+ // Vector
+ val v1 = Vector('a, 'b, 'c)
+ val _v1: Vector[Symbol] = read(write(v1))
+ check(v1, _v1)
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test2_immutable: " + e)
+ throw e
+ }
+}
+
+//############################################################################
+// Test classes in package "scala.collection.mutable"
+
+object Test3_mutable {
+ import scala.reflect.ArrayTag
+ import scala.collection.mutable.{
+ ArrayBuffer, ArrayBuilder, ArraySeq, ArrayStack, BitSet, DoubleLinkedList,
+ HashMap, HashSet, History, LinkedList, ListBuffer, Publisher, Queue,
+ Stack, StringBuilder, WrappedArray, TreeSet}
+ import scala.collection.concurrent.TrieMap
+
+ // in alphabetic order
+ try {
+ // ArrayBuffer
+ val ab1 = new ArrayBuffer[String]
+ ab1 ++= List("one", "two")
+ val _ab1: ArrayBuffer[String] = read(write(ab1))
+ check(ab1, _ab1)
+
+ // ArrayBuilder
+ val abu1 = ArrayBuilder.make[Long]
+ val _abu1: ArrayBuilder[ArrayTag[Long]] = read(write(abu1))
+ check(abu1, _abu1)
+
+ val abu2 = ArrayBuilder.make[Float]
+ val _abu2: ArrayBuilder[ArrayTag[Float]] = read(write(abu2))
+ check(abu2, _abu2)
+
+ // ArraySeq
+ val aq1 = ArraySeq(1, 2, 3)
+ val _aq1: ArraySeq[Int] = read(write(aq1))
+ check(aq1, _aq1)
+
+ // ArrayStack
+ val as1 = new ArrayStack[Int]
+ as1 ++= List(20, 2, 3).iterator
+ val _as1: ArrayStack[Int] = read(write(as1))
+ check(as1, _as1)
+
+ // BitSet
+ val bs1 = new BitSet()
+ bs1 += 0
+ bs1 += 8
+ bs1 += 9
+ val _bs1: BitSet = read(write(bs1))
+ check(bs1, _bs1)
+/*
+ // DoubleLinkedList
+ val dl1 = new DoubleLinkedList[Int](2, null)
+ dl1.append(new DoubleLinkedList(3, null))
+ val _dl1: DoubleLinkedList[Int] = read(write(dl1))
+ check(dl1, _dl1)
+*/
+ // HashMap
+ val hm1 = new HashMap[String, Int]
+ hm1 ++= List(("A", 1), ("B", 2), ("C", 3)).iterator
+ val _hm1: HashMap[String, Int] = read(write(hm1))
+ check(hm1, _hm1)
+
+ // HashSet
+ val hs1 = new HashSet[String]
+ hs1 ++= List("layers", "buffers", "title").iterator
+ val _hs1: HashSet[String] = read(write(hs1))
+ check(hs1, _hs1)
+
+ val h1 = new History[String, Int]
+ val _h1: History[String, Int] = read(write(h1))
+ check(h1, _h1)
+/*
+ // LinkedList
+ val ll1 = new LinkedList[Int](2, null)
+ ll1.append(new LinkedList(3, null))
+ val _ll1: LinkedList[Int] = read(write(ll1))
+ check(ll1, _ll1)
+*/
+ // ListBuffer
+ val lb1 = new ListBuffer[String]
+ lb1 ++= List("white", "black")
+ val _lb1: ListBuffer[String] = read(write(lb1))
+ check(lb1, _lb1)
+
+ // Queue
+ val q1 = new Queue[Int]
+ q1 ++= List(20, 2, 3).iterator
+ val _q1: Queue[Int] = read(write(q1))
+ check(q1, _q1)
+
+ // Stack
+ val s1 = new Stack[Int]
+ s1 pushAll q1
+ val _s1: Stack[Int] = read(write(s1))
+ check(s1, _s1)
+
+ // StringBuilder
+ val sb1 = new StringBuilder
+ sb1 append "abc"
+ val _sb1: StringBuilder = read(write(sb1))
+ check(sb1, _sb1)
+
+ // WrappedArray
+ val wa1 = WrappedArray.make(Array(1, 2, 3))
+ val _wa1: WrappedArray[Int] = read(write(wa1))
+ check(wa1, _wa1)
+
+ // TreeSet
+ val ts1 = TreeSet[Int]() ++= Array(1, 2, 3)
+ val _ts1: TreeSet[Int] = read(write(ts1))
+ check(ts1, _ts1)
+
+ // concurrent.TrieMap
+ val ct1 = TrieMap[Int, String]() ++= Array(1 -> "one", 2 -> "two", 3 -> "three")
+ val _ct1: TrieMap[Int, String] = read(write(ct1))
+ check(ct1, _ct1)
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test3_mutable: " + e)
+ throw e
+ }
+}
+
+
+//############################################################################
+// Test classes in package "scala.xml"
+
+object Test4_xml {
+ import scala.xml.{Attribute, Document, Elem, Null, PrefixedAttribute, Text}
+
+ case class Person(name: String, age: Int)
+
+ try {
+ // Attribute
+ val a1 = new PrefixedAttribute("xml", "src", Text("hello"), Null)
+ val _a1: Attribute = read(write(a1))
+ check(a1, _a1)
+
+ // Document
+ val d1 = new Document
+ d1.docElem = <title></title>
+ d1.encoding = Some("UTF-8")
+ val _d1: Document = read(write(d1))
+ check(d1, _d1)
+
+ // Elem
+ val e1 = <html><title>title</title><body></body></html>;
+ val _e1: Elem = read(write(e1))
+ check(e1, _e1)
+
+ class AddressBook(a: Person*) {
+ private val people: List[Person] = a.toList
+ def toXHTML =
+ <table cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Last Name</th>
+ <th>First Name</th>
+ </tr>
+ { for (p <- people) yield
+ <tr>
+ <td> { p.name } </td>
+ <td> { p.age.toString() } </td>
+ </tr> }
+ </table>;
+ }
+
+ val people = new AddressBook(
+ Person("Tom", 20),
+ Person("Bob", 22),
+ Person("James", 19))
+
+ val e2 =
+ <html>
+ <body>
+ { people.toXHTML }
+ </body>
+ </html>;
+ val _e2: Elem = read(write(e2))
+ check(e2, _e2)
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test4_xml: " + e)
+ throw e
+ }
+}
+
+//############################################################################
+// Test user-defined classes WITHOUT nesting
+
+class Person(_name: String) extends Serializable {
+ private var name = _name
+ override def toString() = name
+ override def equals(that: Any): Boolean =
+ that.isInstanceOf[Person] &&
+ (name == that.asInstanceOf[Person].name)
+}
+
+class Employee(_name: String) extends Serializable {
+ private var name = _name
+ override def toString() = name
+}
+
+object bob extends Employee("Bob")
+
+object Test5 {
+ val x1 = new Person("Tim")
+ val x2 = bob
+
+ try {
+ val y1: Person = read(write(x1))
+ val y2: Employee = read(write(x2))
+
+ check(x1, y1)
+ check(x2, y2)
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test5: " + e)
+ }
+}
+
+//############################################################################
+// Test user-defined classes WITH nesting
+
+object Test6 {
+ object bill extends Employee("Bill") {
+ val x = paul
+ }
+ object paul extends Person("Paul") {
+ val x = 4 // bill; => StackOverflowException !!!
+ }
+ val x1 = new Person("John")
+ val x2 = bill
+ val x3 = paul
+
+ try {
+ val y1: Person = read(write(x1))
+ val y2: Employee = read(write(x2))
+ val y3: Person = read(write(x3))
+
+ check(x1, y1)
+ check(x2, y2)
+ check(x3, y3)
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test6: " + e)
+ }
+}
+
+//############################################################################
+// Nested objects cannot get readresolve automatically because after deserialization
+// they would be null (they are treated as lazy vals)
+class Outer extends Serializable {
+ object Inner extends Serializable
+}
+
+object Test7 {
+ val x = new Outer
+ x.Inner // initialize
+ val y:Outer = read(write(x))
+ if (y.Inner == null)
+ println("Inner object is null")
+}
+
+// Verify that transient lazy vals don't get serialized
+class WithTransient extends Serializable {
+ @transient lazy val a1 = 1
+ @transient private lazy val a2 = 2
+ @transient object B extends Serializable
+ @transient private object C extends Serializable
+
+ def test = {
+ println(a1)
+ println(a2)
+ if (B == null || C == null)
+ println("Transient nested object failed to serialize properly")
+ }
+}
+
+object Test8 {
+ val x = new WithTransient
+ x.test
+ try {
+ val y:WithTransient = read(write(x))
+ y.test
+ }
+ catch {
+ case e: Exception =>
+ println("Error in Test8: " + e)
+ }
+}
+
+//############################################################################
+// Test code
+
+object Test {
+ def main(args: Array[String]) {
+ Test1_scala
+ Test2_immutable
+ Test3_mutable
+ Test4_xml
+ Test5
+ Test6
+ Test7
+ Test8
+ Test9_parallel
+ }
+}
+
+//############################################################################
+
+
+//############################################################################
+// Test classes in package "scala.collection.parallel" and subpackages
+object Test9_parallel {
+ import scala.collection.parallel._
+
+ try {
+ println()
+
+ // UnrolledBuffer
+ val ub = new collection.mutable.UnrolledBuffer[String]
+ ub ++= List("one", "two")
+ val _ub: collection.mutable.UnrolledBuffer[String] = read(write(ub))
+ check(ub, _ub)
+
+ // mutable.ParArray
+ val pa = mutable.ParArray("abc", "def", "etc")
+ val _pa: mutable.ParArray[String] = read(write(pa))
+ check(pa, _pa)
+
+ // mutable.ParHashMap
+ val mpm = mutable.ParHashMap(1 -> 2, 2 -> 4)
+ val _mpm: mutable.ParHashMap[Int, Int] = read(write(mpm))
+ check(mpm, _mpm)
+
+ // mutable.ParTrieMap
+ val mpc = mutable.ParTrieMap(1 -> 2, 2 -> 4)
+ val _mpc: mutable.ParTrieMap[Int, Int] = read(write(mpc))
+ check(mpc, _mpc)
+
+ // mutable.ParHashSet
+ val mps = mutable.ParHashSet(1, 2, 3)
+ val _mps: mutable.ParHashSet[Int] = read(write(mps))
+ check(mps, _mps)
+
+ // immutable.ParRange
+ val pr1 = immutable.ParRange(0, 4, 1, true)
+ val _pr1: immutable.ParRange = read(write(pr1))
+ check(pr1, _pr1)
+
+ val pr2 = immutable.ParRange(0, 4, 1, false)
+ val _pr2: immutable.ParRange = read(write(pr2))
+ check(pr2, _pr2)
+
+ // immutable.ParHashMap
+ val ipm = immutable.ParHashMap(5 -> 1, 10 -> 2)
+ val _ipm: immutable.ParHashMap[Int, Int] = read(write(ipm))
+ check(ipm, _ipm)
+
+ // immutable.ParHashSet
+ val ips = immutable.ParHashSet("one", "two")
+ val _ips: immutable.ParHashSet[String] = read(write(ips))
+ check(ips, _ips)
+
+ } catch {
+ case e: Exception =>
+ println("Error in Test5_parallel: " + e)
+ throw e
+ }
+}
diff --git a/test/files/jvm/si5471.check b/test/files/jvm/si5471.check
new file mode 100644
index 0000000000..bb101b641b
--- /dev/null
+++ b/test/files/jvm/si5471.check
@@ -0,0 +1,2 @@
+true
+true
diff --git a/test/files/jvm/si5471.scala b/test/files/jvm/si5471.scala
new file mode 100644
index 0000000000..2c8c4205c5
--- /dev/null
+++ b/test/files/jvm/si5471.scala
@@ -0,0 +1,17 @@
+
+object Test {
+
+ def main(args: Array[String]) {
+ import scala.math.Numeric
+ import scala.math.Numeric.Implicits._
+
+ val b = BigInt(Long.MaxValue) + 1
+
+ def dbl[N :Numeric](n: N) = n.toDouble
+ def flt[N :Numeric](n: N) = n.toFloat
+
+ println(dbl(b) == b.toDouble)
+ println(flt(b) == b.toFloat)
+ }
+
+}
diff --git a/test/files/jvm/signum.scala b/test/files/jvm/signum.scala
index feb28d3e43..76602a6641 100644
--- a/test/files/jvm/signum.scala
+++ b/test/files/jvm/signum.scala
@@ -11,5 +11,11 @@ object Test {
assert(math.signum(0) == 0)
assert(math.signum(-1) == -1)
assert(math.signum(Int.MinValue) == -1)
+
+ assert(java.lang.Float.floatToIntBits(math.signum(0f)) == 0x0)
+ assert(java.lang.Float.floatToIntBits(math.signum(-0f)) == 0x80000000)
+
+ assert(java.lang.Double.doubleToLongBits(math.signum(0d)) == 0x0L)
+ assert(java.lang.Double.doubleToLongBits(math.signum(-0d)) == 0x8000000000000000L)
}
}
diff --git a/test/files/macros/Printf.scala b/test/files/macros/Printf.scala
deleted file mode 100644
index 4a88e5b069..0000000000
--- a/test/files/macros/Printf.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-// macros should be built separately from their clients, so simple "scalac Printf.scala Test.scala" won't work
-// 1) first build this file with "scalac -Xmacros Printf.scala"
-// 2) the build the test with "scalac -cp <output directory of compiling Printf.scala> Test.scala"
-
-object Printf extends App {
- def macro printf(format: String, params: Any*) : String = {
- var i = 0
- def gensym(name: String) = { i += 1; newTermName(name + i) }
-
- def createTempValDef(value: Tree, clazz: Class[_]): (Option[Tree], Tree) = {
- val local = gensym("temp")
- val tpe = if (clazz == classOf[Int]) Ident(newTypeName("Int"))
- else if (clazz == classOf[String]) Select(Select(Ident(newTermName("java")), newTermName("lang")), newTypeName("String"))
- else throw new Exception("unknown class " + clazz.toString)
- (Some(ValDef(Modifiers(), local, tpe, value)), Ident(local))
- }
-
- def tree_printf(format: Tree, params: Tree*) = {
- val Literal(Constant(s_format: String)) = format
- val paramsStack = scala.collection.mutable.Stack(params: _*)
- val parsed = s_format.split("(?<=%[\\w%])|(?=%[\\w%])") map {
- case "%d" => createTempValDef(paramsStack.pop, classOf[Int])
- case "%s" => createTempValDef(paramsStack.pop, classOf[String])
- case "%%" => (None, Literal(Constant("%")))
- case part => (None, Literal(Constant(part)))
- }
-
- val evals = for ((Some(eval), _) <- parsed if eval != None) yield eval
- val prints = for ((_, ref) <- parsed) yield {
- val print = Select(Select(Ident(newTermName("scala")), newTermName("Predef")), newTermName("print"))
- Apply(print, List(ref))
- }
-
- Block((evals ++ prints).toList, Literal(Constant(())))
- }
-
- tree_printf(format, params: _*)
- }
-}
diff --git a/test/files/macros/Test.scala b/test/files/macros/Test.scala
deleted file mode 100644
index d8cdcf6756..0000000000
--- a/test/files/macros/Test.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-// macros should be built separately from their clients, so simple "scalac Printf.scala Test.scala" won't work
-// 1) first build the printf macro with "scalac -Xmacros Printf.scala"
-// 2) the build this file with "scalac -cp <output directory of compiling Printf.scala> Test.scala"
-
-object Test extends App {
- import Printf._
- printf("hello %s", "world")
-} \ No newline at end of file
diff --git a/test/files/macros/macros_v0001.bat b/test/files/macros/macros_v0001.bat
deleted file mode 100644
index 3395d2e3c1..0000000000
--- a/test/files/macros/macros_v0001.bat
+++ /dev/null
@@ -1,40 +0,0 @@
-@echo off
-
-set scalahome=%~dp0\..\..\..
-set scaladeps=%scalahome%\lib\jline.jar;%scalahome%\lib\fjbg.jar
-set scalalib=%scalahome%\build\pack\lib\scala-library.jar
-if not exist "%scalalib%" set scalalib=%scalahome%\build\locker\classes\library
-set scalacomp="%scalahome%\build\pack\lib\scala-compiler.jar"
-if not exist "%scalacomp%" set scalacomp=%scalahome%\build\locker\classes\compiler
-set stdcp=%scaladeps%;%scalalib%;%scalacomp%
-
-echo Compiling macros...
-set cp=%stdcp%
-call :scalac -Xmacros "%~dp0\Printf.scala"
-
-echo Compiling the program...
-set cp=%stdcp%;%~dp0.
-call :scalac "%~dp0\Test.scala"
-
-echo.
-echo NOW LOOK!!!
-echo ===============================================
-set cp=%stdcp%;%~dp0.
-call :scala Test
-echo.
-echo ===============================================
-goto :eof
-
-:scalac
-setlocal
-call set args=%*
-rem echo java -cp "%cp%" -Dscala.usejavacp=true scala.tools.nsc.Main %args%
-java -cp "%cp%" -Dscala.usejavacp=true scala.tools.nsc.Main %args%
-endlocal&goto :eof
-
-:scala
-setlocal
-call set args=%*
-rem echo java -cp "%cp%" -Dscala.usejavacp=true scala.tools.nsc.MainGenericRunner %args%
-java -cp "%cp%" -Dscala.usejavacp=true scala.tools.nsc.MainGenericRunner %args%
-endlocal&goto :eof
diff --git a/test/files/macros/macros_v0001.sh b/test/files/macros/macros_v0001.sh
deleted file mode 100644
index abe09836bb..0000000000
--- a/test/files/macros/macros_v0001.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-set -o errexit
-
-if [[ $(uname -s) == CYGWIN* ]]; then cpsep=";"; else cpsep=":"; fi
-scripthome="$(dirname "$0")"
-scalahome="$scripthome/../../.."
-scaladeps="$scalahome/lib/jline.jar;$scalahome/lib/fjbg.jar"
-scalalib="$scalahome/build/pack/lib/scala-library.jar"
-if [ ! -f "$scalalib" ]; then scalalib="$scalahome/build/locker/classes/library"; fi
-scalacomp="$scalahome/build/pack/lib/scala-compiler.jar"
-if [ ! -f "$scalacomp" ]; then scalacomp="$scalahome/build/locker/classes/compiler"; fi
-stdcp="$scaladeps$cpsep$scalalib$cpsep$scalacomp"
-function scalac { java -cp "$cp" -Dscala.usejavacp=true scala.tools.nsc.Main $*; }
-function scala { java -cp "$cp" -Dscala.usejavacp=true scala.tools.nsc.MainGenericRunner $*; }
-
-echo "Compiling macros..."
-cp="$stdcp"
-scalac -Xmacros "$scripthome/Printf.scala"
-
-echo "Compiling the program..."
-cp="$stdcp$cpsep$scripthome"
-scalac "$scripthome/Test.scala"
-
-echo ""
-echo "NOW LOOK"
-echo "==============================================="
-cp="$stdcp$cpsep$scripthome"
-scala Test
-echo ""
-echo "==============================================="
diff --git a/test/files/neg/annot-nonconst.check b/test/files/neg/annot-nonconst.check
index e4166e08b6..b43e58a0ca 100644
--- a/test/files/neg/annot-nonconst.check
+++ b/test/files/neg/annot-nonconst.check
@@ -1,12 +1,12 @@
annot-nonconst.scala:1: warning: Implementation restriction: subclassing Classfile does not
make your annotation visible at runtime. If that is what
you want, you must write the annotation class in Java.
-class Length(value: Int) extends ClassfileAnnotation
+class Length(value: Int) extends annotation.ClassfileAnnotation
^
annot-nonconst.scala:2: warning: Implementation restriction: subclassing Classfile does not
make your annotation visible at runtime. If that is what
you want, you must write the annotation class in Java.
-class Ann2(value: String) extends ClassfileAnnotation
+class Ann2(value: String) extends annotation.ClassfileAnnotation
^
annot-nonconst.scala:6: error: annotation argument needs to be a constant; found: n
@Length(n) def foo = "foo"
diff --git a/test/files/neg/annot-nonconst.scala b/test/files/neg/annot-nonconst.scala
index 69bb60d34e..1b5856f8b2 100644
--- a/test/files/neg/annot-nonconst.scala
+++ b/test/files/neg/annot-nonconst.scala
@@ -1,5 +1,5 @@
-class Length(value: Int) extends ClassfileAnnotation
-class Ann2(value: String) extends ClassfileAnnotation
+class Length(value: Int) extends annotation.ClassfileAnnotation
+class Ann2(value: String) extends annotation.ClassfileAnnotation
object Test {
def n = 15
diff --git a/test/files/neg/applydynamic_sip.check b/test/files/neg/applydynamic_sip.check
new file mode 100644
index 0000000000..8845f68a52
--- /dev/null
+++ b/test/files/neg/applydynamic_sip.check
@@ -0,0 +1,10 @@
+applydynamic_sip.scala:7: error: applyDynamic does not support passing a vararg parameter
+ qual.sel(a, a2: _*)
+ ^
+applydynamic_sip.scala:8: error: applyDynamicNamed does not support passing a vararg parameter
+ qual.sel(arg = a, a2: _*)
+ ^
+applydynamic_sip.scala:9: error: applyDynamicNamed does not support passing a vararg parameter
+ qual.sel(arg, arg2 = "a2", a2: _*)
+ ^
+three errors found
diff --git a/test/files/neg/applydynamic_sip.scala b/test/files/neg/applydynamic_sip.scala
new file mode 100644
index 0000000000..362461577b
--- /dev/null
+++ b/test/files/neg/applydynamic_sip.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ val qual: Dynamic = ???
+ val expr = "expr"
+ val a = "a"
+ val a2 = "a2"
+
+ qual.sel(a, a2: _*)
+ qual.sel(arg = a, a2: _*)
+ qual.sel(arg, arg2 = "a2", a2: _*)
+} \ No newline at end of file
diff --git a/test/files/neg/array-not-seq.check b/test/files/neg/array-not-seq.check
index c16ecdad72..a3a639e772 100644
--- a/test/files/neg/array-not-seq.check
+++ b/test/files/neg/array-not-seq.check
@@ -1,7 +1,13 @@
array-not-seq.scala:2: error: An Array will no longer match as Seq[_].
def f1(x: Any) = x.isInstanceOf[Seq[_]]
^
-error: An Array will no longer match as Seq[_].
-error: An Array will no longer match as Seq[_].
-error: An Array will no longer match as Seq[_].
+array-not-seq.scala:4: error: An Array will no longer match as Seq[_].
+ case _: Seq[_] => true
+ ^
+array-not-seq.scala:16: error: An Array will no longer match as Seq[_].
+ case (Some(_: Seq[_]), Nil, _) => 1
+ ^
+array-not-seq.scala:17: error: An Array will no longer match as Seq[_].
+ case (None, List(_: List[_], _), _) => 2
+ ^
four errors found
diff --git a/test/files/neg/checksensible.check b/test/files/neg/checksensible.check
index d785179a56..23af94180a 100644
--- a/test/files/neg/checksensible.check
+++ b/test/files/neg/checksensible.check
@@ -1,100 +1,100 @@
-checksensible.scala:13: error: comparing a fresh object using `eq' will always yield false
- (new AnyRef) eq (new AnyRef)
- ^
-checksensible.scala:14: error: comparing a fresh object using `ne' will always yield true
- (new AnyRef) ne (new AnyRef)
- ^
-checksensible.scala:15: error: comparing a fresh object using `eq' will always yield false
- Shmoopie eq (new AnyRef)
- ^
-checksensible.scala:16: error: comparing a fresh object using `eq' will always yield false
- (Shmoopie: AnyRef) eq (new AnyRef)
- ^
-checksensible.scala:17: error: comparing a fresh object using `eq' will always yield false
- (new AnyRef) eq Shmoopie
- ^
-checksensible.scala:18: error: comparing a fresh object using `eq' will always yield false
- (new AnyRef) eq null
- ^
-checksensible.scala:19: error: comparing a fresh object using `eq' will always yield false
- null eq new AnyRef
- ^
-checksensible.scala:26: error: comparing values of types Unit and Int using `==' will always yield false
- (c = 1) == 0
- ^
-checksensible.scala:27: error: comparing values of types Int and Unit using `==' will always yield false
- 0 == (c = 1)
- ^
-checksensible.scala:29: error: comparing values of types Int and String using `==' will always yield false
- 1 == "abc"
- ^
-checksensible.scala:33: error: comparing values of types Some[Int] and Int using `==' will always yield false
- Some(1) == 1 // as above
- ^
-checksensible.scala:38: error: comparing a fresh object using `==' will always yield false
- new AnyRef == 1
- ^
-checksensible.scala:41: error: comparing values of types Int and Boolean using `==' will always yield false
- 1 == (new java.lang.Boolean(true))
- ^
-checksensible.scala:43: error: comparing values of types Int and Boolean using `!=' will always yield true
- 1 != true
- ^
-checksensible.scala:44: error: comparing values of types Unit and Boolean using `==' will always yield false
- () == true
- ^
-checksensible.scala:45: error: comparing values of types Unit and Unit using `==' will always yield true
- () == ()
- ^
-checksensible.scala:46: error: comparing values of types Unit and Unit using `==' will always yield true
- () == println
- ^
-checksensible.scala:47: error: comparing values of types Unit and scala.runtime.BoxedUnit using `==' will always yield true
- () == scala.runtime.BoxedUnit.UNIT // these should warn for always being true/false
- ^
-checksensible.scala:48: error: comparing values of types scala.runtime.BoxedUnit and Unit using `!=' will always yield false
- scala.runtime.BoxedUnit.UNIT != ()
- ^
-checksensible.scala:51: error: comparing values of types Int and Unit using `!=' will always yield true
- (1 != println)
- ^
-checksensible.scala:52: error: comparing values of types Int and Symbol using `!=' will always yield true
- (1 != 'sym)
- ^
-checksensible.scala:58: error: comparing a fresh object using `==' will always yield false
- ((x: Int) => x + 1) == null
- ^
-checksensible.scala:59: error: comparing a fresh object using `==' will always yield false
- Bep == ((_: Int) + 1)
- ^
-checksensible.scala:61: error: comparing a fresh object using `==' will always yield false
- new Object == new Object
- ^
-checksensible.scala:62: error: comparing a fresh object using `==' will always yield false
- new Object == "abc"
- ^
-checksensible.scala:63: error: comparing a fresh object using `!=' will always yield true
- new Exception() != new Exception()
- ^
-checksensible.scala:66: error: comparing values of types Int and Null using `==' will always yield false
- if (foo.length == null) "plante" else "plante pas"
- ^
-checksensible.scala:71: error: comparing values of types Bip and Bop using `==' will always yield false
- (x1 == x2)
- ^
-checksensible.scala:81: error: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false
- c3 == z1
- ^
-checksensible.scala:82: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false
- z1 == c3
- ^
-checksensible.scala:83: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true
- z1 != c3
- ^
-checksensible.scala:84: error: comparing values of types EqEqRefTest.this.C3 and String using `!=' will always yield true
- c3 != "abc"
- ^
-checksensible.scala:95: error: comparing values of types Unit and Int using `!=' will always yield true
- while ((c = in.read) != -1)
- ^
-33 errors found
+checksensible.scala:13: error: comparing a fresh object using `eq' will always yield false
+ (new AnyRef) eq (new AnyRef)
+ ^
+checksensible.scala:14: error: comparing a fresh object using `ne' will always yield true
+ (new AnyRef) ne (new AnyRef)
+ ^
+checksensible.scala:15: error: comparing a fresh object using `eq' will always yield false
+ Shmoopie eq (new AnyRef)
+ ^
+checksensible.scala:16: error: comparing a fresh object using `eq' will always yield false
+ (Shmoopie: AnyRef) eq (new AnyRef)
+ ^
+checksensible.scala:17: error: comparing a fresh object using `eq' will always yield false
+ (new AnyRef) eq Shmoopie
+ ^
+checksensible.scala:18: error: comparing a fresh object using `eq' will always yield false
+ (new AnyRef) eq null
+ ^
+checksensible.scala:19: error: comparing a fresh object using `eq' will always yield false
+ null eq new AnyRef
+ ^
+checksensible.scala:26: error: comparing values of types Unit and Int using `==' will always yield false
+ (c = 1) == 0
+ ^
+checksensible.scala:27: error: comparing values of types Int and Unit using `==' will always yield false
+ 0 == (c = 1)
+ ^
+checksensible.scala:29: error: comparing values of types Int and String using `==' will always yield false
+ 1 == "abc"
+ ^
+checksensible.scala:33: error: comparing values of types Some[Int] and Int using `==' will always yield false
+ Some(1) == 1 // as above
+ ^
+checksensible.scala:38: error: comparing a fresh object using `==' will always yield false
+ new AnyRef == 1
+ ^
+checksensible.scala:41: error: comparing values of types Int and Boolean using `==' will always yield false
+ 1 == (new java.lang.Boolean(true))
+ ^
+checksensible.scala:43: error: comparing values of types Int and Boolean using `!=' will always yield true
+ 1 != true
+ ^
+checksensible.scala:44: error: comparing values of types Unit and Boolean using `==' will always yield false
+ () == true
+ ^
+checksensible.scala:45: error: comparing values of types Unit and Unit using `==' will always yield true
+ () == ()
+ ^
+checksensible.scala:46: error: comparing values of types Unit and Unit using `==' will always yield true
+ () == println
+ ^
+checksensible.scala:47: error: comparing values of types Unit and scala.runtime.BoxedUnit using `==' will always yield true
+ () == scala.runtime.BoxedUnit.UNIT // these should warn for always being true/false
+ ^
+checksensible.scala:48: error: comparing values of types scala.runtime.BoxedUnit and Unit using `!=' will always yield false
+ scala.runtime.BoxedUnit.UNIT != ()
+ ^
+checksensible.scala:51: error: comparing values of types Int and Unit using `!=' will always yield true
+ (1 != println)
+ ^
+checksensible.scala:52: error: comparing values of types Int and Symbol using `!=' will always yield true
+ (1 != 'sym)
+ ^
+checksensible.scala:58: error: comparing a fresh object using `==' will always yield false
+ ((x: Int) => x + 1) == null
+ ^
+checksensible.scala:59: error: comparing a fresh object using `==' will always yield false
+ Bep == ((_: Int) + 1)
+ ^
+checksensible.scala:61: error: comparing a fresh object using `==' will always yield false
+ new Object == new Object
+ ^
+checksensible.scala:62: error: comparing a fresh object using `==' will always yield false
+ new Object == "abc"
+ ^
+checksensible.scala:63: error: comparing a fresh object using `!=' will always yield true
+ new Exception() != new Exception()
+ ^
+checksensible.scala:66: error: comparing values of types Int and Null using `==' will always yield false
+ if (foo.length == null) "plante" else "plante pas"
+ ^
+checksensible.scala:71: error: comparing values of types Bip and Bop using `==' will always yield false
+ (x1 == x2)
+ ^
+checksensible.scala:81: error: comparing values of types EqEqRefTest.this.C3 and EqEqRefTest.this.Z1 using `==' will always yield false
+ c3 == z1
+ ^
+checksensible.scala:82: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `==' will always yield false
+ z1 == c3
+ ^
+checksensible.scala:83: error: comparing values of types EqEqRefTest.this.Z1 and EqEqRefTest.this.C3 using `!=' will always yield true
+ z1 != c3
+ ^
+checksensible.scala:84: error: comparing values of types EqEqRefTest.this.C3 and String using `!=' will always yield true
+ c3 != "abc"
+ ^
+checksensible.scala:95: error: comparing values of types Unit and Int using `!=' will always yield true
+ while ((c = in.read) != -1)
+ ^
+33 errors found
diff --git a/test/files/neg/classtags_contextbound_a.check b/test/files/neg/classtags_contextbound_a.check
new file mode 100644
index 0000000000..a4fd37506d
--- /dev/null
+++ b/test/files/neg/classtags_contextbound_a.check
@@ -0,0 +1,4 @@
+classtags_contextbound_a.scala:2: error: No ArrayTag available for T
+ def foo[T] = Array[T]()
+ ^
+one error found
diff --git a/test/files/neg/classtags_contextbound_a.scala b/test/files/neg/classtags_contextbound_a.scala
new file mode 100644
index 0000000000..d18beda341
--- /dev/null
+++ b/test/files/neg/classtags_contextbound_a.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo[T] = Array[T]()
+ println(foo[Int].getClass)
+} \ No newline at end of file
diff --git a/test/files/neg/classtags_contextbound_b.check b/test/files/neg/classtags_contextbound_b.check
new file mode 100644
index 0000000000..f1f48bed72
--- /dev/null
+++ b/test/files/neg/classtags_contextbound_b.check
@@ -0,0 +1,4 @@
+classtags_contextbound_b.scala:3: error: No ClassTag available for T
+ def foo[T] = mkArray[T]
+ ^
+one error found
diff --git a/test/files/neg/classtags_contextbound_b.scala b/test/files/neg/classtags_contextbound_b.scala
new file mode 100644
index 0000000000..3247a8ff29
--- /dev/null
+++ b/test/files/neg/classtags_contextbound_b.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ def mkArray[T: ClassTag] = Array[T]()
+ def foo[T] = mkArray[T]
+ println(foo[Int].getClass)
+} \ No newline at end of file
diff --git a/test/files/neg/classtags_contextbound_c.check b/test/files/neg/classtags_contextbound_c.check
new file mode 100644
index 0000000000..a1c5eddfe1
--- /dev/null
+++ b/test/files/neg/classtags_contextbound_c.check
@@ -0,0 +1,4 @@
+classtags_contextbound_c.scala:2: error: No ArrayTag available for T
+ def mkArray[T] = Array[T]()
+ ^
+one error found
diff --git a/test/files/neg/classtags_contextbound_c.scala b/test/files/neg/classtags_contextbound_c.scala
new file mode 100644
index 0000000000..0b63f8407e
--- /dev/null
+++ b/test/files/neg/classtags_contextbound_c.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ def mkArray[T] = Array[T]()
+ def foo[T: ClassTag] = mkArray[T]
+ println(foo[Int].getClass)
+} \ No newline at end of file
diff --git a/test/files/neg/classtags_dont_use_typetags.check b/test/files/neg/classtags_dont_use_typetags.check
new file mode 100644
index 0000000000..c7d2fba35b
--- /dev/null
+++ b/test/files/neg/classtags_dont_use_typetags.check
@@ -0,0 +1,4 @@
+classtags_dont_use_typetags.scala:2: error: No ArrayTag available for T
+ def foo[T: TypeTag] = Array[T]()
+ ^
+one error found
diff --git a/test/files/neg/classtags_dont_use_typetags.scala b/test/files/neg/classtags_dont_use_typetags.scala
new file mode 100644
index 0000000000..0f675f71aa
--- /dev/null
+++ b/test/files/neg/classtags_dont_use_typetags.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ def foo[T: TypeTag] = Array[T]()
+} \ No newline at end of file
diff --git a/test/pending/neg/dbldef.check b/test/files/neg/dbldef.check
index 3ee63475e4..3ee63475e4 100644
--- a/test/pending/neg/dbldef.check
+++ b/test/files/neg/dbldef.check
diff --git a/test/pending/neg/dbldef.scala b/test/files/neg/dbldef.scala
index c70fb97b2c..c70fb97b2c 100644
--- a/test/pending/neg/dbldef.scala
+++ b/test/files/neg/dbldef.scala
diff --git a/test/files/neg/exhausting.flags b/test/files/neg/exhausting.flags
index e8fb65d50c..b7eb21d5f5 100644
--- a/test/files/neg/exhausting.flags
+++ b/test/files/neg/exhausting.flags
@@ -1 +1 @@
--Xfatal-warnings \ No newline at end of file
+-Xfatal-warnings -Xoldpatmat
diff --git a/test/files/neg/interop_classmanifests_arenot_concretetypetags.check b/test/files/neg/interop_classmanifests_arenot_concretetypetags.check
new file mode 100644
index 0000000000..d6fa564df4
--- /dev/null
+++ b/test/files/neg/interop_classmanifests_arenot_concretetypetags.check
@@ -0,0 +1,4 @@
+interop_classmanifests_arenot_concretetypetags.scala:3: error: No ConcreteTypeTag available for T
+ println(concreteTypeTag[T])
+ ^
+one error found
diff --git a/test/files/neg/interop_classmanifests_arenot_concretetypetags.scala b/test/files/neg/interop_classmanifests_arenot_concretetypetags.scala
new file mode 100644
index 0000000000..5b1ed55e47
--- /dev/null
+++ b/test/files/neg/interop_classmanifests_arenot_concretetypetags.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def classManifestIsnotConcreteTypeTag[T: ClassManifest] = {
+ println(concreteTypeTag[T])
+ }
+
+ classManifestIsnotConcreteTypeTag[Int]
+ classManifestIsnotConcreteTypeTag[String]
+ classManifestIsnotConcreteTypeTag[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/neg/interop_classtags_arenot_manifests.check b/test/files/neg/interop_classtags_arenot_manifests.check
new file mode 100644
index 0000000000..95f6a94d4b
--- /dev/null
+++ b/test/files/neg/interop_classtags_arenot_manifests.check
@@ -0,0 +1,7 @@
+interop_classtags_arenot_manifests.scala:3: error: No Manifest available for T.
+ println(manifest[T])
+ ^
+interop_classtags_arenot_manifests.scala:11: error: No Manifest available for T.
+ println(manifest[T])
+ ^
+two errors found
diff --git a/test/files/neg/interop_classtags_arenot_manifests.scala b/test/files/neg/interop_classtags_arenot_manifests.scala
new file mode 100644
index 0000000000..7351f7e305
--- /dev/null
+++ b/test/files/neg/interop_classtags_arenot_manifests.scala
@@ -0,0 +1,17 @@
+object Test extends App {
+ def arrayTagIsnotManifest[T: ArrayTag] = {
+ println(manifest[T])
+ }
+
+ arrayTagIsnotManifest[Int]
+ arrayTagIsnotManifest[String]
+ arrayTagIsnotManifest[Array[Int]]
+
+ def classTagIsnotManifest[T: ClassTag] = {
+ println(manifest[T])
+ }
+
+ classTagIsnotManifest[Int]
+ classTagIsnotManifest[String]
+ classTagIsnotManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/neg/interop_erasuretags_arenot_classmanifests.check b/test/files/neg/interop_erasuretags_arenot_classmanifests.check
new file mode 100644
index 0000000000..4bb81108d1
--- /dev/null
+++ b/test/files/neg/interop_erasuretags_arenot_classmanifests.check
@@ -0,0 +1,4 @@
+interop_erasuretags_arenot_classmanifests.scala:3: error: could not find implicit value for parameter m: ClassManifest[T]
+ println(classManifest[T])
+ ^
+one error found
diff --git a/test/files/neg/interop_erasuretags_arenot_classmanifests.scala b/test/files/neg/interop_erasuretags_arenot_classmanifests.scala
new file mode 100644
index 0000000000..cf7d1ac257
--- /dev/null
+++ b/test/files/neg/interop_erasuretags_arenot_classmanifests.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def erasureTagIsnotClassManifest[T: ErasureTag] = {
+ println(classManifest[T])
+ }
+
+ erasureTagIsnotClassManifest[Int]
+ erasureTagIsnotClassManifest[String]
+ erasureTagIsnotClassManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/neg/interop_erasuretags_arenot_manifests.check b/test/files/neg/interop_erasuretags_arenot_manifests.check
new file mode 100644
index 0000000000..da3c03d371
--- /dev/null
+++ b/test/files/neg/interop_erasuretags_arenot_manifests.check
@@ -0,0 +1,4 @@
+interop_erasuretags_arenot_manifests.scala:3: error: No Manifest available for T.
+ println(manifest[T])
+ ^
+one error found
diff --git a/test/files/neg/interop_erasuretags_arenot_manifests.scala b/test/files/neg/interop_erasuretags_arenot_manifests.scala
new file mode 100644
index 0000000000..5c326549d8
--- /dev/null
+++ b/test/files/neg/interop_erasuretags_arenot_manifests.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def erasureTagIsnotManifest[T: ErasureTag] = {
+ println(manifest[T])
+ }
+
+ erasureTagIsnotManifest[Int]
+ erasureTagIsnotManifest[String]
+ erasureTagIsnotManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/neg/interop_typetags_arenot_classmanifests.check b/test/files/neg/interop_typetags_arenot_classmanifests.check
new file mode 100644
index 0000000000..9ed4fd43d4
--- /dev/null
+++ b/test/files/neg/interop_typetags_arenot_classmanifests.check
@@ -0,0 +1,4 @@
+interop_typetags_arenot_classmanifests.scala:3: error: could not find implicit value for parameter m: ClassManifest[T]
+ println(classManifest[T])
+ ^
+one error found
diff --git a/test/files/neg/interop_typetags_arenot_classmanifests.scala b/test/files/neg/interop_typetags_arenot_classmanifests.scala
new file mode 100644
index 0000000000..b1fbb7b5a6
--- /dev/null
+++ b/test/files/neg/interop_typetags_arenot_classmanifests.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def typeTagIsnotClassManifest[T: TypeTag] = {
+ println(classManifest[T])
+ }
+
+ typeTagIsnotClassManifest[Int]
+ typeTagIsnotClassManifest[String]
+ typeTagIsnotClassManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/neg/interop_typetags_arenot_manifests.check b/test/files/neg/interop_typetags_arenot_manifests.check
new file mode 100644
index 0000000000..7761a747ff
--- /dev/null
+++ b/test/files/neg/interop_typetags_arenot_manifests.check
@@ -0,0 +1,4 @@
+interop_typetags_arenot_manifests.scala:3: error: No Manifest available for T.
+ println(manifest[T])
+ ^
+one error found
diff --git a/test/files/neg/interop_typetags_arenot_manifests.scala b/test/files/neg/interop_typetags_arenot_manifests.scala
new file mode 100644
index 0000000000..4e2a04489b
--- /dev/null
+++ b/test/files/neg/interop_typetags_arenot_manifests.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def typeTagIsnotManifest[T: TypeTag] = {
+ println(manifest[T])
+ }
+
+ typeTagIsnotManifest[Int]
+ typeTagIsnotManifest[String]
+ typeTagIsnotManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/neg/logImplicits.check b/test/files/neg/logImplicits.check
index d98422dacb..54afc6f86d 100644
--- a/test/files/neg/logImplicits.check
+++ b/test/files/neg/logImplicits.check
@@ -1,16 +1,16 @@
-logImplicits.scala:2: applied implicit conversion from xs.type to ?{val size: ?} = implicit def byteArrayOps(xs: Array[Byte]): scala.collection.mutable.ArrayOps[Byte]
+logImplicits.scala:2: applied implicit conversion from xs.type to ?{def size: ?} = implicit def byteArrayOps(xs: Array[Byte]): scala.collection.mutable.ArrayOps[Byte]
def f(xs: Array[Byte]) = xs.size
^
-logImplicits.scala:7: applied implicit conversion from String("abc") to ?{val map: ?} = implicit def augmentString(x: String): scala.collection.immutable.StringOps
+logImplicits.scala:7: applied implicit conversion from String("abc") to ?{def map: ?} = implicit def augmentString(x: String): scala.collection.immutable.StringOps
def f = "abc" map (_ + 1)
^
logImplicits.scala:15: inferred view from String("abc") to Int = C.this.convert:(p: String("abc"))Int
math.max(122, x: Int)
^
-logImplicits.scala:19: applied implicit conversion from Int(1) to ?{val ->: ?} = implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A]
+logImplicits.scala:19: applied implicit conversion from Int(1) to ?{def ->: ?} = implicit def any2ArrowAssoc[A](x: A): ArrowAssoc[A]
def f = (1 -> 2) + "c"
^
-logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{val +: ?} = implicit def any2stringadd(x: Any): scala.runtime.StringAdd
+logImplicits.scala:19: applied implicit conversion from (Int, Int) to ?{def +: ?} = implicit def any2stringadd(x: Any): scala.runtime.StringAdd
def f = (1 -> 2) + "c"
^
logImplicits.scala:22: error: class Un needs to be abstract, since method unimplemented is not defined
diff --git a/test/files/neg/macro-argtype-mismatch.flags b/test/files/neg/macro-argtype-mismatch.flags
index 7fea2ff901..cd66464f2f 100644
--- a/test/files/neg/macro-argtype-mismatch.flags
+++ b/test/files/neg/macro-argtype-mismatch.flags
@@ -1 +1 @@
--Xmacros \ No newline at end of file
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-argtype-mismatch/Macros_1.scala b/test/files/neg/macro-argtype-mismatch/Macros_1.scala
deleted file mode 100644
index 4b5f98ba37..0000000000
--- a/test/files/neg/macro-argtype-mismatch/Macros_1.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-object Macros {
- def macro foo(x: Int) = x
-} \ No newline at end of file
diff --git a/test/files/neg/macro-basic-mamdmi.check b/test/files/neg/macro-basic-mamdmi.check
new file mode 100644
index 0000000000..eef444f7b3
--- /dev/null
+++ b/test/files/neg/macro-basic-mamdmi.check
@@ -0,0 +1,5 @@
+Impls_Macros_Test_1.scala:36: error: macro implementation not found: foo (the most common reason for that is that you cannot use macro implementations in the same compilation run that defines them)
+if you do need to define macro implementations along with the rest of your program, consider two-phase compilation with -Xmacro-fallback-classpath in the second phase pointing to the output of the first phase
+ println(foo(2) + Macros.bar(2) * new Macros().quux(4))
+ ^
+one error found
diff --git a/test/files/neg/macro-basic-mamdmi.flags b/test/files/neg/macro-basic-mamdmi.flags
new file mode 100644
index 0000000000..5e5dd6ce79
--- /dev/null
+++ b/test/files/neg/macro-basic-mamdmi.flags
@@ -0,0 +1 @@
+-language:experimental.macros
diff --git a/test/files/neg/macro-basic-mamdmi/Impls_Macros_Test_1.scala b/test/files/neg/macro-basic-mamdmi/Impls_Macros_Test_1.scala
new file mode 100644
index 0000000000..e9876e32e9
--- /dev/null
+++ b/test/files/neg/macro-basic-mamdmi/Impls_Macros_Test_1.scala
@@ -0,0 +1,37 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1))))
+ Expr[Int](body)
+ }
+
+ def bar(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2))))
+ Expr[Int](body)
+ }
+
+ def quux(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3))))
+ Expr[Int](body)
+ }
+}
+
+object Macros {
+ object Shmacros {
+ def foo(x: Int): Int = macro Impls.foo
+ }
+ def bar(x: Int): Int = macro Impls.bar
+}
+
+class Macros {
+ def quux(x: Int): Int = macro Impls.quux
+}
+
+object Test extends App {
+ import Macros.Shmacros._
+ println(foo(2) + Macros.bar(2) * new Macros().quux(4))
+} \ No newline at end of file
diff --git a/test/files/neg/macro-cyclic.check b/test/files/neg/macro-cyclic.check
new file mode 100644
index 0000000000..608381e0e8
--- /dev/null
+++ b/test/files/neg/macro-cyclic.check
@@ -0,0 +1,4 @@
+Impls_Macros_1.scala:5: error: could not find implicit value for parameter e: SourceLocation
+ c.reify { implicitly[SourceLocation] }
+ ^
+one error found
diff --git a/test/files/neg/macro-cyclic.flags b/test/files/neg/macro-cyclic.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-cyclic.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-cyclic/Impls_Macros_1.scala b/test/files/neg/macro-cyclic/Impls_Macros_1.scala
new file mode 100644
index 0000000000..1ea06fc968
--- /dev/null
+++ b/test/files/neg/macro-cyclic/Impls_Macros_1.scala
@@ -0,0 +1,25 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl(c: Context) = {
+ c.reify { implicitly[SourceLocation] }
+ }
+
+ implicit def sourceLocation: SourceLocation1 = macro impl
+}
+
+trait SourceLocation {
+ /** Source location of the outermost call */
+ val outer: SourceLocation
+
+ /** The name of the source file */
+ val fileName: String
+
+ /** The line number */
+ val line: Int
+
+ /** The character offset */
+ val charOffset: Int
+}
+
+case class SourceLocation1(val outer: SourceLocation, val fileName: String, val line: Int, val charOffset: Int) extends SourceLocation
diff --git a/test/files/neg/macro-deprecate-idents.check b/test/files/neg/macro-deprecate-idents.check
new file mode 100644
index 0000000000..f8a7e519df
--- /dev/null
+++ b/test/files/neg/macro-deprecate-idents.check
@@ -0,0 +1,52 @@
+macro-deprecate-idents.scala:2: error: macro is now a reserved word; usage as an identifier is deprecated
+ val macro = ???
+ ^
+macro-deprecate-idents.scala:6: error: macro is now a reserved word; usage as an identifier is deprecated
+ var macro = ???
+ ^
+macro-deprecate-idents.scala:10: error: macro is now a reserved word; usage as an identifier is deprecated
+ type macro = Int
+ ^
+macro-deprecate-idents.scala:14: error: macro is now a reserved word; usage as an identifier is deprecated
+ class macro
+ ^
+macro-deprecate-idents.scala:18: error: macro is now a reserved word; usage as an identifier is deprecated
+ class macro
+ ^
+macro-deprecate-idents.scala:22: error: macro is now a reserved word; usage as an identifier is deprecated
+ object macro
+ ^
+macro-deprecate-idents.scala:26: error: macro is now a reserved word; usage as an identifier is deprecated
+ object macro
+ ^
+macro-deprecate-idents.scala:30: error: macro is now a reserved word; usage as an identifier is deprecated
+ trait macro
+ ^
+macro-deprecate-idents.scala:34: error: macro is now a reserved word; usage as an identifier is deprecated
+ trait macro
+ ^
+macro-deprecate-idents.scala:37: error: macro is now a reserved word; usage as an identifier is deprecated
+package macro {
+ ^
+macro-deprecate-idents.scala:38: error: macro is now a reserved word; usage as an identifier is deprecated
+ package macro.bar {
+ ^
+macro-deprecate-idents.scala:43: error: macro is now a reserved word; usage as an identifier is deprecated
+ package macro.foo {
+ ^
+macro-deprecate-idents.scala:48: error: macro is now a reserved word; usage as an identifier is deprecated
+ val Some(macro) = Some(42)
+ ^
+macro-deprecate-idents.scala:49: error: macro is now a reserved word; usage as an identifier is deprecated
+ macro match {
+ ^
+macro-deprecate-idents.scala:50: error: macro is now a reserved word; usage as an identifier is deprecated
+ case macro => println(macro)
+ ^
+macro-deprecate-idents.scala:50: error: macro is now a reserved word; usage as an identifier is deprecated
+ case macro => println(macro)
+ ^
+macro-deprecate-idents.scala:55: error: macro is now a reserved word; usage as an identifier is deprecated
+ def macro = 2
+ ^
+17 errors found
diff --git a/test/files/neg/macro-deprecate-idents.flags b/test/files/neg/macro-deprecate-idents.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/neg/macro-deprecate-idents.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/neg/macro-deprecate-idents.scala b/test/files/neg/macro-deprecate-idents.scala
new file mode 100644
index 0000000000..23c398e341
--- /dev/null
+++ b/test/files/neg/macro-deprecate-idents.scala
@@ -0,0 +1,56 @@
+object Test1 {
+ val macro = ???
+}
+
+object Test2 {
+ var macro = ???
+}
+
+object Test3 {
+ type macro = Int
+}
+
+package test4 {
+ class macro
+}
+
+object Test5 {
+ class macro
+}
+
+package test6 {
+ object macro
+}
+
+object Test7 {
+ object macro
+}
+
+package test8 {
+ trait macro
+}
+
+object Test9 {
+ trait macro
+}
+
+package macro {
+ package macro.bar {
+ }
+}
+
+package foo {
+ package macro.foo {
+ }
+}
+
+object Test12 {
+ val Some(macro) = Some(42)
+ macro match {
+ case macro => println(macro)
+ }
+}
+
+object Test13 {
+ def macro = 2
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-a.check b/test/files/neg/macro-invalidimpl-a.check
new file mode 100644
index 0000000000..855fe2d169
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-a.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:3: error: macro implementation must be in statically accessible object
+ def foo(x: Any) = macro impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidimpl-a.flags b/test/files/neg/macro-invalidimpl-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-a/Impls_1.scala b/test/files/neg/macro-invalidimpl-a/Impls_1.scala
new file mode 100644
index 0000000000..c2f1843b8b
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-a/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+class Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-invalidimpl-a/Macros_Test_2.scala b/test/files/neg/macro-invalidimpl-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..2220ddae0c
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-a/Macros_Test_2.scala
@@ -0,0 +1,9 @@
+object Macros {
+ val impls = new Impls
+ def foo(x: Any) = macro impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-b.check b/test/files/neg/macro-invalidimpl-b.check
new file mode 100644
index 0000000000..855fe2d169
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-b.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:3: error: macro implementation must be in statically accessible object
+ def foo(x: Any) = macro impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidimpl-b.flags b/test/files/neg/macro-invalidimpl-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-b/Impls_1.scala b/test/files/neg/macro-invalidimpl-b/Impls_1.scala
new file mode 100644
index 0000000000..7b1620d117
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-b/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-invalidimpl-b/Macros_Test_2.scala b/test/files/neg/macro-invalidimpl-b/Macros_Test_2.scala
new file mode 100644
index 0000000000..81e40837d2
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-b/Macros_Test_2.scala
@@ -0,0 +1,9 @@
+object Macros {
+ val impls = Impls
+ def foo(x: Any) = macro impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-c.check b/test/files/neg/macro-invalidimpl-c.check
new file mode 100644
index 0000000000..722ec3c7bd
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-c.check
@@ -0,0 +1,4 @@
+Impls_Macros_1.scala:8: error: macro implementation must be in statically accessible object
+ def foo(x: Any) = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidimpl-c.flags b/test/files/neg/macro-invalidimpl-c.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-c.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-c/Impls_Macros_1.scala b/test/files/neg/macro-invalidimpl-c/Impls_Macros_1.scala
new file mode 100644
index 0000000000..657e2d4260
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-c/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+class Macros {
+ object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+ }
+
+ def foo(x: Any) = macro Impls.foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-c/Test_2.scala b/test/files/neg/macro-invalidimpl-c/Test_2.scala
new file mode 100644
index 0000000000..e75a8ba101
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-c/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ new Macros().foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-d.check b/test/files/neg/macro-invalidimpl-d.check
new file mode 100644
index 0000000000..6fedfa74fc
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-d.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:2: error: macro implementation must be in statically accessible object
+ def foo(x: Any) = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidimpl-d.flags b/test/files/neg/macro-invalidimpl-d.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-d.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-d/Impls_1.scala b/test/files/neg/macro-invalidimpl-d/Impls_1.scala
new file mode 100644
index 0000000000..f18e699a1e
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-d/Impls_1.scala
@@ -0,0 +1,7 @@
+import scala.reflect.makro.{Context => Ctx}
+
+trait MacroHelpers {
+ object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = x
+ }
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-d/Macros_Test_2.scala b/test/files/neg/macro-invalidimpl-d/Macros_Test_2.scala
new file mode 100644
index 0000000000..067ab1ddec
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-d/Macros_Test_2.scala
@@ -0,0 +1,7 @@
+class Macros extends MacroHelpers {
+ def foo(x: Any) = macro Impls.foo
+}
+
+object Test extends App {
+ println(new Macros().foo(42))
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-e.check b/test/files/neg/macro-invalidimpl-e.check
new file mode 100644
index 0000000000..61d1e05b87
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-e.check
@@ -0,0 +1,13 @@
+Macros_Test_2.scala:2: error: ambiguous reference to overloaded definition,
+both method foo in object Impls of type (c: scala.reflect.makro.Context)(x: c.Expr[Any], y: c.Expr[Any])Nothing
+and method foo in object Impls of type (c: scala.reflect.makro.Context)(x: c.Expr[Any])Nothing
+match expected type ?
+ def foo(x: Any) = macro Impls.foo
+ ^
+Macros_Test_2.scala:3: error: ambiguous reference to overloaded definition,
+both method foo in object Impls of type (c: scala.reflect.makro.Context)(x: c.Expr[Any], y: c.Expr[Any])Nothing
+and method foo in object Impls of type (c: scala.reflect.makro.Context)(x: c.Expr[Any])Nothing
+match expected type ?
+ def foo(x: Any, y: Any) = macro Impls.foo
+ ^
+two errors found
diff --git a/test/files/neg/macro-invalidimpl-e.flags b/test/files/neg/macro-invalidimpl-e.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-e.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-e/Impls_1.scala b/test/files/neg/macro-invalidimpl-e/Impls_1.scala
new file mode 100644
index 0000000000..ad3eed5cd5
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-e/Impls_1.scala
@@ -0,0 +1,6 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+ def foo(c: Ctx)(x: c.Expr[Any], y: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-invalidimpl-e/Macros_Test_2.scala b/test/files/neg/macro-invalidimpl-e/Macros_Test_2.scala
new file mode 100644
index 0000000000..6edde08167
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-e/Macros_Test_2.scala
@@ -0,0 +1,9 @@
+object Macros {
+ def foo(x: Any) = macro Impls.foo
+ def foo(x: Any, y: Any) = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-f.check b/test/files/neg/macro-invalidimpl-f.check
new file mode 100644
index 0000000000..ec82faa58c
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-f.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context)(): c.Expr[Unit]
+ found : (c: scala.reflect.makro.Context): c.Expr[Unit]
+number of parameter sections differ
+ def bar1() = macro Impls.fooNullary
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidimpl-f.flags b/test/files/neg/macro-invalidimpl-f.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-f.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-f/Impls_1.scala b/test/files/neg/macro-invalidimpl-f/Impls_1.scala
new file mode 100644
index 0000000000..06c6efbb1f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-f/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def fooNullary(c: Ctx) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))
+ Expr[Unit](body)
+ }
+
+ def fooEmpty(c: Ctx)() = fooNullary(c)
+}
diff --git a/test/files/neg/macro-invalidimpl-f/Macros_Test_2.scala b/test/files/neg/macro-invalidimpl-f/Macros_Test_2.scala
new file mode 100644
index 0000000000..493edf1df8
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-f/Macros_Test_2.scala
@@ -0,0 +1,9 @@
+object Macros {
+ def bar1() = macro Impls.fooNullary
+}
+
+object Test extends App {
+ Macros.bar1
+ Macros.bar1()
+ println("kkthxbai")
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-g.check b/test/files/neg/macro-invalidimpl-g.check
new file mode 100644
index 0000000000..9c01f01dc8
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-g.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context): c.Expr[Unit]
+ found : (c: scala.reflect.makro.Context)(): c.Expr[Unit]
+number of parameter sections differ
+ def foo1 = macro Impls.fooEmpty
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidimpl-g.flags b/test/files/neg/macro-invalidimpl-g.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-g.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-g/Impls_1.scala b/test/files/neg/macro-invalidimpl-g/Impls_1.scala
new file mode 100644
index 0000000000..06c6efbb1f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-g/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def fooNullary(c: Ctx) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))
+ Expr[Unit](body)
+ }
+
+ def fooEmpty(c: Ctx)() = fooNullary(c)
+}
diff --git a/test/files/neg/macro-invalidimpl-g/Macros_Test_2.scala b/test/files/neg/macro-invalidimpl-g/Macros_Test_2.scala
new file mode 100644
index 0000000000..5561db9f9a
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-g/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo1 = macro Impls.fooEmpty
+}
+
+object Test extends App {
+ Macros.foo1
+ println("kkthxbai")
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-h.check b/test/files/neg/macro-invalidimpl-h.check
new file mode 100644
index 0000000000..cc7fc794d3
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-h.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:2: error: type arguments [String] do not conform to method foo's type parameter bounds [U <: Int]
+ def foo = macro Impls.foo[String]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidimpl-h.flags b/test/files/neg/macro-invalidimpl-h.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-h.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidimpl-h/Impls_1.scala b/test/files/neg/macro-invalidimpl-h/Impls_1.scala
new file mode 100644
index 0000000000..7db8bcd324
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-h/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U <: Int](c: Ctx) = ???
+}
diff --git a/test/files/neg/macro-invalidimpl-h/Macros_Test_2.scala b/test/files/neg/macro-invalidimpl-h/Macros_Test_2.scala
new file mode 100644
index 0000000000..218c7aec7f
--- /dev/null
+++ b/test/files/neg/macro-invalidimpl-h/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo[String]
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidret-nontree.check b/test/files/neg/macro-invalidret-nontree.check
new file mode 100644
index 0000000000..0b793cf421
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nontree.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context): Int
+type mismatch for return type: Int does not conform to c.Expr[Any]
+ def foo = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidret-nontree.flags b/test/files/neg/macro-invalidret-nontree.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nontree.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidret-nontree/Impls_1.scala b/test/files/neg/macro-invalidret-nontree/Impls_1.scala
new file mode 100644
index 0000000000..efc8d4bfec
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nontree/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = 2
+}
diff --git a/test/files/neg/macro-invalidret-nontree/Macros_Test_2.scala b/test/files/neg/macro-invalidret-nontree/Macros_Test_2.scala
new file mode 100644
index 0000000000..96a8de2832
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nontree/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidret-nonuniversetree.check b/test/files/neg/macro-invalidret-nonuniversetree.check
new file mode 100644
index 0000000000..4fc06b5ceb
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nonuniversetree.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context): reflect.mirror.Literal
+type mismatch for return type: reflect.mirror.Literal does not conform to c.Expr[Any]
+ def foo = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidret-nonuniversetree.flags b/test/files/neg/macro-invalidret-nonuniversetree.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nonuniversetree.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidret-nonuniversetree/Impls_1.scala b/test/files/neg/macro-invalidret-nonuniversetree/Impls_1.scala
new file mode 100644
index 0000000000..86b7c8d8d0
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nonuniversetree/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = scala.reflect.mirror.Literal(scala.reflect.mirror.Constant(42))
+}
diff --git a/test/files/neg/macro-invalidret-nonuniversetree/Macros_Test_2.scala b/test/files/neg/macro-invalidret-nonuniversetree/Macros_Test_2.scala
new file mode 100644
index 0000000000..96a8de2832
--- /dev/null
+++ b/test/files/neg/macro-invalidret-nonuniversetree/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-a.check b/test/files/neg/macro-invalidshape-a.check
new file mode 100644
index 0000000000..246b5c3226
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-a.check
@@ -0,0 +1,6 @@
+Macros_Test_2.scala:2: error: macro body has wrong shape:
+ required: macro <reference to implementation object>.<implementation method name>
+ or : macro <implementation method name>
+ def foo(x: Any) = macro 2
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidshape-a.flags b/test/files/neg/macro-invalidshape-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-a/Impls_1.scala b/test/files/neg/macro-invalidshape-a/Impls_1.scala
new file mode 100644
index 0000000000..7b1620d117
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-a/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-invalidshape-a/Macros_Test_2.scala b/test/files/neg/macro-invalidshape-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..ffff17d1e7
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-a/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Any) = macro 2
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-b.check b/test/files/neg/macro-invalidshape-b.check
new file mode 100644
index 0000000000..59701d023b
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-b.check
@@ -0,0 +1,6 @@
+Macros_Test_2.scala:2: error: macro body has wrong shape:
+ required: macro <reference to implementation object>.<implementation method name>
+ or : macro <implementation method name>
+ def foo(x: Any) = macro Impls.foo(null)(null)
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidshape-b.flags b/test/files/neg/macro-invalidshape-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-b/Impls_1.scala b/test/files/neg/macro-invalidshape-b/Impls_1.scala
new file mode 100644
index 0000000000..7b1620d117
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-b/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-invalidshape-b/Macros_Test_2.scala b/test/files/neg/macro-invalidshape-b/Macros_Test_2.scala
new file mode 100644
index 0000000000..b67cd32a6e
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-b/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Any) = macro Impls.foo(null)(null)
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-c.check b/test/files/neg/macro-invalidshape-c.check
new file mode 100644
index 0000000000..84d8c35222
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-c.check
@@ -0,0 +1,6 @@
+Macros_Test_2.scala:2: error: macro body has wrong shape:
+ required: macro <reference to implementation object>.<implementation method name>
+ or : macro <implementation method name>
+ def foo(x: Any) = macro {2; Impls.foo}
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidshape-c.flags b/test/files/neg/macro-invalidshape-c.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-c.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-c/Impls_1.scala b/test/files/neg/macro-invalidshape-c/Impls_1.scala
new file mode 100644
index 0000000000..7b1620d117
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-c/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-invalidshape-c/Macros_Test_2.scala b/test/files/neg/macro-invalidshape-c/Macros_Test_2.scala
new file mode 100644
index 0000000000..552c3710c7
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-c/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Any) = macro {2; Impls.foo}
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-d.check b/test/files/neg/macro-invalidshape-d.check
new file mode 100644
index 0000000000..f0d77e2f2d
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-d.check
@@ -0,0 +1,8 @@
+Macros_Test_2.scala:2: warning: macro is now a reserved word; usage as an identifier is deprecated
+ def foo(x: Any) = {2; macro Impls.foo}
+ ^
+Macros_Test_2.scala:2: error: ';' expected but '.' found.
+ def foo(x: Any) = {2; macro Impls.foo}
+ ^
+one warning found
+one error found
diff --git a/test/files/neg/macro-invalidshape-d.flags b/test/files/neg/macro-invalidshape-d.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-d.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidshape-d/Impls_1.scala b/test/files/neg/macro-invalidshape-d/Impls_1.scala
new file mode 100644
index 0000000000..7b1620d117
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-d/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-invalidshape-d/Macros_Test_2.scala b/test/files/neg/macro-invalidshape-d/Macros_Test_2.scala
new file mode 100644
index 0000000000..bacd9a6e7c
--- /dev/null
+++ b/test/files/neg/macro-invalidshape-d/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Any) = {2; macro Impls.foo}
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-context-bounds.check b/test/files/neg/macro-invalidsig-context-bounds.check
new file mode 100644
index 0000000000..0401993335
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-context-bounds.check
@@ -0,0 +1,4 @@
+Impls_1.scala:4: error: macro implementations cannot have implicit parameters other than TypeTag evidences
+ def foo[U: c.TypeTag: Numeric](c: Ctx) = {
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-context-bounds.flags b/test/files/neg/macro-invalidsig-context-bounds.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-context-bounds.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-context-bounds/Impls_1.scala b/test/files/neg/macro-invalidsig-context-bounds/Impls_1.scala
new file mode 100644
index 0000000000..2eb2ab3947
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-context-bounds/Impls_1.scala
@@ -0,0 +1,8 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U: c.TypeTag: Numeric](c: Ctx) = {
+ import c.mirror._
+ Literal(Constant(42))
+ }
+}
diff --git a/test/files/neg/macro-invalidsig-context-bounds/Macros_Test_1.scala b/test/files/neg/macro-invalidsig-context-bounds/Macros_Test_1.scala
new file mode 100644
index 0000000000..5b4602f328
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-context-bounds/Macros_Test_1.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo[U] = macro Impls.foo[U]
+}
+
+object Test extends App {
+ import Macros._
+ println(foo[String])
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-badargc.check b/test/files/neg/macro-invalidsig-ctx-badargc.check
new file mode 100644
index 0000000000..1e1621ab61
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badargc.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context): c.Expr[Any]
+ found : : Nothing
+number of parameter sections differ
+ def foo = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-ctx-badargc.flags b/test/files/neg/macro-invalidsig-ctx-badargc.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badargc.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-badargc/Impls_1.scala b/test/files/neg/macro-invalidsig-ctx-badargc/Impls_1.scala
new file mode 100644
index 0000000000..da28944d27
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badargc/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.api.{Mirror => Ctx}
+
+object Impls {
+ def foo = ???
+}
diff --git a/test/files/neg/macro-invalidsig-ctx-badargc/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-ctx-badargc/Macros_Test_2.scala
new file mode 100644
index 0000000000..96a8de2832
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badargc/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-badtype.check b/test/files/neg/macro-invalidsig-ctx-badtype.check
new file mode 100644
index 0000000000..3913a8e3cb
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badtype.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context): c.Expr[Any]
+ found : (c: scala.reflect.api.Mirror): Nothing
+type mismatch for parameter c: scala.reflect.makro.Context does not conform to scala.reflect.api.Mirror
+ def foo = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-ctx-badtype.flags b/test/files/neg/macro-invalidsig-ctx-badtype.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badtype.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-badtype/Impls_1.scala b/test/files/neg/macro-invalidsig-ctx-badtype/Impls_1.scala
new file mode 100644
index 0000000000..747a2e9ca8
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badtype/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.api.{Mirror => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = ???
+}
diff --git a/test/files/neg/macro-invalidsig-ctx-badtype/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-ctx-badtype/Macros_Test_2.scala
new file mode 100644
index 0000000000..96a8de2832
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badtype/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-badvarargs.check b/test/files/neg/macro-invalidsig-ctx-badvarargs.check
new file mode 100644
index 0000000000..18e3d6201f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badvarargs.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context): c.Expr[Any]
+ found : (cs: scala.reflect.makro.Context*): Nothing
+types incompatible for parameter cs: corresponding is not a vararg parameter
+ def foo = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-ctx-badvarargs.flags b/test/files/neg/macro-invalidsig-ctx-badvarargs.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badvarargs.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-badvarargs/Impls_1.scala b/test/files/neg/macro-invalidsig-ctx-badvarargs/Impls_1.scala
new file mode 100644
index 0000000000..b2fb2539ec
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badvarargs/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(cs: Ctx*) = ???
+}
diff --git a/test/files/neg/macro-invalidsig-ctx-badvarargs/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-ctx-badvarargs/Macros_Test_2.scala
new file mode 100644
index 0000000000..96a8de2832
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-badvarargs/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-noctx.check b/test/files/neg/macro-invalidsig-ctx-noctx.check
new file mode 100644
index 0000000000..66fa7c3514
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-noctx.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context)(x: c.Expr[Any]): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context): Nothing
+number of parameter sections differ
+ def foo(x: Any) = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-ctx-noctx.flags b/test/files/neg/macro-invalidsig-ctx-noctx.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-noctx.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-ctx-noctx/Impls_1.scala b/test/files/neg/macro-invalidsig-ctx-noctx/Impls_1.scala
new file mode 100644
index 0000000000..1e0ed755af
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-noctx/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = ???
+}
diff --git a/test/files/neg/macro-invalidsig-ctx-noctx/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-ctx-noctx/Macros_Test_2.scala
new file mode 100644
index 0000000000..e053cf99df
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-ctx-noctx/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Any) = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-implicit-params.check b/test/files/neg/macro-invalidsig-implicit-params.check
new file mode 100644
index 0000000000..0dd1c27b50
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-implicit-params.check
@@ -0,0 +1,4 @@
+Impls_Macros_1.scala:4: error: macro implementations cannot have implicit parameters other than TypeTag evidences
+ def foo_targs[T, U: c.TypeTag](c: Ctx)(implicit x: c.Expr[Int]) = {
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-implicit-params.flags b/test/files/neg/macro-invalidsig-implicit-params.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-implicit-params.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala b/test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala
new file mode 100644
index 0000000000..662ad2ab52
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-implicit-params/Impls_Macros_1.scala
@@ -0,0 +1,18 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo_targs[T, U: c.TypeTag](c: Ctx)(implicit x: c.Expr[Int]) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val body = Block(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("invoking foo_targs...")))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("type of prefix is: " + prefix.tpe)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("U is: " + implicitly[c.TypeTag[U]].tpe)))),
+ Literal(Constant(())))
+ Expr[Unit](body)
+ }
+}
+
+class Macros[T] {
+ def foo_targs[U](x: Int) = macro Impls.foo_targs[T, U]
+}
diff --git a/test/files/neg/macro-invalidsig-implicit-params/Test_2.scala b/test/files/neg/macro-invalidsig-implicit-params/Test_2.scala
new file mode 100644
index 0000000000..90e850df21
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-implicit-params/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println("foo_targs:")
+ new Macros[Int]().foo_targs[String](42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-badargc.check b/test/files/neg/macro-invalidsig-params-badargc.check
new file mode 100644
index 0000000000..6de8c5e95a
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badargc.check
@@ -0,0 +1,7 @@
+Impls_Macros_1.scala:8: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context)(x: c.Expr[Int]): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context)(x: c.Expr[Int], y: c.Expr[Int]): Nothing
+parameter lists have different length, found extra parameter y: c.Expr[Int]
+ def foo(x: Int) = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-params-badargc.flags b/test/files/neg/macro-invalidsig-params-badargc.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badargc.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-badargc/Impls_Macros_1.scala b/test/files/neg/macro-invalidsig-params-badargc/Impls_Macros_1.scala
new file mode 100644
index 0000000000..4b449f35ed
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badargc/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int], y: c.Expr[Int]) = ???
+}
+
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
diff --git a/test/files/neg/macro-noexpand/Test_2.scala b/test/files/neg/macro-invalidsig-params-badargc/Test_2.scala
index 0bed592883..cbd6232073 100644
--- a/test/files/neg/macro-noexpand/Test_2.scala
+++ b/test/files/neg/macro-invalidsig-params-badargc/Test_2.scala
@@ -1,4 +1,4 @@
object Test extends App {
import Macros._
- foo(x)
+ foo(42)
} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-badtype.check b/test/files/neg/macro-invalidsig-params-badtype.check
new file mode 100644
index 0000000000..71a65aec84
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badtype.check
@@ -0,0 +1,7 @@
+Impls_Macros_1.scala:8: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context)(x: c.Expr[Int]): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context)(x: c.mirror.Tree): Nothing
+type mismatch for parameter x: c.Expr[Int] does not conform to c.mirror.Tree
+ def foo(x: Int) = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-params-badtype.flags b/test/files/neg/macro-invalidsig-params-badtype.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badtype.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala b/test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala
new file mode 100644
index 0000000000..29220c1c82
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badtype/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.mirror.Tree) = ???
+}
+
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
diff --git a/test/files/neg/macro-argtype-mismatch/Test_2.scala b/test/files/neg/macro-invalidsig-params-badtype/Test_2.scala
index 18feb69425..cbd6232073 100644
--- a/test/files/neg/macro-argtype-mismatch/Test_2.scala
+++ b/test/files/neg/macro-invalidsig-params-badtype/Test_2.scala
@@ -1,4 +1,4 @@
object Test extends App {
import Macros._
- foo("2")
+ foo(42)
} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-badvarargs.check b/test/files/neg/macro-invalidsig-params-badvarargs.check
new file mode 100644
index 0000000000..0827680299
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badvarargs.check
@@ -0,0 +1,7 @@
+Impls_Macros_1.scala:8: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context)(xs: c.Expr[Int]*): Nothing
+parameter lists have different length, required extra parameter y: c.Expr[Int]
+ def foo(x: Int, y: Int) = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-params-badvarargs.flags b/test/files/neg/macro-invalidsig-params-badvarargs.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badvarargs.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-badvarargs/Impls_Macros_1.scala b/test/files/neg/macro-invalidsig-params-badvarargs/Impls_Macros_1.scala
new file mode 100644
index 0000000000..2ee1c2767c
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badvarargs/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(xs: c.Expr[Int]*) = ???
+}
+
+object Macros {
+ def foo(x: Int, y: Int) = macro Impls.foo
+}
diff --git a/test/files/neg/macro-invalidsig-params-badvarargs/Test_2.scala b/test/files/neg/macro-invalidsig-params-badvarargs/Test_2.scala
new file mode 100644
index 0000000000..fa50ac4f73
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-badvarargs/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros._
+ foo(42, 100)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-namemismatch.check b/test/files/neg/macro-invalidsig-params-namemismatch.check
new file mode 100644
index 0000000000..ca7270cca8
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-namemismatch.check
@@ -0,0 +1,7 @@
+Impls_Macros_1.scala:8: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context)(x: c.Expr[Int], y: c.Expr[Int]): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context)(y: c.Expr[Int], x: c.Expr[Int]): Nothing
+parameter names differ: x != y
+ def foo(x: Int, y: Int) = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-params-namemismatch.flags b/test/files/neg/macro-invalidsig-params-namemismatch.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-namemismatch.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-params-namemismatch/Impls_Macros_1.scala b/test/files/neg/macro-invalidsig-params-namemismatch/Impls_Macros_1.scala
new file mode 100644
index 0000000000..89c5347647
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-namemismatch/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(y: c.Expr[Int], x: c.Expr[Int]) = ???
+}
+
+object Macros {
+ def foo(x: Int, y: Int) = macro Impls.foo
+}
diff --git a/test/files/neg/macro-invalidsig-params-namemismatch/Test_2.scala b/test/files/neg/macro-invalidsig-params-namemismatch/Test_2.scala
new file mode 100644
index 0000000000..fa50ac4f73
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-params-namemismatch/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros._
+ foo(42, 100)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-badtype.check b/test/files/neg/macro-invalidsig-tparams-badtype.check
new file mode 100644
index 0000000000..bd1acc4a0a
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-badtype.check
@@ -0,0 +1,7 @@
+Macros_Test_2.scala:2: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context): c.Expr[Any]
+ found : (c: scala.reflect.makro.Context)(U: c.mirror.Type): Nothing
+number of parameter sections differ
+ def foo[U] = macro Impls.foo[U]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-badtype.flags b/test/files/neg/macro-invalidsig-tparams-badtype.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-badtype.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-badtype/Impls_1.scala b/test/files/neg/macro-invalidsig-tparams-badtype/Impls_1.scala
new file mode 100644
index 0000000000..b43251df33
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-badtype/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U](c: Ctx)(U: c.mirror.Type) = ???
+}
diff --git a/test/files/neg/macro-invalidsig-tparams-badtype/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-tparams-badtype/Macros_Test_2.scala
new file mode 100644
index 0000000000..a82e813221
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-badtype/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo[U] = macro Impls.foo[U]
+}
+
+object Test extends App {
+ import Macros._
+ foo[Int]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-a.check b/test/files/neg/macro-invalidsig-tparams-bounds-a.check
new file mode 100644
index 0000000000..6ba80b45c0
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-a.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:2: error: type arguments [U] do not conform to method foo's type parameter bounds [U <: String]
+ def foo[U] = macro Impls.foo[U]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-a.flags b/test/files/neg/macro-invalidsig-tparams-bounds-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-a/Impls_1.scala b/test/files/neg/macro-invalidsig-tparams-bounds-a/Impls_1.scala
new file mode 100644
index 0000000000..88b85d48f4
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-a/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U <: String](c: Ctx) = ???
+}
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-a/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-tparams-bounds-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..a82e813221
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-a/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo[U] = macro Impls.foo[U]
+}
+
+object Test extends App {
+ import Macros._
+ foo[Int]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-b.check b/test/files/neg/macro-invalidsig-tparams-bounds-b.check
new file mode 100644
index 0000000000..50f0944acc
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-b.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:2: error: type arguments [U] do not conform to method foo's type parameter bounds [U <: String]
+ def foo[U <: Int] = macro Impls.foo[U]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-b.flags b/test/files/neg/macro-invalidsig-tparams-bounds-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-b/Impls_1.scala b/test/files/neg/macro-invalidsig-tparams-bounds-b/Impls_1.scala
new file mode 100644
index 0000000000..88b85d48f4
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-b/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U <: String](c: Ctx) = ???
+}
diff --git a/test/files/neg/macro-invalidsig-tparams-bounds-b/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-tparams-bounds-b/Macros_Test_2.scala
new file mode 100644
index 0000000000..eed6369a16
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-bounds-b/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo[U <: Int] = macro Impls.foo[U]
+}
+
+object Test extends App {
+ import Macros._
+ foo[Int]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-a.check b/test/files/neg/macro-invalidsig-tparams-notparams-a.check
new file mode 100644
index 0000000000..5b4ef42ea5
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-a.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:2: error: macro implementation reference needs type arguments
+ def foo = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-a.flags b/test/files/neg/macro-invalidsig-tparams-notparams-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-a/Impls_1.scala b/test/files/neg/macro-invalidsig-tparams-notparams-a/Impls_1.scala
new file mode 100644
index 0000000000..bbe5b4e519
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-a/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U: c.TypeTag](c: Ctx) = ???
+}
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-a/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-tparams-notparams-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..96a8de2832
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-a/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-b.check b/test/files/neg/macro-invalidsig-tparams-notparams-b.check
new file mode 100644
index 0000000000..261e3b8293
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-b.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:3: error: macro implementation reference needs type arguments
+ def foo[V] = macro Impls.foo
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-b.flags b/test/files/neg/macro-invalidsig-tparams-notparams-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-b/Impls_1.scala b/test/files/neg/macro-invalidsig-tparams-notparams-b/Impls_1.scala
new file mode 100644
index 0000000000..db79ddbcd8
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-b/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T: c.TypeTag, U: c.TypeTag, V](c: Ctx)(implicit V: c.TypeTag[V]): c.Expr[Unit] = {
+ println(implicitly[c.TypeTag[T]])
+ println(implicitly[c.TypeTag[U]])
+ println(V)
+ c.literalUnit
+ }
+}
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-b/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-tparams-notparams-b/Macros_Test_2.scala
new file mode 100644
index 0000000000..7d02bf613a
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-b/Macros_Test_2.scala
@@ -0,0 +1,11 @@
+class D[T] {
+ class C[U] {
+ def foo[V] = macro Impls.foo
+ }
+}
+
+object Test extends App {
+ val outer1 = new D[Int]
+ val outer2 = new outer1.C[String]
+ outer2.foo[Boolean]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-c.check b/test/files/neg/macro-invalidsig-tparams-notparams-c.check
new file mode 100644
index 0000000000..b64a469cc3
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-c.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:3: error: wrong number of type parameters for method foo: [T, U, V](c: scala.reflect.makro.Context)(implicit evidence$1: c.TypeTag[T], implicit evidence$2: c.TypeTag[U], implicit V: c.TypeTag[V])c.Expr[Unit]
+ def foo[V] = macro Impls.foo[V]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-c.flags b/test/files/neg/macro-invalidsig-tparams-notparams-c.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-c.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-c/Impls_1.scala b/test/files/neg/macro-invalidsig-tparams-notparams-c/Impls_1.scala
new file mode 100644
index 0000000000..43c5a2acd5
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-c/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T: c.TypeTag, U: c.TypeTag, V](c: Ctx)(implicit V: c.TypeTag[V]): c.Expr[Unit] = {
+ import c.mirror._
+ println(implicitly[c.TypeTag[T]])
+ println(implicitly[c.TypeTag[U]])
+ println(V)
+ c.literalUnit
+ }
+}
diff --git a/test/files/neg/macro-invalidsig-tparams-notparams-c/Macros_Test_2.scala b/test/files/neg/macro-invalidsig-tparams-notparams-c/Macros_Test_2.scala
new file mode 100644
index 0000000000..109e142e52
--- /dev/null
+++ b/test/files/neg/macro-invalidsig-tparams-notparams-c/Macros_Test_2.scala
@@ -0,0 +1,11 @@
+class D[T] {
+ class C[U] {
+ def foo[V] = macro Impls.foo[V]
+ }
+}
+
+object Test extends App {
+ val outer1 = new D[Int]
+ val outer2 = new outer1.C[String]
+ outer2.foo[Boolean]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-badargs.check b/test/files/neg/macro-invalidusage-badargs.check
new file mode 100644
index 0000000000..52beda5b61
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badargs.check
@@ -0,0 +1,6 @@
+Macros_Test_2.scala:7: error: type mismatch;
+ found : String("42")
+ required: Int
+ val s: String = foo("42")
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidusage-badargs.flags b/test/files/neg/macro-invalidusage-badargs.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badargs.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-badargs/Impls_1.scala b/test/files/neg/macro-invalidusage-badargs/Impls_1.scala
new file mode 100644
index 0000000000..2346a6106d
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badargs/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = x
+}
diff --git a/test/files/neg/macro-invalidusage-badargs/Macros_Test_2.scala b/test/files/neg/macro-invalidusage-badargs/Macros_Test_2.scala
new file mode 100644
index 0000000000..a6af1bb277
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badargs/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ val s: String = foo("42")
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-badbounds.check b/test/files/neg/macro-invalidusage-badbounds.check
new file mode 100644
index 0000000000..fd0b64533e
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badbounds.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:7: error: type arguments [Int] do not conform to macro method foo's type parameter bounds [U <: String]
+ foo[Int]
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidusage-badbounds.flags b/test/files/neg/macro-invalidusage-badbounds.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badbounds.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-badbounds/Impls_1.scala b/test/files/neg/macro-invalidusage-badbounds/Impls_1.scala
new file mode 100644
index 0000000000..88b85d48f4
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badbounds/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U <: String](c: Ctx) = ???
+}
diff --git a/test/files/neg/macro-invalidusage-badbounds/Macros_Test_2.scala b/test/files/neg/macro-invalidusage-badbounds/Macros_Test_2.scala
new file mode 100644
index 0000000000..3139599108
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badbounds/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo[U <: String] = macro Impls.foo[U]
+}
+
+object Test extends App {
+ import Macros._
+ foo[Int]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-badtargs.check b/test/files/neg/macro-invalidusage-badtargs.check
new file mode 100644
index 0000000000..61ef6f5af7
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badtargs.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:7: error: macro method foo: (x: Int)Int does not take type parameters.
+ val s: String = foo[String](42)
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidusage-badtargs.flags b/test/files/neg/macro-invalidusage-badtargs.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badtargs.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-badtargs/Impls_1.scala b/test/files/neg/macro-invalidusage-badtargs/Impls_1.scala
new file mode 100644
index 0000000000..2346a6106d
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badtargs/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = x
+}
diff --git a/test/files/neg/macro-invalidusage-badtargs/Macros_Test_2.scala b/test/files/neg/macro-invalidusage-badtargs/Macros_Test_2.scala
new file mode 100644
index 0000000000..c54093b637
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-badtargs/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ val s: String = foo[String](42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-methodvaluesyntax.check b/test/files/neg/macro-invalidusage-methodvaluesyntax.check
new file mode 100644
index 0000000000..27b2023202
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-methodvaluesyntax.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:6: error: macros cannot be eta-expanded
+ val firstClassFoo = Macros.foo _
+ ^
+one error found
diff --git a/test/files/neg/macro-invalidusage-methodvaluesyntax.flags b/test/files/neg/macro-invalidusage-methodvaluesyntax.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-methodvaluesyntax.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-invalidusage-methodvaluesyntax/Impls_1.scala b/test/files/neg/macro-invalidusage-methodvaluesyntax/Impls_1.scala
new file mode 100644
index 0000000000..8e52613b6d
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-methodvaluesyntax/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/neg/macro-invalidusage-methodvaluesyntax/Macros_Test_2.scala b/test/files/neg/macro-invalidusage-methodvaluesyntax/Macros_Test_2.scala
new file mode 100644
index 0000000000..343cec99b5
--- /dev/null
+++ b/test/files/neg/macro-invalidusage-methodvaluesyntax/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ val firstClassFoo = Macros.foo _
+ firstClassFoo
+} \ No newline at end of file
diff --git a/test/files/neg/macro-noexpand.check b/test/files/neg/macro-noexpand.check
index c15d54bb32..c829bbab71 100644
--- a/test/files/neg/macro-noexpand.check
+++ b/test/files/neg/macro-noexpand.check
@@ -1,4 +1,4 @@
-Test_2.scala:3: error: not found: value x
+Macros_Test_2.scala:7: error: not found: value x
foo(x)
^
one error found
diff --git a/test/files/neg/macro-noexpand.flags b/test/files/neg/macro-noexpand.flags
index 7fea2ff901..cd66464f2f 100644
--- a/test/files/neg/macro-noexpand.flags
+++ b/test/files/neg/macro-noexpand.flags
@@ -1 +1 @@
--Xmacros \ No newline at end of file
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-noexpand/Impls_1.scala b/test/files/neg/macro-noexpand/Impls_1.scala
new file mode 100644
index 0000000000..7b1620d117
--- /dev/null
+++ b/test/files/neg/macro-noexpand/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-noexpand/Macros_1.scala b/test/files/neg/macro-noexpand/Macros_1.scala
deleted file mode 100644
index 7a6aadf6a1..0000000000
--- a/test/files/neg/macro-noexpand/Macros_1.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-object Macros {
- def macro foo(x: Any) = ???
-} \ No newline at end of file
diff --git a/test/files/neg/macro-noexpand/Macros_Test_2.scala b/test/files/neg/macro-noexpand/Macros_Test_2.scala
new file mode 100644
index 0000000000..e783e2b53e
--- /dev/null
+++ b/test/files/neg/macro-noexpand/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Any) = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo(x)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-noncompilertree.flags b/test/files/neg/macro-noncompilertree.flags
index 7fea2ff901..cd66464f2f 100644
--- a/test/files/neg/macro-noncompilertree.flags
+++ b/test/files/neg/macro-noncompilertree.flags
@@ -1 +1 @@
--Xmacros \ No newline at end of file
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-noncompilertree/Macros_1.scala b/test/files/neg/macro-noncompilertree/Macros_1.scala
deleted file mode 100644
index eb1253e5e9..0000000000
--- a/test/files/neg/macro-noncompilertree/Macros_1.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-object Macros {
- def macro foo = scala.reflect.mirror.Literal(scala.reflect.mirror.Constant(2))
-} \ No newline at end of file
diff --git a/test/files/neg/macro-nontree.flags b/test/files/neg/macro-nontree.flags
index 7fea2ff901..cd66464f2f 100644
--- a/test/files/neg/macro-nontree.flags
+++ b/test/files/neg/macro-nontree.flags
@@ -1 +1 @@
--Xmacros \ No newline at end of file
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-nontree/Macros_1.scala b/test/files/neg/macro-nontree/Macros_1.scala
deleted file mode 100644
index 2433974a85..0000000000
--- a/test/files/neg/macro-nontree/Macros_1.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-object Macros {
- def macro foo = 2
-} \ No newline at end of file
diff --git a/test/files/neg/macro-nontypeablebody.check b/test/files/neg/macro-nontypeablebody.check
new file mode 100644
index 0000000000..0cfc864df8
--- /dev/null
+++ b/test/files/neg/macro-nontypeablebody.check
@@ -0,0 +1,4 @@
+Macros_Test_2.scala:2: error: value foo2 is not a member of object Impls
+ def foo(x: Any) = macro Impls.foo2
+ ^
+one error found
diff --git a/test/files/neg/macro-nontypeablebody.flags b/test/files/neg/macro-nontypeablebody.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-nontypeablebody.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-nontypeablebody/Impls_1.scala b/test/files/neg/macro-nontypeablebody/Impls_1.scala
new file mode 100644
index 0000000000..7b1620d117
--- /dev/null
+++ b/test/files/neg/macro-nontypeablebody/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = ???
+}
diff --git a/test/files/neg/macro-nontypeablebody/Macros_Test_2.scala b/test/files/neg/macro-nontypeablebody/Macros_Test_2.scala
new file mode 100644
index 0000000000..2031893970
--- /dev/null
+++ b/test/files/neg/macro-nontypeablebody/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(x: Any) = macro Impls.foo2
+}
+
+object Test extends App {
+ import Macros._
+ foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-a.check b/test/files/neg/macro-override-macro-overrides-abstract-method-a.check
new file mode 100644
index 0000000000..4d95dfc45c
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-a.check
@@ -0,0 +1,5 @@
+Impls_Macros_1.scala:12: error: overriding method foo in trait Foo of type (x: Int)Int;
+ macro method foo cannot override an abstract method
+ def foo(x: Int) = macro Impls.impl
+ ^
+one error found
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-a.flags b/test/files/neg/macro-override-macro-overrides-abstract-method-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-a/Impls_Macros_1.scala b/test/files/neg/macro-override-macro-overrides-abstract-method-a/Impls_Macros_1.scala
new file mode 100644
index 0000000000..cb0b152852
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-a/Impls_Macros_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def impl(c: Ctx)(x: c.Expr[Int]) = x
+}
+
+trait Foo {
+ def foo(x: Int): Int
+}
+
+object Macros extends Foo {
+ def foo(x: Int) = macro Impls.impl
+}
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-a/Test_2.scala b/test/files/neg/macro-override-macro-overrides-abstract-method-a/Test_2.scala
new file mode 100644
index 0000000000..7e3357ec28
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-a/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ val designator: Macros.type = Macros
+ designator.foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-b.check b/test/files/neg/macro-override-macro-overrides-abstract-method-b.check
new file mode 100644
index 0000000000..4d95dfc45c
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-b.check
@@ -0,0 +1,5 @@
+Impls_Macros_1.scala:12: error: overriding method foo in trait Foo of type (x: Int)Int;
+ macro method foo cannot override an abstract method
+ def foo(x: Int) = macro Impls.impl
+ ^
+one error found
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-b.flags b/test/files/neg/macro-override-macro-overrides-abstract-method-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala
new file mode 100644
index 0000000000..cb0b152852
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def impl(c: Ctx)(x: c.Expr[Int]) = x
+}
+
+trait Foo {
+ def foo(x: Int): Int
+}
+
+object Macros extends Foo {
+ def foo(x: Int) = macro Impls.impl
+}
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala
new file mode 100644
index 0000000000..08fff30baf
--- /dev/null
+++ b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ val designator: Foo = Macros
+ designator.foo(42)
+} \ No newline at end of file
diff --git a/test/files/neg/macro-override-method-overrides-macro.check b/test/files/neg/macro-override-method-overrides-macro.check
new file mode 100644
index 0000000000..42edb0ff23
--- /dev/null
+++ b/test/files/neg/macro-override-method-overrides-macro.check
@@ -0,0 +1,5 @@
+Macros_Test_2.scala:8: error: overriding macro method foo in class B of type (x: String)Unit;
+ method foo cannot override a macro
+ override def foo(x: String) = println("fooDString")
+ ^
+one error found
diff --git a/test/files/neg/macro-override-method-overrides-macro.flags b/test/files/neg/macro-override-method-overrides-macro.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/macro-override-method-overrides-macro.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/macro-override-method-overrides-macro/Impls_1.scala b/test/files/neg/macro-override-method-overrides-macro/Impls_1.scala
new file mode 100644
index 0000000000..0b127f5a59
--- /dev/null
+++ b/test/files/neg/macro-override-method-overrides-macro/Impls_1.scala
@@ -0,0 +1,15 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def impl(c: Ctx)(tag: String, x: c.Expr[_]) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(tag)), Literal(Constant(prefix.toString)), x.tree))
+ Expr[Unit](body)
+ }
+
+ def fooBString(c: Ctx)(x: c.Expr[_]) = impl(c)("fooBString", x)
+ def fooBInt(c: Ctx)(x: c.Expr[_]) = impl(c)("fooBInt", x)
+ def fooDInt(c: Ctx)(x: c.Expr[_]) = impl(c)("fooDInt", x)
+ def fooZString(c: Ctx)(x: c.Expr[_]) = impl(c)("fooZString", x)
+}
diff --git a/test/files/neg/macro-override-method-overrides-macro/Macros_Test_2.scala b/test/files/neg/macro-override-method-overrides-macro/Macros_Test_2.scala
new file mode 100644
index 0000000000..36821b05d8
--- /dev/null
+++ b/test/files/neg/macro-override-method-overrides-macro/Macros_Test_2.scala
@@ -0,0 +1,15 @@
+class B {
+ def foo(x: String) = macro Impls.fooBString
+ def foo(x: Int) = macro Impls.fooBInt
+ def foo(x: Boolean) = println("fooBBoolean")
+}
+
+class D extends B {
+ override def foo(x: String) = println("fooDString")
+ override def foo(x: Int) = macro Impls.fooDInt
+}
+
+class Z extends D {
+ override def foo(x: String) = macro Impls.fooZString
+ override def foo(x: Boolean) = println("fooZBoolean")
+}
diff --git a/test/files/neg/macro-reify-groundtypetag-hktypeparams-notags.check b/test/files/neg/macro-reify-groundtypetag-hktypeparams-notags.check
new file mode 100644
index 0000000000..39e90f827e
--- /dev/null
+++ b/test/files/neg/macro-reify-groundtypetag-hktypeparams-notags.check
@@ -0,0 +1,7 @@
+Test.scala:5: error: No ConcreteTypeTag available for C[T]
+ println(implicitly[ConcreteTypeTag[C[T]]])
+ ^
+Test.scala:6: error: No ConcreteTypeTag available for List[C[T]]
+ println(implicitly[ConcreteTypeTag[List[C[T]]]])
+ ^
+two errors found
diff --git a/test/files/neg/macro-reify-groundtypetag-hktypeparams-notags/Test.scala b/test/files/neg/macro-reify-groundtypetag-hktypeparams-notags/Test.scala
new file mode 100644
index 0000000000..1302999da6
--- /dev/null
+++ b/test/files/neg/macro-reify-groundtypetag-hktypeparams-notags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooNoTypeTagHK[C[_], T] = {
+ println(implicitly[ConcreteTypeTag[C[T]]])
+ println(implicitly[ConcreteTypeTag[List[C[T]]]])
+ }
+ fooNoTypeTagHK[List, Int]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-reify-groundtypetag-typeparams-notags.check b/test/files/neg/macro-reify-groundtypetag-typeparams-notags.check
new file mode 100644
index 0000000000..164ca3543f
--- /dev/null
+++ b/test/files/neg/macro-reify-groundtypetag-typeparams-notags.check
@@ -0,0 +1,7 @@
+Test.scala:5: error: No ConcreteTypeTag available for T
+ println(implicitly[ConcreteTypeTag[T]])
+ ^
+Test.scala:6: error: No ConcreteTypeTag available for List[T]
+ println(implicitly[ConcreteTypeTag[List[T]]])
+ ^
+two errors found
diff --git a/test/files/neg/macro-reify-groundtypetag-typeparams-notags/Test.scala b/test/files/neg/macro-reify-groundtypetag-typeparams-notags/Test.scala
new file mode 100644
index 0000000000..d2276ce333
--- /dev/null
+++ b/test/files/neg/macro-reify-groundtypetag-typeparams-notags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooNoTypeTag[T] = {
+ println(implicitly[ConcreteTypeTag[T]])
+ println(implicitly[ConcreteTypeTag[List[T]]])
+ }
+ fooNoTypeTag[Int]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-reify-groundtypetag-usetypetag.check b/test/files/neg/macro-reify-groundtypetag-usetypetag.check
new file mode 100644
index 0000000000..164ca3543f
--- /dev/null
+++ b/test/files/neg/macro-reify-groundtypetag-usetypetag.check
@@ -0,0 +1,7 @@
+Test.scala:5: error: No ConcreteTypeTag available for T
+ println(implicitly[ConcreteTypeTag[T]])
+ ^
+Test.scala:6: error: No ConcreteTypeTag available for List[T]
+ println(implicitly[ConcreteTypeTag[List[T]]])
+ ^
+two errors found
diff --git a/test/files/neg/macro-reify-groundtypetag-usetypetag/Test.scala b/test/files/neg/macro-reify-groundtypetag-usetypetag/Test.scala
new file mode 100644
index 0000000000..d82cdc33e9
--- /dev/null
+++ b/test/files/neg/macro-reify-groundtypetag-usetypetag/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooTypeTag[T: TypeTag] = {
+ println(implicitly[ConcreteTypeTag[T]])
+ println(implicitly[ConcreteTypeTag[List[T]]])
+ }
+ fooTypeTag[Int]
+} \ No newline at end of file
diff --git a/test/files/neg/macro-without-xmacros-a.check b/test/files/neg/macro-without-xmacros-a.check
new file mode 100644
index 0000000000..fd2667dbb8
--- /dev/null
+++ b/test/files/neg/macro-without-xmacros-a.check
@@ -0,0 +1,17 @@
+Macros_2.scala:5: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+This can be achieved by adding the import clause 'import language.experimental.macros'
+or by setting the compiler option -language:experimental.macros.
+See the Scala docs for value scala.language.experimental.macros for a discussion
+why the feature needs to be explicitly enabled.
+ def foo(x: Int): Int = macro foo_impl
+ ^
+Macros_2.scala:7: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def bar(x: Int): Int = macro bar_impl
+ ^
+Macros_2.scala:11: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def quux(x: Int): Int = macro quux_impl
+ ^
+three errors found
diff --git a/test/files/neg/macro-without-xmacros-a/Impls_1.scala b/test/files/neg/macro-without-xmacros-a/Impls_1.scala
new file mode 100644
index 0000000000..e6cee46e85
--- /dev/null
+++ b/test/files/neg/macro-without-xmacros-a/Impls_1.scala
@@ -0,0 +1,18 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1)))))
+ }
+
+ def bar_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2)))))
+ }
+
+ def quux_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3)))))
+ }
+}
diff --git a/test/files/neg/macro-without-xmacros-a/Macros_2.scala b/test/files/neg/macro-without-xmacros-a/Macros_2.scala
new file mode 100644
index 0000000000..62f9dcf505
--- /dev/null
+++ b/test/files/neg/macro-without-xmacros-a/Macros_2.scala
@@ -0,0 +1,12 @@
+import Impls._
+
+object Macros {
+ object Shmacros {
+ def foo(x: Int): Int = macro foo_impl
+ }
+ def bar(x: Int): Int = macro bar_impl
+}
+
+class Macros {
+ def quux(x: Int): Int = macro quux_impl
+} \ No newline at end of file
diff --git a/test/files/run/macro-basic/Test_2.scala b/test/files/neg/macro-without-xmacros-a/Test_3.scala
index e9a10e20c9..e9a10e20c9 100644
--- a/test/files/run/macro-basic/Test_2.scala
+++ b/test/files/neg/macro-without-xmacros-a/Test_3.scala
diff --git a/test/files/neg/macro-without-xmacros-b.check b/test/files/neg/macro-without-xmacros-b.check
new file mode 100644
index 0000000000..2d675b8319
--- /dev/null
+++ b/test/files/neg/macro-without-xmacros-b.check
@@ -0,0 +1,17 @@
+Macros_2.scala:3: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+This can be achieved by adding the import clause 'import language.experimental.macros'
+or by setting the compiler option -language:experimental.macros.
+See the Scala docs for value scala.language.experimental.macros for a discussion
+why the feature needs to be explicitly enabled.
+ def foo(x: Int): Int = macro Impls.foo_impl
+ ^
+Macros_2.scala:5: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def bar(x: Int): Int = macro Impls.bar_impl
+ ^
+Macros_2.scala:9: error: macro definition needs to be enabled
+by making the implicit value language.experimental.macros visible.
+ def quux(x: Int): Int = macro Impls.quux_impl
+ ^
+three errors found
diff --git a/test/files/neg/macro-without-xmacros-b/Impls_1.scala b/test/files/neg/macro-without-xmacros-b/Impls_1.scala
new file mode 100644
index 0000000000..e6cee46e85
--- /dev/null
+++ b/test/files/neg/macro-without-xmacros-b/Impls_1.scala
@@ -0,0 +1,18 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1)))))
+ }
+
+ def bar_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2)))))
+ }
+
+ def quux_impl(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3)))))
+ }
+}
diff --git a/test/files/neg/macro-without-xmacros-b/Macros_2.scala b/test/files/neg/macro-without-xmacros-b/Macros_2.scala
new file mode 100644
index 0000000000..de7080c7e8
--- /dev/null
+++ b/test/files/neg/macro-without-xmacros-b/Macros_2.scala
@@ -0,0 +1,10 @@
+object Macros {
+ object Shmacros {
+ def foo(x: Int): Int = macro Impls.foo_impl
+ }
+ def bar(x: Int): Int = macro Impls.bar_impl
+}
+
+class Macros {
+ def quux(x: Int): Int = macro Impls.quux_impl
+} \ No newline at end of file
diff --git a/test/files/neg/macro-without-xmacros-b/Test_3.scala b/test/files/neg/macro-without-xmacros-b/Test_3.scala
new file mode 100644
index 0000000000..e9a10e20c9
--- /dev/null
+++ b/test/files/neg/macro-without-xmacros-b/Test_3.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros.Shmacros._
+ println(foo(2) + Macros.bar(2) * new Macros().quux(4))
+} \ No newline at end of file
diff --git a/test/files/neg/overloaded-unapply.check b/test/files/neg/overloaded-unapply.check
index 1da93f6939..68a826bac2 100644
--- a/test/files/neg/overloaded-unapply.check
+++ b/test/files/neg/overloaded-unapply.check
@@ -7,7 +7,8 @@ match argument types (List[a])
overloaded-unapply.scala:22: error: cannot resolve overloaded unapply
case List(x, xs) => 7
^
-overloaded-unapply.scala:12: error: method unapply is defined twice in overloaded-unapply.scala
+overloaded-unapply.scala:12: error: method unapply is defined twice
+ conflicting symbols both originated in file 'overloaded-unapply.scala'
def unapply[a](xs: List[a]): Option[Null] = xs match {
^
three errors found
diff --git a/test/files/neg/override.check b/test/files/neg/override.check
index 0336fb2b11..fc152cb3b1 100644
--- a/test/files/neg/override.check
+++ b/test/files/neg/override.check
@@ -1,5 +1,5 @@
override.scala:9: error: overriding type T in trait A with bounds >: Int <: Int;
type T in trait B with bounds >: String <: String has incompatible type
lazy val x : A with B = x
- ^
+ ^
one error found
diff --git a/test/files/neg/package-ob-case.flags b/test/files/neg/package-ob-case.flags
index e8fb65d50c..6c1dd108ae 100644
--- a/test/files/neg/package-ob-case.flags
+++ b/test/files/neg/package-ob-case.flags
@@ -1 +1 @@
--Xfatal-warnings \ No newline at end of file
+-Xfatal-warnings -Xlint \ No newline at end of file
diff --git a/test/files/neg/pat_unreachable.flags b/test/files/neg/pat_unreachable.flags
new file mode 100644
index 0000000000..ba80cad69b
--- /dev/null
+++ b/test/files/neg/pat_unreachable.flags
@@ -0,0 +1 @@
+-Xoldpatmat
diff --git a/test/files/neg/patmatexhaust.flags b/test/files/neg/patmatexhaust.flags
index e8fb65d50c..b7eb21d5f5 100644
--- a/test/files/neg/patmatexhaust.flags
+++ b/test/files/neg/patmatexhaust.flags
@@ -1 +1 @@
--Xfatal-warnings \ No newline at end of file
+-Xfatal-warnings -Xoldpatmat
diff --git a/test/files/neg/primitive-sigs-1.check b/test/files/neg/primitive-sigs-1.check
index 8713d95cc3..77dc457a49 100644
--- a/test/files/neg/primitive-sigs-1.check
+++ b/test/files/neg/primitive-sigs-1.check
@@ -1,6 +1,6 @@
-A_3.scala:3: error: type mismatch;
+B.scala:3: error: type mismatch;
found : Bippy
required: AC[Integer]
- J_2.f(new Bippy())
- ^
+ J.f(new Bippy())
+ ^
one error found
diff --git a/test/files/neg/primitive-sigs-1/A_1.scala b/test/files/neg/primitive-sigs-1/A.scala
index 0dd83b5d6a..0dd83b5d6a 100644
--- a/test/files/neg/primitive-sigs-1/A_1.scala
+++ b/test/files/neg/primitive-sigs-1/A.scala
diff --git a/test/files/neg/primitive-sigs-1/A_3.scala b/test/files/neg/primitive-sigs-1/B.scala
index dec617a111..0958bcda57 100644
--- a/test/files/neg/primitive-sigs-1/A_3.scala
+++ b/test/files/neg/primitive-sigs-1/B.scala
@@ -1,5 +1,5 @@
object Test {
def main(args: Array[String]): Unit = {
- J_2.f(new Bippy())
+ J.f(new Bippy())
}
}
diff --git a/test/files/neg/primitive-sigs-1/J_2.java b/test/files/neg/primitive-sigs-1/J.java
index b416befb4d..2e43b8330c 100644
--- a/test/files/neg/primitive-sigs-1/J_2.java
+++ b/test/files/neg/primitive-sigs-1/J.java
@@ -1,6 +1,6 @@
// java: often the java or scala compiler will save us from
// the untruth in the signature, but not always.
-public class J_2 {
+public class J {
public static Integer f(AC<Integer> x) { return x.f(); }
public static void main(String[] args) {
f(new Bippy());
diff --git a/test/files/neg/reify_ann2a.check b/test/files/neg/reify_ann2a.check
deleted file mode 100644
index 2afe37e1d8..0000000000
--- a/test/files/neg/reify_ann2a.check
+++ /dev/null
@@ -1,4 +0,0 @@
-reify_ann2a.scala:9: error: exception during macro expansion: implementation restriction: cannot reify annotation @ann(immutable.this.List.apply[String]("1a")) which involves a symbol declared inside the block being reified
- val tree = scala.reflect.Code.lift{
- ^
-one error found
diff --git a/test/files/neg/reify_ann2b.check b/test/files/neg/reify_ann2b.check
index ceb70689f1..52bdbe5b7c 100644
--- a/test/files/neg/reify_ann2b.check
+++ b/test/files/neg/reify_ann2b.check
@@ -1,7 +1,4 @@
-reify_ann2b.scala:10: error: inner classes cannot be classfile annotations
- class ann(bar: String) extends ClassfileAnnotation
+reify_ann2b.scala:6: error: inner classes cannot be classfile annotations
+ class ann(bar: String) extends annotation.ClassfileAnnotation
^
-reify_ann2b.scala:9: error: exception during macro expansion: implementation restriction: cannot reify annotation @ann(bar = "1a") which involves a symbol declared inside the block being reified
- val tree = scala.reflect.Code.lift{
- ^
-two errors found
+one error found
diff --git a/test/files/neg/reify_ann2b.scala b/test/files/neg/reify_ann2b.scala
index b43567c2a7..397d00210d 100644
--- a/test/files/neg/reify_ann2b.scala
+++ b/test/files/neg/reify_ann2b.scala
@@ -1,13 +1,9 @@
-import scala.reflect._
-import scala.reflect.api._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
// test 1: reify
- val tree = scala.reflect.Code.lift{
- class ann(bar: String) extends ClassfileAnnotation
+ val tree = reify{
+ class ann(bar: String) extends annotation.ClassfileAnnotation
@ann(bar="1a") @ann(bar="1b") class C[@ann(bar="2a") @ann(bar="2b") T](@ann(bar="3a") @ann(bar="3b") x: T @ann(bar="4a") @ann(bar="4b")) {
@ann(bar="5a") @ann(bar="5b") def f(x: Int @ann(bar="6a") @ann(bar="6b")) = {
@@ -20,8 +16,7 @@ object Test extends App {
println(tree.toString)
// test 2: import and typecheck
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val ttree = toolbox.typeCheck(tree)
println(ttree.toString)
diff --git a/test/files/neg/sealed-java-enums.flags b/test/files/neg/sealed-java-enums.flags
index e709c65918..312f3a87ec 100644
--- a/test/files/neg/sealed-java-enums.flags
+++ b/test/files/neg/sealed-java-enums.flags
@@ -1 +1 @@
--Xexperimental -Xfatal-warnings
+-Xexperimental -Xfatal-warnings -Xoldpatmat
diff --git a/test/files/neg/switch.flags b/test/files/neg/switch.flags
new file mode 100644
index 0000000000..809e9ff2f2
--- /dev/null
+++ b/test/files/neg/switch.flags
@@ -0,0 +1 @@
+ -Xoldpatmat
diff --git a/test/files/neg/t1878-typer.check b/test/files/neg/t1878-typer.check
new file mode 100644
index 0000000000..e3a20d0be7
--- /dev/null
+++ b/test/files/neg/t1878-typer.check
@@ -0,0 +1,4 @@
+t1878-typer.scala:4: error: _* may only come last
+ case <p> { _* } </p> =>
+ ^
+one error found
diff --git a/test/files/neg/t1878-typer.scala b/test/files/neg/t1878-typer.scala
new file mode 100644
index 0000000000..1eb0cb7dff
--- /dev/null
+++ b/test/files/neg/t1878-typer.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ // illegal - bug #1764
+ null match {
+ case <p> { _* } </p> =>
+ }
+}
diff --git a/test/files/neg/t1878.check b/test/files/neg/t1878.check
index 128741a022..ac2071c3d8 100644
--- a/test/files/neg/t1878.check
+++ b/test/files/neg/t1878.check
@@ -1,18 +1,7 @@
-t1878.scala:3: error: _* may only come last
+t1878.scala:3: error: bad use of _* (a sequence pattern must be the last pattern)
val err1 = "" match { case Seq(f @ _*, ',') => f }
- ^
-t1878.scala:3: error: scrutinee is incompatible with pattern type;
- found : Seq[A]
- required: String
- val err1 = "" match { case Seq(f @ _*, ',') => f }
- ^
-t1878.scala:3: error: not found: value f
- val err1 = "" match { case Seq(f @ _*, ',') => f }
- ^
-t1878.scala:9: error: _* may only come last
+ ^
+t1878.scala:9: error: bad use of _* (a sequence pattern must be the last pattern)
val List(List(_*, arg2), _) = List(List(1,2,3), List(4,5,6))
- ^
-t1878.scala:13: error: _* may only come last
- case <p> { _* } </p> =>
- ^
-5 errors found
+ ^
+two errors found
diff --git a/test/files/neg/t1878.scala b/test/files/neg/t1878.scala
index 5278fbb7bd..99fee48a96 100644
--- a/test/files/neg/t1878.scala
+++ b/test/files/neg/t1878.scala
@@ -8,8 +8,10 @@ object Test extends App {
// illegal
val List(List(_*, arg2), _) = List(List(1,2,3), List(4,5,6))
+ /* see t1878-typer.scala
// illegal - bug #1764
null match {
case <p> { _* } </p> =>
}
+ */
}
diff --git a/test/files/neg/t200.check b/test/files/neg/t200.check
index 3ef6665fe5..b6b1a32267 100644
--- a/test/files/neg/t200.check
+++ b/test/files/neg/t200.check
@@ -1,4 +1,5 @@
-t200.scala:7: error: method foo is defined twice in t200.scala
+t200.scala:7: error: method foo is defined twice
+ conflicting symbols both originated in file 't200.scala'
def foo: Int;
^
one error found
diff --git a/test/files/neg/t2386.check b/test/files/neg/t2386.check
deleted file mode 100644
index 1a01696a9a..0000000000
--- a/test/files/neg/t2386.check
+++ /dev/null
@@ -1,4 +0,0 @@
-t2386.scala:2: error: could not find implicit value for evidence parameter of type scala.reflect.ClassManifest[Array[_ >: String with Int]]
- val a = Array(Array(1, 2), Array("a","b"))
- ^
-one error found
diff --git a/test/files/neg/t2386.scala b/test/files/neg/t2386.scala
deleted file mode 100644
index 56146cc5c3..0000000000
--- a/test/files/neg/t2386.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-object Test {
- val a = Array(Array(1, 2), Array("a","b"))
-}
diff --git a/test/files/neg/t2775.check b/test/files/neg/t2775.check
index a30d35fdd9..a1e950cf73 100644
--- a/test/files/neg/t2775.check
+++ b/test/files/neg/t2775.check
@@ -1,4 +1,4 @@
-t2775.scala:1: error: cannot find class manifest for element type B.this.T
+t2775.scala:1: error: cannot find array tag for element type B.this.T
trait B[S] { type T = S; val c = new Array[T](1) }
^
one error found
diff --git a/test/files/neg/t2779.check b/test/files/neg/t2779.check
index d642541e3e..0ab4c50d0f 100644
--- a/test/files/neg/t2779.check
+++ b/test/files/neg/t2779.check
@@ -1,4 +1,5 @@
-t2779.scala:16: error: method f is defined twice in t2779.scala
+t2779.scala:16: error: method f is defined twice
+ conflicting symbols both originated in file 't2779.scala'
override def f = List(M1)
^
one error found
diff --git a/test/files/neg/t278.check b/test/files/neg/t278.check
index 0c2dfeb67a..405f7d225c 100644
--- a/test/files/neg/t278.check
+++ b/test/files/neg/t278.check
@@ -4,7 +4,8 @@ t278.scala:5: error: overloaded method value a with alternatives:
does not take type parameters
println(a[A])
^
-t278.scala:4: error: method a is defined twice in t278.scala
+t278.scala:4: error: method a is defined twice
+ conflicting symbols both originated in file 't278.scala'
def a = (p:A) => ()
^
two errors found
diff --git a/test/files/neg/t3098.flags b/test/files/neg/t3098.flags
index e8fb65d50c..b7eb21d5f5 100644
--- a/test/files/neg/t3098.flags
+++ b/test/files/neg/t3098.flags
@@ -1 +1 @@
--Xfatal-warnings \ No newline at end of file
+-Xfatal-warnings -Xoldpatmat
diff --git a/test/files/neg/t3189.check b/test/files/neg/t3189.check
new file mode 100644
index 0000000000..3913c526a2
--- /dev/null
+++ b/test/files/neg/t3189.check
@@ -0,0 +1,4 @@
+t3189.scala:2: error: use _* to match a sequence
+ val Array(a,b*) = ("": Any)
+ ^
+one error found
diff --git a/test/pending/neg/t3189.scala b/test/files/neg/t3189.scala
index 4ea4bb7581..4ea4bb7581 100644
--- a/test/pending/neg/t3189.scala
+++ b/test/files/neg/t3189.scala
diff --git a/test/files/neg/t3507.check b/test/files/neg/t3507-old.check
index 8e538e4a8b..5c58444cb3 100644
--- a/test/files/neg/t3507.check
+++ b/test/files/neg/t3507-old.check
@@ -1,4 +1,4 @@
-t3507.scala:13: error: No Manifest available for _1.b.c.type.
- mani/*[object _1.b.c]*/(c) // kaboom in manifestOfType / TreeGen.mkAttributedQualifier
- ^
-one error found
+t3507-old.scala:13: error: No Manifest available for _1.b.c.type.
+ mani/*[object _1.b.c]*/(c) // kaboom in manifestOfType / TreeGen.mkAttributedQualifier
+ ^
+one error found
diff --git a/test/files/neg/t3507.scala b/test/files/neg/t3507-old.scala
index 32688d3934..32688d3934 100644
--- a/test/files/neg/t3507.scala
+++ b/test/files/neg/t3507-old.scala
diff --git a/test/files/neg/t3683a.flags b/test/files/neg/t3683a.flags
index 85d8eb2ba2..b7eb21d5f5 100644
--- a/test/files/neg/t3683a.flags
+++ b/test/files/neg/t3683a.flags
@@ -1 +1 @@
--Xfatal-warnings
+-Xfatal-warnings -Xoldpatmat
diff --git a/test/files/neg/t3692.check b/test/files/neg/t3692-new.check
index 96ddd2a461..e013daca74 100644
--- a/test/files/neg/t3692.check
+++ b/test/files/neg/t3692-new.check
@@ -1,4 +1,4 @@
-t3692.scala:15: error: unreachable code
- case m2: Map[T, Int] => new java.util.HashMap[T, Integer]
- ^
-one error found
+t3692-new.scala:15: error: unreachable code
+ case m2: Map[T, Int] => new java.util.HashMap[T, Integer]
+ ^
+one error found
diff --git a/test/files/neg/t3692-new.flags b/test/files/neg/t3692-new.flags
new file mode 100644
index 0000000000..82becdfbfd
--- /dev/null
+++ b/test/files/neg/t3692-new.flags
@@ -0,0 +1 @@
+ -Xoldpatmat \ No newline at end of file
diff --git a/test/files/neg/t3692-new.scala b/test/files/neg/t3692-new.scala
new file mode 100644
index 0000000000..46874b02e3
--- /dev/null
+++ b/test/files/neg/t3692-new.scala
@@ -0,0 +1,19 @@
+import java.lang.Integer
+
+object Tester {
+ def main(args: Array[String]) = {
+ val map = Map("John" -> 1, "Josh" -> 2)
+ new Tester().toJavaMap(map)
+ }
+}
+
+class Tester {
+ private final def toJavaMap[T, V](map: Map[T, V])(implicit m1: ClassTag[T], m2: ClassTag[V]): java.util.Map[_, _] = {
+ map match {
+ case m0: Map[Int, Int] => new java.util.HashMap[Integer, Integer]
+ case m1: Map[Int, V] => new java.util.HashMap[Integer, V]
+ case m2: Map[T, Int] => new java.util.HashMap[T, Integer]
+ case _ => new java.util.HashMap[T, V]
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/neg/t3692-old.check b/test/files/neg/t3692-old.check
new file mode 100644
index 0000000000..9da7033239
--- /dev/null
+++ b/test/files/neg/t3692-old.check
@@ -0,0 +1,8 @@
+t3692-old.scala:6: warning: object Manifest in package reflect is deprecated: Use `@scala.reflect.ConcreteTypeTag` instead
+ new ManifestTester().toJavaMap(map)
+ ^
+t3692-old.scala:15: error: unreachable code
+ case m2: Map[T, Int] => new java.util.HashMap[T, Integer]
+ ^
+one warning found
+one error found
diff --git a/test/files/neg/t3692-old.flags b/test/files/neg/t3692-old.flags
new file mode 100644
index 0000000000..82becdfbfd
--- /dev/null
+++ b/test/files/neg/t3692-old.flags
@@ -0,0 +1 @@
+ -Xoldpatmat \ No newline at end of file
diff --git a/test/files/neg/t3692.scala b/test/files/neg/t3692-old.scala
index 151535ae94..151535ae94 100644
--- a/test/files/neg/t3692.scala
+++ b/test/files/neg/t3692-old.scala
diff --git a/test/files/neg/t3816.check b/test/files/neg/t3816.check
index 3658e76b64..40621f8962 100644
--- a/test/files/neg/t3816.check
+++ b/test/files/neg/t3816.check
@@ -1,4 +1,4 @@
-t3816.scala:30: error: stable identifier required, but syncID found.
+t3816.scala:30: error: stable identifier required, but `syncID` found.
case Some( `syncID` ) =>
^
t3816.scala:38: error: stable identifier required, but Test.this.foo found.
diff --git a/test/files/neg/t4134.check b/test/files/neg/t4134.check
new file mode 100644
index 0000000000..35a1820b0a
--- /dev/null
+++ b/test/files/neg/t4134.check
@@ -0,0 +1,4 @@
+t4134.scala:22: error: Member method f of mixin trait T2 is missing a concrete super implementation.
+class Konkret extends T3
+ ^
+one error found
diff --git a/test/files/neg/t4134.scala b/test/files/neg/t4134.scala
new file mode 100644
index 0000000000..678e4806ef
--- /dev/null
+++ b/test/files/neg/t4134.scala
@@ -0,0 +1,30 @@
+
+
+
+trait T1 {
+ def f: String
+}
+
+trait T2 extends T1 {
+ abstract override def f: String = "goo"
+ def something = super.f // So the "abstract override" is needed
+}
+
+trait Q1 {
+ def f: String = "bippy"
+}
+
+//trait T3 extends Q1 with T2 {
+trait T3 extends T2 with Q1 {
+ abstract override def f: String = super[Q1].f + " " + super[T2].f + " hoo"
+}
+
+class Konkret extends T3
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val k = new Konkret
+ println(k.f)
+ println(k.something)
+ }
+}
diff --git a/test/files/neg/t4425.check b/test/files/neg/t4425.check
index 4ff4b1eec0..0f2fe6f2d1 100644
--- a/test/files/neg/t4425.check
+++ b/test/files/neg/t4425.check
@@ -1,4 +1,4 @@
-t4425.scala:3: error: erroneous or inaccessible type
+t4425.scala:3: error: isInstanceOf cannot test if value types are references.
42 match { case _ X _ => () }
^
one error found
diff --git a/test/files/neg/t4568.check b/test/files/neg/t4568.check
new file mode 100644
index 0000000000..f94d699486
--- /dev/null
+++ b/test/files/neg/t4568.check
@@ -0,0 +1,4 @@
+t4568.scala:8: error: recursive method isSubListOf needs result type
+ case h :: t => y.contains(h) && (t.isSubListOf(y.drop(y.indexOf(h) + 1)))
+ ^
+one error found
diff --git a/test/files/neg/t4568.scala b/test/files/neg/t4568.scala
new file mode 100644
index 0000000000..8067759262
--- /dev/null
+++ b/test/files/neg/t4568.scala
@@ -0,0 +1,13 @@
+object SubList {
+ implicit def sublistable[A](x: List[A]) = new SubListable(x)
+
+ class SubListable[A](x: List[A]) {
+ def isSubListOf(y: List[A]) = {
+ x match {
+ case Nil => true
+ case h :: t => y.contains(h) && (t.isSubListOf(y.drop(y.indexOf(h) + 1)))
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/test/files/neg/t5106.check b/test/files/neg/t5106.check
new file mode 100644
index 0000000000..ac16041cf7
--- /dev/null
+++ b/test/files/neg/t5106.check
@@ -0,0 +1,11 @@
+t5106.scala:3: error: type mismatch;
+ found : Int(4)
+ required: String
+ val (n, l): (String, Int) = (4, "")
+ ^
+t5106.scala:3: error: type mismatch;
+ found : String("")
+ required: Int
+ val (n, l): (String, Int) = (4, "")
+ ^
+two errors found
diff --git a/test/files/neg/t5106.scala b/test/files/neg/t5106.scala
new file mode 100644
index 0000000000..419b430ff1
--- /dev/null
+++ b/test/files/neg/t5106.scala
@@ -0,0 +1,5 @@
+class A {
+ def f {
+ val (n, l): (String, Int) = (4, "")
+ }
+}
diff --git a/test/files/neg/t5334_1.check b/test/files/neg/t5334_1.check
new file mode 100644
index 0000000000..1d5a7cbc01
--- /dev/null
+++ b/test/files/neg/t5334_1.check
@@ -0,0 +1,4 @@
+t5334_1.scala:4: error: implementation restriction: cannot reify block of type C that involves a type declared inside the block being reified. consider casting the return value to a suitable type
+ reify {
+ ^
+one error found
diff --git a/test/files/neg/t5334_1.scala b/test/files/neg/t5334_1.scala
new file mode 100644
index 0000000000..a7de5a0915
--- /dev/null
+++ b/test/files/neg/t5334_1.scala
@@ -0,0 +1,8 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ reify {
+ class C { override def toString = "C" }
+ new C
+ }.eval
+}
diff --git a/test/files/neg/t5334_2.check b/test/files/neg/t5334_2.check
new file mode 100644
index 0000000000..a62bfff7a5
--- /dev/null
+++ b/test/files/neg/t5334_2.check
@@ -0,0 +1,4 @@
+t5334_2.scala:4: error: implementation restriction: cannot reify block of type List[(C, C)] that involves a type declared inside the block being reified. consider casting the return value to a suitable type
+ reify {
+ ^
+one error found
diff --git a/test/files/neg/t5334_2.scala b/test/files/neg/t5334_2.scala
new file mode 100644
index 0000000000..fc6dfcd0c1
--- /dev/null
+++ b/test/files/neg/t5334_2.scala
@@ -0,0 +1,8 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ reify {
+ class C { override def toString() = "C" }
+ List((new C, new C))
+ }.eval
+}
diff --git a/test/files/neg/t5452-new.check b/test/files/neg/t5452-new.check
new file mode 100644
index 0000000000..bbd3734f74
--- /dev/null
+++ b/test/files/neg/t5452-new.check
@@ -0,0 +1,8 @@
+t5452-new.scala:28: error: overloaded method value apply with alternatives:
+ ()Queryable[CoffeesTable] <and>
+ (t: Tree)(implicit evidence$2: ClassTag[CoffeesTable])Nothing <and>
+ (implicit evidence$1: ClassTag[CoffeesTable])Nothing
+ cannot be applied to (Queryable[CoffeesTable])
+ Queryable[CoffeesTable]( q.treeFilter(null) )
+ ^
+one error found
diff --git a/test/files/neg/t5452-new.scala b/test/files/neg/t5452-new.scala
new file mode 100644
index 0000000000..c829de7d7c
--- /dev/null
+++ b/test/files/neg/t5452-new.scala
@@ -0,0 +1,29 @@
+// /scala/trac/5452/a.scala
+// Mon Feb 13 22:52:36 PST 2012
+
+// import scala.reflect.mirror._
+
+trait Tree
+
+object Bip {
+ def ??? = sys.error("")
+}
+import Bip._
+
+case class Queryable[T]() {
+ def treeFilter( t:Tree ) : Queryable[T] = ???
+}
+
+object Queryable {
+ def apply[T:ClassTag] = ???
+ def apply[T:ClassTag]( t:Tree ) = ???
+}
+
+trait CoffeesTable{
+ def sales : Int
+}
+
+object Test extends App{
+ val q = new Queryable[CoffeesTable]
+ Queryable[CoffeesTable]( q.treeFilter(null) )
+}
diff --git a/test/files/neg/t5452.check b/test/files/neg/t5452-old.check
index 2f35a45509..e5872a5759 100644
--- a/test/files/neg/t5452.check
+++ b/test/files/neg/t5452-old.check
@@ -1,8 +1,8 @@
-t5452.scala:28: error: overloaded method value apply with alternatives:
- ()Queryable[CoffeesTable] <and>
- (t: Tree)(implicit evidence$2: Manifest[CoffeesTable])Nothing <and>
- (implicit evidence$1: Manifest[CoffeesTable])Nothing
- cannot be applied to (Queryable[CoffeesTable])
- Queryable[CoffeesTable]( q.treeFilter(null) )
- ^
-one error found
+t5452-old.scala:28: error: overloaded method value apply with alternatives:
+ ()Queryable[CoffeesTable] <and>
+ (t: Tree)(implicit evidence$2: Manifest[CoffeesTable])Nothing <and>
+ (implicit evidence$1: Manifest[CoffeesTable])Nothing
+ cannot be applied to (Queryable[CoffeesTable])
+ Queryable[CoffeesTable]( q.treeFilter(null) )
+ ^
+one error found
diff --git a/test/files/neg/t5452.scala b/test/files/neg/t5452-old.scala
index 1032db7a4b..1032db7a4b 100644
--- a/test/files/neg/t5452.scala
+++ b/test/files/neg/t5452-old.scala
diff --git a/test/files/neg/t5504.check b/test/files/neg/t5504.check
new file mode 100644
index 0000000000..2827c02d10
--- /dev/null
+++ b/test/files/neg/t5504.check
@@ -0,0 +1,4 @@
+error: type _$1 is defined twice
+ conflicting symbols both originated in file 't5504/s_1.scala'
+ Note: this may be due to a bug in the compiler involving wildcards in package objects
+one error found
diff --git a/test/files/neg/t5504/s_1.scala b/test/files/neg/t5504/s_1.scala
new file mode 100644
index 0000000000..35cb2c8bae
--- /dev/null
+++ b/test/files/neg/t5504/s_1.scala
@@ -0,0 +1,4 @@
+// a.scala
+package object foo {
+ val m: List[_] = Nil
+}
diff --git a/test/files/neg/t5504/s_2.scala b/test/files/neg/t5504/s_2.scala
new file mode 100644
index 0000000000..03eecf6e19
--- /dev/null
+++ b/test/files/neg/t5504/s_2.scala
@@ -0,0 +1,8 @@
+// b.scala
+package foo
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ println(foo.m)
+ }
+}
diff --git a/test/files/neg/t5510.check b/test/files/neg/t5510.check
new file mode 100644
index 0000000000..60da3bed40
--- /dev/null
+++ b/test/files/neg/t5510.check
@@ -0,0 +1,19 @@
+t5510.scala:2: error: unclosed string literal
+ val s1 = s"xxx
+ ^
+t5510.scala:3: error: unclosed string literal
+ val s2 = s"xxx $x
+ ^
+t5510.scala:4: error: unclosed string literal
+ val s3 = s"xxx $$
+ ^
+t5510.scala:5: error: unclosed string literal
+ val s4 = ""s"
+ ^
+t5510.scala:6: error: unclosed multi-line string literal
+ val s5 = ""s""" $s1 $s2 s"
+ ^
+t5510.scala:7: error: '}' expected but eof found.
+}
+ ^
+6 errors found
diff --git a/test/files/neg/t5510.scala b/test/files/neg/t5510.scala
new file mode 100644
index 0000000000..12630eb2cd
--- /dev/null
+++ b/test/files/neg/t5510.scala
@@ -0,0 +1,7 @@
+object Test {
+ val s1 = s"xxx
+ val s2 = s"xxx $x
+ val s3 = s"xxx $$
+ val s4 = ""s"
+ val s5 = ""s""" $s1 $s2 s"
+}
diff --git a/test/files/neg/t5564.check b/test/files/neg/t5564.check
new file mode 100644
index 0000000000..e7e13ccc9c
--- /dev/null
+++ b/test/files/neg/t5564.check
@@ -0,0 +1,4 @@
+t5564.scala:8: error: inferred type arguments [A] do not conform to method bar's type parameter bounds [B >: A <: C]
+ def bar[B >: A <: C]: T = throw new Exception
+ ^
+one error found
diff --git a/test/files/neg/t5564.scala b/test/files/neg/t5564.scala
new file mode 100644
index 0000000000..663cf88726
--- /dev/null
+++ b/test/files/neg/t5564.scala
@@ -0,0 +1,9 @@
+
+
+
+trait C
+
+
+class Foo[@specialized(Int) T, A] {
+ def bar[B >: A <: C]: T = throw new Exception
+}
diff --git a/test/files/neg/t5578.check b/test/files/neg/t5578.check
new file mode 100644
index 0000000000..d803adb223
--- /dev/null
+++ b/test/files/neg/t5578.check
@@ -0,0 +1,4 @@
+t5578.scala:33: error: No Manifest available for T.
+ def plus[T: Numeric](x: Rep[T], y: Rep[T]): Rep[T] = Plus[T](x,y)
+ ^
+one error found
diff --git a/test/files/neg/t5578.scala b/test/files/neg/t5578.scala
new file mode 100644
index 0000000000..ce72f32d53
--- /dev/null
+++ b/test/files/neg/t5578.scala
@@ -0,0 +1,39 @@
+trait Base {
+ type Rep[T]
+}
+
+trait Expressions {
+ // constants/symbols (atomic)
+ abstract class Exp[T]
+ // ...
+ case class Sym[T](n: Int) extends Exp[T]
+
+ // operations (composite, defined in subtraits)
+ abstract class Def[T]
+
+ // additional members for managing encountered definitions
+ def findOrCreateDefinition[T](rhs: Def[T]): Sym[T]
+ implicit def toExp[T:Manifest](d: Def[T]): Exp[T] = findOrCreateDefinition(d)
+}
+
+trait BaseExp extends Base with Expressions {
+ type Rep[T] = Exp[T]
+
+ def findOrCreateDefinition[T](rhs: Def[T]): Sym[T] = null // stub
+}
+
+trait NumericOps extends Base {
+ def plus[T](x: Rep[T], y: Rep[T]): Rep[T]
+}
+
+trait NumericOpsExp extends BaseExp {
+ case class Plus[T:Numeric](x: Rep[T], y: Rep[T])
+ extends Def[T]
+
+ def plus[T: Numeric](x: Rep[T], y: Rep[T]): Rep[T] = Plus[T](x,y)
+
+ // Possible solutions:
+// def plus[T: Numeric: Manifest](x: Rep[T], y: Rep[T]): Rep[T] = Plus[T](x, y)
+// def plus[T](x: Rep[T], y: Rep[T])(implicit num: Numeric[T], man: Manifest[T]): Rep[T] = Plus(x,y)
+
+}
diff --git a/test/files/neg/t5663-badwarneq.check b/test/files/neg/t5663-badwarneq.check
new file mode 100644
index 0000000000..00c2234e9d
--- /dev/null
+++ b/test/files/neg/t5663-badwarneq.check
@@ -0,0 +1,22 @@
+t5663-badwarneq.scala:42: error: comparing case class values of types Some[Int] and None.type using `==' will always yield false
+ println(new Some(1) == None) // Should complain on type, was: spuriously complains on fresh object
+ ^
+t5663-badwarneq.scala:43: error: comparing case class values of types Some[Int] and Thing using `==' will always yield false
+ println(Some(1) == new Thing(1)) // Should complain on type, was: spuriously complains on fresh object
+ ^
+t5663-badwarneq.scala:51: error: ThingOne and Thingy are unrelated: they will most likely never compare equal
+ println(t1 == t2) // true, but apparently unrelated, a compromise warning
+ ^
+t5663-badwarneq.scala:52: error: ThingThree and Thingy are unrelated: they will most likely never compare equal
+ println(t4 == t2) // true, complains because ThingThree is final and Thingy not a subclass, stronger claim than unrelated
+ ^
+t5663-badwarneq.scala:55: error: comparing case class values of types ThingTwo and Some[Int] using `==' will always yield false
+ println(t3 == Some(1)) // false, warn on different cases
+ ^
+t5663-badwarneq.scala:56: error: comparing values of types ThingOne and Cousin using `==' will always yield false
+ println(t1 == c) // should warn
+ ^
+t5663-badwarneq.scala:64: error: comparing case class values of types Simple and SimpleSibling.type using `==' will always yield false
+ println(new Simple() == SimpleSibling) // like Some(1) == None, but needn't be final case
+ ^
+7 errors found
diff --git a/test/files/neg/t5663-badwarneq.flags b/test/files/neg/t5663-badwarneq.flags
new file mode 100644
index 0000000000..85d8eb2ba2
--- /dev/null
+++ b/test/files/neg/t5663-badwarneq.flags
@@ -0,0 +1 @@
+-Xfatal-warnings
diff --git a/test/files/neg/t5663-badwarneq.scala b/test/files/neg/t5663-badwarneq.scala
new file mode 100644
index 0000000000..56ec389c03
--- /dev/null
+++ b/test/files/neg/t5663-badwarneq.scala
@@ -0,0 +1,76 @@
+
+// alias
+trait Thingy
+
+class Gramps
+
+// sibling classes that extend a case class
+case class Thing(i: Int) extends Gramps
+class ThingOne(x:Int) extends Thing(x)
+class ThingTwo(y:Int) extends Thing(y) with Thingy
+final class ThingThree(z:Int) extends Thing(z)
+
+// not case cousin
+class Cousin extends Gramps
+
+class SimpleParent
+case class Simple() extends SimpleParent
+case object SimpleSibling extends SimpleParent
+
+/* It's not possible to run partest without -deprecation.
+ * Since detecting the warnings requires a neg test with
+ * -Xfatal-warnings, and deprecation terminates the compile,
+ * we'll just comment out the nasty part. The point was
+ * just to show there's nothing special about a trait
+ * that extends a case class, which is only permitted
+ * (deprecatingly) by omitting the parens.
+ *
+// common ancestor is something else
+class AnyThing
+case class SomeThing extends AnyThing // deprecation
+class OtherThing extends AnyThing
+
+// how you inherit caseness doesn't matter
+trait InThing extends SomeThing
+class MyThing extends InThing
+*/
+
+object Test {
+ def main(a: Array[String]) {
+ // nothing to do with Gavin
+ println(new Some(1) == new Some(1)) // OK, true
+ println(new Some(1) == None) // Should complain on type, was: spuriously complains on fresh object
+ println(Some(1) == new Thing(1)) // Should complain on type, was: spuriously complains on fresh object
+
+ val t1 = new ThingOne(11)
+ val t2: Thingy = new ThingTwo(11)
+ val t3 = new ThingTwo(11)
+ val t4 = new ThingThree(11)
+ val c = new Cousin
+
+ println(t1 == t2) // true, but apparently unrelated, a compromise warning
+ println(t4 == t2) // true, complains because ThingThree is final and Thingy not a subclass, stronger claim than unrelated
+ println(t2 == t3) // OK, two Thingy
+ println(t3 == t2) // ditto with case receiver
+ println(t3 == Some(1)) // false, warn on different cases
+ println(t1 == c) // should warn
+
+ // don't warn on fresh cases
+ println(new ThingOne(11) == t1) // OK, was: two cases not warnable on trunk
+ println(new ThingTwo(11) == t2) // true, was: spuriously complains on fresh object
+ println(new ThingOne(11) == t3) // two cases not warnable on trunk
+ println(new ThingTwo(11) == t3) // ditto
+
+ println(new Simple() == SimpleSibling) // like Some(1) == None, but needn't be final case
+
+ /*
+ val mine = new MyThing
+ val some = new SomeThing
+ val other = new OtherThing
+ println(mine == some) // OK, two Something
+ println(some == mine)
+ println(mine == other) // OK, two Anything?
+ println(mine == t1) // false
+ */
+ }
+}
diff --git a/test/files/neg/t5666.check b/test/files/neg/t5666.check
new file mode 100644
index 0000000000..4289b00ade
--- /dev/null
+++ b/test/files/neg/t5666.check
@@ -0,0 +1,37 @@
+t5666.scala:2: error: class Any is abstract; cannot be instantiated
+ new Any
+ ^
+t5666.scala:3: error: class AnyVal is abstract; cannot be instantiated
+ new AnyVal
+ ^
+t5666.scala:4: error: Double does not have a constructor
+ new Double
+ ^
+t5666.scala:5: error: Float does not have a constructor
+ new Float
+ ^
+t5666.scala:6: error: Long does not have a constructor
+ new Long
+ ^
+t5666.scala:7: error: Int does not have a constructor
+ new Int
+ ^
+t5666.scala:8: error: Char does not have a constructor
+ new Char
+ ^
+t5666.scala:9: error: Short does not have a constructor
+ new Short
+ ^
+t5666.scala:10: error: Byte does not have a constructor
+ new Byte
+ ^
+t5666.scala:11: error: Boolean does not have a constructor
+ new Boolean
+ ^
+t5666.scala:12: error: Unit does not have a constructor
+ new Unit
+ ^
+t5666.scala:13: error: class Nothing is abstract; cannot be instantiated
+ new Nothing
+ ^
+12 errors found
diff --git a/test/files/neg/t5666.scala b/test/files/neg/t5666.scala
new file mode 100644
index 0000000000..ffaeaacdaf
--- /dev/null
+++ b/test/files/neg/t5666.scala
@@ -0,0 +1,14 @@
+object t5666 {
+ new Any
+ new AnyVal
+ new Double
+ new Float
+ new Long
+ new Int
+ new Char
+ new Short
+ new Byte
+ new Boolean
+ new Unit
+ new Nothing
+} \ No newline at end of file
diff --git a/test/files/neg/t5689.check b/test/files/neg/t5689.check
new file mode 100644
index 0000000000..6abc4c13f6
--- /dev/null
+++ b/test/files/neg/t5689.check
@@ -0,0 +1,7 @@
+t5689.scala:4: error: macro implementation has wrong shape:
+ required: (c: scala.reflect.makro.Context)(i: c.Expr[Double]): c.Expr[String]
+ found : (c: scala.reflect.makro.Context)(i: c.Expr[Double]): c.Expr[Int]
+type mismatch for return type: c.Expr[Int] does not conform to c.Expr[String]
+ def returnsString(i: Double): String = macro returnsIntImpl
+ ^
+one error found
diff --git a/test/files/neg/t5689.flags b/test/files/neg/t5689.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/neg/t5689.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/neg/t5689.scala b/test/files/neg/t5689.scala
new file mode 100644
index 0000000000..ef7a45b364
--- /dev/null
+++ b/test/files/neg/t5689.scala
@@ -0,0 +1,6 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def returnsString(i: Double): String = macro returnsIntImpl
+ def returnsIntImpl(c: Context)(i: c.Expr[Double]): c.Expr[Int] = ???
+}
diff --git a/test/files/neg/t5702-neg-bad-and-wild.check b/test/files/neg/t5702-neg-bad-and-wild.check
new file mode 100644
index 0000000000..eae81ad5f2
--- /dev/null
+++ b/test/files/neg/t5702-neg-bad-and-wild.check
@@ -0,0 +1,28 @@
+t5702-neg-bad-and-wild.scala:10: error: bad use of _* (a sequence pattern must be the last pattern)
+ case List(1, _*,) => // bad use of _* (a sequence pattern must be the last pattern)
+ ^
+t5702-neg-bad-and-wild.scala:10: error: illegal start of simple pattern
+ case List(1, _*,) => // bad use of _* (a sequence pattern must be the last pattern)
+ ^
+t5702-neg-bad-and-wild.scala:12: error: illegal start of simple pattern
+ case List(1, _*3,) => // illegal start of simple pattern
+ ^
+t5702-neg-bad-and-wild.scala:14: error: use _* to match a sequence
+ case List(1, x*) => // use _* to match a sequence
+ ^
+t5702-neg-bad-and-wild.scala:15: error: trailing * is not a valid pattern
+ case List(x*, 1) => // trailing * is not a valid pattern
+ ^
+t5702-neg-bad-and-wild.scala:16: error: trailing * is not a valid pattern
+ case (1, x*) => // trailing * is not a valid pattern
+ ^
+t5702-neg-bad-and-wild.scala:17: error: bad use of _* (sequence pattern not allowed)
+ case (1, x@_*) => // bad use of _* (sequence pattern not allowed)
+ ^
+t5702-neg-bad-and-wild.scala:23: error: bad use of _* (a sequence pattern must be the last pattern)
+ val K(ns @ _*, x) = k // bad use of _* (a sequence pattern must be the last pattern)
+ ^
+t5702-neg-bad-and-wild.scala:24: error: bad use of _* (sequence pattern not allowed)
+ val (b, _ * ) = Pair(5,6) // bad use of _* (sequence pattern not allowed)
+ ^
+9 errors found
diff --git a/test/files/neg/t5702-neg-bad-and-wild.scala b/test/files/neg/t5702-neg-bad-and-wild.scala
new file mode 100644
index 0000000000..3833a002b1
--- /dev/null
+++ b/test/files/neg/t5702-neg-bad-and-wild.scala
@@ -0,0 +1,29 @@
+
+object Test {
+ case class K(i: Int)
+
+ def main(args: Array[String]) {
+ val k = new K(9)
+ val is = List(1,2,3)
+
+ is match {
+ case List(1, _*,) => // bad use of _* (a sequence pattern must be the last pattern)
+ // illegal start of simple pattern
+ case List(1, _*3,) => // illegal start of simple pattern
+ //case List(1, _*3:) => // poor recovery by parens
+ case List(1, x*) => // use _* to match a sequence
+ case List(x*, 1) => // trailing * is not a valid pattern
+ case (1, x*) => // trailing * is not a valid pattern
+ case (1, x@_*) => // bad use of _* (sequence pattern not allowed)
+ }
+
+// good syntax, bad semantics, detected by typer
+//gowild.scala:14: error: star patterns must correspond with varargs parameters
+ val K(is @ _*) = k
+ val K(ns @ _*, x) = k // bad use of _* (a sequence pattern must be the last pattern)
+ val (b, _ * ) = Pair(5,6) // bad use of _* (sequence pattern not allowed)
+// no longer complains
+//bad-and-wild.scala:15: error: ')' expected but '}' found.
+ }
+}
+
diff --git a/test/files/neg/t5702-neg-bad-brace.check b/test/files/neg/t5702-neg-bad-brace.check
new file mode 100644
index 0000000000..503f7d95ed
--- /dev/null
+++ b/test/files/neg/t5702-neg-bad-brace.check
@@ -0,0 +1,10 @@
+t5702-neg-bad-brace.scala:14: error: Unmatched closing brace '}' ignored here
+ case List(1, _*} =>
+ ^
+t5702-neg-bad-brace.scala:14: error: illegal start of simple pattern
+ case List(1, _*} =>
+ ^
+t5702-neg-bad-brace.scala:15: error: ')' expected but '}' found.
+ }
+ ^
+three errors found
diff --git a/test/files/neg/t5702-neg-bad-brace.scala b/test/files/neg/t5702-neg-bad-brace.scala
new file mode 100644
index 0000000000..16a341cf8c
--- /dev/null
+++ b/test/files/neg/t5702-neg-bad-brace.scala
@@ -0,0 +1,17 @@
+
+object Test {
+
+ def main(args: Array[String]) {
+ val is = List(1,2,3)
+
+ is match {
+// the erroneous brace is ignored, so we can't halt on it.
+// maybe brace healing can detect overlapping unmatched (...}
+// In this case, the fix emits an extra error:
+// t5702-neg-bad-brace.scala:10: error: Unmatched closing brace '}' ignored here
+// t5702-neg-bad-brace.scala:10: error: illegal start of simple pattern (i.e., =>)
+// t5702-neg-bad-brace.scala:11: error: ')' expected but '}' found.
+ case List(1, _*} =>
+ }
+ }
+}
diff --git a/test/files/neg/t5702-neg-bad-xbrace.check b/test/files/neg/t5702-neg-bad-xbrace.check
new file mode 100644
index 0000000000..d88638aee9
--- /dev/null
+++ b/test/files/neg/t5702-neg-bad-xbrace.check
@@ -0,0 +1,7 @@
+t5702-neg-bad-xbrace.scala:19: error: bad brace or paren after _*
+ case <year>{_*)}</year> => y
+ ^
+t5702-neg-bad-xbrace.scala:28: error: bad brace or paren after _*
+ val <top>{a, z@_*)}</top> = xml
+ ^
+two errors found
diff --git a/test/files/neg/t5702-neg-bad-xbrace.scala b/test/files/neg/t5702-neg-bad-xbrace.scala
new file mode 100644
index 0000000000..64bbdb18be
--- /dev/null
+++ b/test/files/neg/t5702-neg-bad-xbrace.scala
@@ -0,0 +1,31 @@
+
+object Test {
+ def main(args: Array[String]) {
+ /* PiS example, minus a brace
+ val yearMade = 1965
+ val old =
+ <a>{ if (yearMade < 2000) <old>yearMade}</old>
+ else xml.NodeSeq.Empty } </a>
+ println(old)
+ */
+
+ // bad brace or paren after _*
+ // actually, we know it's a bad paren...
+ // we skip it because not in a context looking for rparen
+ val xyear = <year>1965</year>
+ val ancient =
+ <b>{
+ val when = xyear match {
+ case <year>{_*)}</year> => y
+ case _ => "2035"
+ }
+ <old>{when}</old>
+ }</b>
+ println(ancient)
+
+ val xml = <top><a>apple</a><b>boy</b><c>child</c></top>
+ // bad brace or paren after _*
+ val <top>{a, z@_*)}</top> = xml
+ println("A for "+ a +", ending with "+ z)
+ }
+}
diff --git a/test/files/neg/t5702-neg-ugly-xbrace.check b/test/files/neg/t5702-neg-ugly-xbrace.check
new file mode 100644
index 0000000000..7d80bbf6be
--- /dev/null
+++ b/test/files/neg/t5702-neg-ugly-xbrace.check
@@ -0,0 +1,19 @@
+t5702-neg-ugly-xbrace.scala:11: error: bad brace or paren after _*
+ val <top>{a, z@_*)</top> = xml
+ ^
+t5702-neg-ugly-xbrace.scala:12: error: Missing closing brace `}' assumed here
+ println("A for "+ a +", ending with "+ z)
+ ^
+t5702-neg-ugly-xbrace.scala:13: error: in XML literal: in XML content, please use '}}' to express '}'
+ }
+ ^
+t5702-neg-ugly-xbrace.scala:11: error: I encountered a '}' where I didn't expect one, maybe this tag isn't closed <top>
+ val <top>{a, z@_*)</top> = xml
+ ^
+t5702-neg-ugly-xbrace.scala:14: error: illegal start of simple pattern
+}
+^
+t5702-neg-ugly-xbrace.scala:14: error: '}' expected but eof found.
+}
+ ^
+6 errors found
diff --git a/test/files/neg/t5702-neg-ugly-xbrace.scala b/test/files/neg/t5702-neg-ugly-xbrace.scala
new file mode 100644
index 0000000000..0ff7bfa09d
--- /dev/null
+++ b/test/files/neg/t5702-neg-ugly-xbrace.scala
@@ -0,0 +1,14 @@
+
+object Test {
+ def main(args: Array[String]) {
+
+ val xml = <top><a>apple</a><b>boy</b><c>child</c></top>
+ // This is the more likely typo, and the uglier parse.
+ // We could turn it into a } if } does not follow (to
+ // avoid handing }} back to xml) but that is quite ad hoc.
+ // Assuming } for ) after _* would not be not outlandish.
+ // bad brace or paren after _*
+ val <top>{a, z@_*)</top> = xml
+ println("A for "+ a +", ending with "+ z)
+ }
+}
diff --git a/test/files/neg/t5728.check b/test/files/neg/t5728.check
new file mode 100644
index 0000000000..14f9c42ae0
--- /dev/null
+++ b/test/files/neg/t5728.check
@@ -0,0 +1,4 @@
+t5728.scala:3: error: implicit classes must accept exactly one primary constructor parameter
+ implicit class Foo
+ ^
+one error found
diff --git a/test/files/neg/t5728.scala b/test/files/neg/t5728.scala
new file mode 100644
index 0000000000..99337d06d4
--- /dev/null
+++ b/test/files/neg/t5728.scala
@@ -0,0 +1,7 @@
+object Test {
+
+ implicit class Foo
+
+ implicit def Foo = new Foo
+
+}
diff --git a/test/files/neg/t591.check b/test/files/neg/t591.check
index 5cdeebf079..d33f6d7a2f 100644
--- a/test/files/neg/t591.check
+++ b/test/files/neg/t591.check
@@ -1,4 +1,5 @@
-t591.scala:38: error: method input_= is defined twice in t591.scala
+t591.scala:38: error: method input_= is defined twice
+ conflicting symbols both originated in file 't591.scala'
def input_=(in : Input) = {}
^
one error found
diff --git a/test/files/neg/t750.check b/test/files/neg/t750.check
new file mode 100644
index 0000000000..c17ca334e6
--- /dev/null
+++ b/test/files/neg/t750.check
@@ -0,0 +1,15 @@
+Test_2.scala:4: error: type mismatch;
+ found : Array[Int]
+ required: Array[? with Object]
+Note: Int >: ? with Object, but class Array is invariant in type T.
+You may wish to investigate a wildcard type such as `_ >: ? with Object`. (SLS 3.2.10)
+ AO_1.f(a)
+ ^
+Test_2.scala:5: error: type mismatch;
+ found : Array[Int]
+ required: Array[Int]
+Note: Int >: Int, but class Array is invariant in type T.
+You may wish to investigate a wildcard type such as `_ >: Int`. (SLS 3.2.10)
+ AO_1.f[Int](a)
+ ^
+two errors found
diff --git a/test/files/neg/t750/AO_1.java b/test/files/neg/t750/AO_1.java
new file mode 100644
index 0000000000..4c7360ec6f
--- /dev/null
+++ b/test/files/neg/t750/AO_1.java
@@ -0,0 +1,5 @@
+public class AO_1 {
+ public static <T> void f(T[] ar0) {
+ System.out.println(ar0);
+ }
+} \ No newline at end of file
diff --git a/test/files/neg/t750/Test_2.scala b/test/files/neg/t750/Test_2.scala
new file mode 100644
index 0000000000..80977431c5
--- /dev/null
+++ b/test/files/neg/t750/Test_2.scala
@@ -0,0 +1,6 @@
+// t750
+object Test extends App {
+ val a = Array(1, 2, 3)
+ AO_1.f(a)
+ AO_1.f[Int](a)
+}
diff --git a/test/files/neg/t750b.check b/test/files/neg/t750b.check
new file mode 100644
index 0000000000..72a249191e
--- /dev/null
+++ b/test/files/neg/t750b.check
@@ -0,0 +1,15 @@
+Test.scala:4: error: type mismatch;
+ found : Array[Int]
+ required: Array[? with Object]
+Note: Int >: ? with Object, but class Array is invariant in type T.
+You may wish to investigate a wildcard type such as `_ >: ? with Object`. (SLS 3.2.10)
+ AO.f(a)
+ ^
+Test.scala:5: error: type mismatch;
+ found : Array[Int]
+ required: Array[Int]
+Note: Int >: Int, but class Array is invariant in type T.
+You may wish to investigate a wildcard type such as `_ >: Int`. (SLS 3.2.10)
+ AO.f[Int](a)
+ ^
+two errors found
diff --git a/test/files/neg/t750b/AO.java b/test/files/neg/t750b/AO.java
new file mode 100644
index 0000000000..060baf9a3c
--- /dev/null
+++ b/test/files/neg/t750b/AO.java
@@ -0,0 +1,5 @@
+public class AO {
+ public static <T> void f(T[] ar0) {
+ System.out.println(ar0);
+ }
+} \ No newline at end of file
diff --git a/test/files/neg/t750b/Test.scala b/test/files/neg/t750b/Test.scala
new file mode 100644
index 0000000000..5f792a7be8
--- /dev/null
+++ b/test/files/neg/t750b/Test.scala
@@ -0,0 +1,6 @@
+// t750
+object Test extends App {
+ val a = Array(1, 2, 3)
+ AO.f(a)
+ AO.f[Int](a)
+}
diff --git a/test/files/neg/t800.check b/test/files/neg/t800.check
index 44c316a95b..8ba95fddde 100644
--- a/test/files/neg/t800.check
+++ b/test/files/neg/t800.check
@@ -1,13 +1,16 @@
t800.scala:4: error: qualification is already defined as value qualification
val qualification = false;
^
-t800.scala:8: error: method qualification is defined twice in t800.scala
+t800.scala:8: error: method qualification is defined twice
+ conflicting symbols both originated in file 't800.scala'
val qualification = false;
^
-t800.scala:12: error: value qualification is defined twice in t800.scala
+t800.scala:12: error: value qualification is defined twice
+ conflicting symbols both originated in file 't800.scala'
var qualification = false;
^
-t800.scala:16: error: method qualification is defined twice in t800.scala
+t800.scala:16: error: method qualification is defined twice
+ conflicting symbols both originated in file 't800.scala'
var qualification = false;
^
four errors found
diff --git a/test/files/neg/t900.check b/test/files/neg/t900.check
index 047094ad6e..4611ceba8c 100644
--- a/test/files/neg/t900.check
+++ b/test/files/neg/t900.check
@@ -2,8 +2,8 @@ t900.scala:4: error: type mismatch;
found : Foo.this.x.type (with underlying type Foo.this.bar)
required: AnyRef
Note that implicit conversions are not applicable because they are ambiguous:
- both method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd
- and method any2stringfmt in object Predef of type (x: Any)scala.runtime.StringFormat
+ both method any2stringfmt in object Predef of type (x: Any)scala.runtime.StringFormat
+ and method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd
are possible conversion functions from Foo.this.x.type to AnyRef
def break(): x.type
^
diff --git a/test/files/neg/t963.check b/test/files/neg/t963.check
new file mode 100644
index 0000000000..1f2d0687b3
--- /dev/null
+++ b/test/files/neg/t963.check
@@ -0,0 +1,12 @@
+t963.scala:14: error: stable identifier required, but Test.this.y3.x found.
+ val w3 : y3.x.type = y3.x
+ ^
+t963.scala:17: error: stable identifier required, but Test.this.y4.x found.
+ val w4 : y4.x.type = y4.x
+ ^
+t963.scala:10: error: type mismatch;
+ found : Object{def x: Integer}
+ required: AnyRef{val x: Integer}
+ val y2 : { val x : java.lang.Integer } = new { def x = new java.lang.Integer(r.nextInt) }
+ ^
+three errors found
diff --git a/test/files/neg/t963.scala b/test/files/neg/t963.scala
new file mode 100644
index 0000000000..0cc2034299
--- /dev/null
+++ b/test/files/neg/t963.scala
@@ -0,0 +1,18 @@
+import scala.util.Random
+
+// Only y1 (val/val) should actually compile.
+object Test {
+ val r = new Random()
+
+ val y1 : { val x : java.lang.Integer } = new { val x = new java.lang.Integer(r.nextInt) }
+ val w1 : y1.x.type = y1.x
+
+ val y2 : { val x : java.lang.Integer } = new { def x = new java.lang.Integer(r.nextInt) }
+ val w2 : y2.x.type = y2.x
+
+ val y3 : { def x : java.lang.Integer } = new { val x = new java.lang.Integer(r.nextInt) }
+ val w3 : y3.x.type = y3.x
+
+ val y4 : { def x : java.lang.Integer } = new { def x = new java.lang.Integer(r.nextInt) }
+ val w4 : y4.x.type = y4.x
+}
diff --git a/test/files/neg/tailrec.check b/test/files/neg/tailrec.check
index ad92731b2c..946d3421e6 100644
--- a/test/files/neg/tailrec.check
+++ b/test/files/neg/tailrec.check
@@ -4,9 +4,9 @@ tailrec.scala:45: error: could not optimize @tailrec annotated method facfail: i
tailrec.scala:50: error: could not optimize @tailrec annotated method fail1: it is neither private nor final so can be overridden
@tailrec def fail1(x: Int): Int = fail1(x)
^
-tailrec.scala:55: error: could not optimize @tailrec annotated method fail2: it contains a recursive call not in tail position
- case x :: xs => x :: fail2[T](xs)
- ^
+tailrec.scala:53: error: could not optimize @tailrec annotated method fail2: it contains a recursive call not in tail position
+ @tailrec final def fail2[T](xs: List[T]): List[T] = xs match {
+ ^
tailrec.scala:59: error: could not optimize @tailrec annotated method fail3: it is called recursively with different type arguments
@tailrec final def fail3[T](x: Int): Int = fail3(x - 1)
^
diff --git a/test/files/neg/unreachablechar.flags b/test/files/neg/unreachablechar.flags
new file mode 100644
index 0000000000..809e9ff2f2
--- /dev/null
+++ b/test/files/neg/unreachablechar.flags
@@ -0,0 +1 @@
+ -Xoldpatmat
diff --git a/test/files/pos/annot-inner.scala b/test/files/pos/annot-inner.scala
index f2ecb5ddb3..9f155a5a83 100644
--- a/test/files/pos/annot-inner.scala
+++ b/test/files/pos/annot-inner.scala
@@ -1,5 +1,5 @@
object test {
- class annot extends Annotation
+ class annot extends scala.annotation.Annotation
def foo {
@annot def bar(i: Int): Int = i
diff --git a/test/files/pos/annotDepMethType.scala b/test/files/pos/annotDepMethType.scala
index b5e7cb9e8b..079ca6224c 100644
--- a/test/files/pos/annotDepMethType.scala
+++ b/test/files/pos/annotDepMethType.scala
@@ -1,4 +1,4 @@
-case class pc(calls: Any*) extends TypeConstraint
+case class pc(calls: Any*) extends annotation.TypeConstraint
object Main {
class C0 { def baz: String = "" }
diff --git a/test/files/pos/annotations.scala b/test/files/pos/annotations.scala
index 4e5fddda39..706a715bad 100644
--- a/test/files/pos/annotations.scala
+++ b/test/files/pos/annotations.scala
@@ -1,5 +1,5 @@
-class ann(i: Int) extends Annotation
-class cfann(x: String) extends ClassfileAnnotation
+class ann(i: Int) extends scala.annotation.Annotation
+class cfann(x: String) extends annotation.ClassfileAnnotation
// annotations on abstract types
abstract class C1[@serializable @cloneable +T, U, V[_]]
@@ -91,9 +91,9 @@ trait BeanF {
}
-class Ann3(arr: Array[String]) extends ClassfileAnnotation
-class Ann4(i: Int) extends ClassfileAnnotation
-class Ann5(value: Class[_]) extends ClassfileAnnotation
+class Ann3(arr: Array[String]) extends annotation.ClassfileAnnotation
+class Ann4(i: Int) extends annotation.ClassfileAnnotation
+class Ann5(value: Class[_]) extends annotation.ClassfileAnnotation
object Test3 {
final val i = 1083
diff --git a/test/files/pos/attributes.scala b/test/files/pos/attributes.scala
index f3bbb4c42e..ec735d0aae 100644
--- a/test/files/pos/attributes.scala
+++ b/test/files/pos/attributes.scala
@@ -52,15 +52,15 @@ object O6 {
}
object myAttrs {
- class a1 extends scala.Annotation;
- class a2(x: Int) extends scala.Annotation;
- class a3(x: a1) extends scala.Annotation;
+ class a1 extends scala.annotation.Annotation;
+ class a2(x: Int) extends scala.annotation.Annotation;
+ class a3(x: a1) extends scala.annotation.Annotation;
}
-class a4(ns: Array[Int]) extends scala.Annotation;
+class a4(ns: Array[Int]) extends scala.annotation.Annotation;
object O7 {
- class a1 extends scala.Annotation;
- class a2(x: Int) extends scala.Annotation;
- class a3(x: a1) extends scala.Annotation;
+ class a1 extends scala.annotation.Annotation;
+ class a2(x: Int) extends scala.annotation.Annotation;
+ class a3(x: a1) extends scala.annotation.Annotation;
final val x = new a1;
@a1 class C1;
diff --git a/test/files/pos/contextbounds-implicits-new.scala b/test/files/pos/contextbounds-implicits-new.scala
new file mode 100644
index 0000000000..71b3cca36f
--- /dev/null
+++ b/test/files/pos/contextbounds-implicits-new.scala
@@ -0,0 +1,8 @@
+/* Tests implicit parameters in the presence of context bounds.
+ * See Section 7.4 of the Scala Language Specification.
+ */
+class C {
+
+ def f[T: TypeTag, S: TypeTag](x: T, y: S)(implicit p: C) { }
+
+}
diff --git a/test/files/pos/contextbounds-implicits.scala b/test/files/pos/contextbounds-implicits-old.scala
index f9113ee320..f9113ee320 100644
--- a/test/files/pos/contextbounds-implicits.scala
+++ b/test/files/pos/contextbounds-implicits-old.scala
diff --git a/test/files/pos/gen-traversable-methods.scala b/test/files/pos/gen-traversable-methods.scala
new file mode 100644
index 0000000000..2604a09f11
--- /dev/null
+++ b/test/files/pos/gen-traversable-methods.scala
@@ -0,0 +1,20 @@
+
+
+
+import collection._
+
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ val gen: GenTraversable[Int] = List(1, 2, 3)
+ gen.head
+ gen.headOption
+ gen.tail
+ gen.last
+ gen.lastOption
+ gen.init
+ }
+
+}
diff --git a/test/files/pos/generic-sigs.scala b/test/files/pos/generic-sigs.scala
index 40ec044656..b112766056 100644
--- a/test/files/pos/generic-sigs.scala
+++ b/test/files/pos/generic-sigs.scala
@@ -1,3 +1,5 @@
+import language.existentials
+
object A {
def f1 = List(classOf[Int], classOf[String])
def f2 = List(classOf[String], classOf[Int])
@@ -15,4 +17,4 @@ object A {
class Boppy[+T1,-T2]
def g1 = new Boppy[t forSome { type t <: Int }, u forSome { type u <: String }]
-} \ No newline at end of file
+}
diff --git a/test/files/pos/hkarray.flags b/test/files/pos/hkarray.flags
index e8fb65d50c..e745d8bbe3 100644
--- a/test/files/pos/hkarray.flags
+++ b/test/files/pos/hkarray.flags
@@ -1 +1 @@
--Xfatal-warnings \ No newline at end of file
+-Xfatal-warnings -language:higherKinds \ No newline at end of file
diff --git a/test/files/pos/implicits-new.scala b/test/files/pos/implicits-new.scala
new file mode 100644
index 0000000000..7eb7e100c3
--- /dev/null
+++ b/test/files/pos/implicits-new.scala
@@ -0,0 +1,89 @@
+// #1435
+object t1435 {
+ implicit def a(s:String):String = error("")
+ implicit def a(i:Int):String = error("")
+ implicit def b(i:Int):String = error("")
+}
+
+class C1435 {
+ val v:String = {
+ import t1435.a
+ 2
+ }
+}
+
+// #1492
+class C1492 {
+
+ class X
+
+ def foo(x: X => X) {}
+
+ foo ( implicit x => implicitly[X] )
+ foo { implicit x => implicitly[X] }
+}
+
+// #1579
+object Test1579 {
+ class Column
+ class Query[E](val value: E)
+ class Invoker(q: Any) { val foo = null }
+
+ implicit def unwrap[C](q: Query[C]) = q.value
+ implicit def invoker(q: Query[Column]) = new Invoker(q)
+
+ val q = new Query(new Column)
+ q.foo
+}
+// #1625
+object Test1625 {
+
+ class Wrapped(x:Any) {
+ def unwrap() = x
+ }
+
+ implicit def byName[A](x: =>A) = new Wrapped(x)
+
+ implicit def byVal[A](x: A) = x
+
+ def main(args: Array[String]) = {
+
+// val res:Wrapped = 7 // works
+
+ val res = 7.unwrap() // doesn't work
+
+ println("=> result: " + res)
+ }
+}
+
+object Test2188 {
+ implicit def toJavaList[A: ArrayTag](t:collection.Seq[A]):java.util.List[A] = java.util.Arrays.asList(t.toArray:_*)
+
+ val x: java.util.List[String] = List("foo")
+}
+
+object TestNumericWidening {
+ val y = 1
+ val x: java.lang.Long = y
+}
+
+// #2709
+package foo2709 {
+ class A
+ class B
+
+ package object bar {
+ implicit def a2b(a: A): B = new B
+ }
+
+ package bar {
+ object test {
+ new A: B
+ }
+ }
+}
+
+// Problem with specs
+object specsProblem {
+ println(implicitly[ConcreteTypeTag[Class[_]]])
+}
diff --git a/test/files/pos/implicits.scala b/test/files/pos/implicits-old.scala
index 2c01dd0ba8..2c01dd0ba8 100644
--- a/test/files/pos/implicits.scala
+++ b/test/files/pos/implicits-old.scala
diff --git a/test/files/pos/liftcode_polymorphic.scala b/test/files/pos/liftcode_polymorphic.scala
index 3d4b159c83..9c59b34bee 100644
--- a/test/files/pos/liftcode_polymorphic.scala
+++ b/test/files/pos/liftcode_polymorphic.scala
@@ -1,3 +1,5 @@
+import scala.reflect.mirror._
+
object Append extends Application {
def append[A](l1: List[A], l2: List[A]):List[A] =
@@ -6,6 +8,6 @@ object Append extends Application {
case x::xs => x :: append(xs, l2)
}
- println(scala.reflect.Code.lift(append _).tree)
+ println(reify(append _).tree)
}
diff --git a/test/files/pos/macro-deprecate-dont-touch-backquotedidents.flags b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/pos/macro-deprecate-dont-touch-backquotedidents.scala b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.scala
new file mode 100644
index 0000000000..69a7333011
--- /dev/null
+++ b/test/files/pos/macro-deprecate-dont-touch-backquotedidents.scala
@@ -0,0 +1,56 @@
+object Test1 {
+ val `macro` = ???
+}
+
+object Test2 {
+ var `macro` = ???
+}
+
+object Test3 {
+ type `macro` = Int
+}
+
+package test4 {
+ class `macro`
+}
+
+object Test5 {
+ class `macro`
+}
+
+package test6 {
+ object `macro`
+}
+
+object Test7 {
+ object `macro`
+}
+
+package test8 {
+ trait `macro`
+}
+
+object Test9 {
+ trait `macro`
+}
+
+package `macro` {
+ package `macro`.bar {
+ }
+}
+
+package foo {
+ package `macro`.foo {
+ }
+}
+
+//object Test12 {
+// val Some(`macro`) = Some(42)
+// `macro` match {
+// case `macro` => println(`macro`)
+// }
+//}
+
+object Test13 {
+ def `macro` = 2
+} \ No newline at end of file
diff --git a/test/files/pos/macros.scala b/test/files/pos/macros.scala
deleted file mode 100644
index 303610d464..0000000000
--- a/test/files/pos/macros.scala
+++ /dev/null
@@ -1,8 +0,0 @@
-object Test {
-
- class C {
- def macro foo[T](xs: List[T]): T = (T, xs) match {
- case (t1: Type, t2: Tree) => t2
- }
- }
-}
diff --git a/test/files/pos/manifest1-new.scala b/test/files/pos/manifest1-new.scala
new file mode 100644
index 0000000000..645bd42665
--- /dev/null
+++ b/test/files/pos/manifest1-new.scala
@@ -0,0 +1,21 @@
+import scala.reflect.TypeTag
+
+object Test {
+ def foo[T](x: T)(implicit m: TypeTag[T]) {
+ foo(List(x))
+ }
+ foo(1)
+ foo("abc")
+ foo(List(1, 2, 3))
+ val x: List[Int] with Ordered[List[Int]] = null
+ foo(x)
+ foo[x.type](x)
+ abstract class C { type T = String; val x: T }
+ val c = new C { val x = "abc" }
+ foo(c.x)
+ abstract class D { type T; implicit val m: TypeTag[T]; val x: T }
+ val stringm = implicitly[TypeTag[String]]
+ val d: D = new D { type T = String; val m = stringm; val x = "x" }
+ import d.m
+ foo(d.x)
+}
diff --git a/test/files/pos/manifest1.scala b/test/files/pos/manifest1-old.scala
index 8901aa7437..8901aa7437 100644
--- a/test/files/pos/manifest1.scala
+++ b/test/files/pos/manifest1-old.scala
diff --git a/test/pending/pos/no-widen-locals.scala b/test/files/pos/no-widen-locals.scala
index 013e63f0a2..013e63f0a2 100644
--- a/test/pending/pos/no-widen-locals.scala
+++ b/test/files/pos/no-widen-locals.scala
diff --git a/test/files/pos/nothing_manifest_disambig-new.scala b/test/files/pos/nothing_manifest_disambig-new.scala
new file mode 100644
index 0000000000..a60b0fdbf8
--- /dev/null
+++ b/test/files/pos/nothing_manifest_disambig-new.scala
@@ -0,0 +1,10 @@
+object Test {
+ def mani[T: TypeTag](xs: T) = xs
+ mani(List())
+
+ def listElMani[T: TypeTag](xs: List[T]) = xs
+ listElMani(List())
+
+ def foo[A, C](m : C)(implicit ev: C <:< Traversable[A], mani: TypeTag[A]): (C, A, TypeTag[A]) = (m, m.head, mani)
+ foo(List(1,2,3))
+} \ No newline at end of file
diff --git a/test/files/pos/nothing_manifest_disambig.scala b/test/files/pos/nothing_manifest_disambig-old.scala
index 076742033f..076742033f 100644
--- a/test/files/pos/nothing_manifest_disambig.scala
+++ b/test/files/pos/nothing_manifest_disambig-old.scala
diff --git a/test/files/pos/spec-annotations.scala b/test/files/pos/spec-annotations.scala
index 35cab6de09..48281e5df5 100644
--- a/test/files/pos/spec-annotations.scala
+++ b/test/files/pos/spec-annotations.scala
@@ -1,4 +1,4 @@
-class ann(i: Int) extends Annotation
+class ann(i: Int) extends scala.annotation.Annotation
// annotations on abstract types
abstract class C1[@serializable @cloneable +T, U, V[_]]
diff --git a/test/files/pos/spec-constr-new.scala b/test/files/pos/spec-constr-new.scala
new file mode 100644
index 0000000000..7cd02b0680
--- /dev/null
+++ b/test/files/pos/spec-constr-new.scala
@@ -0,0 +1,7 @@
+class SparseArray2[@specialized(Int) T:ArrayTag](val maxSize: Int, initialLength:Int = 3) {
+ private var data = new Array[T](initialLength);
+ private var index = new Array[Int](initialLength);
+
+ // comment out to compile correctly
+ data.length + 3;
+}
diff --git a/test/files/pos/spec-constr.scala b/test/files/pos/spec-constr-old.scala
index e908b65a41..e908b65a41 100644
--- a/test/files/pos/spec-constr.scala
+++ b/test/files/pos/spec-constr-old.scala
diff --git a/test/files/pos/spec-doubledef-new.scala b/test/files/pos/spec-doubledef-new.scala
new file mode 100644
index 0000000000..33f1e82b6e
--- /dev/null
+++ b/test/files/pos/spec-doubledef-new.scala
@@ -0,0 +1,28 @@
+object Test {
+ def fn[@specialized T, @specialized U](t : T => Int, u : U => Int) : T =
+ null.asInstanceOf[T]
+}
+
+trait A[@specialized(Int) T] {
+ var value: T
+ def getWith[@specialized(Int) Z](f: T => Z) = f(value)
+}
+
+class C extends A[Int] {
+ var value = 10
+ override def getWith[@specialized(Int) Z](f: Int => Z) = f(value)
+}
+
+abstract class B[T, @specialized(scala.Int) U : TypeTag, @specialized(scala.Int) V <% Ordered[V]] {
+ val u: U
+ val v: V
+
+ def f(t: T, v2: V): Pair[U, V] = {
+ val m: Array[U] = null
+ if (m.isEmpty) {
+ Pair(u, v)
+ } else {
+ Pair(u, v2)
+ }
+ }
+}
diff --git a/test/files/pos/spec-doubledef.scala b/test/files/pos/spec-doubledef-old.scala
index 86b0d857d3..86b0d857d3 100644
--- a/test/files/pos/spec-doubledef.scala
+++ b/test/files/pos/spec-doubledef-old.scala
diff --git a/test/files/pos/spec-fields-new.scala b/test/files/pos/spec-fields-new.scala
new file mode 100644
index 0000000000..ddd8bd6624
--- /dev/null
+++ b/test/files/pos/spec-fields-new.scala
@@ -0,0 +1,10 @@
+abstract class Foo[@specialized T: ArrayTag, U <: Ordered[U]](x: T, size: Int) {
+ var y: T
+ var z: T = x
+
+ def initialSize = 16
+ val array = new Array[T](initialSize + size)
+
+ def getZ = z
+ def setZ(zz: T) = z = zz
+}
diff --git a/test/files/pos/spec-fields.scala b/test/files/pos/spec-fields-old.scala
index 26a8c4ffbd..26a8c4ffbd 100644
--- a/test/files/pos/spec-fields.scala
+++ b/test/files/pos/spec-fields-old.scala
diff --git a/test/files/pos/spec-params-new.scala b/test/files/pos/spec-params-new.scala
new file mode 100644
index 0000000000..5fe0c82d40
--- /dev/null
+++ b/test/files/pos/spec-params-new.scala
@@ -0,0 +1,32 @@
+class Foo[@specialized A: ArrayTag] {
+
+ // conflicting in bounds, expect a normalized member calling m
+ // and bridge + implementation in specialized subclasses
+ // and overloads here according to specialization on A
+ def m1[@specialized B <: A](x: B, y: A) =
+ goal(x)
+
+ // conflicting, unsolvable, expect a warning
+ def m2[@specialized B <: String](x: B) = x.concat("a")
+
+ // conflicting in bounds, no mention of other spec members
+ // expect an overload here plus implementation in
+ // compatible specialized subclasses
+ def m3[@specialized B >: A](x: B) = ()
+
+ // non-conflicting, expect a normalized overload implementation here
+ def m4[@specialized T, U <: Ordered[T]](x: T, y: U) = ()
+
+ // non-conflicting, expect a normalized overload implementation here
+ def m5[@specialized B](x: B) = x
+
+ // non-conflicting, expect a normalized implementation here
+ // and specialized implementations for all expansions in specialized subclasses
+ def m6[@specialized B](x: B, y: A) =
+ goal(y)
+
+ def goal(x: A) = {
+ val xs = new Array[A](1)
+ xs(0) = x
+ }
+}
diff --git a/test/files/pos/spec-params.scala b/test/files/pos/spec-params-old.scala
index f522512846..f522512846 100644
--- a/test/files/pos/spec-params.scala
+++ b/test/files/pos/spec-params-old.scala
diff --git a/test/files/pos/spec-sparsearray-new.scala b/test/files/pos/spec-sparsearray-new.scala
new file mode 100644
index 0000000000..0659bf7926
--- /dev/null
+++ b/test/files/pos/spec-sparsearray-new.scala
@@ -0,0 +1,24 @@
+import scala.collection.mutable.MapLike
+
+class SparseArray[@specialized(Int) T:ArrayTag] extends collection.mutable.Map[Int,T] with collection.mutable.MapLike[Int,T,SparseArray[T]] {
+ override def get(x: Int) = {
+ val ind = findOffset(x)
+ if(ind < 0) None else Some(error("ignore"))
+ }
+
+ /**
+ * Returns the offset into index and data for the requested vector
+ * index. If the requested index is not found, the return value is
+ * negative and can be converted into an insertion point with -(rv+1).
+ */
+ private def findOffset(i : Int) : Int = {
+ error("impl doesn't matter")
+ }
+
+ override def apply(i : Int) : T = { error("ignore") }
+ override def update(i : Int, value : T) = error("ignore")
+ override def empty = new SparseArray[T]
+ def -=(ind: Int) = error("ignore")
+ def +=(kv: (Int,T)) = error("ignore")
+ override final def iterator = error("ignore")
+}
diff --git a/test/files/pos/spec-sparsearray.scala b/test/files/pos/spec-sparsearray-old.scala
index ea7710a785..ea7710a785 100644
--- a/test/files/pos/spec-sparsearray.scala
+++ b/test/files/pos/spec-sparsearray-old.scala
diff --git a/test/files/pos/t1029/Test_1.scala b/test/files/pos/t1029/Test_1.scala
index e828087f2c..d268c71429 100644
--- a/test/files/pos/t1029/Test_1.scala
+++ b/test/files/pos/t1029/Test_1.scala
@@ -1,4 +1,4 @@
-class ann(a: Array[Int]) extends StaticAnnotation
+class ann(a: Array[Int]) extends annotation.StaticAnnotation
object Test1 {
// bug #1029
diff --git a/test/files/pos/t1203.scala b/test/files/pos/t1203.scala
index 4938621aa9..062ef93fc6 100644
--- a/test/files/pos/t1203.scala
+++ b/test/files/pos/t1203.scala
@@ -1,4 +1,4 @@
-case class ant(t: String) extends Annotation
+case class ant(t: String) extends scala.annotation.Annotation
object Test {
def main(args: Array[String]): Unit = {
val a: scala.xml.NodeSeq @ant("12") = Nil
diff --git a/test/files/pos/t1279a.scala b/test/files/pos/t1279a.scala
index 9212b583d4..18b1e53f46 100644
--- a/test/files/pos/t1279a.scala
+++ b/test/files/pos/t1279a.scala
@@ -1,40 +1,39 @@
-// see #13
-// providing the type parameter in the recursive call to all4Impl
-// avoids the problem
-
-
// covariant linked list
-abstract class M
-{ self =>
-
- type T
- final type selfType = M {type T <: self.T}
- type actualSelfType >: self.type <: selfType
-
- def next: selfType
+abstract class M {
+ self =>
+ type T
+ final type selfType = M {type T <: self.T}
+ type actualSelfType >: self.type <: selfType
- // I don't understand why this doesn't compile, but that's a separate matter
- // error: method all2 cannot be accessed in M.this.selfType
- // because its instance type => Stream[M{type T <: M.this.selfType#T}]
- // contains a malformed type: M.this.selfType#T
- // def all2: Stream[M {type T <: self.T}] = Stream.cons(self: actualSelfType, next.all2)
+ def next: selfType
+ // I don't understand why this doesn't compile, but that's a separate matter
+ // error: method all2 cannot be accessed in M.this.selfType
+ // because its instance type => Stream[M{type T <: M.this.selfType#T}]
+ // contains a malformed type: M.this.selfType#T
+ def all2: Stream[M {type T <: self.T}] = Stream.cons(self: actualSelfType, next.all2)
- // compiles successfully
- // def all3: Stream[M {type T <: self.T}] = all3Impl(self: actualSelfType)
- // private def all3Impl(first: M {type T <: self.T}): Stream[M {type T <: self.T}] = Stream.cons(first, all3Impl(first.next))
+ // compiles successfully
+ def all3: Stream[M {type T <: self.T}] = all3Impl(self: actualSelfType)
+ private def all3Impl(first: M {type T <: self.T}): Stream[M {type T <: self.T}] = Stream.cons(first, all3Impl(first.next))
-
-
- def all4: Stream[M {type T <: self.T}] = Unrelated.all4Impl[T](self: actualSelfType)
+ def all4: Stream[M {type T <: self.T}] = Unrelated.all4Impl[T](self: actualSelfType)
}
-object Unrelated
-{
- // TODO!!! fix this bug for real, it compiles successfully, but weird types are inferred
- // def all4Impl[U](first: M {type T <: U}): Stream[M {type T <: U}] = Stream.cons(first, all4Impl(first.next))
-
-// compiles successfully
- def all4Impl[U](first: M {type T <: U}): Stream[M {type T <: U}] = Stream.cons(first, all4Impl[U](first.next))
+// TODO!!! fix this bug for real, it compiles successfully, but weird types are inferred
+object Unrelated {
+ // compiles successfully
+ def all4Impl[U](first: M {type T <: U}): Stream[M {type T <: U}] = Stream.cons(first, all4Impl[U](first.next))
+
+ // should compile successfully without the [U], but:
+ // def all4ImplFail[U](first: M {type T <: U}): Stream[M {type T <: U}] = Stream.cons(first, all4ImplFail(first.next))
+ //
+ // test/files/pos/t1279a.scala:31: error: type mismatch;
+ // found : first.selfType
+ // (which expands to) M{type T <: first.T}
+ // required: M{type T <: Nothing}
+ // def all4ImplFail[U](first: M {type T <: U}): Stream[M {type T <: U}] = Stream.cons(first, all4ImplFail(first.next))
+ // ^
+ // one error found
}
diff --git a/test/pending/pos/t1357.scala b/test/files/pos/t1357.scala
index 7bc6d45034..7bc6d45034 100644
--- a/test/pending/pos/t1357.scala
+++ b/test/files/pos/t1357.scala
diff --git a/test/files/pos/t1381-new.scala b/test/files/pos/t1381-new.scala
new file mode 100644
index 0000000000..8781ef4fdb
--- /dev/null
+++ b/test/files/pos/t1381-new.scala
@@ -0,0 +1,31 @@
+import scala.reflect.TypeTag
+
+class D[V <: Variable]
+
+class ID[V<:IV] extends D[V] {
+ type E = V#ValueType
+ def index(value:E) : Int = 0
+ // Comment this out to eliminate crash. Or see below
+ def index(values:E*) : Iterable[Int] = null
+}
+
+abstract class Variable {
+ type VT <: Variable
+ def d : D[VT] = null
+}
+
+abstract class PV[T](initval:T) extends Variable {
+ type VT <: PV[T]
+ type ValueType = T
+}
+
+trait IV extends Variable {
+ type ValueType
+}
+
+abstract class EV[T](initval:T) extends PV[T](initval) with IV {
+ type VT <: EV[T]
+ override def d : ID[VT] = null
+ // Comment this out to eliminate crash
+ protected var indx = d.index(initval)
+}
diff --git a/test/files/pos/t1381.scala b/test/files/pos/t1381-old.scala
index 0762891898..0762891898 100644
--- a/test/files/pos/t1381.scala
+++ b/test/files/pos/t1381-old.scala
diff --git a/test/files/pos/t1439.flags b/test/files/pos/t1439.flags
index 779916d58f..1e70f5c5c7 100644
--- a/test/files/pos/t1439.flags
+++ b/test/files/pos/t1439.flags
@@ -1 +1 @@
--unchecked -Xfatal-warnings \ No newline at end of file
+-unchecked -Xfatal-warnings -Xoldpatmat -language:higherKinds
diff --git a/test/files/pos/t1785.scala b/test/files/pos/t1785.scala
new file mode 100644
index 0000000000..0b1fafb27c
--- /dev/null
+++ b/test/files/pos/t1785.scala
@@ -0,0 +1,7 @@
+class t1785 {
+ def apply[T](x: Int) = 1
+}
+
+object test {
+ (new t1785)[Int](1)
+}
diff --git a/test/files/pos/t1942/A_1.scala b/test/files/pos/t1942/A_1.scala
index 19a7575a0a..4915b54a64 100644
--- a/test/files/pos/t1942/A_1.scala
+++ b/test/files/pos/t1942/A_1.scala
@@ -3,7 +3,7 @@ class A {
def foo(x: String) = 1
}
-class ann(x: Int) extends StaticAnnotation
+class ann(x: Int) extends annotation.StaticAnnotation
class t {
val a = new A
diff --git a/test/files/pos/t2795-new.scala b/test/files/pos/t2795-new.scala
new file mode 100644
index 0000000000..af9c4e8b1c
--- /dev/null
+++ b/test/files/pos/t2795-new.scala
@@ -0,0 +1,17 @@
+package t1
+
+trait Element[T] {
+}
+
+trait Config {
+ type T <: Element[T]
+ implicit val m: ArrayTag[T]
+ // XXX Following works fine:
+ // type T <: Element[_]
+}
+
+trait Transform { self: Config =>
+ def processBlock(block: Array[T]): Unit = {
+ var X = new Array[T](1)
+ }
+}
diff --git a/test/files/pos/t2795.scala b/test/files/pos/t2795-old.scala
index 935cb1f444..935cb1f444 100644
--- a/test/files/pos/t2795.scala
+++ b/test/files/pos/t2795-old.scala
diff --git a/test/files/pos/t2868/pick_1.scala b/test/files/pos/t2868/pick_1.scala
index e91728ec2f..a211687432 100644
--- a/test/files/pos/t2868/pick_1.scala
+++ b/test/files/pos/t2868/pick_1.scala
@@ -1,4 +1,4 @@
-class ann(s: String) extends StaticAnnotation
+class ann(s: String) extends annotation.StaticAnnotation
class pick {
final val s = "bang!"
@ann("bang!") def foo = 1
diff --git a/test/files/pos/t3363-new.scala b/test/files/pos/t3363-new.scala
new file mode 100644
index 0000000000..270462745c
--- /dev/null
+++ b/test/files/pos/t3363-new.scala
@@ -0,0 +1,18 @@
+object TestCase {
+
+ //now matter if you put (abstract) class or trait it will fail in all cases
+ trait MapOps[T]
+
+ //if fs was reduced to List (generic type with one parameter) then the code compiles
+ //if you inherit from MapOps[T] instead of MapOps[F] then code compiles fine
+ implicit def map2ops[T,F](fs: Map[T,F]) = new MapOps[F] {
+ //if you remove this line, then code compiles
+ lazy val m: TypeTag[T] = error("just something to make it compile")
+ def is(xs: List[T]) = List(xs)
+ }
+
+ def main(args: Array[String]) {
+ println(Map(1 -> "2") is List(2))
+ }
+
+ }
diff --git a/test/files/pos/t3363.scala b/test/files/pos/t3363-old.scala
index bae54084ea..bae54084ea 100755..100644
--- a/test/files/pos/t3363.scala
+++ b/test/files/pos/t3363-old.scala
diff --git a/test/files/pos/t3498-new.scala b/test/files/pos/t3498-new.scala
new file mode 100644
index 0000000000..653c50042a
--- /dev/null
+++ b/test/files/pos/t3498-new.scala
@@ -0,0 +1,15 @@
+abstract class A[T, @specialized(scala.Int) U : ArrayTag] {
+ def f(state: T): Array[U]
+}
+
+abstract class B extends A[ Array[Byte], Int ] {
+ type T = Array[Byte]
+ type U = Int
+
+ val N = 0
+
+ def f(state: T): Array[U] =
+ {
+ new Array[U](N + state(N))
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t3498.scala b/test/files/pos/t3498-old.scala
index bcc90ca64c..bcc90ca64c 100644
--- a/test/files/pos/t3498.scala
+++ b/test/files/pos/t3498-old.scala
diff --git a/test/files/pos/t3800.scala b/test/files/pos/t3800.scala
index 796eb268c5..61dbeafff3 100644
--- a/test/files/pos/t3800.scala
+++ b/test/files/pos/t3800.scala
@@ -1,4 +1,4 @@
-class meh extends StaticAnnotation
+class meh extends annotation.StaticAnnotation
class ALike[C]
abstract class AFactory[CC[x] <: ALike[CC[x]]] {
diff --git a/test/files/pos/t3951/Coll_1.scala b/test/files/pos/t3951/Coll_1.scala
index c2cc39a1a9..556c848688 100644
--- a/test/files/pos/t3951/Coll_1.scala
+++ b/test/files/pos/t3951/Coll_1.scala
@@ -15,7 +15,7 @@ sealed trait DynamicDocument extends Document {
class Coll extends StaticDocument
// similiar issue with annotations
-class ann[T] extends StaticAnnotation
+class ann[T] extends annotation.StaticAnnotation
trait StatDoc extends Doc {
@ann[StatFB]
diff --git a/test/files/pos/t4910.scala b/test/files/pos/t4910.scala
new file mode 100644
index 0000000000..c66fd523f5
--- /dev/null
+++ b/test/files/pos/t4910.scala
@@ -0,0 +1,6 @@
+class A {
+ implicit object foo
+ // it compiles if we uncomment this
+ // implicit val bar = foo
+ implicitly[foo.type]
+}
diff --git a/test/files/pos/t5198.scala b/test/files/pos/t5198.scala
new file mode 100644
index 0000000000..f403f77f7d
--- /dev/null
+++ b/test/files/pos/t5198.scala
@@ -0,0 +1,15 @@
+package gaga
+
+
+
+
+
+trait Sys[Self <: Sys[Self]] {
+ type Tx
+}
+
+
+sealed trait AssocEntry[S <: Sys[S], @specialized(Int) A] {
+ def value: A
+ def value(implicit tx: S#Tx): A
+}
diff --git a/test/files/pos/t5223.scala b/test/files/pos/t5223.scala
index 51682e9254..398630dc61 100644
--- a/test/files/pos/t5223.scala
+++ b/test/files/pos/t5223.scala
@@ -1,6 +1,6 @@
-import scala.reflect._
+import scala.reflect.mirror._
object Foo extends App {
- Code.lift{def printf(format: String, args: Any*): String = null }
- Code.lift{def printf(format: String, args: Any*): String = ("abc": @cloneable)}
+ reify{def printf(format: String, args: Any*): String = null }
+ reify{def printf(format: String, args: Any*): String = ("abc": @cloneable)}
}
diff --git a/test/files/pos/t5240.scala b/test/files/pos/t5240.scala
new file mode 100644
index 0000000000..2db689c27d
--- /dev/null
+++ b/test/files/pos/t5240.scala
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+package object foo {
+
+ var labels: Array[_ <: String] = null
+
+}
diff --git a/test/files/pos/t531.scala b/test/files/pos/t531.scala
index 856926de4f..5176912ef0 100644
--- a/test/files/pos/t531.scala
+++ b/test/files/pos/t531.scala
@@ -1,8 +1,9 @@
+import scala.reflect.mirror._
+
object Test extends App {
- import scala.reflect._;
def titi = {
var truc = 0
- val tata = Code.lift{() => {
+ val tata = reify{() => {
truc = 6
}}
()
diff --git a/test/files/pos/t532.scala b/test/files/pos/t532.scala
index f864bbf45e..a319fdfa27 100644
--- a/test/files/pos/t532.scala
+++ b/test/files/pos/t532.scala
@@ -1,8 +1,9 @@
+import scala.reflect.mirror._
+
object Test extends App {
- import scala.reflect._;
def titi: Unit = {
var truc = 0
- val tata = Code.lift{() => {
+ val tata = reify{() => {
truc = truc + 6
}}
()
diff --git a/test/files/pos/t5542.flags b/test/files/pos/t5542.flags
new file mode 100644
index 0000000000..464cc20ea6
--- /dev/null
+++ b/test/files/pos/t5542.flags
@@ -0,0 +1 @@
+-Xfatal-warnings -unchecked \ No newline at end of file
diff --git a/test/files/pos/t5542.scala b/test/files/pos/t5542.scala
new file mode 100644
index 0000000000..80b8cef030
--- /dev/null
+++ b/test/files/pos/t5542.scala
@@ -0,0 +1,3 @@
+class Test {
+ Option(3) match { case Some(n) => n; case None => 0 }
+} \ No newline at end of file
diff --git a/test/files/pos/t5644/BoxesRunTime.java b/test/files/pos/t5644/BoxesRunTime.java
new file mode 100644
index 0000000000..241bf79ac8
--- /dev/null
+++ b/test/files/pos/t5644/BoxesRunTime.java
@@ -0,0 +1,836 @@
+/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2006-2011, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+
+
+package scala.runtime;
+
+import java.io.*;
+import scala.math.ScalaNumber;
+
+/** An object (static class) that defines methods used for creating,
+ * reverting, and calculating with, boxed values. There are four classes
+ * of methods in this object:
+ * - Convenience boxing methods which call the static valueOf method
+ * on the boxed class, thus utilizing the JVM boxing cache.
+ * - Convenience unboxing methods returning default value on null.
+ * - The generalised comparison method to be used when an object may
+ * be a boxed value.
+ * - Standard value operators for boxed number and quasi-number values.
+ *
+ * @author Gilles Dubochet
+ * @author Martin Odersky
+ * @contributor Stepan Koltsov
+ * @version 2.0 */
+public final class BoxesRunTime
+{
+ private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7;
+
+ /** We don't need to return BYTE and SHORT, as everything which might
+ * care widens to INT.
+ */
+ private static int typeCode(Object a) {
+ if (a instanceof java.lang.Integer) return INT;
+ if (a instanceof java.lang.Double) return DOUBLE;
+ if (a instanceof java.lang.Long) return LONG;
+ if (a instanceof java.lang.Character) return CHAR;
+ if (a instanceof java.lang.Float) return FLOAT;
+ if ((a instanceof java.lang.Byte) || (a instanceof java.lang.Short)) return INT;
+ return OTHER;
+ }
+
+ private static int eqTypeCode(Number a) {
+ int code = typeCode(a);
+ if (code == CHAR)
+ return OTHER;
+ else
+ return code;
+ }
+
+ private static String boxDescription(Object a) {
+ return "" + a.getClass().getSimpleName() + "(" + a + ")";
+ }
+
+/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */
+
+ public static java.lang.Boolean boxToBoolean(boolean b) {
+ return java.lang.Boolean.valueOf(b);
+ }
+
+ public static java.lang.Character boxToCharacter(char c) {
+ return java.lang.Character.valueOf(c);
+ }
+
+ public static java.lang.Byte boxToByte(byte b) {
+ return java.lang.Byte.valueOf(b);
+ }
+
+ public static java.lang.Short boxToShort(short s) {
+ return java.lang.Short.valueOf(s);
+ }
+
+ public static java.lang.Integer boxToInteger(int i) {
+ return java.lang.Integer.valueOf(i);
+ }
+
+ public static java.lang.Long boxToLong(long l) {
+ return java.lang.Long.valueOf(l);
+ }
+
+ public static java.lang.Float boxToFloat(float f) {
+ return java.lang.Float.valueOf(f);
+ }
+
+ public static java.lang.Double boxToDouble(double d) {
+ // System.out.println("box " + d);
+ // (new Throwable()).printStackTrace();
+ return java.lang.Double.valueOf(d);
+ }
+
+/* UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING ... UNBOXING */
+
+ public static boolean unboxToBoolean(Object b) {
+ return b == null ? false : ((java.lang.Boolean)b).booleanValue();
+ }
+
+ public static char unboxToChar(Object c) {
+ return c == null ? 0 : ((java.lang.Character)c).charValue();
+ }
+
+ public static byte unboxToByte(Object b) {
+ return b == null ? 0 : ((java.lang.Byte)b).byteValue();
+ }
+
+ public static short unboxToShort(Object s) {
+ return s == null ? 0 : ((java.lang.Short)s).shortValue();
+ }
+
+ public static int unboxToInt(Object i) {
+ return i == null ? 0 : ((java.lang.Integer)i).intValue();
+ }
+
+ public static long unboxToLong(Object l) {
+ return l == null ? 0 : ((java.lang.Long)l).longValue();
+ }
+
+ public static float unboxToFloat(Object f) {
+ return f == null ? 0.0f : ((java.lang.Float)f).floatValue();
+ }
+
+ public static double unboxToDouble(Object d) {
+ // System.out.println("unbox " + d);
+ return d == null ? 0.0d : ((java.lang.Double)d).doubleValue();
+ }
+
+ /* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */
+
+ public static boolean equals(Object x, Object y) {
+ if (x == y) return true;
+ return equals2(x, y);
+ }
+
+ /** Since all applicable logic has to be present in the equals method of a ScalaNumber
+ * in any case, we dispatch to it as soon as we spot one on either side.
+ */
+ public static boolean equals2(Object x, Object y) {
+ if (x instanceof java.lang.Number)
+ return equalsNumObject((java.lang.Number)x, y);
+ if (x instanceof java.lang.Character)
+ return equalsCharObject((java.lang.Character)x, y);
+ if (x == null)
+ return y == null;
+
+ return x.equals(y);
+ }
+
+ public static boolean equalsNumObject(java.lang.Number xn, Object y) {
+ if (y instanceof java.lang.Number)
+ return equalsNumNum(xn, (java.lang.Number)y);
+ if (y instanceof java.lang.Character)
+ return equalsNumChar(xn, (java.lang.Character)y);
+ if (xn == null)
+ return y == null;
+
+ return xn.equals(y);
+ }
+
+ public static boolean equalsNumNum(java.lang.Number xn, java.lang.Number yn) {
+ int xcode = eqTypeCode(xn);
+ int ycode = eqTypeCode(yn);
+ switch (ycode > xcode ? ycode : xcode) {
+ case INT:
+ return xn.intValue() == yn.intValue();
+ case LONG:
+ return xn.longValue() == yn.longValue();
+ case FLOAT:
+ return xn.floatValue() == yn.floatValue();
+ case DOUBLE:
+ return xn.doubleValue() == yn.doubleValue();
+ default:
+ if ((yn instanceof ScalaNumber) && !(xn instanceof ScalaNumber))
+ return yn.equals(xn);
+ }
+ if (xn == null)
+ return yn == null;
+
+ return xn.equals(yn);
+ }
+
+ public static boolean equalsCharObject(java.lang.Character xc, Object y) {
+ if (y instanceof java.lang.Character)
+ return xc.charValue() == ((java.lang.Character)y).charValue();
+ if (y instanceof java.lang.Number)
+ return equalsNumChar((java.lang.Number)y, xc);
+ if (xc == null)
+ return y == null;
+
+ return xc.equals(y);
+ }
+
+ private static boolean equalsNumChar(java.lang.Number xn, java.lang.Character yc) {
+ if (yc == null)
+ return xn == null;
+
+ char ch = yc.charValue();
+ switch (eqTypeCode(xn)) {
+ case INT:
+ return xn.intValue() == ch;
+ case LONG:
+ return xn.longValue() == ch;
+ case FLOAT:
+ return xn.floatValue() == ch;
+ case DOUBLE:
+ return xn.doubleValue() == ch;
+ default:
+ return xn.equals(yc);
+ }
+ }
+
+ /** Hashcode algorithm is driven by the requirements imposed
+ * by primitive equality semantics, namely that equal objects
+ * have equal hashCodes. The first priority are the integral/char
+ * types, which already have the same hashCodes for the same
+ * values except for Long. So Long's hashCode is altered to
+ * conform to Int's for all values in Int's range.
+ *
+ * Float is problematic because it's far too small to hold
+ * all the Ints, so for instance Int.MaxValue.toFloat claims
+ * to be == to each of the largest 64 Ints. There is no way
+ * to preserve equals/hashCode alignment without compromising
+ * the hashCode distribution, so Floats are only guaranteed
+ * to have the same hashCode for whole Floats in the range
+ * Short.MinValue to Short.MaxValue (2^16 total.)
+ *
+ * Double has its hashCode altered to match the entire Int range,
+ * but is not guaranteed beyond that. (But could/should it be?
+ * The hashCode is only 32 bits so this is a more tractable
+ * issue than Float's, but it might be better simply to exclude it.)
+ *
+ * Note: BigInt and BigDecimal, being arbitrary precision, could
+ * be made consistent with all other types for the Int range, but
+ * as yet have not.
+ *
+ * Note: Among primitives, Float.NaN != Float.NaN, but the boxed
+ * verisons are equal. This still needs reconciliation.
+ */
+ public static int hashFromLong(java.lang.Long n) {
+ int iv = n.intValue();
+ if (iv == n.longValue()) return iv;
+ else return n.hashCode();
+ }
+ public static int hashFromDouble(java.lang.Double n) {
+ int iv = n.intValue();
+ double dv = n.doubleValue();
+ if (iv == dv) return iv;
+
+ long lv = n.longValue();
+ if (lv == dv) return java.lang.Long.valueOf(lv).hashCode();
+ else return n.hashCode();
+ }
+ public static int hashFromFloat(java.lang.Float n) {
+ int iv = n.intValue();
+ float fv = n.floatValue();
+ if (iv == fv) return iv;
+
+ long lv = n.longValue();
+ if (lv == fv) return java.lang.Long.valueOf(lv).hashCode();
+ else return n.hashCode();
+ }
+ public static int hashFromNumber(java.lang.Number n) {
+ if (n instanceof java.lang.Long) return hashFromLong((java.lang.Long)n);
+ else if (n instanceof java.lang.Double) return hashFromDouble((java.lang.Double)n);
+ else if (n instanceof java.lang.Float) return hashFromFloat((java.lang.Float)n);
+ else return n.hashCode();
+ }
+ public static int hashFromObject(Object a) {
+ if (a instanceof Number) return hashFromNumber((Number)a);
+ else return a.hashCode();
+ }
+
+ private static int unboxCharOrInt(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).intValue();
+ }
+ private static long unboxCharOrLong(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).longValue();
+ }
+ private static float unboxCharOrFloat(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).floatValue();
+ }
+ private static double unboxCharOrDouble(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).doubleValue();
+ }
+
+/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */
+
+ /** arg1 + arg2 */
+ public static Object add(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+ if (maxcode <= INT) {
+ return boxToInteger(unboxCharOrInt(arg1, code1) + unboxCharOrInt(arg2, code2));
+ }
+ if (maxcode <= LONG) {
+ return boxToLong(unboxCharOrLong(arg1, code1) + unboxCharOrLong(arg2, code2));
+ }
+ if (maxcode <= FLOAT) {
+ return boxToFloat(unboxCharOrFloat(arg1, code1) + unboxCharOrFloat(arg2, code2));
+ }
+ if (maxcode <= DOUBLE) {
+ return boxToDouble(unboxCharOrDouble(arg1, code1) + unboxCharOrDouble(arg2, code2));
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 - arg2 */
+ public static Object subtract(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+ if (maxcode <= INT) {
+ return boxToInteger(unboxCharOrInt(arg1, code1) - unboxCharOrInt(arg2, code2));
+ }
+ if (maxcode <= LONG) {
+ return boxToLong(unboxCharOrLong(arg1, code1) - unboxCharOrLong(arg2, code2));
+ }
+ if (maxcode <= FLOAT) {
+ return boxToFloat(unboxCharOrFloat(arg1, code1) - unboxCharOrFloat(arg2, code2));
+ }
+ if (maxcode <= DOUBLE) {
+ return boxToDouble(unboxCharOrDouble(arg1, code1) - unboxCharOrDouble(arg2, code2));
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 * arg2 */
+ public static Object multiply(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+ if (maxcode <= INT) {
+ return boxToInteger(unboxCharOrInt(arg1, code1) * unboxCharOrInt(arg2, code2));
+ }
+ if (maxcode <= LONG) {
+ return boxToLong(unboxCharOrLong(arg1, code1) * unboxCharOrLong(arg2, code2));
+ }
+ if (maxcode <= FLOAT) {
+ return boxToFloat(unboxCharOrFloat(arg1, code1) * unboxCharOrFloat(arg2, code2));
+ }
+ if (maxcode <= DOUBLE) {
+ return boxToDouble(unboxCharOrDouble(arg1, code1) * unboxCharOrDouble(arg2, code2));
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 / arg2 */
+ public static Object divide(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) / unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) / unboxCharOrLong(arg2, code2));
+ if (maxcode <= FLOAT)
+ return boxToFloat(unboxCharOrFloat(arg1, code1) / unboxCharOrFloat(arg2, code2));
+ if (maxcode <= DOUBLE)
+ return boxToDouble(unboxCharOrDouble(arg1, code1) / unboxCharOrDouble(arg2, code2));
+
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 % arg2 */
+ public static Object takeModulo(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) % unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) % unboxCharOrLong(arg2, code2));
+ if (maxcode <= FLOAT)
+ return boxToFloat(unboxCharOrFloat(arg1, code1) % unboxCharOrFloat(arg2, code2));
+ if (maxcode <= DOUBLE)
+ return boxToDouble(unboxCharOrDouble(arg1, code1) % unboxCharOrDouble(arg2, code2));
+
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 >> arg2 */
+ public static Object shiftSignedRight(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ if (code1 <= INT) {
+ int val1 = unboxCharOrInt(arg1, code1);
+ if (code2 <= INT) {
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToInteger(val1 >> val2);
+ }
+ if (code2 <= LONG) {
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToInteger(val1 >> val2);
+ }
+ }
+ if (code1 <= LONG) {
+ long val1 = unboxCharOrLong(arg1, code1);
+ if (code2 <= INT) {
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToLong(val1 >> val2);
+ }
+ if (code2 <= LONG) {
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToLong(val1 >> val2);
+ }
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 << arg2 */
+ public static Object shiftSignedLeft(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ if (code1 <= INT) {
+ int val1 = unboxCharOrInt(arg1, code1);
+ if (code2 <= INT) {
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToInteger(val1 << val2);
+ }
+ if (code2 <= LONG) {
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToInteger(val1 << val2);
+ }
+ }
+ if (code1 <= LONG) {
+ long val1 = unboxCharOrLong(arg1, code1);
+ if (code2 <= INT) {
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToLong(val1 << val2);
+ }
+ if (code2 <= LONG) {
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToLong(val1 << val2);
+ }
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 >>> arg2 */
+ public static Object shiftLogicalRight(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ if (code1 <= INT) {
+ int val1 = unboxCharOrInt(arg1, code1);
+ if (code2 <= INT) {
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToInteger(val1 >>> val2);
+ }
+ if (code2 <= LONG) {
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToInteger(val1 >>> val2);
+ }
+ }
+ if (code1 <= LONG) {
+ long val1 = unboxCharOrLong(arg1, code1);
+ if (code2 <= INT) {
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToLong(val1 >>> val2);
+ }
+ if (code2 <= LONG) {
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToLong(val1 >>> val2);
+ }
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** -arg */
+ public static Object negate(Object arg) throws NoSuchMethodException {
+ int code = typeCode(arg);
+ if (code <= INT) {
+ int val = unboxCharOrInt(arg, code);
+ return boxToInteger(-val);
+ }
+ if (code <= LONG) {
+ long val = unboxCharOrLong(arg, code);
+ return boxToLong(-val);
+ }
+ if (code <= FLOAT) {
+ float val = unboxCharOrFloat(arg, code);
+ return boxToFloat(-val);
+ }
+ if (code <= DOUBLE) {
+ double val = unboxCharOrDouble(arg, code);
+ return boxToDouble(-val);
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** +arg */
+ public static Object positive(Object arg) throws NoSuchMethodException {
+ int code = typeCode(arg);
+ if (code <= INT) {
+ return boxToInteger(+unboxCharOrInt(arg, code));
+ }
+ if (code <= LONG) {
+ return boxToLong(+unboxCharOrLong(arg, code));
+ }
+ if (code <= FLOAT) {
+ return boxToFloat(+unboxCharOrFloat(arg, code));
+ }
+ if (code <= DOUBLE) {
+ return boxToDouble(+unboxCharOrDouble(arg, code));
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 & arg2 */
+ public static Object takeAnd(Object arg1, Object arg2) throws NoSuchMethodException {
+ if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue());
+ else
+ throw new NoSuchMethodException();
+ }
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) & unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) & unboxCharOrLong(arg2, code2));
+
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 | arg2 */
+ public static Object takeOr(Object arg1, Object arg2) throws NoSuchMethodException {
+ if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue());
+ else
+ throw new NoSuchMethodException();
+ }
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) | unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) | unboxCharOrLong(arg2, code2));
+
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 ^ arg2 */
+ public static Object takeXor(Object arg1, Object arg2) throws NoSuchMethodException {
+ if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue());
+ else
+ throw new NoSuchMethodException();
+ }
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) ^ unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) ^ unboxCharOrLong(arg2, code2));
+
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 && arg2 */
+ public static Object takeConditionalAnd(Object arg1, Object arg2) throws NoSuchMethodException {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) {
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() && ((java.lang.Boolean) arg2).booleanValue());
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** arg1 || arg2 */
+ public static Object takeConditionalOr(Object arg1, Object arg2) throws NoSuchMethodException {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean)) {
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() || ((java.lang.Boolean) arg2).booleanValue());
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** ~arg */
+ public static Object complement(Object arg) throws NoSuchMethodException {
+ int code = typeCode(arg);
+ if (code <= INT) {
+ return boxToInteger(~unboxCharOrInt(arg, code));
+ }
+ if (code <= LONG) {
+ return boxToLong(~unboxCharOrLong(arg, code));
+ }
+ throw new NoSuchMethodException();
+ }
+
+ /** !arg */
+ public static Object takeNot(Object arg) throws NoSuchMethodException {
+ if (arg instanceof Boolean) {
+ return boxToBoolean(!((java.lang.Boolean) arg).booleanValue());
+ }
+ throw new NoSuchMethodException();
+ }
+
+ public static Object testEqual(Object arg1, Object arg2) throws NoSuchMethodException {
+ return boxToBoolean(arg1 == arg2);
+ }
+
+ public static Object testNotEqual(Object arg1, Object arg2) throws NoSuchMethodException {
+ return boxToBoolean(arg1 != arg2);
+ }
+
+ public static Object testLessThan(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+ if (maxcode <= INT) {
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToBoolean(val1 < val2);
+ }
+ if (maxcode <= LONG) {
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToBoolean(val1 < val2);
+ }
+ if (maxcode <= FLOAT) {
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
+ return boxToBoolean(val1 < val2);
+ }
+ if (maxcode <= DOUBLE) {
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
+ return boxToBoolean(val1 < val2);
+ }
+ throw new NoSuchMethodException();
+ }
+
+ public static Object testLessOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+ if (maxcode <= INT) {
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToBoolean(val1 <= val2);
+ }
+ if (maxcode <= LONG) {
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToBoolean(val1 <= val2);
+ }
+ if (maxcode <= FLOAT) {
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
+ return boxToBoolean(val1 <= val2);
+ }
+ if (maxcode <= DOUBLE) {
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
+ return boxToBoolean(val1 <= val2);
+ }
+ throw new NoSuchMethodException();
+ }
+
+ public static Object testGreaterOrEqualThan(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+ if (maxcode <= INT) {
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToBoolean(val1 >= val2);
+ }
+ if (maxcode <= LONG) {
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToBoolean(val1 >= val2);
+ }
+ if (maxcode <= FLOAT) {
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
+ return boxToBoolean(val1 >= val2);
+ }
+ if (maxcode <= DOUBLE) {
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
+ return boxToBoolean(val1 >= val2);
+ }
+ throw new NoSuchMethodException();
+ }
+
+ public static Object testGreaterThan(Object arg1, Object arg2) throws NoSuchMethodException {
+ int code1 = typeCode(arg1);
+ int code2 = typeCode(arg2);
+ int maxcode = (code1 < code2) ? code2 : code1;
+ if (maxcode <= INT) {
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
+ return boxToBoolean(val1 > val2);
+ }
+ if (maxcode <= LONG) {
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
+ return boxToBoolean(val1 > val2);
+ }
+ if (maxcode <= FLOAT) {
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
+ return boxToBoolean(val1 > val2);
+ }
+ if (maxcode <= DOUBLE) {
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
+ return boxToBoolean(val1 > val2);
+ }
+ throw new NoSuchMethodException();
+ }
+
+ public static boolean isBoxedNumberOrBoolean(Object arg) {
+ return (arg instanceof java.lang.Boolean) || isBoxedNumber(arg);
+ }
+ public static boolean isBoxedNumber(Object arg) {
+ return (
+ (arg instanceof java.lang.Integer)
+ || (arg instanceof java.lang.Long)
+ || (arg instanceof java.lang.Double)
+ || (arg instanceof java.lang.Float)
+ || (arg instanceof java.lang.Short)
+ || (arg instanceof java.lang.Character)
+ || (arg instanceof java.lang.Byte)
+ );
+ }
+
+ /** arg.toChar */
+ public static java.lang.Character toCharacter(Object arg) throws NoSuchMethodException {
+ if (arg instanceof java.lang.Integer) return boxToCharacter((char)unboxToInt(arg));
+ if (arg instanceof java.lang.Short) return boxToCharacter((char)unboxToShort(arg));
+ if (arg instanceof java.lang.Character) return (java.lang.Character)arg;
+ if (arg instanceof java.lang.Long) return boxToCharacter((char)unboxToLong(arg));
+ if (arg instanceof java.lang.Byte) return boxToCharacter((char)unboxToByte(arg));
+ if (arg instanceof java.lang.Float) return boxToCharacter((char)unboxToFloat(arg));
+ if (arg instanceof java.lang.Double) return boxToCharacter((char)unboxToDouble(arg));
+ throw new NoSuchMethodException();
+ }
+
+ /** arg.toByte */
+ public static java.lang.Byte toByte(Object arg) throws NoSuchMethodException {
+ if (arg instanceof java.lang.Integer) return boxToByte((byte)unboxToInt(arg));
+ if (arg instanceof java.lang.Character) return boxToByte((byte)unboxToChar(arg));
+ if (arg instanceof java.lang.Byte) return (java.lang.Byte)arg;
+ if (arg instanceof java.lang.Long) return boxToByte((byte)unboxToLong(arg));
+ if (arg instanceof java.lang.Short) return boxToByte((byte)unboxToShort(arg));
+ if (arg instanceof java.lang.Float) return boxToByte((byte)unboxToFloat(arg));
+ if (arg instanceof java.lang.Double) return boxToByte((byte)unboxToDouble(arg));
+ throw new NoSuchMethodException();
+ }
+
+ /** arg.toShort */
+ public static java.lang.Short toShort(Object arg) throws NoSuchMethodException {
+ if (arg instanceof java.lang.Integer) return boxToShort((short)unboxToInt(arg));
+ if (arg instanceof java.lang.Long) return boxToShort((short)unboxToLong(arg));
+ if (arg instanceof java.lang.Character) return boxToShort((short)unboxToChar(arg));
+ if (arg instanceof java.lang.Byte) return boxToShort((short)unboxToByte(arg));
+ if (arg instanceof java.lang.Short) return (java.lang.Short)arg;
+ if (arg instanceof java.lang.Float) return boxToShort((short)unboxToFloat(arg));
+ if (arg instanceof java.lang.Double) return boxToShort((short)unboxToDouble(arg));
+ throw new NoSuchMethodException();
+ }
+
+ /** arg.toInt */
+ public static java.lang.Integer toInteger(Object arg) throws NoSuchMethodException {
+ if (arg instanceof java.lang.Integer) return (java.lang.Integer)arg;
+ if (arg instanceof java.lang.Long) return boxToInteger((int)unboxToLong(arg));
+ if (arg instanceof java.lang.Double) return boxToInteger((int)unboxToDouble(arg));
+ if (arg instanceof java.lang.Float) return boxToInteger((int)unboxToFloat(arg));
+ if (arg instanceof java.lang.Character) return boxToInteger((int)unboxToChar(arg));
+ if (arg instanceof java.lang.Byte) return boxToInteger((int)unboxToByte(arg));
+ if (arg instanceof java.lang.Short) return boxToInteger((int)unboxToShort(arg));
+ throw new NoSuchMethodException();
+ }
+
+ /** arg.toLong */
+ public static java.lang.Long toLong(Object arg) throws NoSuchMethodException {
+ if (arg instanceof java.lang.Integer) return boxToLong((long)unboxToInt(arg));
+ if (arg instanceof java.lang.Double) return boxToLong((long)unboxToDouble(arg));
+ if (arg instanceof java.lang.Float) return boxToLong((long)unboxToFloat(arg));
+ if (arg instanceof java.lang.Long) return (java.lang.Long)arg;
+ if (arg instanceof java.lang.Character) return boxToLong((long)unboxToChar(arg));
+ if (arg instanceof java.lang.Byte) return boxToLong((long)unboxToByte(arg));
+ if (arg instanceof java.lang.Short) return boxToLong((long)unboxToShort(arg));
+ throw new NoSuchMethodException();
+ }
+
+ /** arg.toFloat */
+ public static java.lang.Float toFloat(Object arg) throws NoSuchMethodException {
+ if (arg instanceof java.lang.Integer) return boxToFloat((float)unboxToInt(arg));
+ if (arg instanceof java.lang.Long) return boxToFloat((float)unboxToLong(arg));
+ if (arg instanceof java.lang.Float) return (java.lang.Float)arg;
+ if (arg instanceof java.lang.Double) return boxToFloat((float)unboxToDouble(arg));
+ if (arg instanceof java.lang.Character) return boxToFloat((float)unboxToChar(arg));
+ if (arg instanceof java.lang.Byte) return boxToFloat((float)unboxToByte(arg));
+ if (arg instanceof java.lang.Short) return boxToFloat((float)unboxToShort(arg));
+ throw new NoSuchMethodException();
+ }
+
+ /** arg.toDouble */
+ public static java.lang.Double toDouble(Object arg) throws NoSuchMethodException {
+ if (arg instanceof java.lang.Integer) return boxToDouble((double)unboxToInt(arg));
+ if (arg instanceof java.lang.Float) return boxToDouble((double)unboxToFloat(arg));
+ if (arg instanceof java.lang.Double) return (java.lang.Double)arg;
+ if (arg instanceof java.lang.Long) return boxToDouble((double)unboxToLong(arg));
+ if (arg instanceof java.lang.Character) return boxToDouble((double)unboxToChar(arg));
+ if (arg instanceof java.lang.Byte) return boxToDouble((double)unboxToByte(arg));
+ if (arg instanceof java.lang.Short) return boxToDouble((double)unboxToShort(arg));
+ throw new NoSuchMethodException();
+ }
+
+}
diff --git a/test/files/pos/t5644/other.scala b/test/files/pos/t5644/other.scala
new file mode 100644
index 0000000000..50388fd9ec
--- /dev/null
+++ b/test/files/pos/t5644/other.scala
@@ -0,0 +1,3 @@
+class Foo {
+ List(1) exists(_ == (null: Any))
+}
diff --git a/test/files/pos/t5667.scala b/test/files/pos/t5667.scala
new file mode 100644
index 0000000000..513de5b663
--- /dev/null
+++ b/test/files/pos/t5667.scala
@@ -0,0 +1,6 @@
+object Main {
+ implicit class C(val s: String) extends AnyVal
+ implicit class C2(val s: String) extends AnyRef
+
+ implicit case class Foo(i: Int)
+}
diff --git a/test/files/pos/t5702-pos-infix-star.scala b/test/files/pos/t5702-pos-infix-star.scala
new file mode 100644
index 0000000000..756bcdd8de
--- /dev/null
+++ b/test/files/pos/t5702-pos-infix-star.scala
@@ -0,0 +1,15 @@
+
+object Test {
+ case class *(a: Int, b: Int)
+ type Star = *
+ case class P(a: Int, b: Star) // alias still required
+
+ def main(args: Array[String]) {
+ val v = new *(6,7)
+ val x * y = v
+ printf("%d,%d\n",x,y)
+ val p = P(5, v)
+ val P(a, b * c) = p
+ printf("%d,%d,%d\n",a,b,c)
+ }
+}
diff --git a/test/files/pos/t5703/Base.java b/test/files/pos/t5703/Base.java
new file mode 100644
index 0000000000..fa75cc3bdd
--- /dev/null
+++ b/test/files/pos/t5703/Base.java
@@ -0,0 +1,3 @@
+public abstract class Base<Params> {
+ public abstract void func(Params[] params);
+} \ No newline at end of file
diff --git a/test/files/pos/t5703/Impl.scala b/test/files/pos/t5703/Impl.scala
new file mode 100644
index 0000000000..ee22d8fb4b
--- /dev/null
+++ b/test/files/pos/t5703/Impl.scala
@@ -0,0 +1,3 @@
+class Implementation extends Base[Object] {
+ def func(params: Array[Object]): Unit = {}
+} \ No newline at end of file
diff --git a/test/files/pos/t5706.flags b/test/files/pos/t5706.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/pos/t5706.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/pos/t5706.scala b/test/files/pos/t5706.scala
new file mode 100644
index 0000000000..847acb693f
--- /dev/null
+++ b/test/files/pos/t5706.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.Context
+
+class Logger {
+ def error(message: String) = macro Impls.error
+}
+
+object Impls {
+ type LoggerContext = Context { type PrefixType = Logger }
+ def error(c: LoggerContext)(message: c.Expr[String]): c.Expr[Unit] = ???
+}
diff --git a/test/files/pos/t5720-ownerous.scala b/test/files/pos/t5720-ownerous.scala
new file mode 100644
index 0000000000..3a12499612
--- /dev/null
+++ b/test/files/pos/t5720-ownerous.scala
@@ -0,0 +1,56 @@
+
+/*
+ * The block under qual$1 must be owned by it.
+ * In the sample bug, the first default arg generates x$4,
+ * the second default arg generates qual$1, hence the maximal
+ * minimization.
+ *
+ <method> <triedcooking> def model: C.this.M = {
+ val qual$1: C.this.M = scala.Option.apply[C.this.M]({
+ val x$1: lang.this.String("foo") = "foo";
+ val x$2: String = C.this.M.apply$default$2("foo");
+ C.this.M.apply("foo")(x$2)
+}).getOrElse[C.this.M]({
+ val x$3: lang.this.String("bar") = "bar";
+ val x$4: String = C.this.M.apply$default$2("bar");
+ C.this.M.apply("bar")(x$4)
+ });
+ val x$5: lang.this.String("baz") = "baz";
+ val x$6: String = qual$1.copy$default$2("baz");
+ qual$1.copy("baz")(x$6)
+ }
+ */
+class C {
+ case class M(currentUser: String = "anon")(val message: String = "empty")
+ val m = M("foo")()
+
+ // reported
+ //def model = Option(M("foo")()).getOrElse(M("bar")()).copy(currentUser = "")()
+
+ // the bug
+ def model = Option(m).getOrElse(M("bar")()).copy("baz")()
+
+ // style points for this version
+ def modish = ((null: Option[M]) getOrElse new M()()).copy()()
+
+ // various simplifications are too simple
+ case class N(currentUser: String = "anon")
+ val n = N("fun")
+ def nudel = Option(n).getOrElse(N()).copy()
+}
+
+object Test {
+ def main(args: Array[String]) {
+ val c = new C
+ println(c.model.currentUser)
+ println(c.model.message)
+ }
+}
+/*
+symbol value x$4$1 does not exist in badcopy.C.model
+at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:45)
+at scala.tools.nsc.Global.abort(Global.scala:202)
+at scala.tools.nsc.backend.icode.GenICode$ICodePhase.liftedTree2$1(GenICode.scala:998)
+at scala.tools.nsc.backend.icode.GenICode$ICodePhase.scala$tools$nsc$backend$icode$GenICode$ICodePhase$$genLoad(GenICode.scala:992)
+*/
+
diff --git a/test/files/pos/t5727.scala b/test/files/pos/t5727.scala
new file mode 100644
index 0000000000..e091d827b4
--- /dev/null
+++ b/test/files/pos/t5727.scala
@@ -0,0 +1,31 @@
+
+/*
+ * We like operators, bar none.
+ */
+object Test {
+
+ trait SomeInfo
+ case object NoInfo extends SomeInfo
+
+ sealed abstract class Res[+T]
+ case object NotRes extends Res[Nothing]
+
+
+ abstract class Base[+T] {
+ def apply(f: String): Res[T]
+ // 'i' crashes the compiler, similarly if we use currying
+ //def |[U >: T](a: => Base[U], i: SomeInfo = NoInfo): Base[U] = null
+ def bar[U >: T](a: => Base[U], i: SomeInfo = NoInfo): Base[U] = null
+ }
+
+ implicit def fromStringToBase(a: String): Base[String] = new Base[String] { def apply(in: String) = NotRes }
+
+ // bug
+ //def Sample: Base[Any] = ( rep("foo" | "bar") | "sth")
+ def Sample: Base[Any] = ( rep("foo" bar "bar") bar "sth")
+
+ def rep[T](p: => Base[T]): Base[T] = null // whatever
+
+ def main(args: Array[String]) {
+ }
+}
diff --git a/test/files/pos/t5729.scala b/test/files/pos/t5729.scala
new file mode 100644
index 0000000000..9fd9c9ffbb
--- /dev/null
+++ b/test/files/pos/t5729.scala
@@ -0,0 +1,6 @@
+trait T[X]
+object Test {
+ def join(in: Seq[T[_]]): Int = ???
+ def join[S](in: Seq[T[S]]): String = ???
+ join(null: Seq[T[_]])
+} \ No newline at end of file
diff --git a/test/files/pos/t5769.scala b/test/files/pos/t5769.scala
new file mode 100644
index 0000000000..723d37bfee
--- /dev/null
+++ b/test/files/pos/t5769.scala
@@ -0,0 +1,8 @@
+// a.scala
+
+class A {
+ type AI = Array[Int]
+
+ def f1 = arrayTag[Array[Int]]
+ def f2 = arrayTag[AI]
+} \ No newline at end of file
diff --git a/test/files/pos/virtpatmat_alts_subst.flags b/test/files/pos/virtpatmat_alts_subst.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_alts_subst.flags
+++ b/test/files/pos/virtpatmat_alts_subst.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_anonfun_for.flags b/test/files/pos/virtpatmat_anonfun_for.flags
index 23e3dc7d26..e69de29bb2 100644
--- a/test/files/pos/virtpatmat_anonfun_for.flags
+++ b/test/files/pos/virtpatmat_anonfun_for.flags
@@ -1 +0,0 @@
--Yvirtpatmat \ No newline at end of file
diff --git a/test/files/pos/virtpatmat_binding_opt.flags b/test/files/pos/virtpatmat_binding_opt.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_binding_opt.flags
+++ b/test/files/pos/virtpatmat_binding_opt.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_castbinder.flags b/test/files/pos/virtpatmat_castbinder.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_castbinder.flags
+++ b/test/files/pos/virtpatmat_castbinder.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_exist1.flags b/test/files/pos/virtpatmat_exist1.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_exist1.flags
+++ b/test/files/pos/virtpatmat_exist1.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_exist2.flags b/test/files/pos/virtpatmat_exist2.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_exist2.flags
+++ b/test/files/pos/virtpatmat_exist2.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_exist3.flags b/test/files/pos/virtpatmat_exist3.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_exist3.flags
+++ b/test/files/pos/virtpatmat_exist3.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_exist_uncurry.scala b/test/files/pos/virtpatmat_exist_uncurry.scala
new file mode 100644
index 0000000000..e017da6343
--- /dev/null
+++ b/test/files/pos/virtpatmat_exist_uncurry.scala
@@ -0,0 +1,6 @@
+object Test {
+ trait Leaf[T] {
+ def collect[U](f: PartialFunction[Leaf[_], U]): List[U]
+ def leaves: List[Leaf[T]] = collect { case l: Leaf[T] => l }
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/virtpatmat_gadt_array.flags b/test/files/pos/virtpatmat_gadt_array.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_gadt_array.flags
+++ b/test/files/pos/virtpatmat_gadt_array.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_infer_single_1.flags b/test/files/pos/virtpatmat_infer_single_1.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_infer_single_1.flags
+++ b/test/files/pos/virtpatmat_infer_single_1.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_instof_valuetype.flags b/test/files/pos/virtpatmat_instof_valuetype.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_instof_valuetype.flags
+++ b/test/files/pos/virtpatmat_instof_valuetype.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_obj_in_case.flags b/test/files/pos/virtpatmat_obj_in_case.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/pos/virtpatmat_obj_in_case.flags
+++ b/test/files/pos/virtpatmat_obj_in_case.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/pos/virtpatmat_partialfun_nsdnho.scala b/test/files/pos/virtpatmat_partialfun_nsdnho.scala
new file mode 100644
index 0000000000..f79e82813c
--- /dev/null
+++ b/test/files/pos/virtpatmat_partialfun_nsdnho.scala
@@ -0,0 +1,18 @@
+class Test {
+ // m.$minus(1)
+ // at scala.Predef$.assert(Predef.scala:185)
+ // at scala.tools.nsc.Global.assert(Global.scala:187)
+ // at scala.tools.nsc.typechecker.SuperAccessors$SuperAccTransformer.transform(SuperAccessors.scala:291)
+ val a: (Map[Int, Int] => (Any => Any)) = { m => { case _ => m - 1} }
+
+ // patmat-crash.scala:9: error: erroneous or inaccessible type
+ val b: (Int => (Any => Any)) = { m => { case _ => m } }
+
+ // no-symbol does not have an owner (this is a bug: scala version 2.10.0-20120420-170445-56c1f29250)
+ // at scala.reflect.internal.SymbolTable.abort(SymbolTable.scala:45)
+ // at scala.tools.nsc.Global.abort(Global.scala:202)
+ // at scala.reflect.internal.Symbols$NoSymbol.owner(Symbols.scala:3031)
+ // at scala.tools.nsc.typechecker.SuperAccessors$SuperAccTransformer.hostForAccessorOf(SuperAccessors.scala:474)
+ // at scala.tools.nsc.typechecker.SuperAccessors$SuperAccTransformer.needsProtectedAccessor(SuperAccessors.scala:457)
+ val c: (Int => (Any => Any)) = { m => { case _ => m.toInt } }
+} \ No newline at end of file
diff --git a/test/files/presentation/callcc-interpreter.check b/test/files/presentation/callcc-interpreter.check
index c50e171b4e..68ac904b18 100644
--- a/test/files/presentation/callcc-interpreter.check
+++ b/test/files/presentation/callcc-interpreter.check
@@ -4,66 +4,66 @@ askTypeCompletion at CallccInterpreter.scala(51,38)
================================================================================
[response] aksTypeCompletion at (51,38)
retrieved 64 members
-`class AddcallccInterpreter.Add`
-`class AppcallccInterpreter.App`
-`class CcccallccInterpreter.Ccc`
-`class ConcallccInterpreter.Con`
-`class FuncallccInterpreter.Fun`
-`class LamcallccInterpreter.Lam`
-`class McallccInterpreter.M`
-`class NumcallccInterpreter.Num`
-`class VarcallccInterpreter.Var`
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(callccInterpreter.type, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method add(a: callccInterpreter.Value, b: callccInterpreter.Value)callccInterpreter.M[_ >: callccInterpreter.Num with callccInterpreter.Wrong.type <: Product with Serializable with callccInterpreter.Value]`
-`method apply(a: callccInterpreter.Value, b: callccInterpreter.Value)callccInterpreter.M[callccInterpreter.Value]`
-`method asInstanceOf[T0]=> T0`
-`method callCC[A](h: (A => callccInterpreter.M[A]) => callccInterpreter.M[A])callccInterpreter.M[A]`
-`method clone()Object`
-`method ensuring(cond: Boolean)callccInterpreter.type`
-`method ensuring(cond: Boolean, msg: => Any)callccInterpreter.type`
-`method ensuring(cond: callccInterpreter.type => Boolean)callccInterpreter.type`
-`method ensuring(cond: callccInterpreter.type => Boolean, msg: => Any)callccInterpreter.type`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method id[A]=> A => A`
-`method interp(t: callccInterpreter.Term, e: callccInterpreter.Environment)callccInterpreter.M[callccInterpreter.Value]`
-`method isInstanceOf[T0]=> Boolean`
-`method lookup(x: callccInterpreter.Name, e: callccInterpreter.Environment)callccInterpreter.M[callccInterpreter.Value]`
-`method main(args: Array[String])Unit`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method showM(m: callccInterpreter.M[callccInterpreter.Value])String`
-`method synchronized[T0](x$1: T0)T0`
-`method test(t: callccInterpreter.Term)String`
-`method toString()String`
-`method unitM[A](a: A)callccInterpreter.M[A]`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> callccInterpreter.type`
-`method →[B](y: B)(callccInterpreter.type, B)`
-`object WrongcallccInterpreter.Wrong.type`
-`trait TermcallccInterpreter.Term`
-`trait ValuecallccInterpreter.Value`
-`type AnswercallccInterpreter.Answer`
-`type EnvironmentcallccInterpreter.Environment`
-`type NamecallccInterpreter.Name`
-`value __leftOfArrowcallccInterpreter.type`
-`value __resultOfEnsuringcallccInterpreter.type`
-`value selfAny`
-`value term0callccInterpreter.App`
-`value term1callccInterpreter.App`
-`value term2callccInterpreter.Add`
+[accessible: true] `class AddcallccInterpreter.Add`
+[accessible: true] `class AppcallccInterpreter.App`
+[accessible: true] `class CcccallccInterpreter.Ccc`
+[accessible: true] `class ConcallccInterpreter.Con`
+[accessible: true] `class FuncallccInterpreter.Fun`
+[accessible: true] `class LamcallccInterpreter.Lam`
+[accessible: true] `class McallccInterpreter.M`
+[accessible: true] `class NumcallccInterpreter.Num`
+[accessible: true] `class VarcallccInterpreter.Var`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(callccInterpreter.type, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method add(a: callccInterpreter.Value, b: callccInterpreter.Value)callccInterpreter.M[_ >: callccInterpreter.Num with callccInterpreter.Wrong.type <: Product with Serializable with callccInterpreter.Value]`
+[accessible: true] `method apply(a: callccInterpreter.Value, b: callccInterpreter.Value)callccInterpreter.M[callccInterpreter.Value]`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method callCC[A](h: (A => callccInterpreter.M[A]) => callccInterpreter.M[A])callccInterpreter.M[A]`
+[accessible: true] `method clone()Object`
+[accessible: true] `method ensuring(cond: Boolean)callccInterpreter.type`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)callccInterpreter.type`
+[accessible: true] `method ensuring(cond: callccInterpreter.type => Boolean)callccInterpreter.type`
+[accessible: true] `method ensuring(cond: callccInterpreter.type => Boolean, msg: => Any)callccInterpreter.type`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method finalize()Unit`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method id[A]=> A => A`
+[accessible: true] `method interp(t: callccInterpreter.Term, e: callccInterpreter.Environment)callccInterpreter.M[callccInterpreter.Value]`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method lookup(x: callccInterpreter.Name, e: callccInterpreter.Environment)callccInterpreter.M[callccInterpreter.Value]`
+[accessible: true] `method main(args: Array[String])Unit`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method showM(m: callccInterpreter.M[callccInterpreter.Value])String`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method test(t: callccInterpreter.Term)String`
+[accessible: true] `method toString()String`
+[accessible: true] `method unitM[A](a: A)callccInterpreter.M[A]`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> callccInterpreter.type`
+[accessible: true] `method →[B](y: B)(callccInterpreter.type, B)`
+[accessible: true] `object WrongcallccInterpreter.Wrong.type`
+[accessible: true] `trait TermcallccInterpreter.Term`
+[accessible: true] `trait ValuecallccInterpreter.Value`
+[accessible: true] `type AnswercallccInterpreter.Answer`
+[accessible: true] `type EnvironmentcallccInterpreter.Environment`
+[accessible: true] `type NamecallccInterpreter.Name`
+[accessible: true] `value term0callccInterpreter.App`
+[accessible: true] `value term1callccInterpreter.App`
+[accessible: true] `value term2callccInterpreter.Add`
+[accessible: false] `value __leftOfArrowcallccInterpreter.type`
+[accessible: false] `value __resultOfEnsuringcallccInterpreter.type`
+[accessible: false] `value selfAny`
================================================================================
askType at CallccInterpreter.scala(14,21)
diff --git a/test/files/presentation/hyperlinks.check b/test/files/presentation/hyperlinks.check
new file mode 100644
index 0000000000..85d295dd7d
--- /dev/null
+++ b/test/files/presentation/hyperlinks.check
@@ -0,0 +1,46 @@
+reload: NameDefaultTests.scala, PatMatTests.scala
+
+askHyperlinkPos for `someOtherInt` at (14,24) NameDefaultTests.scala
+================================================================================
+[response] found askHyperlinkPos for `someOtherInt` at (12,9) NameDefaultTests.scala
+================================================================================
+
+askHyperlinkPos for `someString` at (14,45) NameDefaultTests.scala
+================================================================================
+[response] found askHyperlinkPos for `someString` at (3,7) NameDefaultTests.scala
+================================================================================
+
+askHyperlinkPos for `CaseOne` at (12,18) PatMatTests.scala
+================================================================================
+[response] found askHyperlinkPos for `CaseOne` at (5,12) PatMatTests.scala
+================================================================================
+
+askHyperlinkPos for `first` at (14,21) PatMatTests.scala
+================================================================================
+[response] found askHyperlinkPos for `first` at (12,29) PatMatTests.scala
+================================================================================
+
+askHyperlinkPos for `tmp` at (15,19) PatMatTests.scala
+================================================================================
+[response] found askHyperlinkPos for `tmp` at (13,13) PatMatTests.scala
+================================================================================
+
+askHyperlinkPos for `CaseTwo` at (17,18) PatMatTests.scala
+================================================================================
+[response] found askHyperlinkPos for `CaseTwo` at (6,12) PatMatTests.scala
+================================================================================
+
+askHyperlinkPos for `mystring` at (18,24) PatMatTests.scala
+================================================================================
+[response] found askHyperlinkPos for `mystring` at (17,25) PatMatTests.scala
+================================================================================
+
+askHyperlinkPos for `x` at (25,13) PatMatTests.scala
+================================================================================
+[response] found askHyperlinkPos for `x` at (23,10) PatMatTests.scala
+================================================================================
+
+askHyperlinkPos for `y` at (25,21) PatMatTests.scala
+================================================================================
+[response] found askHyperlinkPos for `y` at (23,13) PatMatTests.scala
+================================================================================
diff --git a/test/files/presentation/hyperlinks.flags b/test/files/presentation/hyperlinks.flags
new file mode 100644
index 0000000000..dc13682c5e
--- /dev/null
+++ b/test/files/presentation/hyperlinks.flags
@@ -0,0 +1,2 @@
+# This test will fail in the new pattern matcher because
+# it generates trees whose positions are not transparent
diff --git a/test/files/presentation/hyperlinks/Runner.scala b/test/files/presentation/hyperlinks/Runner.scala
new file mode 100644
index 0000000000..3d19f2d948
--- /dev/null
+++ b/test/files/presentation/hyperlinks/Runner.scala
@@ -0,0 +1,11 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+object Test extends InteractiveTest {
+ override def runTests() {
+ // make sure typer is done.. the virtual pattern matcher might translate
+ // some trees and mess up positions. But we'll catch it red handed!
+ sourceFiles foreach (src => askLoadedTyped(src).get)
+ super.runTests()
+ }
+
+} \ No newline at end of file
diff --git a/test/files/presentation/hyperlinks/src/NameDefaultTests.scala b/test/files/presentation/hyperlinks/src/NameDefaultTests.scala
new file mode 100644
index 0000000000..b218040fe3
--- /dev/null
+++ b/test/files/presentation/hyperlinks/src/NameDefaultTests.scala
@@ -0,0 +1,16 @@
+
+class NameDefaults {
+ val someString = "abc"
+ val someInt = 42
+
+ def foo(x: String, y: Int)(implicit logger: Int): Int = y
+
+ implicit val l = 42
+
+ def bar {
+ println()
+ val someOtherInt = 10
+
+ foo(y = someOtherInt/*#*/, x = someString/*#*/)
+ }
+}
diff --git a/test/files/presentation/hyperlinks/src/PatMatTests.scala b/test/files/presentation/hyperlinks/src/PatMatTests.scala
new file mode 100644
index 0000000000..bbd0f2e7ed
--- /dev/null
+++ b/test/files/presentation/hyperlinks/src/PatMatTests.scala
@@ -0,0 +1,28 @@
+package patmat
+
+abstract class BaseType
+
+case class CaseOne(x: Int, y: List[Int]) extends BaseType
+case class CaseTwo(str: String) extends BaseType
+
+class PatMatTests {
+
+ def foo(x: BaseType) {
+ x match {
+ case CaseOne/*#*/(10, first :: second :: Nil) =>
+ val tmp = 23
+ println(first/*#*/)
+ println(tmp/*#*/)
+
+ case CaseTwo/*#*/(mystring) =>
+ println(mystring/*#*/)
+ }
+ }
+
+ def multipleAssign() {
+ val (x, y) = ("abc", "def")
+
+ println(x/*#*/, y/*#*/)
+ }
+
+} \ No newline at end of file
diff --git a/test/files/presentation/ide-bug-1000349.check b/test/files/presentation/ide-bug-1000349.check
index 9c070ef24e..d643f82a25 100644
--- a/test/files/presentation/ide-bug-1000349.check
+++ b/test/files/presentation/ide-bug-1000349.check
@@ -4,37 +4,37 @@ askTypeCompletion at CompletionOnEmptyArgMethod.scala(2,17)
================================================================================
[response] aksTypeCompletion at (2,17)
retrieved 37 members
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(Foo, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method asInstanceOf[T0]=> T0`
-`method clone()Object`
-`method ensuring(cond: Boolean)Foo`
-`method ensuring(cond: Boolean, msg: => Any)Foo`
-`method ensuring(cond: Foo => Boolean)Foo`
-`method ensuring(cond: Foo => Boolean, msg: => Any)Foo`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method foo=> Foo`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method isInstanceOf[T0]=> Boolean`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method synchronized[T0](x$1: T0)T0`
-`method toString()String`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> Foo`
-`method →[B](y: B)(Foo, B)`
-`value __leftOfArrowFoo`
-`value __resultOfEnsuringFoo`
-`value selfAny`
-================================================================================ \ No newline at end of file
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(Foo, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method clone()Object`
+[accessible: true] `method ensuring(cond: Boolean)Foo`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)Foo`
+[accessible: true] `method ensuring(cond: Foo => Boolean)Foo`
+[accessible: true] `method ensuring(cond: Foo => Boolean, msg: => Any)Foo`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method finalize()Unit`
+[accessible: true] `method foo=> Foo`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> Foo`
+[accessible: true] `method →[B](y: B)(Foo, B)`
+[accessible: false] `value __leftOfArrowFoo`
+[accessible: false] `value __resultOfEnsuringFoo`
+[accessible: false] `value selfAny`
+================================================================================
diff --git a/test/files/presentation/ide-bug-1000475.check b/test/files/presentation/ide-bug-1000475.check
index 1718119385..2410ebf71d 100644
--- a/test/files/presentation/ide-bug-1000475.check
+++ b/test/files/presentation/ide-bug-1000475.check
@@ -4,112 +4,112 @@ askTypeCompletion at Foo.scala(3,7)
================================================================================
[response] aksTypeCompletion at (3,7)
retrieved 36 members
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(Object, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method asInstanceOf[T0]=> T0`
-`method clone()Object`
-`method ensuring(cond: Boolean)Object`
-`method ensuring(cond: Boolean, msg: => Any)Object`
-`method ensuring(cond: Object => Boolean)Object`
-`method ensuring(cond: Object => Boolean, msg: => Any)Object`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method isInstanceOf[T0]=> Boolean`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method synchronized[T0](x$1: T0)T0`
-`method toString()String`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> Object`
-`method →[B](y: B)(Object, B)`
-`value __leftOfArrowObject`
-`value __resultOfEnsuringObject`
-`value selfAny`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(Object, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)Object`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)Object`
+[accessible: true] `method ensuring(cond: Object => Boolean)Object`
+[accessible: true] `method ensuring(cond: Object => Boolean, msg: => Any)Object`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> Object`
+[accessible: true] `method →[B](y: B)(Object, B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `value __leftOfArrowObject`
+[accessible: false] `value __resultOfEnsuringObject`
+[accessible: false] `value selfAny`
================================================================================
askTypeCompletion at Foo.scala(6,10)
================================================================================
[response] aksTypeCompletion at (6,10)
retrieved 36 members
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(Object, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method asInstanceOf[T0]=> T0`
-`method clone()Object`
-`method ensuring(cond: Boolean)Object`
-`method ensuring(cond: Boolean, msg: => Any)Object`
-`method ensuring(cond: Object => Boolean)Object`
-`method ensuring(cond: Object => Boolean, msg: => Any)Object`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method isInstanceOf[T0]=> Boolean`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method synchronized[T0](x$1: T0)T0`
-`method toString()String`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> Object`
-`method →[B](y: B)(Object, B)`
-`value __leftOfArrowObject`
-`value __resultOfEnsuringObject`
-`value selfAny`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(Object, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)Object`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)Object`
+[accessible: true] `method ensuring(cond: Object => Boolean)Object`
+[accessible: true] `method ensuring(cond: Object => Boolean, msg: => Any)Object`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> Object`
+[accessible: true] `method →[B](y: B)(Object, B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `value __leftOfArrowObject`
+[accessible: false] `value __resultOfEnsuringObject`
+[accessible: false] `value selfAny`
================================================================================
askTypeCompletion at Foo.scala(7,7)
================================================================================
[response] aksTypeCompletion at (7,7)
retrieved 36 members
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(Object, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method asInstanceOf[T0]=> T0`
-`method clone()Object`
-`method ensuring(cond: Boolean)Object`
-`method ensuring(cond: Boolean, msg: => Any)Object`
-`method ensuring(cond: Object => Boolean)Object`
-`method ensuring(cond: Object => Boolean, msg: => Any)Object`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method isInstanceOf[T0]=> Boolean`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method synchronized[T0](x$1: T0)T0`
-`method toString()String`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> Object`
-`method →[B](y: B)(Object, B)`
-`value __leftOfArrowObject`
-`value __resultOfEnsuringObject`
-`value selfAny`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(Object, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)Object`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)Object`
+[accessible: true] `method ensuring(cond: Object => Boolean)Object`
+[accessible: true] `method ensuring(cond: Object => Boolean, msg: => Any)Object`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> Object`
+[accessible: true] `method →[B](y: B)(Object, B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `value __leftOfArrowObject`
+[accessible: false] `value __resultOfEnsuringObject`
+[accessible: false] `value selfAny`
================================================================================
diff --git a/test/files/presentation/ide-bug-1000531.check b/test/files/presentation/ide-bug-1000531.check
index ae202001eb..2ae0158a13 100644
--- a/test/files/presentation/ide-bug-1000531.check
+++ b/test/files/presentation/ide-bug-1000531.check
@@ -3,124 +3,125 @@ reload: CrashOnLoad.scala
askTypeCompletion at CrashOnLoad.scala(6,12)
================================================================================
[response] aksTypeCompletion at (6,12)
-retrieved 123 members
-`class GroupedIteratorIterator[B]#GroupedIterator`
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ++[B >: B](that: => scala.collection.GenTraversableOnce[B])Iterator[B]`
-`method ->[B](y: B)(java.util.Iterator[B], B)`
-`method /:[B](z: B)(op: (B, B) => B)B`
-`method /:\[A1 >: B](z: A1)(op: (A1, A1) => A1)A1`
-`method :\[B](z: B)(op: (B, B) => B)B`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method addString(b: StringBuilder)StringBuilder`
-`method addString(b: StringBuilder, sep: String)StringBuilder`
-`method addString(b: StringBuilder, start: String, sep: String, end: String)StringBuilder`
-`method aggregate[B](z: B)(seqop: (B, B) => B, combop: (B, B) => B)B`
-`method asInstanceOf[T0]=> T0`
-`method buffered=> scala.collection.BufferedIterator[B]`
-`method clone()Object`
-`method collectFirst[B](pf: PartialFunction[B,B])Option[B]`
-`method collect[B](pf: PartialFunction[B,B])Iterator[B]`
-`method contains(elem: Any)Boolean`
-`method copyToArray[B >: B](xs: Array[B])Unit`
-`method copyToArray[B >: B](xs: Array[B], start: Int)Unit`
-`method copyToArray[B >: B](xs: Array[B], start: Int, len: Int)Unit`
-`method copyToBuffer[B >: B](dest: scala.collection.mutable.Buffer[B])Unit`
-`method count(p: B => Boolean)Int`
-`method drop(n: Int)Iterator[B]`
-`method dropWhile(p: B => Boolean)Iterator[B]`
-`method duplicate=> (Iterator[B], Iterator[B])`
-`method ensuring(cond: Boolean)java.util.Iterator[B]`
-`method ensuring(cond: Boolean, msg: => Any)java.util.Iterator[B]`
-`method ensuring(cond: java.util.Iterator[B] => Boolean)java.util.Iterator[B]`
-`method ensuring(cond: java.util.Iterator[B] => Boolean, msg: => Any)java.util.Iterator[B]`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method exists(p: B => Boolean)Boolean`
-`method filter(p: B => Boolean)Iterator[B]`
-`method filterNot(p: B => Boolean)Iterator[B]`
-`method finalize()Unit`
-`method find(p: B => Boolean)Option[B]`
-`method flatMap[B](f: B => scala.collection.GenTraversableOnce[B])Iterator[B]`
-`method foldLeft[B](z: B)(op: (B, B) => B)B`
-`method foldRight[B](z: B)(op: (B, B) => B)B`
-`method fold[A1 >: B](z: A1)(op: (A1, A1) => A1)A1`
-`method forall(p: B => Boolean)Boolean`
-`method foreach[U](f: B => U)Unit`
-`method formatted(fmtstr: String)String`
-`method grouped[B >: B](size: Int)Iterator[B]#GroupedIterator[B]`
-`method hasDefiniteSize=> Boolean`
-`method hasNext()Boolean`
-`method hashCode()Int`
-`method indexOf[B >: B](elem: B)Int`
-`method indexWhere(p: B => Boolean)Int`
-`method isEmpty=> Boolean`
-`method isInstanceOf[T0]=> Boolean`
-`method isTraversableAgain=> Boolean`
-`method length=> Int`
-`method map[B](f: B => B)Iterator[B]`
-`method maxBy[B](f: B => B)(implicit cmp: Ordering[B])B`
-`method max[B >: B](implicit cmp: Ordering[B])B`
-`method minBy[B](f: B => B)(implicit cmp: Ordering[B])B`
-`method min[B >: B](implicit cmp: Ordering[B])B`
-`method mkString(sep: String)String`
-`method mkString(start: String, sep: String, end: String)String`
-`method mkString=> String`
-`method ne(x$1: AnyRef)Boolean`
-`method next()B`
-`method nonEmpty=> Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method padTo[A1 >: B](len: Int, elem: A1)Iterator[A1]`
-`method partition(p: B => Boolean)(Iterator[B], Iterator[B])`
-`method patch[B >: B](from: Int, patchElems: Iterator[B], replaced: Int)Iterator[B]`
-`method product[B >: B](implicit num: Numeric[B])B`
-`method reduceLeftOption[B >: B](op: (B, B) => B)Option[B]`
-`method reduceLeft[B >: B](op: (B, B) => B)B`
-`method reduceOption[A1 >: B](op: (A1, A1) => A1)Option[A1]`
-`method reduceRightOption[B >: B](op: (B, B) => B)Option[B]`
-`method reduceRight[B >: B](op: (B, B) => B)B`
-`method reduce[A1 >: B](op: (A1, A1) => A1)A1`
-`method remove()Unit`
-`method reversed=> List[B]`
-`method sameElements(that: Iterator[_])Boolean`
-`method scanLeft[B](z: B)(op: (B, B) => B)Iterator[B]`
-`method scanRight[B](z: B)(op: (B, B) => B)Iterator[B]`
-`method seq=> Iterator[B]`
-`method size=> Int`
-`method slice(from: Int, until: Int)Iterator[B]`
-`method sliding[B >: B](size: Int, step: Int)Iterator[B]#GroupedIterator[B]`
-`method span(p: B => Boolean)(Iterator[B], Iterator[B])`
-`method sum[B >: B](implicit num: Numeric[B])B`
-`method synchronized[T0](x$1: T0)T0`
-`method take(n: Int)Iterator[B]`
-`method takeWhile(p: B => Boolean)Iterator[B]`
-`method toArray[B >: B](implicit evidence$1: ClassManifest[B])Array[B]`
-`method toBuffer[B >: B]=> scala.collection.mutable.Buffer[B]`
-`method toIndexedSeq=> scala.collection.immutable.IndexedSeq[B]`
-`method toIterable=> Iterable[B]`
-`method toIterator=> Iterator[B]`
-`method toList=> List[B]`
-`method toMap[T, U](implicit ev: <:<[B,(T, U)])scala.collection.immutable.Map[T,U]`
-`method toSeq=> Seq[B]`
-`method toSet[B >: B]=> scala.collection.immutable.Set[B]`
-`method toStream=> scala.collection.immutable.Stream[B]`
-`method toString()String`
-`method toTraversable=> Traversable[B]`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method withFilter(p: B => Boolean)Iterator[B]`
-`method x=> java.util.Iterator[B]`
-`method zipAll[B, A1 >: B, B1 >: B](that: Iterator[B], thisElem: A1, thatElem: B1)Iterator[(A1, B1)]`
-`method zipWithIndex=> Iterator[(B, Int)]`
-`method zip[B](that: Iterator[B])Iterator[(B, B)]`
-`method →[B](y: B)(java.util.Iterator[B], B)`
-`value __leftOfArrowjava.util.Iterator[B]`
-`value __resultOfEnsuringjava.util.Iterator[B]`
-`value selfAny`
+retrieved 124 members
+[accessible: true] `class GroupedIteratorIterator[B]#GroupedIterator`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ++[B >: B](that: => scala.collection.GenTraversableOnce[B])Iterator[B]`
+[accessible: true] `method ->[B](y: B)(java.util.Iterator[B], B)`
+[accessible: true] `method /:[B](z: B)(op: (B, B) => B)B`
+[accessible: true] `method /:\[A1 >: B](z: A1)(op: (A1, A1) => A1)A1`
+[accessible: true] `method :\[B](z: B)(op: (B, B) => B)B`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method addString(b: StringBuilder)StringBuilder`
+[accessible: true] `method addString(b: StringBuilder, sep: String)StringBuilder`
+[accessible: true] `method addString(b: StringBuilder, start: String, sep: String, end: String)StringBuilder`
+[accessible: true] `method aggregate[B](z: B)(seqop: (B, B) => B, combop: (B, B) => B)B`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method buffered=> scala.collection.BufferedIterator[B]`
+[accessible: true] `method collectFirst[B](pf: PartialFunction[B,B])Option[B]`
+[accessible: true] `method collect[B](pf: PartialFunction[B,B])Iterator[B]`
+[accessible: true] `method contains(elem: Any)Boolean`
+[accessible: true] `method copyToArray[B >: B](xs: Array[B])Unit`
+[accessible: true] `method copyToArray[B >: B](xs: Array[B], start: Int)Unit`
+[accessible: true] `method copyToArray[B >: B](xs: Array[B], start: Int, len: Int)Unit`
+[accessible: true] `method copyToBuffer[B >: B](dest: scala.collection.mutable.Buffer[B])Unit`
+[accessible: true] `method corresponds[B](that: scala.collection.GenTraversableOnce[B])(p: (B, B) => Boolean)Boolean`
+[accessible: true] `method count(p: B => Boolean)Int`
+[accessible: true] `method drop(n: Int)Iterator[B]`
+[accessible: true] `method dropWhile(p: B => Boolean)Iterator[B]`
+[accessible: true] `method duplicate=> (Iterator[B], Iterator[B])`
+[accessible: true] `method ensuring(cond: Boolean)java.util.Iterator[B]`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)java.util.Iterator[B]`
+[accessible: true] `method ensuring(cond: java.util.Iterator[B] => Boolean)java.util.Iterator[B]`
+[accessible: true] `method ensuring(cond: java.util.Iterator[B] => Boolean, msg: => Any)java.util.Iterator[B]`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method exists(p: B => Boolean)Boolean`
+[accessible: true] `method filter(p: B => Boolean)Iterator[B]`
+[accessible: true] `method filterNot(p: B => Boolean)Iterator[B]`
+[accessible: true] `method find(p: B => Boolean)Option[B]`
+[accessible: true] `method flatMap[B](f: B => scala.collection.GenTraversableOnce[B])Iterator[B]`
+[accessible: true] `method foldLeft[B](z: B)(op: (B, B) => B)B`
+[accessible: true] `method foldRight[B](z: B)(op: (B, B) => B)B`
+[accessible: true] `method fold[A1 >: B](z: A1)(op: (A1, A1) => A1)A1`
+[accessible: true] `method forall(p: B => Boolean)Boolean`
+[accessible: true] `method foreach[U](f: B => U)Unit`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method grouped[B >: B](size: Int)Iterator[B]#GroupedIterator[B]`
+[accessible: true] `method hasDefiniteSize=> Boolean`
+[accessible: true] `method hasNext()Boolean`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method indexOf[B >: B](elem: B)Int`
+[accessible: true] `method indexWhere(p: B => Boolean)Int`
+[accessible: true] `method isEmpty=> Boolean`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method isTraversableAgain=> Boolean`
+[accessible: true] `method length=> Int`
+[accessible: true] `method map[B](f: B => B)Iterator[B]`
+[accessible: true] `method maxBy[B](f: B => B)(implicit cmp: Ordering[B])B`
+[accessible: true] `method max[B >: B](implicit cmp: Ordering[B])B`
+[accessible: true] `method minBy[B](f: B => B)(implicit cmp: Ordering[B])B`
+[accessible: true] `method min[B >: B](implicit cmp: Ordering[B])B`
+[accessible: true] `method mkString(sep: String)String`
+[accessible: true] `method mkString(start: String, sep: String, end: String)String`
+[accessible: true] `method mkString=> String`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method next()B`
+[accessible: true] `method nonEmpty=> Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method padTo[A1 >: B](len: Int, elem: A1)Iterator[A1]`
+[accessible: true] `method partition(p: B => Boolean)(Iterator[B], Iterator[B])`
+[accessible: true] `method patch[B >: B](from: Int, patchElems: Iterator[B], replaced: Int)Iterator[B]`
+[accessible: true] `method product[B >: B](implicit num: Numeric[B])B`
+[accessible: true] `method reduceLeftOption[B >: B](op: (B, B) => B)Option[B]`
+[accessible: true] `method reduceLeft[B >: B](op: (B, B) => B)B`
+[accessible: true] `method reduceOption[A1 >: B](op: (A1, A1) => A1)Option[A1]`
+[accessible: true] `method reduceRightOption[B >: B](op: (B, B) => B)Option[B]`
+[accessible: true] `method reduceRight[B >: B](op: (B, B) => B)B`
+[accessible: true] `method reduce[A1 >: B](op: (A1, A1) => A1)A1`
+[accessible: true] `method remove()Unit`
+[accessible: true] `method sameElements(that: Iterator[_])Boolean`
+[accessible: true] `method scanLeft[B](z: B)(op: (B, B) => B)Iterator[B]`
+[accessible: true] `method scanRight[B](z: B)(op: (B, B) => B)Iterator[B]`
+[accessible: true] `method seq=> Iterator[B]`
+[accessible: true] `method size=> Int`
+[accessible: true] `method slice(from: Int, until: Int)Iterator[B]`
+[accessible: true] `method sliding[B >: B](size: Int, step: Int)Iterator[B]#GroupedIterator[B]`
+[accessible: true] `method span(p: B => Boolean)(Iterator[B], Iterator[B])`
+[accessible: true] `method sum[B >: B](implicit num: Numeric[B])B`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method take(n: Int)Iterator[B]`
+[accessible: true] `method takeWhile(p: B => Boolean)Iterator[B]`
+[accessible: true] `method toArray[B >: B](implicit evidence$1: ArrayTag[B])Array[B]`
+[accessible: true] `method toBuffer[B >: B]=> scala.collection.mutable.Buffer[B]`
+[accessible: true] `method toIndexedSeq=> scala.collection.immutable.IndexedSeq[B]`
+[accessible: true] `method toIterable=> Iterable[B]`
+[accessible: true] `method toIterator=> Iterator[B]`
+[accessible: true] `method toList=> List[B]`
+[accessible: true] `method toMap[T, U](implicit ev: <:<[B,(T, U)])scala.collection.immutable.Map[T,U]`
+[accessible: true] `method toSeq=> Seq[B]`
+[accessible: true] `method toSet[B >: B]=> scala.collection.immutable.Set[B]`
+[accessible: true] `method toStream=> scala.collection.immutable.Stream[B]`
+[accessible: true] `method toString()String`
+[accessible: true] `method toTraversable=> Traversable[B]`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method withFilter(p: B => Boolean)Iterator[B]`
+[accessible: true] `method x=> java.util.Iterator[B]`
+[accessible: true] `method zipAll[B, A1 >: B, B1 >: B](that: Iterator[B], thisElem: A1, thatElem: B1)Iterator[(A1, B1)]`
+[accessible: true] `method zipWithIndex=> Iterator[(B, Int)]`
+[accessible: true] `method zip[B](that: Iterator[B])Iterator[(B, B)]`
+[accessible: true] `method →[B](y: B)(java.util.Iterator[B], B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `method reversed=> List[B]`
+[accessible: false] `value __leftOfArrowjava.util.Iterator[B]`
+[accessible: false] `value __resultOfEnsuringjava.util.Iterator[B]`
+[accessible: false] `value selfAny`
================================================================================
diff --git a/test/files/presentation/implicit-member.check b/test/files/presentation/implicit-member.check
index e8e656f12a..ce21293ae5 100644
--- a/test/files/presentation/implicit-member.check
+++ b/test/files/presentation/implicit-member.check
@@ -4,39 +4,39 @@ askTypeCompletion at ImplicitMember.scala(7,7)
================================================================================
[response] aksTypeCompletion at (7,7)
retrieved 39 members
-`class AppliedImplicitImplicit.AppliedImplicit`
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(Implicit.type, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method AppliedImplicit[A](x: A)Implicit.AppliedImplicit[A]`
-`method asInstanceOf[T0]=> T0`
-`method clone()Object`
-`method ensuring(cond: Boolean)Implicit.type`
-`method ensuring(cond: Boolean, msg: => Any)Implicit.type`
-`method ensuring(cond: Implicit.type => Boolean)Implicit.type`
-`method ensuring(cond: Implicit.type => Boolean, msg: => Any)Implicit.type`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method isInstanceOf[T0]=> Boolean`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method synchronized[T0](x$1: T0)T0`
-`method toString()String`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> Implicit.type`
-`method →[B](y: B)(Implicit.type, B)`
-`value __leftOfArrowImplicit.type`
-`value __resultOfEnsuringImplicit.type`
-`value selfAny`
-`value xImplicit.type`
+[accessible: true] `class AppliedImplicitImplicit.AppliedImplicit`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(Implicit.type, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method AppliedImplicit[A](x: A)Implicit.AppliedImplicit[A]`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method clone()Object`
+[accessible: true] `method ensuring(cond: Boolean)Implicit.type`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)Implicit.type`
+[accessible: true] `method ensuring(cond: Implicit.type => Boolean)Implicit.type`
+[accessible: true] `method ensuring(cond: Implicit.type => Boolean, msg: => Any)Implicit.type`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method finalize()Unit`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> Implicit.type`
+[accessible: true] `method →[B](y: B)(Implicit.type, B)`
+[accessible: false] `value __leftOfArrowImplicit.type`
+[accessible: false] `value __resultOfEnsuringImplicit.type`
+[accessible: false] `value selfAny`
+[accessible: false] `value xImplicit.type`
================================================================================
diff --git a/test/files/presentation/memory-leaks.check b/test/files/presentation/memory-leaks.check
new file mode 100644
index 0000000000..86fb07757d
--- /dev/null
+++ b/test/files/presentation/memory-leaks.check
@@ -0,0 +1,54 @@
+reload: Trees.scala, Typers.scala, Types.scala
+reload: Trees.scala
+reload: Types.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+reload: Typers.scala
+No leaks detected.
diff --git a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
new file mode 100644
index 0000000000..45b38da85b
--- /dev/null
+++ b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
@@ -0,0 +1,126 @@
+import java.io.PrintWriter
+import java.io.FileOutputStream
+import java.util.Calendar
+
+import scala.tools.nsc.interactive.tests._
+import scala.tools.nsc.util._
+import scala.tools.nsc.io._
+
+/** This test runs the presentation compiler on the Scala compiler project itself and records memory consumption.
+ *
+ * The test scenario is to open Typers, Trees and Types, then repeatedly add and remove one character
+ * in Typers.scala. Each step causes the parser, namer, and type checker to run.
+ *
+ * At each step we record the memory usage after the GC has run. At the end of the test,
+ * simple linear regression is used to compute the straight line that best fits the
+ * curve, and if the slope is higher than 1 (meaning a leak of 1MB/run), we fail the test.
+ *
+ * The Scala compiler sources are assumed to be under 'basedir/src/compiler'.
+ *
+ * The individual data points are saved under 'usedMem-<date>.txt', under the test project
+ * directory. Use the cool graph-it.R (https://github.com/scala-ide/scala-ide/blob/master/org.scala-ide.sdt.core.tests/graph-it.R)
+ * script to see the memory curve for the given test run.
+ */
+object Test extends InteractiveTest {
+ final val mega = 1024 * 1024
+
+ override def main(args: Array[String]) {
+ memoryConsumptionTest()
+ compiler.askShutdown()
+ }
+
+ def batchSource(name: String) =
+ new BatchSourceFile(AbstractFile.getFile(name))
+
+ def memoryConsumptionTest() {
+ val N = 50
+ val filename = "usedmem-%tF.txt".format(Calendar.getInstance.getTime)
+
+ val typerUnit = AbstractFile.getFile(baseDir.parent.parent.parent.parent / "src/compiler/scala/tools/nsc/typechecker/Typers.scala")
+ val typesUnit = AbstractFile.getFile(baseDir.parent.parent.parent.parent / "src/compiler/scala/reflect/internal/Types.scala")
+ val treesUnit = AbstractFile.getFile(baseDir.parent.parent.parent.parent / "src/compiler/scala/reflect/internal/Trees.scala")
+
+ askReload(Seq(new BatchSourceFile(typerUnit), new BatchSourceFile(typesUnit), new BatchSourceFile(treesUnit)))
+ typeCheckWith(treesUnit, new String(treesUnit.toCharArray))
+ typeCheckWith(typesUnit, new String(typesUnit.toCharArray))
+
+ val originalTyper = new String(typerUnit.toCharArray)
+
+ val (prefix, postfix) = originalTyper.splitAt(originalTyper.indexOf("import global._"))
+ val changedTyper = prefix + " a\n " + postfix
+
+ val usedMem = for (i <- 1 to N) yield {
+ val src = if (i % 2 == 0) originalTyper else changedTyper
+
+ val usedMem = withGC {
+ typeCheckWith(typerUnit, src)
+ }
+
+ usedMem / mega // report size in MB
+ }
+
+ //dumpDataToFile(filename, usedMem)
+ // drop the first two measurements, since the compiler needs some memory when initializing
+ val (a, b) = linearModel((3L to N).toSeq, usedMem.drop(2))
+ //println("LinearModel: constant: %.4f\tslope:%.4f".format(a, b))
+
+ if (b > 1.0)
+ println("Rate of memory consumption is alarming! %.4f MB/run".format(b))
+ else
+ println("No leaks detected.")
+ }
+
+ private def typeCheckWith(file: AbstractFile, src: String) = {
+ val sourceFile = new BatchSourceFile(file, src.toCharArray)
+ askReload(Seq(sourceFile))
+ askLoadedTyped(sourceFile).get // block until it's here
+ }
+
+ private def dumpDataToFile(filename: String, usedMem: Seq[Long]) {
+ val outputFile = new PrintWriter(new FileOutputStream(filename))
+ outputFile.println("\tusedMem")
+ for ((dataPoint, i) <- usedMem.zipWithIndex) {
+ outputFile.println("%d\t%d".format(i, dataPoint))
+ }
+ outputFile.close()
+ }
+
+
+ /** Return the linear model of these values, (a, b). First value is the constant factor,
+ * second value is the slope, i.e. `y = a + bx`
+ *
+ * The linear model of a set of points is a straight line that minimizes the square distance
+ * between the each point and the line.
+ *
+ * See: http://en.wikipedia.org/wiki/Simple_linear_regression
+ */
+ def linearModel(xs: Seq[Long], ys: Seq[Long]): (Double, Double) = {
+ require(xs.length == ys.length)
+
+ def mean(v: Seq[Long]): Double = v.sum.toDouble / v.length
+
+ val meanXs = mean(xs)
+ val meanYs = mean(ys)
+
+ val beta = (mean((xs, ys).zipped.map(_ * _)) - meanXs * meanYs) / (mean(xs.map(x => x * x)) - meanXs * meanXs)
+ val alfa = meanYs - beta * meanXs
+
+ (alfa, beta)
+ }
+
+ /** Run the given closure and return the amount of used memory at the end of its execution.
+ *
+ * Runs the GC before and after the execution of `f'.
+ */
+ def withGC(f: => Unit): Long = {
+ val r = Runtime.getRuntime
+ System.gc()
+
+ f;
+
+ System.gc()
+
+ r.totalMemory() - r.freeMemory()
+ }
+
+} \ No newline at end of file
diff --git a/test/files/presentation/ping-pong.check b/test/files/presentation/ping-pong.check
index 38040bdacf..1f02274736 100644
--- a/test/files/presentation/ping-pong.check
+++ b/test/files/presentation/ping-pong.check
@@ -4,83 +4,83 @@ askTypeCompletion at PingPong.scala(10,23)
================================================================================
[response] aksTypeCompletion at (10,23)
retrieved 40 members
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(Pong, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method asInstanceOf[T0]=> T0`
-`method clone()Object`
-`method ensuring(cond: Boolean)Pong`
-`method ensuring(cond: Boolean, msg: => Any)Pong`
-`method ensuring(cond: Pong => Boolean)Pong`
-`method ensuring(cond: Pong => Boolean, msg: => Any)Pong`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method isInstanceOf[T0]=> Boolean`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method poke()Unit`
-`method synchronized[T0](x$1: T0)T0`
-`method toString()String`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> Pong`
-`method →[B](y: B)(Pong, B)`
-`value __leftOfArrowPong`
-`value __resultOfEnsuringPong`
-`value nameString`
-`value pingPing`
-`value selfAny`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(Pong, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)Pong`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)Pong`
+[accessible: true] `method ensuring(cond: Pong => Boolean)Pong`
+[accessible: true] `method ensuring(cond: Pong => Boolean, msg: => Any)Pong`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method poke()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> Pong`
+[accessible: true] `method →[B](y: B)(Pong, B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `value __leftOfArrowPong`
+[accessible: false] `value __resultOfEnsuringPong`
+[accessible: false] `value nameString`
+[accessible: false] `value pingPing`
+[accessible: false] `value selfAny`
================================================================================
askTypeCompletion at PingPong.scala(19,20)
================================================================================
[response] aksTypeCompletion at (19,20)
retrieved 40 members
-`method !=(x$1: Any)Boolean`
-`method !=(x$1: AnyRef)Boolean`
-`method ##()Int`
-`method +(other: String)String`
-`method ->[B](y: B)(Ping, B)`
-`method ==(x$1: Any)Boolean`
-`method ==(x$1: AnyRef)Boolean`
-`method asInstanceOf[T0]=> T0`
-`method clone()Object`
-`method ensuring(cond: Boolean)Ping`
-`method ensuring(cond: Boolean, msg: => Any)Ping`
-`method ensuring(cond: Ping => Boolean)Ping`
-`method ensuring(cond: Ping => Boolean, msg: => Any)Ping`
-`method eq(x$1: AnyRef)Boolean`
-`method equals(x$1: Any)Boolean`
-`method finalize()Unit`
-`method formatted(fmtstr: String)String`
-`method hashCode()Int`
-`method isInstanceOf[T0]=> Boolean`
-`method loop=> Unit`
-`method name=> String`
-`method ne(x$1: AnyRef)Boolean`
-`method notify()Unit`
-`method notifyAll()Unit`
-`method poke=> Unit`
-`method synchronized[T0](x$1: T0)T0`
-`method toString()String`
-`method wait()Unit`
-`method wait(x$1: Long)Unit`
-`method wait(x$1: Long, x$2: Int)Unit`
-`method x=> Ping`
-`method →[B](y: B)(Ping, B)`
-`value __leftOfArrowPing`
-`value __resultOfEnsuringPing`
-`value pongPong`
-`value selfAny`
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(Ping, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)Ping`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)Ping`
+[accessible: true] `method ensuring(cond: Ping => Boolean)Ping`
+[accessible: true] `method ensuring(cond: Ping => Boolean, msg: => Any)Ping`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method loop=> Unit`
+[accessible: true] `method name=> String`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method poke=> Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> Ping`
+[accessible: true] `method →[B](y: B)(Ping, B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `value __leftOfArrowPing`
+[accessible: false] `value __resultOfEnsuringPing`
+[accessible: false] `value pongPong`
+[accessible: false] `value selfAny`
================================================================================
askType at PingPong.scala(8,10)
diff --git a/test/files/presentation/visibility.check b/test/files/presentation/visibility.check
new file mode 100644
index 0000000000..290a5ac381
--- /dev/null
+++ b/test/files/presentation/visibility.check
@@ -0,0 +1,221 @@
+reload: Completions.scala
+
+askTypeCompletion at Completions.scala(14,12)
+================================================================================
+[response] aksTypeCompletion at (14,12)
+retrieved 42 members
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(accessibility.Foo, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method clone()Object`
+[accessible: true] `method ensuring(cond: Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method finalize()Unit`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method secretPrivate()Unit`
+[accessible: true] `method secretProtected()Unit`
+[accessible: true] `method secretProtectedInPackage()Unit`
+[accessible: true] `method secretPublic()Unit`
+[accessible: true] `method someTests(other: accessibility.Foo)Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> accessibility.Foo`
+[accessible: true] `method →[B](y: B)(accessibility.Foo, B)`
+[accessible: false] `method secretPrivateThis()Unit`
+[accessible: false] `value __leftOfArrowaccessibility.Foo`
+[accessible: false] `value __resultOfEnsuringaccessibility.Foo`
+[accessible: false] `value selfAny`
+================================================================================
+
+askTypeCompletion at Completions.scala(16,11)
+================================================================================
+[response] aksTypeCompletion at (16,11)
+retrieved 42 members
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(accessibility.Foo, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method clone()Object`
+[accessible: true] `method ensuring(cond: Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method finalize()Unit`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method secretPrivate()Unit`
+[accessible: true] `method secretPrivateThis()Unit`
+[accessible: true] `method secretProtected()Unit`
+[accessible: true] `method secretProtectedInPackage()Unit`
+[accessible: true] `method secretPublic()Unit`
+[accessible: true] `method someTests(other: accessibility.Foo)Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> accessibility.Foo`
+[accessible: true] `method →[B](y: B)(accessibility.Foo, B)`
+[accessible: false] `value __leftOfArrowaccessibility.Foo`
+[accessible: false] `value __resultOfEnsuringaccessibility.Foo`
+[accessible: false] `value selfAny`
+================================================================================
+
+askTypeCompletion at Completions.scala(22,11)
+================================================================================
+[response] aksTypeCompletion at (22,11)
+retrieved 42 members
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(accessibility.AccessibilityChecks, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method clone()Object`
+[accessible: true] `method ensuring(cond: Boolean)accessibility.AccessibilityChecks`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)accessibility.AccessibilityChecks`
+[accessible: true] `method ensuring(cond: accessibility.AccessibilityChecks => Boolean)accessibility.AccessibilityChecks`
+[accessible: true] `method ensuring(cond: accessibility.AccessibilityChecks => Boolean, msg: => Any)accessibility.AccessibilityChecks`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method finalize()Unit`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method secretProtected()Unit`
+[accessible: true] `method secretProtectedInPackage()Unit`
+[accessible: true] `method secretPublic()Unit`
+[accessible: true] `method someTests(other: accessibility.Foo)Unit`
+[accessible: true] `method someTests=> Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> accessibility.AccessibilityChecks`
+[accessible: true] `method →[B](y: B)(accessibility.AccessibilityChecks, B)`
+[accessible: false] `method secretPrivate()Unit`
+[accessible: false] `value __leftOfArrowaccessibility.AccessibilityChecks`
+[accessible: false] `value __resultOfEnsuringaccessibility.AccessibilityChecks`
+[accessible: false] `value selfAny`
+================================================================================
+
+askTypeCompletion at Completions.scala(28,10)
+================================================================================
+[response] aksTypeCompletion at (28,10)
+retrieved 42 members
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(accessibility.Foo, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method secretProtectedInPackage()Unit`
+[accessible: true] `method secretPublic()Unit`
+[accessible: true] `method someTests(other: accessibility.Foo)Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> accessibility.Foo`
+[accessible: true] `method →[B](y: B)(accessibility.Foo, B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `method secretPrivate()Unit`
+[accessible: false] `method secretPrivateThis()Unit`
+[accessible: false] `method secretProtected()Unit`
+[accessible: false] `value __leftOfArrowaccessibility.Foo`
+[accessible: false] `value __resultOfEnsuringaccessibility.Foo`
+[accessible: false] `value selfAny`
+================================================================================
+
+askTypeCompletion at Completions.scala(37,8)
+================================================================================
+[response] aksTypeCompletion at (37,8)
+retrieved 42 members
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(accessibility.Foo, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean)accessibility.Foo`
+[accessible: true] `method ensuring(cond: accessibility.Foo => Boolean, msg: => Any)accessibility.Foo`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method secretPublic()Unit`
+[accessible: true] `method someTests(other: accessibility.Foo)Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> accessibility.Foo`
+[accessible: true] `method →[B](y: B)(accessibility.Foo, B)`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: false] `method secretPrivate()Unit`
+[accessible: false] `method secretPrivateThis()Unit`
+[accessible: false] `method secretProtected()Unit`
+[accessible: false] `method secretProtectedInPackage()Unit`
+[accessible: false] `value __leftOfArrowaccessibility.Foo`
+[accessible: false] `value __resultOfEnsuringaccessibility.Foo`
+[accessible: false] `value selfAny`
+================================================================================
diff --git a/test/files/presentation/visibility/Test.scala b/test/files/presentation/visibility/Test.scala
new file mode 100644
index 0000000000..96e758d974
--- /dev/null
+++ b/test/files/presentation/visibility/Test.scala
@@ -0,0 +1,5 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+object Test extends InteractiveTest {
+
+} \ No newline at end of file
diff --git a/test/files/presentation/visibility/src/Completions.scala b/test/files/presentation/visibility/src/Completions.scala
new file mode 100644
index 0000000000..098b98a0fd
--- /dev/null
+++ b/test/files/presentation/visibility/src/Completions.scala
@@ -0,0 +1,40 @@
+package accessibility {
+
+ class Foo {
+ private def secretPrivate(): Unit = ()
+ private[this] def secretPrivateThis(): Unit = ()
+
+ protected def secretProtected(): Unit
+
+ protected[accessibility] def secretProtectedInPackage(): Unit
+
+ def secretPublic(): Unit
+
+ def someTests(other: Foo) {
+ other./*!*/secretPrivate // should be all but scretThis
+
+ this./*!*/secretProtected // should hit five completions
+ }
+ }
+
+ class AccessibilityChecks extends Foo {
+ def someTests {
+ this./*!*/ // should not list secretPrivate*
+ }
+ }
+
+ class UnrelatedClass {
+ def someTests(foo: Foo) {
+ foo./*!*/ // should list public and protected[accessiblity]
+ }
+ }
+
+}
+
+package other {
+ class SomeChecsk {
+ def foo(o: accessibility.Foo) {
+ o./*!*/ // should only match secretPublic
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/Meter.check b/test/files/run/Meter.check
index 7562f9a1bf..b7e2eac125 100644
--- a/test/files/run/Meter.check
+++ b/test/files/run/Meter.check
@@ -11,11 +11,3 @@ Array(1.0m, 2.0m)
1.0m
>>>1.0m<<< 1.0m
>>>2.0m<<< 2.0m
-testing wrapped arrays
-FlatArray(1.0m, 2.0m)
-1.0m
->>>1.0m<<< 1.0m
->>>2.0m<<< 2.0m
-FlatArray(2.0m, 3.0m)
-ArrayBuffer(1.0, 2.0)
-FlatArray(0.3048ft, 0.6096ft)
diff --git a/test/files/run/Meter.scala b/test/files/run/Meter.scala
index 515e46de24..d94f338ca9 100644
--- a/test/files/run/Meter.scala
+++ b/test/files/run/Meter.scala
@@ -80,23 +80,23 @@ object Test extends App {
println(m)
foo(arr)
}
-
- { println("testing wrapped arrays")
- import collection.mutable.FlatArray
- val arr = FlatArray(x, y + x)
- println(arr)
- def foo(x: FlatArray[Meter]) {
- for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) }
- }
- val m = arr(0)
- println(m)
- foo(arr)
- val ys: Seq[Meter] = arr map (_ + new Meter(1))
- println(ys)
- val zs = arr map (_ / Meter(1))
- println(zs)
- val fs = arr map (_.toFoot)
- println(fs)
- }
+ //
+ // { println("testing wrapped arrays")
+ // import collection.mutable.FlatArray
+ // val arr = FlatArray(x, y + x)
+ // println(arr)
+ // def foo(x: FlatArray[Meter]) {
+ // for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) }
+ // }
+ // val m = arr(0)
+ // println(m)
+ // foo(arr)
+ // val ys: Seq[Meter] = arr map (_ + new Meter(1))
+ // println(ys)
+ // val zs = arr map (_ / Meter(1))
+ // println(zs)
+ // val fs = arr map (_.toFoot)
+ // println(fs)
+ // }
}
diff --git a/test/files/run/MeterCaseClass.check b/test/files/run/MeterCaseClass.check
index 08370d2097..2528753657 100644
--- a/test/files/run/MeterCaseClass.check
+++ b/test/files/run/MeterCaseClass.check
@@ -11,11 +11,3 @@ Array(Meter(1.0), Meter(2.0))
Meter(1.0)
>>>Meter(1.0)<<< Meter(1.0)
>>>Meter(2.0)<<< Meter(2.0)
-testing wrapped arrays
-FlatArray(Meter(1.0), Meter(2.0))
-Meter(1.0)
->>>Meter(1.0)<<< Meter(1.0)
->>>Meter(2.0)<<< Meter(2.0)
-FlatArray(Meter(2.0), Meter(3.0))
-ArrayBuffer(1.0, 2.0)
-FlatArray(0.3048ft, 0.6096ft)
diff --git a/test/files/run/MeterCaseClass.scala b/test/files/run/MeterCaseClass.scala
index 8459163f31..e5979cf761 100644
--- a/test/files/run/MeterCaseClass.scala
+++ b/test/files/run/MeterCaseClass.scala
@@ -77,23 +77,23 @@ object Test extends App {
println(m)
foo(arr)
}
-
- { println("testing wrapped arrays")
- import collection.mutable.FlatArray
- val arr = FlatArray(x, y + x)
- println(arr)
- def foo(x: FlatArray[Meter]) {
- for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) }
- }
- val m = arr(0)
- println(m)
- foo(arr)
- val ys: Seq[Meter] = arr map (_ + new Meter(1))
- println(ys)
- val zs = arr map (_ / Meter(1))
- println(zs)
- val fs = arr map (_.toFoot)
- println(fs)
- }
+ //
+ // { println("testing wrapped arrays")
+ // import collection.mutable.FlatArray
+ // val arr = FlatArray(x, y + x)
+ // println(arr)
+ // def foo(x: FlatArray[Meter]) {
+ // for (i <- 0 until x.length) { x(i).print; println(" "+x(i)) }
+ // }
+ // val m = arr(0)
+ // println(m)
+ // foo(arr)
+ // val ys: Seq[Meter] = arr map (_ + new Meter(1))
+ // println(ys)
+ // val zs = arr map (_ / Meter(1))
+ // println(zs)
+ // val fs = arr map (_.toFoot)
+ // println(fs)
+ // }
}
diff --git a/test/files/run/applydynamic_sip.check b/test/files/run/applydynamic_sip.check
new file mode 100644
index 0000000000..d94db4417e
--- /dev/null
+++ b/test/files/run/applydynamic_sip.check
@@ -0,0 +1,22 @@
+qual.applyDynamic(sel)()
+qual.applyDynamic(sel)(a)
+qual.applyDynamic(sel)(a)
+.apply(a2)
+qual.applyDynamic(sel)(a)
+qual.applyDynamic(sel)(a)
+.apply(a2)
+qual.applyDynamicNamed(sel)((arg,a))
+qual.applyDynamicNamed(sel)((arg,a))
+qual.applyDynamicNamed(sel)((,a), (arg2,a2))
+qual.updateDynamic(sel)(expr)
+qual.selectDynamic(sel)
+qual.selectDynamic(sel)
+qual.selectDynamic(sel)
+.update(1, expr)
+qual.selectDynamic(sel)
+.update(expr)
+qual.selectDynamic(sel)
+.apply(1)
+qual.selectDynamic(sel)
+.apply
+.update(1, 1)
diff --git a/test/files/run/applydynamic_sip.scala b/test/files/run/applydynamic_sip.scala
new file mode 100644
index 0000000000..57cb4349f7
--- /dev/null
+++ b/test/files/run/applydynamic_sip.scala
@@ -0,0 +1,58 @@
+object Test extends App {
+ object stubUpdate {
+ def update(as: Any*) = println(".update"+as.toList.mkString("(",", ", ")"))
+ }
+
+ object stub {
+ def apply = {println(".apply"); stubUpdate}
+ def apply(as: Any*) = println(".apply"+as.toList.mkString("(",", ", ")"))
+ def update(as: Any*) = println(".update"+as.toList.mkString("(",", ", ")"))
+ }
+ class MyDynamic extends Dynamic {
+ def applyDynamic[T](n: String)(as: Any*) = {println("qual.applyDynamic("+ n +")"+ as.toList.mkString("(",", ", ")")); stub}
+ def applyDynamicNamed[T](n: String)(as: (String, Any)*) = {println("qual.applyDynamicNamed("+ n +")"+ as.toList.mkString("(",", ", ")")); stub}
+ def selectDynamic[T](n: String) = {println("qual.selectDynamic("+ n +")"); stub}
+ def updateDynamic(n: String)(x: Any): Unit = {println("qual.updateDynamic("+ n +")("+ x +")")}
+ }
+ val qual = new MyDynamic
+ val expr = "expr"
+ val a = "a"
+ val a2 = "a2"
+ type T = String
+
+ // If qual.sel is followed by a potential type argument list [Ts] and an argument list (arg1, …, argn) where none of the arguments argi are named:
+ // qual.applyDynamic(“sel”)(arg1, …, argn)
+ qual.sel()
+ qual.sel(a)
+ // qual.sel(a, a2: _*) -- should not accept varargs?
+ qual.sel(a)(a2)
+ qual.sel[T](a)
+ qual.sel[T](a)(a2)
+
+ // If qual.sel is followed by a potential type argument list [Ts]
+ // and a non-empty named argument list (x1 = arg1, …, xn = argn) where some name prefixes xi = might be missing:
+ // qual.applyDynamicNamed(“sel”)(xs1 -> arg1, …, xsn -> argn)
+ qual.sel(arg = a)
+ qual.sel[T](arg = a)
+ qual.sel(a, arg2 = "a2")
+ // qual.sel(a)(a2, arg2 = "a2")
+ // qual.sel[T](a)(a2, arg2 = "a2")
+ // qual.sel(arg = a, a2: _*)
+ // qual.sel(arg, arg2 = "a2", a2: _*)
+
+ // If qual.sel appears immediately on the left-hand side of an assigment
+ // qual.updateDynamic(“sel”)(expr)
+ qual.sel = expr
+
+ // If qual.sel, possibly applied to type arguments, but is
+ // not applied to explicit value arguments,
+ // nor immediately followed by an assignment operator:
+ // qual.selectDynamic[Ts](“sel”)
+ qual.sel
+ qual.sel[T]
+
+ qual.sel(1) = expr // parser turns this into qual.sel.update(1, expr)
+ qual.sel() = expr // parser turns this into qual.sel.update(expr)
+ qual.sel.apply(1)
+ qual.sel.apply(1) = 1
+} \ No newline at end of file
diff --git a/test/files/run/array-charSeq.check b/test/files/run/array-charSeq.check
new file mode 100644
index 0000000000..f1f374f63e
--- /dev/null
+++ b/test/files/run/array-charSeq.check
@@ -0,0 +1,248 @@
+
+[check 'abcdefghi'] len = 9
+sub(0, 9) == 'abcdefghi'
+sub(0, 0) == ''
+sub(1, 9) == 'bcdefghi'
+sub(0, 1) == 'a'
+sub(2, 9) == 'cdefghi'
+sub(0, 2) == 'ab'
+sub(3, 9) == 'defghi'
+sub(0, 3) == 'abc'
+sub(4, 9) == 'efghi'
+sub(0, 4) == 'abcd'
+sub(5, 9) == 'fghi'
+sub(0, 5) == 'abcde'
+sub(6, 9) == 'ghi'
+sub(0, 6) == 'abcdef'
+sub(7, 9) == 'hi'
+sub(0, 7) == 'abcdefg'
+sub(8, 9) == 'i'
+sub(0, 8) == 'abcdefgh'
+
+[check 'bcdefgh'] len = 7
+sub(0, 7) == 'bcdefgh'
+sub(0, 0) == ''
+sub(1, 7) == 'cdefgh'
+sub(0, 1) == 'b'
+sub(2, 7) == 'defgh'
+sub(0, 2) == 'bc'
+sub(3, 7) == 'efgh'
+sub(0, 3) == 'bcd'
+sub(4, 7) == 'fgh'
+sub(0, 4) == 'bcde'
+sub(5, 7) == 'gh'
+sub(0, 5) == 'bcdef'
+sub(6, 7) == 'h'
+sub(0, 6) == 'bcdefg'
+
+[check 'cdefg'] len = 5
+sub(0, 5) == 'cdefg'
+sub(0, 0) == ''
+sub(1, 5) == 'defg'
+sub(0, 1) == 'c'
+sub(2, 5) == 'efg'
+sub(0, 2) == 'cd'
+sub(3, 5) == 'fg'
+sub(0, 3) == 'cde'
+sub(4, 5) == 'g'
+sub(0, 4) == 'cdef'
+
+[check 'def'] len = 3
+sub(0, 3) == 'def'
+sub(0, 0) == ''
+sub(1, 3) == 'ef'
+sub(0, 1) == 'd'
+sub(2, 3) == 'f'
+sub(0, 2) == 'de'
+
+[check 'e'] len = 1
+sub(0, 1) == 'e'
+sub(0, 0) == ''
+
+[check 'abcdefgh'] len = 8
+sub(0, 8) == 'abcdefgh'
+sub(0, 0) == ''
+sub(1, 8) == 'bcdefgh'
+sub(0, 1) == 'a'
+sub(2, 8) == 'cdefgh'
+sub(0, 2) == 'ab'
+sub(3, 8) == 'defgh'
+sub(0, 3) == 'abc'
+sub(4, 8) == 'efgh'
+sub(0, 4) == 'abcd'
+sub(5, 8) == 'fgh'
+sub(0, 5) == 'abcde'
+sub(6, 8) == 'gh'
+sub(0, 6) == 'abcdef'
+sub(7, 8) == 'h'
+sub(0, 7) == 'abcdefg'
+
+[check 'bcdefg'] len = 6
+sub(0, 6) == 'bcdefg'
+sub(0, 0) == ''
+sub(1, 6) == 'cdefg'
+sub(0, 1) == 'b'
+sub(2, 6) == 'defg'
+sub(0, 2) == 'bc'
+sub(3, 6) == 'efg'
+sub(0, 3) == 'bcd'
+sub(4, 6) == 'fg'
+sub(0, 4) == 'bcde'
+sub(5, 6) == 'g'
+sub(0, 5) == 'bcdef'
+
+[check 'cdef'] len = 4
+sub(0, 4) == 'cdef'
+sub(0, 0) == ''
+sub(1, 4) == 'def'
+sub(0, 1) == 'c'
+sub(2, 4) == 'ef'
+sub(0, 2) == 'cd'
+sub(3, 4) == 'f'
+sub(0, 3) == 'cde'
+
+[check 'de'] len = 2
+sub(0, 2) == 'de'
+sub(0, 0) == ''
+sub(1, 2) == 'e'
+sub(0, 1) == 'd'
+
+[check ''] len = 0
+
+[check 'abcdefg'] len = 7
+sub(0, 7) == 'abcdefg'
+sub(0, 0) == ''
+sub(1, 7) == 'bcdefg'
+sub(0, 1) == 'a'
+sub(2, 7) == 'cdefg'
+sub(0, 2) == 'ab'
+sub(3, 7) == 'defg'
+sub(0, 3) == 'abc'
+sub(4, 7) == 'efg'
+sub(0, 4) == 'abcd'
+sub(5, 7) == 'fg'
+sub(0, 5) == 'abcde'
+sub(6, 7) == 'g'
+sub(0, 6) == 'abcdef'
+
+[check 'bcdef'] len = 5
+sub(0, 5) == 'bcdef'
+sub(0, 0) == ''
+sub(1, 5) == 'cdef'
+sub(0, 1) == 'b'
+sub(2, 5) == 'def'
+sub(0, 2) == 'bc'
+sub(3, 5) == 'ef'
+sub(0, 3) == 'bcd'
+sub(4, 5) == 'f'
+sub(0, 4) == 'bcde'
+
+[check 'cde'] len = 3
+sub(0, 3) == 'cde'
+sub(0, 0) == ''
+sub(1, 3) == 'de'
+sub(0, 1) == 'c'
+sub(2, 3) == 'e'
+sub(0, 2) == 'cd'
+
+[check 'd'] len = 1
+sub(0, 1) == 'd'
+sub(0, 0) == ''
+
+[check 'abcdef'] len = 6
+sub(0, 6) == 'abcdef'
+sub(0, 0) == ''
+sub(1, 6) == 'bcdef'
+sub(0, 1) == 'a'
+sub(2, 6) == 'cdef'
+sub(0, 2) == 'ab'
+sub(3, 6) == 'def'
+sub(0, 3) == 'abc'
+sub(4, 6) == 'ef'
+sub(0, 4) == 'abcd'
+sub(5, 6) == 'f'
+sub(0, 5) == 'abcde'
+
+[check 'bcde'] len = 4
+sub(0, 4) == 'bcde'
+sub(0, 0) == ''
+sub(1, 4) == 'cde'
+sub(0, 1) == 'b'
+sub(2, 4) == 'de'
+sub(0, 2) == 'bc'
+sub(3, 4) == 'e'
+sub(0, 3) == 'bcd'
+
+[check 'cd'] len = 2
+sub(0, 2) == 'cd'
+sub(0, 0) == ''
+sub(1, 2) == 'd'
+sub(0, 1) == 'c'
+
+[check ''] len = 0
+
+[check 'abcde'] len = 5
+sub(0, 5) == 'abcde'
+sub(0, 0) == ''
+sub(1, 5) == 'bcde'
+sub(0, 1) == 'a'
+sub(2, 5) == 'cde'
+sub(0, 2) == 'ab'
+sub(3, 5) == 'de'
+sub(0, 3) == 'abc'
+sub(4, 5) == 'e'
+sub(0, 4) == 'abcd'
+
+[check 'bcd'] len = 3
+sub(0, 3) == 'bcd'
+sub(0, 0) == ''
+sub(1, 3) == 'cd'
+sub(0, 1) == 'b'
+sub(2, 3) == 'd'
+sub(0, 2) == 'bc'
+
+[check 'c'] len = 1
+sub(0, 1) == 'c'
+sub(0, 0) == ''
+
+[check 'abcd'] len = 4
+sub(0, 4) == 'abcd'
+sub(0, 0) == ''
+sub(1, 4) == 'bcd'
+sub(0, 1) == 'a'
+sub(2, 4) == 'cd'
+sub(0, 2) == 'ab'
+sub(3, 4) == 'd'
+sub(0, 3) == 'abc'
+
+[check 'bc'] len = 2
+sub(0, 2) == 'bc'
+sub(0, 0) == ''
+sub(1, 2) == 'c'
+sub(0, 1) == 'b'
+
+[check ''] len = 0
+
+[check 'abc'] len = 3
+sub(0, 3) == 'abc'
+sub(0, 0) == ''
+sub(1, 3) == 'bc'
+sub(0, 1) == 'a'
+sub(2, 3) == 'c'
+sub(0, 2) == 'ab'
+
+[check 'b'] len = 1
+sub(0, 1) == 'b'
+sub(0, 0) == ''
+
+[check 'ab'] len = 2
+sub(0, 2) == 'ab'
+sub(0, 0) == ''
+sub(1, 2) == 'b'
+sub(0, 1) == 'a'
+
+[check ''] len = 0
+
+[check 'a'] len = 1
+sub(0, 1) == 'a'
+sub(0, 0) == ''
diff --git a/test/files/run/array-charSeq.scala b/test/files/run/array-charSeq.scala
new file mode 100644
index 0000000000..f7d0586f03
--- /dev/null
+++ b/test/files/run/array-charSeq.scala
@@ -0,0 +1,27 @@
+object Test {
+ val arr = Array[Char]('a' to 'i': _*)
+ var xs: CharSequence = arr
+ val hash = xs.hashCode
+
+ def check(chars: CharSequence) {
+ println("\n[check '" + chars + "'] len = " + chars.length)
+ chars match {
+ case x: runtime.ArrayCharSequence => assert(x.xs eq arr, ((x.xs, arr)))
+ case x => assert(false, x)
+ }
+
+ 0 until chars.length foreach { i =>
+ println("sub(%s, %s) == '%s'".format(i, chars.length, chars.subSequence(i, chars.length)))
+ println("sub(%s, %s) == '%s'".format(0, i, chars.subSequence(0, i)))
+ }
+ if (chars.length >= 2)
+ check(chars.subSequence(1, chars.length - 1))
+ }
+
+ def main(args: Array[String]): Unit = {
+ while (xs.length > 0) {
+ check(xs)
+ xs = xs.subSequence(0, xs.length - 1)
+ }
+ }
+}
diff --git a/test/files/run/arrayclone-new.scala b/test/files/run/arrayclone-new.scala
new file mode 100644
index 0000000000..a4ba021409
--- /dev/null
+++ b/test/files/run/arrayclone-new.scala
@@ -0,0 +1,106 @@
+object Test extends App{
+ BooleanArrayClone;
+ ByteArrayClone;
+ ShortArrayClone;
+ CharArrayClone;
+ IntArrayClone;
+ LongArrayClone;
+ FloatArrayClone;
+ DoubleArrayClone;
+ ObjectArrayClone;
+ PolymorphicArrayClone;
+}
+
+object BooleanArrayClone{
+ val it : Array[Boolean] = Array(true, false);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = false;
+ assert(it(0) == true)
+}
+
+object ByteArrayClone{
+ val it : Array[Byte] = Array(1, 0);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = 0;
+ assert(it(0) == 1)
+}
+
+object ShortArrayClone{
+ val it : Array[Short] = Array(1, 0);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = 0;
+ assert(it(0) == 1)
+}
+
+object CharArrayClone{
+ val it : Array[Char] = Array(1, 0);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = 0;
+ assert(it(0) == 1)
+}
+
+object IntArrayClone{
+ val it : Array[Int] = Array(1, 0);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = 0;
+ assert(it(0) == 1)
+}
+
+object LongArrayClone{
+ val it : Array[Long] = Array(1, 0);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = 0;
+ assert(it(0) == 1)
+}
+
+object FloatArrayClone{
+ val it : Array[Float] = Array(1, 0);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = 0;
+ assert(it(0) == 1)
+}
+
+object DoubleArrayClone{
+ val it : Array[Double] = Array(1, 0);
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = 0;
+ assert(it(0) == 1)
+}
+
+object ObjectArrayClone{
+ val it : Array[String] = Array("1", "0");
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = "0";
+ assert(it(0) == "1")
+}
+
+object PolymorphicArrayClone{
+ def testIt[T](it : Array[T], one : T, zero : T) = {
+ val cloned = it.clone();
+ assert(cloned.sameElements(it));
+ cloned(0) = zero;
+ assert(it(0) == one)
+ }
+
+ testIt(Array("one", "two"), "one", "two");
+
+ class Mangler[T: ArrayTag](ts : T*){
+ // this will always be a BoxedAnyArray even after we've unboxed its contents.
+ val it = ts.toArray[T];
+ }
+
+ val mangled = new Mangler[Int](0, 1);
+
+ val y : Array[Int] = mangled.it; // make sure it's unboxed
+
+ testIt(mangled.it, 0, 1);
+}
diff --git a/test/files/run/arrayclone.scala b/test/files/run/arrayclone-old.scala
index c9f7556b47..c9f7556b47 100644
--- a/test/files/run/arrayclone.scala
+++ b/test/files/run/arrayclone-old.scala
diff --git a/test/files/run/arraytags_basic.check b/test/files/run/arraytags_basic.check
new file mode 100644
index 0000000000..92816b91bd
--- /dev/null
+++ b/test/files/run/arraytags_basic.check
@@ -0,0 +1,36 @@
+class [I
+class [[I
+class [[[I
+class [Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.List;
+class [Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.List;
+class [Lscala.collection.immutable.Map;
+class [[Lscala.collection.immutable.Map;
+class [[[Lscala.collection.immutable.Map;
+class [[I
+class [[[I
+class [[[[I
+class [[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.List;
+class [[[[Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.List;
+class [[[[Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.Map;
+class [[[Lscala.collection.immutable.Map;
+class [[[[Lscala.collection.immutable.Map;
+class [[[I
+class [[[[I
+class [[[[[I
+class [[[Lscala.collection.immutable.List;
+class [[[[Lscala.collection.immutable.List;
+class [[[[[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.List;
+class [[[[Lscala.collection.immutable.List;
+class [[[[[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.Map;
+class [[[[Lscala.collection.immutable.Map;
+class [[[[[Lscala.collection.immutable.Map;
diff --git a/test/files/run/arraytags_basic.scala b/test/files/run/arraytags_basic.scala
new file mode 100644
index 0000000000..edc20e9bc1
--- /dev/null
+++ b/test/files/run/arraytags_basic.scala
@@ -0,0 +1,22 @@
+object Test extends App {
+ def test[T: ArrayTag] = {
+ println(implicitly[ArrayTag[T]].newArray(10).getClass)
+ println(implicitly[ArrayTag[T]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[T]]].wrap.newArray(10).getClass)
+ }
+
+ test[Int]
+ test[List[Int]]
+ test[List[String]]
+ test[Map[Int, String]]
+
+ test[Array[Int]]
+ test[Array[List[Int]]]
+ test[Array[List[String]]]
+ test[Array[Map[Int, String]]]
+
+ test[Array[Array[Int]]]
+ test[Array[Array[List[Int]]]]
+ test[Array[Array[List[String]]]]
+ test[Array[Array[Map[Int, String]]]]
+} \ No newline at end of file
diff --git a/test/files/run/arraytags_core.check b/test/files/run/arraytags_core.check
new file mode 100644
index 0000000000..82ed84ad78
--- /dev/null
+++ b/test/files/run/arraytags_core.check
@@ -0,0 +1,48 @@
+class [B
+class [[B
+class [[[B
+class [S
+class [[S
+class [[[S
+class [C
+class [[C
+class [[[C
+class [I
+class [[I
+class [[[I
+class [J
+class [[J
+class [[[J
+class [F
+class [[F
+class [[[F
+class [D
+class [[D
+class [[[D
+class [Z
+class [[Z
+class [[[Z
+class [Lscala.runtime.BoxedUnit;
+class [[Lscala.runtime.BoxedUnit;
+class [[[Lscala.runtime.BoxedUnit;
+class [Ljava.lang.Object;
+class [[Ljava.lang.Object;
+class [[[Ljava.lang.Object;
+class [Ljava.lang.Object;
+class [[Ljava.lang.Object;
+class [[[Ljava.lang.Object;
+class [Ljava.lang.Object;
+class [[Ljava.lang.Object;
+class [[[Ljava.lang.Object;
+class [Ljava.lang.Object;
+class [[Ljava.lang.Object;
+class [[[Ljava.lang.Object;
+class [Lscala.runtime.Null$;
+class [[Lscala.runtime.Null$;
+class [[[Lscala.runtime.Null$;
+class [Lscala.runtime.Nothing$;
+class [[Lscala.runtime.Nothing$;
+class [[[Lscala.runtime.Nothing$;
+class [Ljava.lang.String;
+class [[Ljava.lang.String;
+class [[[Ljava.lang.String;
diff --git a/test/files/run/arraytags_core.scala b/test/files/run/arraytags_core.scala
new file mode 100644
index 0000000000..a59ae24f30
--- /dev/null
+++ b/test/files/run/arraytags_core.scala
@@ -0,0 +1,50 @@
+object Test extends App {
+ println(implicitly[ArrayTag[Byte]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Byte]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Byte]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Short]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Short]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Short]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Char]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Char]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Char]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Int]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Int]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Int]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Long]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Long]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Long]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Float]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Float]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Float]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Double]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Double]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Double]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Boolean]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Boolean]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Boolean]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Unit]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Unit]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Unit]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Any]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Any]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Any]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Object]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Object]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Object]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[AnyVal]].newArray(10).getClass)
+ println(implicitly[ArrayTag[AnyVal]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[AnyVal]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[AnyRef]].newArray(10).getClass)
+ println(implicitly[ArrayTag[AnyRef]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[AnyRef]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Null]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Null]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Null]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Nothing]].newArray(10).getClass)
+ println(implicitly[ArrayTag[Nothing]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[Nothing]]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[String]].newArray(10).getClass)
+ println(implicitly[ArrayTag[String]].wrap.newArray(10).getClass)
+ println(implicitly[ArrayTag[Array[String]]].wrap.newArray(10).getClass)
+} \ No newline at end of file
diff --git a/test/files/run/arraytags_usage.check b/test/files/run/arraytags_usage.check
new file mode 100644
index 0000000000..b1d02b7bfe
--- /dev/null
+++ b/test/files/run/arraytags_usage.check
@@ -0,0 +1,3 @@
+class [I
+class [I
+class [I
diff --git a/test/files/run/arraytags_usage.scala b/test/files/run/arraytags_usage.scala
new file mode 100644
index 0000000000..60b0a8f218
--- /dev/null
+++ b/test/files/run/arraytags_usage.scala
@@ -0,0 +1,15 @@
+object Test extends App {
+ def foo[T] = {
+ class MyArrayTag extends ArrayTag[T] {
+ def wrap: ArrayTag[Array[T]] = ???
+ def newArray(len: Int): Array[T] = new Array[Int](len).asInstanceOf[Array[T]]
+ }
+
+ implicit val tag = new MyArrayTag()
+ println(Array[T]().getClass)
+ }
+
+ foo[Int]
+ foo[String]
+ foo[Array[String]]
+} \ No newline at end of file
diff --git a/test/files/run/bugs.scala b/test/files/run/bugs.scala
index d5905af76c..ca598603bb 100644
--- a/test/files/run/bugs.scala
+++ b/test/files/run/bugs.scala
@@ -445,8 +445,7 @@ object Test {
test;
} catch {
case exception =>
- val curr: String = currentThread.toString();
- Console.print("Exception in thread \"" + curr + "\" " + exception);
+ Console.print("Exception in thread \"" + Thread.currentThread + "\" " + exception);
Console.println;
errors += 1
}
diff --git a/test/files/run/classtags_contextbound.check b/test/files/run/classtags_contextbound.check
new file mode 100644
index 0000000000..4104d544ba
--- /dev/null
+++ b/test/files/run/classtags_contextbound.check
@@ -0,0 +1 @@
+class [I
diff --git a/test/files/run/classtags_contextbound.scala b/test/files/run/classtags_contextbound.scala
new file mode 100644
index 0000000000..5bb0ae8d80
--- /dev/null
+++ b/test/files/run/classtags_contextbound.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ def mkArray[T: ClassTag] = Array[T]()
+ def foo[T: ClassTag] = mkArray[T]
+ println(foo[Int].getClass)
+} \ No newline at end of file
diff --git a/test/files/run/classtags_core.check b/test/files/run/classtags_core.check
new file mode 100644
index 0000000000..ebccfcd54c
--- /dev/null
+++ b/test/files/run/classtags_core.check
@@ -0,0 +1,32 @@
+true
+ClassTag[byte]
+true
+ClassTag[short]
+true
+ClassTag[char]
+true
+ClassTag[int]
+true
+ClassTag[long]
+true
+ClassTag[float]
+true
+ClassTag[double]
+true
+ClassTag[boolean]
+true
+ClassTag[void]
+true
+ClassTag[class java.lang.Object]
+true
+ClassTag[class java.lang.Object]
+true
+ClassTag[class java.lang.Object]
+true
+ClassTag[class java.lang.Object]
+true
+ClassTag[class scala.runtime.Null$]
+true
+ClassTag[class scala.runtime.Nothing$]
+true
+ClassTag[class java.lang.String]
diff --git a/test/files/run/classtags_core.scala b/test/files/run/classtags_core.scala
new file mode 100644
index 0000000000..9f2031377d
--- /dev/null
+++ b/test/files/run/classtags_core.scala
@@ -0,0 +1,34 @@
+object Test extends App {
+ println(implicitly[ClassTag[Byte]] eq ClassTag.Byte)
+ println(implicitly[ClassTag[Byte]])
+ println(implicitly[ClassTag[Short]] eq ClassTag.Short)
+ println(implicitly[ClassTag[Short]])
+ println(implicitly[ClassTag[Char]] eq ClassTag.Char)
+ println(implicitly[ClassTag[Char]])
+ println(implicitly[ClassTag[Int]] eq ClassTag.Int)
+ println(implicitly[ClassTag[Int]])
+ println(implicitly[ClassTag[Long]] eq ClassTag.Long)
+ println(implicitly[ClassTag[Long]])
+ println(implicitly[ClassTag[Float]] eq ClassTag.Float)
+ println(implicitly[ClassTag[Float]])
+ println(implicitly[ClassTag[Double]] eq ClassTag.Double)
+ println(implicitly[ClassTag[Double]])
+ println(implicitly[ClassTag[Boolean]] eq ClassTag.Boolean)
+ println(implicitly[ClassTag[Boolean]])
+ println(implicitly[ClassTag[Unit]] eq ClassTag.Unit)
+ println(implicitly[ClassTag[Unit]])
+ println(implicitly[ClassTag[Any]] eq ClassTag.Any)
+ println(implicitly[ClassTag[Any]])
+ println(implicitly[ClassTag[Object]] eq ClassTag.Object)
+ println(implicitly[ClassTag[Object]])
+ println(implicitly[ClassTag[AnyVal]] eq ClassTag.AnyVal)
+ println(implicitly[ClassTag[AnyVal]])
+ println(implicitly[ClassTag[AnyRef]] eq ClassTag.AnyRef)
+ println(implicitly[ClassTag[AnyRef]])
+ println(implicitly[ClassTag[Null]] eq ClassTag.Null)
+ println(implicitly[ClassTag[Null]])
+ println(implicitly[ClassTag[Nothing]] eq ClassTag.Nothing)
+ println(implicitly[ClassTag[Nothing]])
+ println(implicitly[ClassTag[String]] eq ClassTag.String)
+ println(implicitly[ClassTag[String]])
+} \ No newline at end of file
diff --git a/test/files/run/classtags_multi.check b/test/files/run/classtags_multi.check
new file mode 100644
index 0000000000..3a7f16c3a0
--- /dev/null
+++ b/test/files/run/classtags_multi.check
@@ -0,0 +1,5 @@
+ClassTag[int]
+ClassTag[class [I]
+ClassTag[class [[I]
+ClassTag[class [[[I]
+ClassTag[class [[[[I]
diff --git a/test/files/run/classtags_multi.scala b/test/files/run/classtags_multi.scala
new file mode 100644
index 0000000000..5aafb55223
--- /dev/null
+++ b/test/files/run/classtags_multi.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ println(classTag[Int])
+ println(classTag[Array[Int]])
+ println(classTag[Array[Array[Int]]])
+ println(classTag[Array[Array[Array[Int]]]])
+ println(classTag[Array[Array[Array[Array[Int]]]]])
+} \ No newline at end of file
diff --git a/test/files/run/classtags_use_concretetypetags.scala b/test/files/run/classtags_use_concretetypetags.scala
new file mode 100644
index 0000000000..57e7085cec
--- /dev/null
+++ b/test/files/run/classtags_use_concretetypetags.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ def foo[T: ConcreteTypeTag] = Array[T]()
+} \ No newline at end of file
diff --git a/test/files/run/compiler-asSeenFrom.check b/test/files/run/compiler-asSeenFrom.check
index f198e61072..96e257d303 100644
--- a/test/files/run/compiler-asSeenFrom.check
+++ b/test/files/run/compiler-asSeenFrom.check
@@ -187,69 +187,69 @@ class J {
D[A1]#J[T4] Z.dZ.J[P] D[A1]#J[P]
}
class D { // after parser
- private val cD: ll.C[List[T3]]
+ private[this] val cD: ll.C[List[T3]]
val cD: ll.C[List[T3]]
}
class D { // after uncurry
- private val cD: ll.C[List[T3]]
+ private[this] val cD: ll.C[List[T3]]
val cD(): ll.C[List[T3]]
}
class D { // after erasure
- private val cD: ll.C
+ private[this] val cD: ll.C
val cD(): ll.C
}
object Z { // after parser
def kz[P <: ll.Z.dZ.J[ll.A2]]: ll.Z.dZ.J[P]
- private val jZ: ll.Z.dZ.J[ll.A2]
+ private[this] val jZ: ll.Z.dZ.J[ll.A2]
val jZ: ll.Z.dZ.J[ll.A2]
- private val dZ: ll.D[ll.A1]
+ private[this] val dZ: ll.D[ll.A1]
val dZ: ll.D[ll.A1]
}
object Z { // after uncurry
def kz[P <: ll.Z.dZ.J[ll.A2]](): ll.Z.dZ.J[P]
- private val jZ: ll.Z.dZ.J[ll.A2]
+ private[this] val jZ: ll.Z.dZ.J[ll.A2]
val jZ(): ll.Z.dZ.J[ll.A2]
- private val dZ: ll.D[ll.A1]
+ private[this] val dZ: ll.D[ll.A1]
val dZ(): ll.D[ll.A1]
}
object Z { // after erasure
def kz(): ll.D#J
- private val jZ: ll.D#J
+ private[this] val jZ: ll.D#J
val jZ(): ll.D#J
- private val dZ: ll.D
+ private[this] val dZ: ll.D
val dZ(): ll.D
}
object Z { // after flatten
def kz(): ll.D#D$J
- private val jZ: ll.D#D$J
+ private[this] val jZ: ll.D#D$J
val jZ(): ll.D#D$J
- private val dZ: ll.D
+ private[this] val dZ: ll.D
val dZ(): ll.D
}
value dZ { // after parser
- private val cD: ll.C[List[T3]]
+ private[this] val cD: ll.C[List[T3]]
val cD: ll.C[List[T3]]
}
value dZ { // after parser
- private val cD: ll.C[List[T3]]
+ private[this] val cD: ll.C[List[T3]]
val cD: ll.C[List[T3]]
}
value dZ { // after uncurry
- private val cD: ll.C[List[T3]]
+ private[this] val cD: ll.C[List[T3]]
val cD(): ll.C[List[T3]]
}
value dZ { // after erasure
- private val cD: ll.C
+ private[this] val cD: ll.C
val cD(): ll.C
}
@@ -307,17 +307,17 @@ method kz { // after parser
}
value $outer { // after parser
- private val cD: ll.C[List[T3]]
+ private[this] val cD: ll.C[List[T3]]
val cD: ll.C[List[T3]]
}
value $outer { // after uncurry
- private val cD: ll.C[List[T3]]
+ private[this] val cD: ll.C[List[T3]]
val cD(): ll.C[List[T3]]
}
value $outer { // after erasure
- private val cD: ll.C
+ private[this] val cD: ll.C
val cD(): ll.C
}
diff --git a/test/files/run/concretetypetags_core.check b/test/files/run/concretetypetags_core.check
new file mode 100644
index 0000000000..f124aa6a35
--- /dev/null
+++ b/test/files/run/concretetypetags_core.check
@@ -0,0 +1,32 @@
+true
+ConcreteTypeTag[Byte]
+true
+ConcreteTypeTag[Short]
+true
+ConcreteTypeTag[Char]
+true
+ConcreteTypeTag[Int]
+true
+ConcreteTypeTag[Long]
+true
+ConcreteTypeTag[Float]
+true
+ConcreteTypeTag[Double]
+true
+ConcreteTypeTag[Boolean]
+true
+ConcreteTypeTag[Unit]
+true
+ConcreteTypeTag[Any]
+true
+ConcreteTypeTag[Object]
+true
+ConcreteTypeTag[AnyVal]
+true
+ConcreteTypeTag[AnyRef]
+true
+ConcreteTypeTag[Null]
+true
+ConcreteTypeTag[Nothing]
+true
+ConcreteTypeTag[String]
diff --git a/test/files/run/concretetypetags_core.scala b/test/files/run/concretetypetags_core.scala
new file mode 100644
index 0000000000..b6cfea3895
--- /dev/null
+++ b/test/files/run/concretetypetags_core.scala
@@ -0,0 +1,34 @@
+object Test extends App {
+ println(implicitly[ConcreteTypeTag[Byte]] eq ConcreteTypeTag.Byte)
+ println(implicitly[ConcreteTypeTag[Byte]])
+ println(implicitly[ConcreteTypeTag[Short]] eq ConcreteTypeTag.Short)
+ println(implicitly[ConcreteTypeTag[Short]])
+ println(implicitly[ConcreteTypeTag[Char]] eq ConcreteTypeTag.Char)
+ println(implicitly[ConcreteTypeTag[Char]])
+ println(implicitly[ConcreteTypeTag[Int]] eq ConcreteTypeTag.Int)
+ println(implicitly[ConcreteTypeTag[Int]])
+ println(implicitly[ConcreteTypeTag[Long]] eq ConcreteTypeTag.Long)
+ println(implicitly[ConcreteTypeTag[Long]])
+ println(implicitly[ConcreteTypeTag[Float]] eq ConcreteTypeTag.Float)
+ println(implicitly[ConcreteTypeTag[Float]])
+ println(implicitly[ConcreteTypeTag[Double]] eq ConcreteTypeTag.Double)
+ println(implicitly[ConcreteTypeTag[Double]])
+ println(implicitly[ConcreteTypeTag[Boolean]] eq ConcreteTypeTag.Boolean)
+ println(implicitly[ConcreteTypeTag[Boolean]])
+ println(implicitly[ConcreteTypeTag[Unit]] eq ConcreteTypeTag.Unit)
+ println(implicitly[ConcreteTypeTag[Unit]])
+ println(implicitly[ConcreteTypeTag[Any]] eq ConcreteTypeTag.Any)
+ println(implicitly[ConcreteTypeTag[Any]])
+ println(implicitly[ConcreteTypeTag[Object]] eq ConcreteTypeTag.Object)
+ println(implicitly[ConcreteTypeTag[Object]])
+ println(implicitly[ConcreteTypeTag[AnyVal]] eq ConcreteTypeTag.AnyVal)
+ println(implicitly[ConcreteTypeTag[AnyVal]])
+ println(implicitly[ConcreteTypeTag[AnyRef]] eq ConcreteTypeTag.AnyRef)
+ println(implicitly[ConcreteTypeTag[AnyRef]])
+ println(implicitly[ConcreteTypeTag[Null]] eq ConcreteTypeTag.Null)
+ println(implicitly[ConcreteTypeTag[Null]])
+ println(implicitly[ConcreteTypeTag[Nothing]] eq ConcreteTypeTag.Nothing)
+ println(implicitly[ConcreteTypeTag[Nothing]])
+ println(implicitly[ConcreteTypeTag[String]] eq ConcreteTypeTag.String)
+ println(implicitly[ConcreteTypeTag[String]])
+} \ No newline at end of file
diff --git a/test/files/run/concretetypetags_multi.check b/test/files/run/concretetypetags_multi.check
new file mode 100644
index 0000000000..613106985c
--- /dev/null
+++ b/test/files/run/concretetypetags_multi.check
@@ -0,0 +1,5 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[Array[Int]]
+ConcreteTypeTag[Array[Array[Int]]]
+ConcreteTypeTag[Array[Array[Array[Int]]]]
+ConcreteTypeTag[Array[Array[Array[Array[Int]]]]]
diff --git a/test/files/run/concretetypetags_multi.scala b/test/files/run/concretetypetags_multi.scala
new file mode 100644
index 0000000000..7e19d7db34
--- /dev/null
+++ b/test/files/run/concretetypetags_multi.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ println(concreteTypeTag[Int])
+ println(concreteTypeTag[Array[Int]])
+ println(concreteTypeTag[Array[Array[Int]]])
+ println(concreteTypeTag[Array[Array[Array[Int]]]])
+ println(concreteTypeTag[Array[Array[Array[Array[Int]]]]])
+} \ No newline at end of file
diff --git a/test/files/run/constrained-types.check b/test/files/run/constrained-types.check
index ac8817cb08..37784a20ca 100644
--- a/test/files/run/constrained-types.check
+++ b/test/files/run/constrained-types.check
@@ -75,9 +75,13 @@ scala> var four = "four"
four: String = four
scala> val four2 = m(four) // should have an existential bound
+warning: there were 1 feature warnings; re-run with -feature for details
+warning: there were 1 feature warnings; re-run with -feature for details
four2: String @Annot(x) forSome { val x: String } = four
scala> val four3 = four2 // should have the same type as four2
+warning: there were 1 feature warnings; re-run with -feature for details
+warning: there were 1 feature warnings; re-run with -feature for details
four3: String @Annot(x) forSome { val x: String } = four
scala> val stuff = m("stuff") // should not crash
@@ -100,6 +104,8 @@ scala> def m = {
val y : String @Annot(x) = x
y
} // x should not escape the local scope with a narrow type
+warning: there were 1 feature warnings; re-run with -feature for details
+warning: there were 1 feature warnings; re-run with -feature for details
m: String @Annot(x) forSome { val x: String }
scala>
@@ -113,6 +119,7 @@ scala> def n(y: String) = {
}
m("stuff".stripMargin)
} // x should be existentially bound
+warning: there were 1 feature warnings; re-run with -feature for details
n: (y: String)String @Annot(x) forSome { val x: String }
scala>
diff --git a/test/files/run/ctries/DumbHash.scala b/test/files/run/ctries-new/DumbHash.scala
index 8ef325b67c..8ef325b67c 100644
--- a/test/files/run/ctries/DumbHash.scala
+++ b/test/files/run/ctries-new/DumbHash.scala
diff --git a/test/files/run/ctries/Wrap.scala b/test/files/run/ctries-new/Wrap.scala
index 7b645c1612..7b645c1612 100644
--- a/test/files/run/ctries/Wrap.scala
+++ b/test/files/run/ctries-new/Wrap.scala
diff --git a/test/files/run/ctries/concmap.scala b/test/files/run/ctries-new/concmap.scala
index 3ec0256afb..3ec0256afb 100644
--- a/test/files/run/ctries/concmap.scala
+++ b/test/files/run/ctries-new/concmap.scala
diff --git a/test/files/run/ctries/iterator.scala b/test/files/run/ctries-new/iterator.scala
index b953a40e00..b953a40e00 100644
--- a/test/files/run/ctries/iterator.scala
+++ b/test/files/run/ctries-new/iterator.scala
diff --git a/test/files/run/ctries/lnode.scala b/test/files/run/ctries-new/lnode.scala
index 92a31088e5..92a31088e5 100644
--- a/test/files/run/ctries/lnode.scala
+++ b/test/files/run/ctries-new/lnode.scala
diff --git a/test/files/run/ctries-new/main.scala b/test/files/run/ctries-new/main.scala
new file mode 100644
index 0000000000..1d40dab6c5
--- /dev/null
+++ b/test/files/run/ctries-new/main.scala
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ ConcurrentMapSpec.test()
+ IteratorSpec.test()
+ LNodeSpec.test()
+ SnapshotSpec.test()
+ }
+
+}
+
+
+trait Spec {
+
+ implicit def str2ops(s: String) = new {
+ def in[U](body: =>U) {
+ // just execute body
+ body
+ }
+ }
+
+ implicit def any2ops(a: Any) = new {
+ def shouldEqual(other: Any) = assert(a == other)
+ }
+
+ def evaluating[U](body: =>U) = new {
+ def shouldProduce[T <: Throwable: ClassTag]() = {
+ var produced = false
+ try body
+ catch {
+ case e => if (e.getClass == implicitly[ClassTag[T]].erasure) produced = true
+ } finally {
+ assert(produced, "Did not produce exception of type: " + implicitly[ClassTag[T]])
+ }
+ }
+ }
+
+}
diff --git a/test/files/run/ctries/snapshot.scala b/test/files/run/ctries-new/snapshot.scala
index 5fe77d445b..5fe77d445b 100644
--- a/test/files/run/ctries/snapshot.scala
+++ b/test/files/run/ctries-new/snapshot.scala
diff --git a/test/files/run/ctries-old/DumbHash.scala b/test/files/run/ctries-old/DumbHash.scala
new file mode 100644
index 0000000000..8ef325b67c
--- /dev/null
+++ b/test/files/run/ctries-old/DumbHash.scala
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+class DumbHash(val i: Int) {
+ override def equals(other: Any) = other match {
+ case that: DumbHash => that.i == this.i
+ case _ => false
+ }
+ override def hashCode = i % 5
+ override def toString = "DH(%s)".format(i)
+}
diff --git a/test/files/run/ctries-old/Wrap.scala b/test/files/run/ctries-old/Wrap.scala
new file mode 100644
index 0000000000..7b645c1612
--- /dev/null
+++ b/test/files/run/ctries-old/Wrap.scala
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+case class Wrap(i: Int) {
+ override def hashCode = i * 0x9e3775cd
+}
diff --git a/test/files/run/ctries-old/concmap.scala b/test/files/run/ctries-old/concmap.scala
new file mode 100644
index 0000000000..3ec0256afb
--- /dev/null
+++ b/test/files/run/ctries-old/concmap.scala
@@ -0,0 +1,188 @@
+
+
+
+import collection.concurrent.TrieMap
+
+
+object ConcurrentMapSpec extends Spec {
+
+ val initsz = 500
+ val secondsz = 750
+
+ def test() {
+ "support put" in {
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until initsz) assert(ct.put(new Wrap(i), i) == None)
+ for (i <- 0 until initsz) assert(ct.put(new Wrap(i), -i) == Some(i))
+ }
+
+ "support put if absent" in {
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until initsz) ct.update(new Wrap(i), i)
+ for (i <- 0 until initsz) assert(ct.putIfAbsent(new Wrap(i), -i) == Some(i))
+ for (i <- 0 until initsz) assert(ct.putIfAbsent(new Wrap(i), -i) == Some(i))
+ for (i <- initsz until secondsz) assert(ct.putIfAbsent(new Wrap(i), -i) == None)
+ for (i <- initsz until secondsz) assert(ct.putIfAbsent(new Wrap(i), i) == Some(-i))
+ }
+
+ "support remove if mapped to a specific value" in {
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until initsz) ct.update(new Wrap(i), i)
+ for (i <- 0 until initsz) assert(ct.remove(new Wrap(i), -i - 1) == false)
+ for (i <- 0 until initsz) assert(ct.remove(new Wrap(i), i) == true)
+ for (i <- 0 until initsz) assert(ct.remove(new Wrap(i), i) == false)
+ }
+
+ "support replace if mapped to a specific value" in {
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until initsz) ct.update(new Wrap(i), i)
+ for (i <- 0 until initsz) assert(ct.replace(new Wrap(i), -i - 1, -i - 2) == false)
+ for (i <- 0 until initsz) assert(ct.replace(new Wrap(i), i, -i - 2) == true)
+ for (i <- 0 until initsz) assert(ct.replace(new Wrap(i), i, -i - 2) == false)
+ for (i <- initsz until secondsz) assert(ct.replace(new Wrap(i), i, 0) == false)
+ }
+
+ "support replace if present" in {
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until initsz) ct.update(new Wrap(i), i)
+ for (i <- 0 until initsz) assert(ct.replace(new Wrap(i), -i) == Some(i))
+ for (i <- 0 until initsz) assert(ct.replace(new Wrap(i), i) == Some(-i))
+ for (i <- initsz until secondsz) assert(ct.replace(new Wrap(i), i) == None)
+ }
+
+ def assertEqual(a: Any, b: Any) = {
+ if (a != b) println(a, b)
+ assert(a == b)
+ }
+
+ "support replace if mapped to a specific value, using several threads" in {
+ val ct = new TrieMap[Wrap, Int]
+ val sz = 55000
+ for (i <- 0 until sz) ct.update(new Wrap(i), i)
+
+ class Updater(index: Int, offs: Int) extends Thread {
+ override def run() {
+ var repeats = 0
+ for (i <- 0 until sz) {
+ val j = (offs + i) % sz
+ var k = Int.MaxValue
+ do {
+ if (k != Int.MaxValue) repeats += 1
+ k = ct.lookup(new Wrap(j))
+ } while (!ct.replace(new Wrap(j), k, -k))
+ }
+ //println("Thread %d repeats: %d".format(index, repeats))
+ }
+ }
+
+ val threads = for (i <- 0 until 16) yield new Updater(i, sz / 32 * i)
+ threads.foreach(_.start())
+ threads.foreach(_.join())
+
+ for (i <- 0 until sz) assertEqual(ct(new Wrap(i)), i)
+
+ val threads2 = for (i <- 0 until 15) yield new Updater(i, sz / 32 * i)
+ threads2.foreach(_.start())
+ threads2.foreach(_.join())
+
+ for (i <- 0 until sz) assertEqual(ct(new Wrap(i)), -i)
+ }
+
+ "support put if absent, several threads" in {
+ val ct = new TrieMap[Wrap, Int]
+ val sz = 110000
+
+ class Updater(offs: Int) extends Thread {
+ override def run() {
+ for (i <- 0 until sz) {
+ val j = (offs + i) % sz
+ ct.putIfAbsent(new Wrap(j), j)
+ assert(ct.lookup(new Wrap(j)) == j)
+ }
+ }
+ }
+
+ val threads = for (i <- 0 until 16) yield new Updater(sz / 32 * i)
+ threads.foreach(_.start())
+ threads.foreach(_.join())
+
+ for (i <- 0 until sz) assert(ct(new Wrap(i)) == i)
+ }
+
+ "support remove if mapped to a specific value, several threads" in {
+ val ct = new TrieMap[Wrap, Int]
+ val sz = 55000
+ for (i <- 0 until sz) ct.update(new Wrap(i), i)
+
+ class Remover(offs: Int) extends Thread {
+ override def run() {
+ for (i <- 0 until sz) {
+ val j = (offs + i) % sz
+ ct.remove(new Wrap(j), j)
+ assert(ct.get(new Wrap(j)) == None)
+ }
+ }
+ }
+
+ val threads = for (i <- 0 until 16) yield new Remover(sz / 32 * i)
+ threads.foreach(_.start())
+ threads.foreach(_.join())
+
+ for (i <- 0 until sz) assert(ct.get(new Wrap(i)) == None)
+ }
+
+ "have all or none of the elements depending on the oddity" in {
+ val ct = new TrieMap[Wrap, Int]
+ val sz = 65000
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+
+ class Modifier(index: Int, offs: Int) extends Thread {
+ override def run() {
+ for (j <- 0 until sz) {
+ val i = (offs + j) % sz
+ var success = false
+ do {
+ if (ct.contains(new Wrap(i))) {
+ success = ct.remove(new Wrap(i)) != None
+ } else {
+ success = ct.putIfAbsent(new Wrap(i), i) == None
+ }
+ } while (!success)
+ }
+ }
+ }
+
+ def modify(n: Int) = {
+ val threads = for (i <- 0 until n) yield new Modifier(i, sz / n * i)
+ threads.foreach(_.start())
+ threads.foreach(_.join())
+ }
+
+ modify(16)
+ for (i <- 0 until sz) assertEqual(ct.get(new Wrap(i)), Some(i))
+ modify(15)
+ for (i <- 0 until sz) assertEqual(ct.get(new Wrap(i)), None)
+ }
+
+ "compute size correctly" in {
+ val ct = new TrieMap[Wrap, Int]
+ val sz = 36450
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+
+ assertEqual(ct.size, sz)
+ assertEqual(ct.size, sz)
+ }
+
+ "compute size correctly in parallel" in {
+ val ct = new TrieMap[Wrap, Int]
+ val sz = 36450
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+ val pct = ct.par
+
+ assertEqual(pct.size, sz)
+ assertEqual(pct.size, sz)
+ }
+
+ }
+
+}
diff --git a/test/files/run/ctries-old/iterator.scala b/test/files/run/ctries-old/iterator.scala
new file mode 100644
index 0000000000..b953a40e00
--- /dev/null
+++ b/test/files/run/ctries-old/iterator.scala
@@ -0,0 +1,289 @@
+
+
+
+
+import collection._
+import collection.concurrent.TrieMap
+
+
+
+object IteratorSpec extends Spec {
+
+ def test() {
+ "work for an empty trie" in {
+ val ct = new TrieMap
+ val it = ct.iterator
+
+ it.hasNext shouldEqual (false)
+ evaluating { it.next() }.shouldProduce [NoSuchElementException]
+ }
+
+ def nonEmptyIteratorCheck(sz: Int) {
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct.put(new Wrap(i), i)
+
+ val it = ct.iterator
+ val tracker = mutable.Map[Wrap, Int]()
+ for (i <- 0 until sz) {
+ assert(it.hasNext == true)
+ tracker += it.next
+ }
+
+ it.hasNext shouldEqual (false)
+ evaluating { it.next() }.shouldProduce [NoSuchElementException]
+ tracker.size shouldEqual (sz)
+ tracker shouldEqual (ct)
+ }
+
+ "work for a 1 element trie" in {
+ nonEmptyIteratorCheck(1)
+ }
+
+ "work for a 2 element trie" in {
+ nonEmptyIteratorCheck(2)
+ }
+
+ "work for a 3 element trie" in {
+ nonEmptyIteratorCheck(3)
+ }
+
+ "work for a 5 element trie" in {
+ nonEmptyIteratorCheck(5)
+ }
+
+ "work for a 10 element trie" in {
+ nonEmptyIteratorCheck(10)
+ }
+
+ "work for a 20 element trie" in {
+ nonEmptyIteratorCheck(20)
+ }
+
+ "work for a 50 element trie" in {
+ nonEmptyIteratorCheck(50)
+ }
+
+ "work for a 100 element trie" in {
+ nonEmptyIteratorCheck(100)
+ }
+
+ "work for a 1k element trie" in {
+ nonEmptyIteratorCheck(1000)
+ }
+
+ "work for a 5k element trie" in {
+ nonEmptyIteratorCheck(5000)
+ }
+
+ "work for a 75k element trie" in {
+ nonEmptyIteratorCheck(75000)
+ }
+
+ "work for a 250k element trie" in {
+ nonEmptyIteratorCheck(500000)
+ }
+
+ def nonEmptyCollideCheck(sz: Int) {
+ val ct = new TrieMap[DumbHash, Int]
+ for (i <- 0 until sz) ct.put(new DumbHash(i), i)
+
+ val it = ct.iterator
+ val tracker = mutable.Map[DumbHash, Int]()
+ for (i <- 0 until sz) {
+ assert(it.hasNext == true)
+ tracker += it.next
+ }
+
+ it.hasNext shouldEqual (false)
+ evaluating { it.next() }.shouldProduce [NoSuchElementException]
+ tracker.size shouldEqual (sz)
+ tracker shouldEqual (ct)
+ }
+
+ "work for colliding hashcodes, 2 element trie" in {
+ nonEmptyCollideCheck(2)
+ }
+
+ "work for colliding hashcodes, 3 element trie" in {
+ nonEmptyCollideCheck(3)
+ }
+
+ "work for colliding hashcodes, 5 element trie" in {
+ nonEmptyCollideCheck(5)
+ }
+
+ "work for colliding hashcodes, 10 element trie" in {
+ nonEmptyCollideCheck(10)
+ }
+
+ "work for colliding hashcodes, 100 element trie" in {
+ nonEmptyCollideCheck(100)
+ }
+
+ "work for colliding hashcodes, 500 element trie" in {
+ nonEmptyCollideCheck(500)
+ }
+
+ "work for colliding hashcodes, 5k element trie" in {
+ nonEmptyCollideCheck(5000)
+ }
+
+ def assertEqual(a: Map[Wrap, Int], b: Map[Wrap, Int]) {
+ if (a != b) {
+ println(a.size + " vs " + b.size)
+ // println(a)
+ // println(b)
+ // println(a.toSeq.sortBy((x: (Wrap, Int)) => x._1.i))
+ // println(b.toSeq.sortBy((x: (Wrap, Int)) => x._1.i))
+ }
+ assert(a == b)
+ }
+
+ "be consistent when taken with concurrent modifications" in {
+ val sz = 25000
+ val W = 15
+ val S = 5
+ val checks = 5
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct.put(new Wrap(i), i)
+
+ class Modifier extends Thread {
+ override def run() {
+ for (i <- 0 until sz) ct.putIfAbsent(new Wrap(i), i) match {
+ case Some(_) => ct.remove(new Wrap(i))
+ case None =>
+ }
+ }
+ }
+
+ def consistentIteration(ct: TrieMap[Wrap, Int], checks: Int) {
+ class Iter extends Thread {
+ override def run() {
+ val snap = ct.readOnlySnapshot()
+ val initial = mutable.Map[Wrap, Int]()
+ for (kv <- snap) initial += kv
+
+ for (i <- 0 until checks) {
+ assertEqual(snap.iterator.toMap, initial)
+ }
+ }
+ }
+
+ val iter = new Iter
+ iter.start()
+ iter.join()
+ }
+
+ val threads = for (_ <- 0 until W) yield new Modifier
+ threads.foreach(_.start())
+ for (_ <- 0 until S) consistentIteration(ct, checks)
+ threads.foreach(_.join())
+ }
+
+ "be consistent with a concurrent removal with a well defined order" in {
+ val sz = 150000
+ val sgroupsize = 10
+ val sgroupnum = 5
+ val removerslowdown = 50
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct.put(new Wrap(i), i)
+
+ class Remover extends Thread {
+ override def run() {
+ for (i <- 0 until sz) {
+ assert(ct.remove(new Wrap(i)) == Some(i))
+ for (i <- 0 until removerslowdown) ct.get(new Wrap(i)) // slow down, mate
+ }
+ //println("done removing")
+ }
+ }
+
+ def consistentIteration(it: Iterator[(Wrap, Int)]) = {
+ class Iter extends Thread {
+ override def run() {
+ val elems = it.toBuffer
+ if (elems.nonEmpty) {
+ val minelem = elems.minBy((x: (Wrap, Int)) => x._1.i)._1.i
+ assert(elems.forall(_._1.i >= minelem))
+ }
+ }
+ }
+ new Iter
+ }
+
+ val remover = new Remover
+ remover.start()
+ for (_ <- 0 until sgroupnum) {
+ val iters = for (_ <- 0 until sgroupsize) yield consistentIteration(ct.iterator)
+ iters.foreach(_.start())
+ iters.foreach(_.join())
+ }
+ //println("done with iterators")
+ remover.join()
+ }
+
+ "be consistent with a concurrent insertion with a well defined order" in {
+ val sz = 150000
+ val sgroupsize = 10
+ val sgroupnum = 10
+ val inserterslowdown = 50
+ val ct = new TrieMap[Wrap, Int]
+
+ class Inserter extends Thread {
+ override def run() {
+ for (i <- 0 until sz) {
+ assert(ct.put(new Wrap(i), i) == None)
+ for (i <- 0 until inserterslowdown) ct.get(new Wrap(i)) // slow down, mate
+ }
+ //println("done inserting")
+ }
+ }
+
+ def consistentIteration(it: Iterator[(Wrap, Int)]) = {
+ class Iter extends Thread {
+ override def run() {
+ val elems = it.toSeq
+ if (elems.nonEmpty) {
+ val maxelem = elems.maxBy((x: (Wrap, Int)) => x._1.i)._1.i
+ assert(elems.forall(_._1.i <= maxelem))
+ }
+ }
+ }
+ new Iter
+ }
+
+ val inserter = new Inserter
+ inserter.start()
+ for (_ <- 0 until sgroupnum) {
+ val iters = for (_ <- 0 until sgroupsize) yield consistentIteration(ct.iterator)
+ iters.foreach(_.start())
+ iters.foreach(_.join())
+ }
+ //println("done with iterators")
+ inserter.join()
+ }
+
+ "work on a yet unevaluated snapshot" in {
+ val sz = 50000
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct.update(new Wrap(i), i)
+
+ val snap = ct.snapshot()
+ val it = snap.iterator
+
+ while (it.hasNext) it.next()
+ }
+
+ "be duplicated" in {
+ val sz = 50
+ val ct = collection.parallel.mutable.ParTrieMap((0 until sz) zip (0 until sz): _*)
+ val it = ct.splitter
+ for (_ <- 0 until (sz / 2)) it.next()
+ val dupit = it.dup
+
+ it.toList shouldEqual dupit.toList
+ }
+
+ }
+
+}
diff --git a/test/files/run/ctries-old/lnode.scala b/test/files/run/ctries-old/lnode.scala
new file mode 100644
index 0000000000..92a31088e5
--- /dev/null
+++ b/test/files/run/ctries-old/lnode.scala
@@ -0,0 +1,61 @@
+
+
+
+import collection.concurrent.TrieMap
+
+
+object LNodeSpec extends Spec {
+
+ val initsz = 1500
+ val secondsz = 1750
+
+ def test() {
+ "accept elements with the same hash codes" in {
+ val ct = new TrieMap[DumbHash, Int]
+ for (i <- 0 until initsz) ct.update(new DumbHash(i), i)
+ }
+
+ "lookup elements with the same hash codes" in {
+ val ct = new TrieMap[DumbHash, Int]
+ for (i <- 0 until initsz) ct.update(new DumbHash(i), i)
+ for (i <- 0 until initsz) assert(ct.get(new DumbHash(i)) == Some(i))
+ for (i <- initsz until secondsz) assert(ct.get(new DumbHash(i)) == None)
+ }
+
+ "remove elements with the same hash codes" in {
+ val ct = new TrieMap[DumbHash, Int]
+ for (i <- 0 until initsz) ct.update(new DumbHash(i), i)
+ for (i <- 0 until initsz) {
+ val remelem = ct.remove(new DumbHash(i))
+ assert(remelem == Some(i), "removing " + i + " yields " + remelem)
+ }
+ for (i <- 0 until initsz) assert(ct.get(new DumbHash(i)) == None)
+ }
+
+ "put elements with the same hash codes if absent" in {
+ val ct = new TrieMap[DumbHash, Int]
+ for (i <- 0 until initsz) ct.put(new DumbHash(i), i)
+ for (i <- 0 until initsz) assert(ct.lookup(new DumbHash(i)) == i)
+ for (i <- 0 until initsz) assert(ct.putIfAbsent(new DumbHash(i), i) == Some(i))
+ for (i <- initsz until secondsz) assert(ct.putIfAbsent(new DumbHash(i), i) == None)
+ for (i <- initsz until secondsz) assert(ct.lookup(new DumbHash(i)) == i)
+ }
+
+ "replace elements with the same hash codes" in {
+ val ct = new TrieMap[DumbHash, Int]
+ for (i <- 0 until initsz) assert(ct.put(new DumbHash(i), i) == None)
+ for (i <- 0 until initsz) assert(ct.lookup(new DumbHash(i)) == i)
+ for (i <- 0 until initsz) assert(ct.replace(new DumbHash(i), -i) == Some(i))
+ for (i <- 0 until initsz) assert(ct.lookup(new DumbHash(i)) == -i)
+ for (i <- 0 until initsz) assert(ct.replace(new DumbHash(i), -i, i) == true)
+ }
+
+ "remove elements with the same hash codes if mapped to a specific value" in {
+ val ct = new TrieMap[DumbHash, Int]
+ for (i <- 0 until initsz) assert(ct.put(new DumbHash(i), i) == None)
+ for (i <- 0 until initsz) assert(ct.remove(new DumbHash(i), i) == true)
+ }
+
+ }
+
+}
diff --git a/test/files/run/ctries/main.scala b/test/files/run/ctries-old/main.scala
index 8db7fcef54..8db7fcef54 100644
--- a/test/files/run/ctries/main.scala
+++ b/test/files/run/ctries-old/main.scala
diff --git a/test/files/run/ctries-old/snapshot.scala b/test/files/run/ctries-old/snapshot.scala
new file mode 100644
index 0000000000..5fe77d445b
--- /dev/null
+++ b/test/files/run/ctries-old/snapshot.scala
@@ -0,0 +1,267 @@
+
+
+
+
+import collection._
+import collection.concurrent.TrieMap
+
+
+
+object SnapshotSpec extends Spec {
+
+ def test() {
+ "support snapshots" in {
+ val ctn = new TrieMap
+ ctn.snapshot()
+ ctn.readOnlySnapshot()
+
+ val ct = new TrieMap[Int, Int]
+ for (i <- 0 until 100) ct.put(i, i)
+ ct.snapshot()
+ ct.readOnlySnapshot()
+ }
+
+ "empty 2 quiescent snapshots in isolation" in {
+ val sz = 4000
+
+ class Worker(trie: TrieMap[Wrap, Int]) extends Thread {
+ override def run() {
+ for (i <- 0 until sz) {
+ assert(trie.remove(new Wrap(i)) == Some(i))
+ for (j <- 0 until sz)
+ if (j <= i) assert(trie.get(new Wrap(j)) == None)
+ else assert(trie.get(new Wrap(j)) == Some(j))
+ }
+ }
+ }
+
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct.put(new Wrap(i), i)
+ val snapt = ct.snapshot()
+
+ val original = new Worker(ct)
+ val snapshot = new Worker(snapt)
+ original.start()
+ snapshot.start()
+ original.join()
+ snapshot.join()
+
+ for (i <- 0 until sz) {
+ assert(ct.get(new Wrap(i)) == None)
+ assert(snapt.get(new Wrap(i)) == None)
+ }
+ }
+
+ def consistentReadOnly(name: String, readonly: Map[Wrap, Int], sz: Int, N: Int) {
+ @volatile var e: Exception = null
+
+ // reads possible entries once and stores them
+ // then reads all these N more times to check if the
+ // state stayed the same
+ class Reader(trie: Map[Wrap, Int]) extends Thread {
+ setName("Reader " + name)
+
+ override def run() =
+ try check()
+ catch {
+ case ex: Exception => e = ex
+ }
+
+ def check() {
+ val initial = mutable.Map[Wrap, Int]()
+ for (i <- 0 until sz) trie.get(new Wrap(i)) match {
+ case Some(i) => initial.put(new Wrap(i), i)
+ case None => // do nothing
+ }
+
+ for (k <- 0 until N) {
+ for (i <- 0 until sz) {
+ val tres = trie.get(new Wrap(i))
+ val ires = initial.get(new Wrap(i))
+ if (tres != ires) println(i, "initially: " + ires, "traversal %d: %s".format(k, tres))
+ assert(tres == ires)
+ }
+ }
+ }
+ }
+
+ val reader = new Reader(readonly)
+ reader.start()
+ reader.join()
+
+ if (e ne null) {
+ e.printStackTrace()
+ throw e
+ }
+ }
+
+ // traverses the trie `rep` times and modifies each entry
+ class Modifier(trie: TrieMap[Wrap, Int], index: Int, rep: Int, sz: Int) extends Thread {
+ setName("Modifier %d".format(index))
+
+ override def run() {
+ for (k <- 0 until rep) {
+ for (i <- 0 until sz) trie.putIfAbsent(new Wrap(i), i) match {
+ case Some(_) => trie.remove(new Wrap(i))
+ case None => // do nothing
+ }
+ }
+ }
+ }
+
+ // removes all the elements from the trie
+ class Remover(trie: TrieMap[Wrap, Int], index: Int, totremovers: Int, sz: Int) extends Thread {
+ setName("Remover %d".format(index))
+
+ override def run() {
+ for (i <- 0 until sz) trie.remove(new Wrap((i + sz / totremovers * index) % sz))
+ }
+ }
+
+ "have a consistent quiescent read-only snapshot" in {
+ val sz = 10000
+ val N = 100
+ val W = 10
+
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+ val readonly = ct.readOnlySnapshot()
+ val threads = for (i <- 0 until W) yield new Modifier(ct, i, N, sz)
+
+ threads.foreach(_.start())
+ consistentReadOnly("qm", readonly, sz, N)
+ threads.foreach(_.join())
+ }
+
+ // now, we check non-quiescent snapshots, as these permit situations
+ // where a thread is caught in the middle of the update when a snapshot is taken
+
+ "have a consistent non-quiescent read-only snapshot, concurrent with removes only" in {
+ val sz = 1250
+ val W = 100
+ val S = 5000
+
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+ val threads = for (i <- 0 until W) yield new Remover(ct, i, W, sz)
+
+ threads.foreach(_.start())
+ for (i <- 0 until S) consistentReadOnly("non-qr", ct.readOnlySnapshot(), sz, 5)
+ threads.foreach(_.join())
+ }
+
+ "have a consistent non-quiescent read-only snapshot, concurrent with modifications" in {
+ val sz = 1000
+ val N = 7000
+ val W = 10
+ val S = 7000
+
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+ val threads = for (i <- 0 until W) yield new Modifier(ct, i, N, sz)
+
+ threads.foreach(_.start())
+ for (i <- 0 until S) consistentReadOnly("non-qm", ct.readOnlySnapshot(), sz, 5)
+ threads.foreach(_.join())
+ }
+
+ def consistentNonReadOnly(name: String, trie: TrieMap[Wrap, Int], sz: Int, N: Int) {
+ @volatile var e: Exception = null
+
+ // reads possible entries once and stores them
+ // then reads all these N more times to check if the
+ // state stayed the same
+ class Worker extends Thread {
+ setName("Worker " + name)
+
+ override def run() =
+ try check()
+ catch {
+ case ex: Exception => e = ex
+ }
+
+ def check() {
+ val initial = mutable.Map[Wrap, Int]()
+ for (i <- 0 until sz) trie.get(new Wrap(i)) match {
+ case Some(i) => initial.put(new Wrap(i), i)
+ case None => // do nothing
+ }
+
+ for (k <- 0 until N) {
+ // modify
+ for ((key, value) <- initial) {
+ val oldv = if (k % 2 == 0) value else -value
+ val newv = -oldv
+ trie.replace(key, oldv, newv)
+ }
+
+ // check
+ for (i <- 0 until sz) if (initial.contains(new Wrap(i))) {
+ val expected = if (k % 2 == 0) -i else i
+ //println(trie.get(new Wrap(i)))
+ assert(trie.get(new Wrap(i)) == Some(expected))
+ } else {
+ assert(trie.get(new Wrap(i)) == None)
+ }
+ }
+ }
+ }
+
+ val worker = new Worker
+ worker.start()
+ worker.join()
+
+ if (e ne null) {
+ e.printStackTrace()
+ throw e
+ }
+ }
+
+ "have a consistent non-quiescent snapshot, concurrent with modifications" in {
+ val sz = 9000
+ val N = 1000
+ val W = 10
+ val S = 400
+
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+ val threads = for (i <- 0 until W) yield new Modifier(ct, i, N, sz)
+
+ threads.foreach(_.start())
+ for (i <- 0 until S) {
+ consistentReadOnly("non-qm", ct.snapshot(), sz, 5)
+ consistentNonReadOnly("non-qsnap", ct.snapshot(), sz, 5)
+ }
+ threads.foreach(_.join())
+ }
+
+ "work when many concurrent snapshots are taken, concurrent with modifications" in {
+ val sz = 12000
+ val W = 10
+ val S = 10
+ val modifytimes = 1200
+ val snaptimes = 600
+ val ct = new TrieMap[Wrap, Int]
+ for (i <- 0 until sz) ct(new Wrap(i)) = i
+
+ class Snapshooter extends Thread {
+ setName("Snapshooter")
+ override def run() {
+ for (k <- 0 until snaptimes) {
+ val snap = ct.snapshot()
+ for (i <- 0 until sz) snap.remove(new Wrap(i))
+ for (i <- 0 until sz) assert(!snap.contains(new Wrap(i)))
+ }
+ }
+ }
+
+ val mods = for (i <- 0 until W) yield new Modifier(ct, i, modifytimes, sz)
+ val shooters = for (i <- 0 until S) yield new Snapshooter
+ val threads = mods ++ shooters
+ threads.foreach(_.start())
+ threads.foreach(_.join())
+ }
+
+ }
+
+}
diff --git a/test/files/run/dynamic-proxy.check b/test/files/run/dynamic-proxy.check
new file mode 100644
index 0000000000..d1b85daff4
--- /dev/null
+++ b/test/files/run/dynamic-proxy.check
@@ -0,0 +1,20 @@
+noargs
+noargs
+nullary
+value
+symbolic
+symbolic with args
+non-existent method
+before mutation
+mutation 1
+after mutation 1
+mutation 2
+after mutation 2
+overloaded with object
+overloaded with primitive
+overloaded with object in var
+overloaded with object in var 2
+typeArgs: I am a car
+default: 4
+default: 3
+named: 6
diff --git a/test/files/run/dynamic-proxy.flags b/test/files/run/dynamic-proxy.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/run/dynamic-proxy.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/run/dynamic-proxy.scala b/test/files/run/dynamic-proxy.scala
new file mode 100644
index 0000000000..ab5a8b1d66
--- /dev/null
+++ b/test/files/run/dynamic-proxy.scala
@@ -0,0 +1,72 @@
+import scala.reflect._
+
+class Car{ override def toString = "I am a car" }
+object x{
+ def nullary = "nullary"
+ def noargs() = "noargs"
+ def - = "symbolic"
+ def $(s:String) = "symbolic with args"
+ val value = "value"
+ def overloaded(i:Int) = "overloaded with primitive"
+ def overloaded(s:String) = s
+ def default( a:Int, b:Int = 2 ) = "default: "+(a+b)
+ def named( a:Int, b:Int, c:Int ) = "named: "+(a+b+c)
+ def typeArgs[T]( v:T ) = "typeArgs: "+v
+ var mutable = "before mutation"
+ def multiArgLists( a:String )( b:String ) = "multiArgList " + a + b
+ def bar( s:String )(implicit car:Car) = s + car.toString
+}
+
+object Test extends App{
+ val d = new DynamicProxy{ val dynamicProxyTarget = x }
+
+ println( d.noargs )
+ println( d.noargs() )
+ println( d.nullary )
+ println( d.value )
+ println( d.- )
+ println( d.$("x") )
+
+ try{
+ println( d.test )
+ } catch {
+ case _ => println("non-existent method")
+ }
+
+ println( d.mutable )
+
+ println("mutation 1")
+ d.mutable_=("after mutation 1")
+ println( d.mutable )
+
+ println("mutation 2")
+ d.mutable = "after mutation 2"
+ println( d.mutable )
+
+ println( d.overloaded("overloaded with object") )
+ println( d.overloaded(1) )
+
+ // test some non-constant arguments
+ def s = "overloaded with object in var"
+ println( d.overloaded(s) )
+ println( d.overloaded(s + " 2") )
+
+ val car = new Car
+ println( d.typeArgs(car) ) // inferred
+ // println( d.typeArgs[Car](car) ) // explicit not working (yet)
+
+ println( d.default( 1,3 ) )
+ println( d.default( 1 ) )
+
+ println( d.named(1,c=3,b=2) ) // applyDynamicNamed seems to be broken
+
+ // println( d.multiArgLists("a")("b") ) // not working yet
+
+ /*
+ // may never work
+ // testing implicit parameters (first test works when moving x into TestDynamicReflect)
+ implicit val car2 = new Car
+ println( d.bar( "Yeah, ") ); // FAILS: could not find implicit value for parameter car
+ {println( d.bar( "Yeah, ") )} // FAILS: could not find implicit value for parameter car
+ */
+}
diff --git a/test/files/run/erasuretags_abstract.check b/test/files/run/erasuretags_abstract.check
new file mode 100644
index 0000000000..17e7204664
--- /dev/null
+++ b/test/files/run/erasuretags_abstract.check
@@ -0,0 +1,4 @@
+class java.lang.Object
+class java.lang.Object
+class java.lang.Object
+int
diff --git a/test/files/run/erasuretags_abstract.scala b/test/files/run/erasuretags_abstract.scala
new file mode 100644
index 0000000000..8e4ad0d090
--- /dev/null
+++ b/test/files/run/erasuretags_abstract.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def foo1[T] = erasureTag[T]
+ println(foo1[Int].erasure)
+ println(foo1[String].erasure)
+ println(foo1[Array[Int]].erasure)
+
+ def foo2[T <: Int] = erasureTag[T]
+ println(foo2[Int].erasure)
+} \ No newline at end of file
diff --git a/test/files/run/erasuretags_basic.check b/test/files/run/erasuretags_basic.check
new file mode 100644
index 0000000000..c02a4d32af
--- /dev/null
+++ b/test/files/run/erasuretags_basic.check
@@ -0,0 +1,24 @@
+int
+class [I
+class scala.collection.immutable.List
+class [Lscala.collection.immutable.List;
+class scala.collection.immutable.List
+class [Lscala.collection.immutable.List;
+interface scala.collection.immutable.Map
+class [Lscala.collection.immutable.Map;
+class [I
+class [[I
+class [Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.List;
+class [Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.List;
+class [Lscala.collection.immutable.Map;
+class [[Lscala.collection.immutable.Map;
+class [[I
+class [[[I
+class [[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.List;
+class [[[Lscala.collection.immutable.List;
+class [[Lscala.collection.immutable.Map;
+class [[[Lscala.collection.immutable.Map;
diff --git a/test/files/run/erasuretags_basic.scala b/test/files/run/erasuretags_basic.scala
new file mode 100644
index 0000000000..d894fdf2e9
--- /dev/null
+++ b/test/files/run/erasuretags_basic.scala
@@ -0,0 +1,21 @@
+object Test extends App {
+ def test[T: ErasureTag] = {
+ println(implicitly[ErasureTag[T]].erasure)
+ println(implicitly[ErasureTag[Array[T]]].erasure)
+ }
+
+ test[Int]
+ test[List[Int]]
+ test[List[String]]
+ test[Map[Int, String]]
+
+ test[Array[Int]]
+ test[Array[List[Int]]]
+ test[Array[List[String]]]
+ test[Array[Map[Int, String]]]
+
+ test[Array[Array[Int]]]
+ test[Array[Array[List[Int]]]]
+ test[Array[Array[List[String]]]]
+ test[Array[Array[Map[Int, String]]]]
+} \ No newline at end of file
diff --git a/test/files/run/erasuretags_core.check b/test/files/run/erasuretags_core.check
new file mode 100644
index 0000000000..2c544678d1
--- /dev/null
+++ b/test/files/run/erasuretags_core.check
@@ -0,0 +1,32 @@
+byte
+class [B
+short
+class [S
+char
+class [C
+int
+class [I
+long
+class [J
+float
+class [F
+double
+class [D
+boolean
+class [Z
+void
+class [Lscala.runtime.BoxedUnit;
+class java.lang.Object
+class [Ljava.lang.Object;
+class java.lang.Object
+class [Ljava.lang.Object;
+class java.lang.Object
+class [Ljava.lang.Object;
+class java.lang.Object
+class [Ljava.lang.Object;
+class scala.runtime.Null$
+class [Lscala.runtime.Null$;
+class scala.runtime.Nothing$
+class [Lscala.runtime.Nothing$;
+class java.lang.String
+class [Ljava.lang.String;
diff --git a/test/files/run/erasuretags_core.scala b/test/files/run/erasuretags_core.scala
new file mode 100644
index 0000000000..5ed06dcd31
--- /dev/null
+++ b/test/files/run/erasuretags_core.scala
@@ -0,0 +1,34 @@
+object Test extends App {
+ println(implicitly[ErasureTag[Byte]].erasure)
+ println(implicitly[ErasureTag[Array[Byte]]].erasure)
+ println(implicitly[ErasureTag[Short]].erasure)
+ println(implicitly[ErasureTag[Array[Short]]].erasure)
+ println(implicitly[ErasureTag[Char]].erasure)
+ println(implicitly[ErasureTag[Array[Char]]].erasure)
+ println(implicitly[ErasureTag[Int]].erasure)
+ println(implicitly[ErasureTag[Array[Int]]].erasure)
+ println(implicitly[ErasureTag[Long]].erasure)
+ println(implicitly[ErasureTag[Array[Long]]].erasure)
+ println(implicitly[ErasureTag[Float]].erasure)
+ println(implicitly[ErasureTag[Array[Float]]].erasure)
+ println(implicitly[ErasureTag[Double]].erasure)
+ println(implicitly[ErasureTag[Array[Double]]].erasure)
+ println(implicitly[ErasureTag[Boolean]].erasure)
+ println(implicitly[ErasureTag[Array[Boolean]]].erasure)
+ println(implicitly[ErasureTag[Unit]].erasure)
+ println(implicitly[ErasureTag[Array[Unit]]].erasure)
+ println(implicitly[ErasureTag[Any]].erasure)
+ println(implicitly[ErasureTag[Array[Any]]].erasure)
+ println(implicitly[ErasureTag[Object]].erasure)
+ println(implicitly[ErasureTag[Array[Object]]].erasure)
+ println(implicitly[ErasureTag[AnyVal]].erasure)
+ println(implicitly[ErasureTag[Array[AnyVal]]].erasure)
+ println(implicitly[ErasureTag[AnyRef]].erasure)
+ println(implicitly[ErasureTag[Array[AnyRef]]].erasure)
+ println(implicitly[ErasureTag[Null]].erasure)
+ println(implicitly[ErasureTag[Array[Null]]].erasure)
+ println(implicitly[ErasureTag[Nothing]].erasure)
+ println(implicitly[ErasureTag[Array[Nothing]]].erasure)
+ println(implicitly[ErasureTag[String]].erasure)
+ println(implicitly[ErasureTag[Array[String]]].erasure)
+} \ No newline at end of file
diff --git a/test/files/run/erasuretags_usage.scala b/test/files/run/erasuretags_usage.scala
new file mode 100644
index 0000000000..16e53af071
--- /dev/null
+++ b/test/files/run/erasuretags_usage.scala
@@ -0,0 +1,12 @@
+object Test extends App {
+ def foo[T] = {
+ class MyErasureTag(_erasure: Class[_]) extends ErasureTag[T] {
+ def erasure: Class[T] = _erasure.asInstanceOf[Class[T]]
+ }
+
+ implicit val tag = new MyErasureTag(classOf[Int])
+ println(typeTag[T])
+ println(typeTag[T].tpe)
+ println(typeTag[T].erasure)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/existentials-in-compiler.check b/test/files/run/existentials-in-compiler.check
index 83e3cdf435..4df4b0ca96 100644
--- a/test/files/run/existentials-in-compiler.check
+++ b/test/files/run/existentials-in-compiler.check
@@ -100,8 +100,8 @@ abstract trait Cov31[+A, +B, C <: (A, B)] extends Object
abstract trait Cov32[+A, B, C <: (A, B)] extends Object
extest.Cov32[A,B,C] forSome { +A; B; C <: (A, B) }
-abstract trait Cov33[+A, -B, C <: (A, _$10) forSome { type _$10 }] extends Object
- extest.Cov33[A,B,C] forSome { +A; -B; C <: (A, _$10) forSome { type _$10 } }
+abstract trait Cov33[+A, -B, C <: Tuple2[A, _]] extends Object
+ extest.Cov33[A,B,C] forSome { +A; -B; C <: Tuple2[A, _] }
abstract trait Cov34[A, +B, C <: (A, B)] extends Object
extest.Cov34[A,B,C] forSome { A; +B; C <: (A, B) }
@@ -109,14 +109,14 @@ abstract trait Cov34[A, +B, C <: (A, B)] extends Object
abstract trait Cov35[A, B, C <: (A, B)] extends Object
extest.Cov35[A,B,C] forSome { A; B; C <: (A, B) }
-abstract trait Cov36[A, -B, C <: (A, _$11) forSome { type _$11 }] extends Object
- extest.Cov36[A,B,C] forSome { A; -B; C <: (A, _$11) forSome { type _$11 } }
+abstract trait Cov36[A, -B, C <: Tuple2[A, _]] extends Object
+ extest.Cov36[A,B,C] forSome { A; -B; C <: Tuple2[A, _] }
-abstract trait Cov37[-A, +B, C <: (_$12, B) forSome { type _$12 }] extends Object
- extest.Cov37[A,B,C] forSome { -A; +B; C <: (_$12, B) forSome { type _$12 } }
+abstract trait Cov37[-A, +B, C <: Tuple2[_, B]] extends Object
+ extest.Cov37[A,B,C] forSome { -A; +B; C <: Tuple2[_, B] }
-abstract trait Cov38[-A, B, C <: (_$13, B) forSome { type _$13 }] extends Object
- extest.Cov38[A,B,C] forSome { -A; B; C <: (_$13, B) forSome { type _$13 } }
+abstract trait Cov38[-A, B, C <: Tuple2[_, B]] extends Object
+ extest.Cov38[A,B,C] forSome { -A; B; C <: Tuple2[_, B] }
abstract trait Cov39[-A, -B, C <: Tuple2[_, _]] extends Object
extest.Cov39[_, _, _ <: Tuple2[_, _]]
diff --git a/test/files/run/existentials3-new.check b/test/files/run/existentials3-new.check
new file mode 100644
index 0000000000..66674fbbd6
--- /dev/null
+++ b/test/files/run/existentials3-new.check
@@ -0,0 +1,24 @@
+ConcreteTypeTag[Bar.type], t=AbstractTypeRef, s= <: scala.runtime.AbstractFunction0[Bar] with Serializable{case def unapply(x$0: Bar): Boolean} with Singleton
+ConcreteTypeTag[Bar], t=AbstractTypeRef, s= <: Test.ToS with Product with Serializable{def copy(): Bar}
+ConcreteTypeTag[Test.ToS], t=RefinedType, s=f3
+ConcreteTypeTag[Test.ToS], t=RefinedType, s=f4
+ConcreteTypeTag[Test.ToS], t=RefinedType, s=f5
+ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0
+ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0
+ConcreteTypeTag[$anon], t=AbstractTypeRef, s= <: B with Test.ToS
+ConcreteTypeTag[$anon], t=AbstractTypeRef, s= <: B with A with Test.ToS
+TypeTag[List[Object{type T1}#T1]], t=TypeRef, s=class List
+ConcreteTypeTag[List[Seq[Int]]], t=TypeRef, s=class List
+ConcreteTypeTag[List[Seq[U forSome { type U <: Int }]]], t=TypeRef, s=class List
+ConcreteTypeTag[Bar.type], t=AbstractTypeRef, s= <: scala.runtime.AbstractFunction0[Bar] with Serializable{case def unapply(x$0: Bar): Boolean} with Singleton
+ConcreteTypeTag[Bar], t=AbstractTypeRef, s= <: Test.ToS with Product with Serializable{def copy(): Bar}
+ConcreteTypeTag[Test.ToS], t=RefinedType, s=g3
+ConcreteTypeTag[Test.ToS], t=RefinedType, s=g4
+ConcreteTypeTag[Test.ToS], t=RefinedType, s=g5
+ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0
+ConcreteTypeTag[() => Test.ToS], t=TypeRef, s=class Function0
+ConcreteTypeTag[$anon], t=AbstractTypeRef, s= <: B with Test.ToS
+ConcreteTypeTag[$anon], t=AbstractTypeRef, s= <: B with A with Test.ToS
+TypeTag[List[Object{type T1}#T1]], t=TypeRef, s=class List
+ConcreteTypeTag[List[Seq[Int]]], t=TypeRef, s=class List
+ConcreteTypeTag[List[Seq[U forSome { type U <: Int }]]], t=TypeRef, s=class List
diff --git a/test/files/run/existentials3-new.scala b/test/files/run/existentials3-new.scala
new file mode 100644
index 0000000000..32129a04c6
--- /dev/null
+++ b/test/files/run/existentials3-new.scala
@@ -0,0 +1,78 @@
+object Test {
+ trait ToS { final override def toString = getClass.getName }
+
+ def f1 = { case class Bar() extends ToS; Bar }
+ def f2 = { case class Bar() extends ToS; Bar() }
+ def f3 = { class Bar() extends ToS; object Bar extends ToS; Bar }
+ def f4 = { class Bar() extends ToS; new Bar() }
+ def f5 = { object Bar extends ToS; Bar }
+ def f6 = { () => { object Bar extends ToS ; Bar } }
+ def f7 = { val f = { () => { object Bar extends ToS ; Bar } } ; f }
+
+ def f8 = { trait A ; trait B extends A ; class C extends B with ToS; new C { } }
+ def f9 = { trait A ; trait B ; class C extends B with A with ToS; new C { } }
+
+ def f10 = { class A { type T1 } ; List[A#T1]() }
+ def f11 = { abstract class A extends Seq[Int] ; List[A]() }
+ def f12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() }
+
+ val g1 = { case class Bar() extends ToS; Bar }
+ val g2 = { case class Bar() extends ToS; Bar() }
+ val g3 = { class Bar() extends ToS; object Bar extends ToS; Bar }
+ val g4 = { class Bar() extends ToS; new Bar() }
+ val g5 = { object Bar extends ToS; Bar }
+ val g6 = { () => { object Bar extends ToS ; Bar } }
+ val g7 = { val f = { () => { object Bar extends ToS ; Bar } } ; f }
+
+ val g8 = { trait A ; trait B extends A ; class C extends B with ToS; new C { } }
+ val g9 = { trait A ; trait B ; class C extends B with A with ToS; new C { } }
+
+ val g10 = { class A { type T1 } ; List[A#T1]() }
+ val g11 = { abstract class A extends Seq[Int] ; List[A]() }
+ val g12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() }
+
+ def printTag(t: TypeTag[_]) = {
+ val s = if (t.sym.isFreeType) t.sym.typeSignature.toString else t.sym.toString
+ println("%s, t=%s, s=%s".format(t, t.tpe.kind, s))
+ }
+ def m[T: ConcreteTypeTag](x: T) = printTag(concreteTypeTag[T])
+ def m2[T: TypeTag](x: T) = printTag(typeTag[T])
+
+ // tags do work for f10/g10
+ def main(args: Array[String]): Unit = {
+ m(f1)
+ m(f2)
+ m(f3)
+ m(f4)
+ m(f5)
+ m(f6)
+ m(f7)
+ m(f8)
+ m(f9)
+ m2(f10)
+ m(f11)
+ m(f12)
+ m(g1)
+ m(g2)
+ m(g3)
+ m(g4)
+ m(g5)
+ m(g6)
+ m(g7)
+ m(g8)
+ m(g9)
+ m2(g10)
+ m(g11)
+ m(g12)
+ }
+}
+
+object Misc {
+ trait Bippy { def bippy = "I'm Bippy!" }
+ object o1 {
+ def f1 = { trait A extends Seq[U forSome { type U <: Bippy }] ; abstract class B extends A ; trait C extends B ; (null: C) }
+ def f2 = f1.head.bippy
+ }
+ def g1 = o1.f1 _
+ def g2 = o1.f2 _
+}
diff --git a/test/files/run/existentials3.check b/test/files/run/existentials3-old.check
index 36a458dacc..72abfac637 100644
--- a/test/files/run/existentials3.check
+++ b/test/files/run/existentials3-old.check
@@ -5,7 +5,7 @@ Object with Test$ToS
Object with Test$ToS
scala.Function0[Object with Test$ToS]
scala.Function0[Object with Test$ToS]
-_ <: Object with _ <: Object with Object with Test$ToS
+_ <: Object with _ <: Object with Test$ToS
_ <: Object with _ <: Object with _ <: Object with Test$ToS
scala.collection.immutable.List[Object with scala.collection.Seq[Int]]
scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int]]
@@ -16,7 +16,7 @@ Object with Test$ToS
Object with Test$ToS
scala.Function0[Object with Test$ToS]
scala.Function0[Object with Test$ToS]
-_ <: Object with _ <: Object with Object with Test$ToS
+_ <: Object with _ <: Object with Test$ToS
_ <: Object with _ <: Object with _ <: Object with Test$ToS
scala.collection.immutable.List[Object with scala.collection.Seq[Int]]
scala.collection.immutable.List[Object with scala.collection.Seq[_ <: Int]]
diff --git a/test/files/run/existentials3.scala b/test/files/run/existentials3-old.scala
index bb80d366cc..944160ff12 100644
--- a/test/files/run/existentials3.scala
+++ b/test/files/run/existentials3-old.scala
@@ -11,11 +11,11 @@ object Test {
def f8 = { trait A ; trait B extends A ; class C extends B with ToS; new C { } }
def f9 = { trait A ; trait B ; class C extends B with A with ToS; new C { } }
-
+
def f10 = { class A { type T1 } ; List[A#T1]() }
def f11 = { abstract class A extends Seq[Int] ; List[A]() }
def f12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() }
-
+
val g1 = { case class Bar() extends ToS; Bar }
val g2 = { case class Bar() extends ToS; Bar() }
val g3 = { class Bar() extends ToS; object Bar extends ToS; Bar }
@@ -30,9 +30,9 @@ object Test {
val g10 = { class A { type T1 } ; List[A#T1]() }
val g11 = { abstract class A extends Seq[Int] ; List[A]() }
val g12 = { abstract class A extends Seq[U forSome { type U <: Int }] ; List[A]() }
-
+
def m[T: Manifest](x: T) = println(manifest[T])
-
+
// manifests don't work for f10/g10
def main(args: Array[String]): Unit = {
m(f1)
diff --git a/test/files/run/getClassTest.check b/test/files/run/getClassTest-new.check
index 94e86c3889..94e86c3889 100644
--- a/test/files/run/getClassTest.check
+++ b/test/files/run/getClassTest-new.check
diff --git a/test/files/run/getClassTest-new.scala b/test/files/run/getClassTest-new.scala
new file mode 100644
index 0000000000..89778ca2d3
--- /dev/null
+++ b/test/files/run/getClassTest-new.scala
@@ -0,0 +1,66 @@
+class AnyVals {
+ def f1 = (5: Any).getClass
+ def f2 = (5: AnyVal).getClass
+ def f3 = 5.getClass
+ def f4 = (5: java.lang.Integer).getClass
+ def f5 = (5.asInstanceOf[AnyRef]).getClass
+
+ // scalap says:
+ //
+ // def f1 : java.lang.Class[?0] forSome {type ?0} = { /* compiled code */ }
+ // def f2 : java.lang.Class[?0] forSome {type ?0} = { /* compiled code */ }
+ // def f3 : java.lang.Class[scala.Int] = { /* compiled code */ }
+ // def f4 : java.lang.Class[?0] forSome {type ?0 <: java.lang.Integer} = { /* compiled code */ }
+ // def f5 : java.lang.Class[?0] forSome {type ?0 <: scala.AnyRef} = { /* compiled code */ }
+ //
+ // java generic signature says:
+ //
+ // f1: java.lang.Class<?>
+ // f2: java.lang.Class<?>
+ // f3: java.lang.Class<java.lang.Object>
+ // f4: java.lang.Class<? extends java.lang.Integer>
+ // f5: java.lang.Class<?>
+}
+
+class AnyRefs {
+ class A
+ class B extends A
+
+ def f1 = (new B: Any).getClass().newInstance()
+ def f2 = (new B: AnyRef).getClass().newInstance()
+ def f3 = (new B: A).getClass().newInstance()
+ def f4 = (new B: B).getClass().newInstance()
+
+ def f0[T >: B] = (new B: T).getClass().newInstance()
+
+ def f5 = f0[Any]
+ def f6 = f0[AnyRef]
+ def f7 = f0[A]
+ def f8 = f0[B]
+}
+
+class MoreAnyRefs {
+ trait A
+ trait B
+
+ // don't leak anon/refinements
+ def f1 = (new A with B { }).getClass()
+ def f2 = (new B with A { }).getClass()
+ def f3 = (new { def bippy() = 5 }).getClass()
+ def f4 = (new A { def bippy() = 5 }).getClass()
+}
+
+object Test {
+ def returnTypes[T: ClassTag] = (
+ classTag[T].erasure.getMethods.toList
+ filter (_.getName startsWith "f")
+ sortBy (_.getName)
+ map (m => m.getName + ": " + m.getGenericReturnType.toString)
+ )
+
+ def main(args: Array[String]): Unit = {
+ returnTypes[AnyVals] foreach println
+ returnTypes[AnyRefs] foreach println
+ returnTypes[MoreAnyRefs] foreach println
+ }
+}
diff --git a/test/files/run/getClassTest-old.check b/test/files/run/getClassTest-old.check
new file mode 100644
index 0000000000..94e86c3889
--- /dev/null
+++ b/test/files/run/getClassTest-old.check
@@ -0,0 +1,18 @@
+f1: java.lang.Class<?>
+f2: java.lang.Class<?>
+f3: java.lang.Class<java.lang.Object>
+f4: java.lang.Class<? extends java.lang.Integer>
+f5: java.lang.Class<?>
+f0: T
+f1: class java.lang.Object
+f2: class java.lang.Object
+f3: class AnyRefs$A
+f4: class AnyRefs$B
+f5: class java.lang.Object
+f6: class java.lang.Object
+f7: class AnyRefs$A
+f8: class AnyRefs$B
+f1: java.lang.Class<? extends MoreAnyRefs$A>
+f2: java.lang.Class<? extends MoreAnyRefs$B>
+f3: java.lang.Class<?>
+f4: java.lang.Class<? extends MoreAnyRefs$A>
diff --git a/test/files/run/getClassTest.scala b/test/files/run/getClassTest-old.scala
index 2485cd2c71..951cc8d931 100644
--- a/test/files/run/getClassTest.scala
+++ b/test/files/run/getClassTest-old.scala
@@ -4,7 +4,7 @@ class AnyVals {
def f3 = 5.getClass
def f4 = (5: java.lang.Integer).getClass
def f5 = (5.asInstanceOf[AnyRef]).getClass
-
+
// scalap says:
//
// def f1 : java.lang.Class[?0] forSome {type ?0} = { /* compiled code */ }
@@ -19,18 +19,18 @@ class AnyVals {
// f2: java.lang.Class<?>
// f3: java.lang.Class<java.lang.Object>
// f4: java.lang.Class<? extends java.lang.Integer>
- // f5: java.lang.Class<?>
+ // f5: java.lang.Class<?>
}
class AnyRefs {
class A
class B extends A
-
+
def f1 = (new B: Any).getClass().newInstance()
def f2 = (new B: AnyRef).getClass().newInstance()
def f3 = (new B: A).getClass().newInstance()
def f4 = (new B: B).getClass().newInstance()
-
+
def f0[T >: B] = (new B: T).getClass().newInstance()
def f5 = f0[Any]
@@ -52,7 +52,7 @@ class MoreAnyRefs {
object Test {
def returnTypes[T: Manifest] = (
- manifest[T].erasure.getMethods.toList
+ manifest[T].erasure.getMethods.toList
filter (_.getName startsWith "f")
sortBy (_.getName)
map (m => m.getName + ": " + m.getGenericReturnType.toString)
diff --git a/test/files/run/hashhash.scala b/test/files/run/hashhash.scala
index b9cec99a12..dc31df8cfa 100644
--- a/test/files/run/hashhash.scala
+++ b/test/files/run/hashhash.scala
@@ -6,5 +6,10 @@ object Test {
/** Just a little sanity check, not to be confused with a unit test. */
List(5, 5.5f, "abc", new AnyRef, ()) foreach confirmSame
List(5.0f, 1.0d, -(5.0f), (-1.0d)) foreach confirmDifferent
+
+ val x = (BigInt(1) << 64).toDouble
+ val y: Any = x
+
+ assert(x.## == y.##, ((x, y)))
}
}
diff --git a/test/files/run/implicitclasses.scala b/test/files/run/implicitclasses.scala
new file mode 100644
index 0000000000..886d4dede0
--- /dev/null
+++ b/test/files/run/implicitclasses.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+
+ implicit class C(s: String) {
+ def nElems = s.length
+ }
+
+ assert("abc".nElems == 3)
+
+}
+
diff --git a/test/files/run/inline-ex-handlers.check b/test/files/run/inline-ex-handlers.check
index 7a8a744bfa..a5d7e93334 100644
--- a/test/files/run/inline-ex-handlers.check
+++ b/test/files/run/inline-ex-handlers.check
@@ -1,40 +1,48 @@
172c172
-< locals: value x$1, value temp1
+< locals: value x$1, value x1, value x2, value x
---
-> locals: value x$1, value temp1, variable boxed1
+> locals: value x$1, value x1, value x2, value x, variable boxed1
174c174
-< blocks: [1,2,3,4]
+< blocks: [1,2,3,5,6,7]
---
-> blocks: [1,2,3]
-187,189d186
-< 92 JUMP 4
+> blocks: [1,3,5,6]
+180,182d179
+< 92 JUMP 2
<
-< 4:
-195a193,194
+< 2:
+194,196d190
+< 92 JUMP 7
+<
+< 7:
+204a199,200
> 92 STORE_LOCAL(variable boxed1)
> 92 LOAD_LOCAL(variable boxed1)
-386c385
-< blocks: [1,2,3,4,5,7,8,10]
+395c391
+< blocks: [1,2,3,4,5,8,11,13,14,16]
---
-> blocks: [1,2,3,4,5,7,8,10,11]
-410c409,418
+> blocks: [1,2,3,5,8,11,13,14,16,17]
+419c415,424
< 103 THROW(MyException)
---
-> ? STORE_LOCAL(value ex$1)
-> ? JUMP 11
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 17
>
-> 11:
-> 101 LOAD_LOCAL(value ex$1)
-> 101 STORE_LOCAL(value temp2)
-> 101 SCOPE_ENTER value temp2
-> 101 LOAD_LOCAL(value temp2)
-> 101 IS_INSTANCE REF(class MyException)
-> 101 CZJUMP (BOOL)NE ? 4 : 5
-501c509
+> 17:
+> 101 LOAD_LOCAL(value ex5)
+> 101 STORE_LOCAL(value x3)
+> 101 SCOPE_ENTER value x3
+> 106 LOAD_LOCAL(value x3)
+> 106 IS_INSTANCE REF(class MyException)
+> 106 CZJUMP (BOOL)NE ? 5 : 11
+432,434d436
+< 101 JUMP 4
+<
+< 4:
+522c524
< blocks: [1,2,3,4,6,7,8,9,10]
---
> blocks: [1,2,3,4,6,7,8,9,10,11,12,13]
-530c538,543
+551c553,558
< 306 THROW(MyException)
---
> ? JUMP 11
@@ -43,7 +51,7 @@
> ? LOAD_LOCAL(variable monitor4)
> 305 MONITOR_EXIT
> ? JUMP 12
-536c549,555
+557c564,570
< ? THROW(Throwable)
---
> ? JUMP 12
@@ -53,7 +61,7 @@
> 304 MONITOR_EXIT
> ? STORE_LOCAL(value t)
> ? JUMP 13
-542c561,574
+563c576,589
< ? THROW(Throwable)
---
> ? STORE_LOCAL(value t)
@@ -70,29 +78,30 @@
> 310 CALL_PRIMITIVE(EndConcat)
> 310 CALL_METHOD scala.Predef.println (dynamic)
> 310 JUMP 2
-566c598
+587c613
< catch (Throwable) in ArrayBuffer(7, 8, 9, 10) starting at: 6
---
> catch (Throwable) in ArrayBuffer(7, 8, 9, 10, 11) starting at: 6
-569c601
+590c616
< catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10) starting at: 3
---
> catch (Throwable) in ArrayBuffer(4, 6, 7, 8, 9, 10, 11, 12) starting at: 3
-601c633
+622c648
< blocks: [1,2,3,4,5,6,7,9,10]
---
> blocks: [1,2,3,4,5,6,7,9,10,11,12]
-625c657,663
+646c672,673
< 78 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
> ? JUMP 11
->
+647a675,679
> 11:
> 81 LOAD_LOCAL(value e)
> ? STORE_LOCAL(variable exc1)
> ? JUMP 12
-654c692,706
+>
+675c707,721
< 81 THROW(Exception)
---
> ? STORE_LOCAL(variable exc1)
@@ -110,57 +119,53 @@
> 84 STORE_LOCAL(variable result)
> 84 LOAD_LOCAL(variable exc1)
> 84 THROW(Throwable)
-676c728
+697c743
< catch (<none>) in ArrayBuffer(4, 6, 7, 9) starting at: 3
---
> catch (<none>) in ArrayBuffer(4, 6, 7, 9, 11) starting at: 3
-702c754
-< blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,18,19]
+723c769
+< blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31]
---
-> blocks: [1,2,3,4,5,6,7,8,11,12,13,14,15,16,18,19,20,21,22]
-726c778,787
+> blocks: [1,2,3,4,5,6,9,12,14,17,18,19,22,25,27,28,30,31,32,33,34]
+747c793,800
< 172 THROW(MyException)
---
-> ? STORE_LOCAL(value ex$4)
-> ? JUMP 20
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 32
>
-> 20:
-> 170 LOAD_LOCAL(value ex$4)
-> 170 STORE_LOCAL(value temp11)
-> 170 SCOPE_ENTER value temp11
-> 170 LOAD_LOCAL(value temp11)
-> 170 IS_INSTANCE REF(class MyException)
-> 170 CZJUMP (BOOL)NE ? 12 : 13
-780c841,842
+> 32:
+> 170 LOAD_LOCAL(value ex5)
+> 170 STORE_LOCAL(value x3)
+> 170 SCOPE_ENTER value x3
+> 170 JUMP 18
+803c856,857
< 177 THROW(MyException)
---
-> ? STORE_LOCAL(value ex$5)
-> ? JUMP 21
-784c846,855
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 33
+807c861,868
< 170 THROW(Throwable)
---
-> ? STORE_LOCAL(value ex$5)
-> ? JUMP 21
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 33
>
-> 21:
-> 169 LOAD_LOCAL(value ex$5)
-> 169 STORE_LOCAL(value temp14)
-> 169 SCOPE_ENTER value temp14
-> 169 LOAD_LOCAL(value temp14)
-> 169 IS_INSTANCE REF(class MyException)
-> 169 CZJUMP (BOOL)NE ? 5 : 6
-815c886,887
+> 33:
+> 169 LOAD_LOCAL(value ex5)
+> 169 STORE_LOCAL(value x3)
+> 169 SCOPE_ENTER value x3
+> 169 JUMP 5
+840c901,902
< 182 THROW(MyException)
---
> ? STORE_LOCAL(variable exc2)
-> ? JUMP 22
-819c891,905
+> ? JUMP 34
+844c906,907
< 169 THROW(Throwable)
---
> ? STORE_LOCAL(variable exc2)
-> ? JUMP 22
->
-> 22:
+> ? JUMP 34
+845a909,921
+> 34:
> 184 LOAD_MODULE object Predef
> 184 CONSTANT("finally")
> 184 CALL_METHOD scala.Predef.println (dynamic)
@@ -172,57 +177,60 @@
> 185 STORE_LOCAL(variable result)
> 185 LOAD_LOCAL(variable exc2)
> 185 THROW(Throwable)
-841c927
-< catch (Throwable) in ArrayBuffer(11, 12, 13, 14, 15, 16, 18) starting at: 4
+>
+866c942
+< catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30) starting at: 4
---
-> catch (Throwable) in ArrayBuffer(11, 12, 13, 14, 15, 16, 18, 20) starting at: 4
-844c930
-< catch (<none>) in ArrayBuffer(4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 18) starting at: 3
+> catch (Throwable) in ArrayBuffer(17, 18, 19, 22, 25, 27, 28, 30, 32) starting at: 4
+869c945
+< catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30) starting at: 3
---
-> catch (<none>) in ArrayBuffer(4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 18, 20, 21) starting at: 3
-870c956
-< blocks: [1,2,3,6,7,8,10,11,13]
+> catch (<none>) in ArrayBuffer(4, 5, 6, 9, 12, 17, 18, 19, 22, 25, 27, 28, 30, 32, 33) starting at: 3
+895c971
+< blocks: [1,2,3,6,7,8,11,14,16,17,19]
---
-> blocks: [1,2,3,6,7,8,10,11,13,14]
-894c980,989
+> blocks: [1,2,3,6,7,8,11,14,16,17,19,20]
+919c995,1002
< 124 THROW(MyException)
---
-> ? STORE_LOCAL(value ex$2)
-> ? JUMP 14
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 20
>
-> 14:
-> 122 LOAD_LOCAL(value ex$2)
-> 122 STORE_LOCAL(value temp5)
-> 122 SCOPE_ENTER value temp5
-> 122 LOAD_LOCAL(value temp5)
-> 122 IS_INSTANCE REF(class MyException)
-> 122 CZJUMP (BOOL)NE ? 7 : 8
-942c1037
-< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 10, 11, 13) starting at: 3
----
-> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 10, 11, 13, 14) starting at: 3
-968c1063
-< blocks: [1,2,3,4,5,9,10,11,13]
----
-> blocks: [1,2,3,4,5,9,10,11,13,14]
-992c1087,1096
+> 20:
+> 122 LOAD_LOCAL(value ex5)
+> 122 STORE_LOCAL(value x3)
+> 122 SCOPE_ENTER value x3
+> 122 JUMP 7
+979c1062
+< catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19) starting at: 3
+---
+> catch (IllegalArgumentException) in ArrayBuffer(6, 7, 8, 11, 14, 16, 17, 19, 20) starting at: 3
+1005c1088
+< blocks: [1,2,3,4,5,8,11,15,16,17,19]
+---
+> blocks: [1,2,3,5,8,11,15,16,17,19,20]
+1029c1112,1121
< 148 THROW(MyException)
---
-> ? STORE_LOCAL(value ex$3)
-> ? JUMP 14
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 20
>
-> 14:
-> 145 LOAD_LOCAL(value ex$3)
-> 145 STORE_LOCAL(value temp8)
-> 145 SCOPE_ENTER value temp8
-> 145 LOAD_LOCAL(value temp8)
-> 145 IS_INSTANCE REF(class MyException)
-> 145 CZJUMP (BOOL)NE ? 4 : 5
-1236c1340
+> 20:
+> 145 LOAD_LOCAL(value ex5)
+> 145 STORE_LOCAL(value x3)
+> 145 SCOPE_ENTER value x3
+> 154 LOAD_LOCAL(value x3)
+> 154 IS_INSTANCE REF(class MyException)
+> 154 CZJUMP (BOOL)NE ? 5 : 11
+1050,1052d1141
+< 145 JUMP 4
+<
+< 4:
+1285c1374
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1260c1364,1371
+1309c1398,1405
< 38 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -233,33 +241,37 @@
> 42 CONSTANT("IllegalArgumentException")
> 42 CALL_METHOD scala.Predef.println (dynamic)
> 42 JUMP 2
-1309c1420
-< blocks: [1,2,3,4,5,7,8,10,11,13]
+1358c1454
+< blocks: [1,2,3,4,5,8,11,13,14,16,17,19]
---
-> blocks: [1,2,3,4,5,7,8,10,11,13,14]
-1333c1444,1445
+> blocks: [1,2,3,5,8,11,13,14,16,17,19,20]
+1382c1478,1479
< 203 THROW(MyException)
---
-> ? STORE_LOCAL(value ex$6)
-> ? JUMP 14
-1353c1465,1474
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 20
+1402c1499,1508
< 209 THROW(MyException)
---
-> ? STORE_LOCAL(value ex$6)
-> ? JUMP 14
+> ? STORE_LOCAL(value ex5)
+> ? JUMP 20
>
-> 14:
-> 200 LOAD_LOCAL(value ex$6)
-> 200 STORE_LOCAL(value temp17)
-> 200 SCOPE_ENTER value temp17
-> 200 LOAD_LOCAL(value temp17)
-> 200 IS_INSTANCE REF(class MyException)
-> 200 CZJUMP (BOOL)NE ? 4 : 5
-1416c1537
+> 20:
+> 200 LOAD_LOCAL(value ex5)
+> 200 STORE_LOCAL(value x3)
+> 200 SCOPE_ENTER value x3
+> 212 LOAD_LOCAL(value x3)
+> 212 IS_INSTANCE REF(class MyException)
+> 212 CZJUMP (BOOL)NE ? 5 : 11
+1415,1417d1520
+< 200 JUMP 4
+<
+< 4:
+1477c1580
< blocks: [1,2,3,4,5,7]
---
> blocks: [1,2,3,4,5,7,8]
-1440c1561,1568
+1501c1604,1611
< 58 THROW(IllegalArgumentException)
---
> ? STORE_LOCAL(value e)
@@ -270,11 +282,11 @@
> 62 CONSTANT("RuntimeException")
> 62 CALL_METHOD scala.Predef.println (dynamic)
> 62 JUMP 2
-1489c1617
+1550c1660
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1509c1637,1642
+1570c1680,1685
< 229 THROW(MyException)
---
> ? JUMP 5
@@ -283,19 +295,19 @@
> ? LOAD_LOCAL(variable monitor1)
> 228 MONITOR_EXIT
> 228 THROW(Throwable)
-1515c1648
+1576c1691
< ? THROW(Throwable)
---
> 228 THROW(Throwable)
-1543c1676
+1604c1719
< locals: value args, variable result, variable monitor2, variable monitorResult1
---
> locals: value exception$1, value args, variable result, variable monitor2, variable monitorResult1
-1545c1678
+1606c1721
< blocks: [1,2,3,4]
---
> blocks: [1,2,3,4,5]
-1568c1701,1709
+1629c1744,1752
< 245 THROW(MyException)
---
> ? STORE_LOCAL(value exception$1)
@@ -307,7 +319,7 @@
> ? LOAD_LOCAL(variable monitor2)
> 244 MONITOR_EXIT
> 244 THROW(Throwable)
-1574c1715
+1635c1758
< ? THROW(Throwable)
---
> 244 THROW(Throwable)
diff --git a/test/files/run/inner-parse.check b/test/files/run/inner-parse.check
new file mode 100644
index 0000000000..e4a30714bd
--- /dev/null
+++ b/test/files/run/inner-parse.check
@@ -0,0 +1,87 @@
+file Test$$anonfun$main$1.class
+class Test$$anonfun$main$1 extends scala.runtime.AbstractFunction1$mcVL$sp
+ interface scala.Serializable
+ inner/anon anonymous class: Test$$anonfun$main$1
+ descriptor <clinit> ()V
+ descriptor apply (Lscala/Tuple2;)V
+ descriptor apply (Ljava/lang/Object;)Ljava/lang/Object;
+ descriptor apply (Ljava/lang/Object;)V
+ descriptor cwd$1 Ljava/lang/String;
+ descriptor serialVersionUID J
+ descriptor <init> (Ljava/lang/String;)V
+ signature apply (Lscala/Tuple2<Ljava/lang/String;Lscala/reflect/internal/JvmClassInfo;>;)V
+
+file Test$.class
+class Test$ extends java.lang.Object
+ inner/anon anonymous class: Test$$anonfun$main$1
+ descriptor <clinit> ()V
+ descriptor MODULE$ LTest$;
+ descriptor main ([Ljava/lang/String;)V
+ descriptor <init> ()V
+
+file Test.class
+class Test extends java.lang.Object
+ inner/anon anonymous class: Test$$anonfun$main$1
+ descriptor main ([Ljava/lang/String;)V
+
+file j/J_1$B$C$D.class
+class j.J_1$B$C$D extends java.lang.Object
+ inner B j.J_1$B in j.J_1
+ inner C j.J_1$B$C in j.J_1$B
+ inner/enclosing D enclosing class: j.J_1$B$C
+ descriptor <init> (Lj/J_1$B$C;)V
+ descriptor this$2 Lj/J_1$B$C;
+
+file j/J_1$B$C.class
+class j.J_1$B$C extends java.lang.Object
+ inner B j.J_1$B in j.J_1
+ inner/enclosing C enclosing class: j.J_1$B
+ inner/nested D member class: j.J_1$B$C$D
+ descriptor <init> (Lj/J_1$B;)V
+ descriptor this$1 Lj/J_1$B;
+
+file j/J_1$B.class
+class j.J_1$B extends java.lang.Object
+ inner/enclosing B enclosing class: j.J_1
+ inner/nested C member class: j.J_1$B$C
+ descriptor <init> (Lj/J_1;)V
+ descriptor this$0 Lj/J_1;
+
+file j/J_1.class
+class j.J_1 extends java.lang.Object
+ interface java.util.RandomAccess
+ inner/nested B member class: j.J_1$B
+ descriptor <init> ()V
+
+file s/J_1$B$C$D.class
+class s.J_1$B$C$D extends java.lang.Object
+ inner B s.J_1$B in s.J_1
+ inner C s.J_1$B$C in s.J_1$B
+ inner/enclosing D enclosing class: s.J_1$B$C
+ descriptor $outer Ls/J_1$B$C;
+ descriptor s$J_1$B$C$D$$$outer ()Ls/J_1$B$C;
+ descriptor <init> (Ls/J_1$B$C;)V
+
+file s/J_1$B$C.class
+class s.J_1$B$C extends java.lang.Object
+ inner B s.J_1$B in s.J_1
+ inner/enclosing C enclosing class: s.J_1$B
+ inner/nested D member class: s.J_1$B$C$D
+ descriptor $outer Ls/J_1$B;
+ descriptor s$J_1$B$C$$$outer ()Ls/J_1$B;
+ descriptor <init> (Ls/J_1$B;)V
+
+file s/J_1$B.class
+class s.J_1$B extends java.lang.Object
+ inner/enclosing B enclosing class: s.J_1
+ inner/nested C member class: s.J_1$B$C
+ descriptor $outer Ls/J_1;
+ descriptor s$J_1$B$$$outer ()Ls/J_1;
+ descriptor <init> (Ls/J_1;)V
+
+file s/J_1.class
+class s.J_1 extends java.lang.Object
+ interface java.util.RandomAccess
+ inner/nested B member class: s.J_1$B
+ descriptor <init> ()V
+
diff --git a/test/files/run/inner-parse/J_1.java b/test/files/run/inner-parse/J_1.java
new file mode 100644
index 0000000000..920ab951ab
--- /dev/null
+++ b/test/files/run/inner-parse/J_1.java
@@ -0,0 +1,9 @@
+package j;
+
+public class J_1 implements java.util.RandomAccess { // "random" marker interface
+ class B {
+ class C {
+ class D { }
+ }
+ }
+}
diff --git a/test/files/run/inner-parse/S_2.scala b/test/files/run/inner-parse/S_2.scala
new file mode 100644
index 0000000000..fd144a40b7
--- /dev/null
+++ b/test/files/run/inner-parse/S_2.scala
@@ -0,0 +1,9 @@
+package s;
+
+class J_1 extends java.util.RandomAccess {
+ class B {
+ class C {
+ class D { }
+ }
+ }
+}
diff --git a/test/files/run/inner-parse/S_3.scala b/test/files/run/inner-parse/S_3.scala
new file mode 100644
index 0000000000..aaa6a6ad35
--- /dev/null
+++ b/test/files/run/inner-parse/S_3.scala
@@ -0,0 +1,12 @@
+import scala.reflect.internal.JvmClassInfo
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val cwd = sys.props("partest.output")
+
+ for ((f, info) <- JvmClassInfo.classInfoList(cwd)) {
+ println("file " + f.stripPrefix(cwd).substring(1).replace('\\', '/'))
+ println(info)
+ }
+ }
+}
diff --git a/test/files/run/interop_classmanifests_arepartially_typetags.check b/test/files/run/interop_classmanifests_arepartially_typetags.check
new file mode 100644
index 0000000000..3dfcdccbec
--- /dev/null
+++ b/test/files/run/interop_classmanifests_arepartially_typetags.check
@@ -0,0 +1,6 @@
+T
+int
+T
+class java.lang.String
+T
+class [I
diff --git a/test/files/run/interop_classmanifests_arepartially_typetags.scala b/test/files/run/interop_classmanifests_arepartially_typetags.scala
new file mode 100644
index 0000000000..9bc1f32e86
--- /dev/null
+++ b/test/files/run/interop_classmanifests_arepartially_typetags.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ def classManifestIspartiallyTypeTag[T: ClassManifest] = {
+ println(typeTag[T].tpe)
+ println(typeTag[T].erasure)
+ }
+
+ classManifestIspartiallyTypeTag[Int]
+ classManifestIspartiallyTypeTag[String]
+ classManifestIspartiallyTypeTag[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/run/interop_classtags_are_classmanifests.check b/test/files/run/interop_classtags_are_classmanifests.check
new file mode 100644
index 0000000000..02393dff23
--- /dev/null
+++ b/test/files/run/interop_classtags_are_classmanifests.check
@@ -0,0 +1,6 @@
+Int
+java.lang.String
+Array[Int]
+Int
+java.lang.String
+Array[Int]
diff --git a/test/files/run/interop_classtags_are_classmanifests.scala b/test/files/run/interop_classtags_are_classmanifests.scala
new file mode 100644
index 0000000000..309c99a3f5
--- /dev/null
+++ b/test/files/run/interop_classtags_are_classmanifests.scala
@@ -0,0 +1,17 @@
+object Test extends App {
+ def arrayTagIsClassManifest[T: ArrayTag] = {
+ println(classManifest[T])
+ }
+
+ arrayTagIsClassManifest[Int]
+ arrayTagIsClassManifest[String]
+ arrayTagIsClassManifest[Array[Int]]
+
+ def classTagIsClassManifest[T: ClassTag] = {
+ println(classManifest[T])
+ }
+
+ classTagIsClassManifest[Int]
+ classTagIsClassManifest[String]
+ classTagIsClassManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/run/interop_concretetypetags_are_classmanifests.check b/test/files/run/interop_concretetypetags_are_classmanifests.check
new file mode 100644
index 0000000000..c59e92d4eb
--- /dev/null
+++ b/test/files/run/interop_concretetypetags_are_classmanifests.check
@@ -0,0 +1,3 @@
+Int
+java.lang.String
+Array[Int]
diff --git a/test/files/run/interop_concretetypetags_are_classmanifests.scala b/test/files/run/interop_concretetypetags_are_classmanifests.scala
new file mode 100644
index 0000000000..b578d7e626
--- /dev/null
+++ b/test/files/run/interop_concretetypetags_are_classmanifests.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def concreteTypeTagIsClassManifest[T: ConcreteTypeTag] = {
+ println(classManifest[T])
+ }
+
+ concreteTypeTagIsClassManifest[Int]
+ concreteTypeTagIsClassManifest[String]
+ concreteTypeTagIsClassManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/run/interop_concretetypetags_are_manifests.check b/test/files/run/interop_concretetypetags_are_manifests.check
new file mode 100644
index 0000000000..c59e92d4eb
--- /dev/null
+++ b/test/files/run/interop_concretetypetags_are_manifests.check
@@ -0,0 +1,3 @@
+Int
+java.lang.String
+Array[Int]
diff --git a/test/files/run/interop_concretetypetags_are_manifests.scala b/test/files/run/interop_concretetypetags_are_manifests.scala
new file mode 100644
index 0000000000..731410bc10
--- /dev/null
+++ b/test/files/run/interop_concretetypetags_are_manifests.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ def concreteTypeTagIsManifest[T: ConcreteTypeTag] = {
+ println(manifest[T])
+ }
+
+ concreteTypeTagIsManifest[Int]
+ concreteTypeTagIsManifest[String]
+ concreteTypeTagIsManifest[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/run/interop_manifests_are_classtags.check b/test/files/run/interop_manifests_are_classtags.check
new file mode 100644
index 0000000000..07ff6b984a
--- /dev/null
+++ b/test/files/run/interop_manifests_are_classtags.check
@@ -0,0 +1,24 @@
+Int
+Int
+List()
+List(0, 0, 0, 0, 0)
+java.lang.String
+java.lang.String
+List()
+List(null, null, null, null, null)
+Array[Int]
+Array[Int]
+List()
+List(null, null, null, null, null)
+Int
+Int
+List()
+List(0, 0, 0, 0, 0)
+java.lang.String
+java.lang.String
+List()
+List(null, null, null, null, null)
+Array[Int]
+Array[Int]
+List()
+List(null, null, null, null, null)
diff --git a/test/files/run/interop_manifests_are_classtags.scala b/test/files/run/interop_manifests_are_classtags.scala
new file mode 100644
index 0000000000..582cea3467
--- /dev/null
+++ b/test/files/run/interop_manifests_are_classtags.scala
@@ -0,0 +1,23 @@
+object Test extends App {
+ def classManifestIsClassTag[T: ClassManifest] = {
+ println(arrayTag[T])
+ println(erasureTag[T])
+ println(Array[T]().toList)
+ println(new Array[T](5).toList)
+ }
+
+ classManifestIsClassTag[Int]
+ classManifestIsClassTag[String]
+ classManifestIsClassTag[Array[Int]]
+
+ def manifestIsClassTag[T: Manifest] = {
+ println(arrayTag[T])
+ println(erasureTag[T])
+ println(Array[T]().toList)
+ println(new Array[T](5).toList)
+ }
+
+ manifestIsClassTag[Int]
+ manifestIsClassTag[String]
+ manifestIsClassTag[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/run/interop_manifests_are_concretetypetags.check b/test/files/run/interop_manifests_are_concretetypetags.check
new file mode 100644
index 0000000000..edab85ecf1
--- /dev/null
+++ b/test/files/run/interop_manifests_are_concretetypetags.check
@@ -0,0 +1,6 @@
+Int
+int
+String
+class java.lang.String
+Array[Int]
+class [I
diff --git a/test/files/run/interop_manifests_are_concretetypetags.scala b/test/files/run/interop_manifests_are_concretetypetags.scala
new file mode 100644
index 0000000000..0b82a56d0a
--- /dev/null
+++ b/test/files/run/interop_manifests_are_concretetypetags.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ def manifestIsConcreteTypeTag[T: Manifest] = {
+ println(concreteTypeTag[T].tpe)
+ println(concreteTypeTag[T].erasure)
+ }
+
+ manifestIsConcreteTypeTag[Int]
+ manifestIsConcreteTypeTag[String]
+ manifestIsConcreteTypeTag[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/run/interop_manifests_are_typetags.check b/test/files/run/interop_manifests_are_typetags.check
new file mode 100644
index 0000000000..edab85ecf1
--- /dev/null
+++ b/test/files/run/interop_manifests_are_typetags.check
@@ -0,0 +1,6 @@
+Int
+int
+String
+class java.lang.String
+Array[Int]
+class [I
diff --git a/test/files/run/interop_manifests_are_typetags.scala b/test/files/run/interop_manifests_are_typetags.scala
new file mode 100644
index 0000000000..03a7b7b6d5
--- /dev/null
+++ b/test/files/run/interop_manifests_are_typetags.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ def manifestIsTypeTag[T: Manifest] = {
+ println(typeTag[T].tpe)
+ println(typeTag[T].erasure)
+ }
+
+ manifestIsTypeTag[Int]
+ manifestIsTypeTag[String]
+ manifestIsTypeTag[Array[Int]]
+} \ No newline at end of file
diff --git a/test/files/run/is-valid-num.scala b/test/files/run/is-valid-num.scala
index 9c43e98911..402eff99d6 100644
--- a/test/files/run/is-valid-num.scala
+++ b/test/files/run/is-valid-num.scala
@@ -3,95 +3,310 @@ object Test {
def y = BigDecimal("" + (Short.MaxValue + 1) + ".0")
def y1 = BigDecimal("0.1")
def y2 = BigDecimal("0.5")
-
+
def l1 = Int.MaxValue.toLong + 1
def l2 = Int.MinValue.toLong - 1
def main(args: Array[String]): Unit = {
+// assert(x.isWhole, x)
assert(!x.isValidDouble, x)
assert(!x.isValidFloat, x)
assert(!x.isValidLong, x)
assert(!x.isValidInt, x)
assert(!x.isValidChar, x)
+ assert(!x.isValidShort, x)
assert(!x.isValidByte, x)
+// assert(y.isWhole, y)
assert(!y.isValidShort, y)
assert(y.isValidChar, y)
assert(y.isValidInt, y)
assert(y.isValidFloat, y)
assert(y.isValidDouble, y)
+ assert(y.isValidLong, y)
+ assert(!y.isValidByte, y)
+// assert(!y1.isWhole)
assert(!y1.isValidLong, y1)
assert(!y1.isValidFloat, y1)
assert(!y1.isValidDouble, y1)
+ assert(!y1.isValidInt, y1)
+ assert(!y1.isValidChar, y1)
+ assert(!y1.isValidShort, y1)
+ assert(!y1.isValidByte, y1)
assert(!y2.isValidLong, y2)
assert(y2.isValidFloat, y2)
assert(y2.isValidDouble, y2)
- testBigIntIsFloat()
- testBigIntIsDouble()
-
assert(!l1.isValidInt && (l1 - 1).isValidInt, l1)
assert(!l2.isValidInt && (l2 + 1).isValidInt, l2)
+
+ testBigInts()
+ testNonWholeDoubles()
+ testNaNs()
+ }
+
+ def testBigInts() {
+ def biExp2(e: Int) = BigInt(1) << e
+ def checkBigInt2(bi: BigInt) { checkBigInt(-bi); checkBigInt(bi) }
+
+ val pf = 24
+ val pd = 53
+
+ checkBigInt(BigInt(0))
+ checkBigInt2(biExp2(0))
+
+ checkBigInt2(biExp2(7) - 1)
+ checkBigInt2(biExp2(7))
+ checkBigInt2(biExp2(7) + 1)
+
+ checkBigInt2(biExp2(8) - 1)
+ checkBigInt2(biExp2(8))
+ checkBigInt2(biExp2(8) + 1)
+
+ checkBigInt2(biExp2(15) - 1)
+ checkBigInt2(biExp2(15))
+ checkBigInt2(biExp2(15) + 1)
+
+ checkBigInt2(biExp2(16) - 1)
+ checkBigInt2(biExp2(16))
+ checkBigInt2(biExp2(16) + 1)
+
+ checkBigInt2(biExp2(pf) - 1)
+ checkBigInt2(biExp2(pf))
+ checkBigInt2(biExp2(pf) + 1)
+ checkBigInt2(biExp2(pf) + 2)
+ checkBigInt2(biExp2(pf) - 2)
+ checkBigInt2(biExp2(pf + 1) - 1)
+ checkBigInt2(biExp2(pf + 1))
+ checkBigInt2(biExp2(pf + 1) + 1)
+ checkBigInt2(biExp2(pf + 1) + 2)
+ checkBigInt2(biExp2(pf + 1) + 3)
+ checkBigInt2(biExp2(pf + 1) + 4)
+
+ checkBigInt2(biExp2(31) - 1)
+ checkBigInt2(biExp2(31))
+ checkBigInt2(biExp2(31) + 1)
+
+ checkBigInt2(biExp2(32) - 1)
+ checkBigInt2(biExp2(32))
+ checkBigInt2(biExp2(32) + 1)
+ checkBigInt2(biExp2(32) + biExp2(64 - pf))
+ checkBigInt2(biExp2(32) + biExp2(64 - pf + 1))
+
+ checkBigInt2(biExp2(pd) - 1)
+ checkBigInt2(biExp2(pd))
+ checkBigInt2(biExp2(pd) + 1)
+ checkBigInt2(biExp2(pd) + 2)
+ checkBigInt2(biExp2(pd + 1) - 2)
+ checkBigInt2(biExp2(pd + 1) - 1)
+ checkBigInt2(biExp2(pd + 1))
+ checkBigInt2(biExp2(pd + 1) + 1)
+ checkBigInt2(biExp2(pd + 1) + 2)
+ checkBigInt2(biExp2(pd + 1) + 3)
+ checkBigInt2(biExp2(pd + 1) + 4)
+
+ checkBigInt2(biExp2(63) - 1)
+ checkBigInt2(biExp2(63))
+ checkBigInt2(biExp2(63) + 1)
+ checkBigInt2(biExp2(63) + biExp2(63 - pd))
+ checkBigInt2(biExp2(63) + biExp2(63 - pd + 1))
+ checkBigInt2(biExp2(63) + biExp2(63 - pf))
+ checkBigInt2(biExp2(63) + biExp2(63 - pf + 1))
+
+ checkBigInt2(biExp2(64) - 1)
+ checkBigInt2(biExp2(64))
+ checkBigInt2(biExp2(64) + 1)
+ checkBigInt2(biExp2(64) + biExp2(64 - pd))
+ checkBigInt2(biExp2(64) + biExp2(64 - pd + 1))
+ checkBigInt2(biExp2(64) + biExp2(64 - pf))
+ checkBigInt2(biExp2(64) + biExp2(64 - pf + 1))
+
+ checkBigInt2(biExp2(127))
+ checkBigInt2(biExp2(128) - biExp2(128 - pf))
+ checkBigInt2(biExp2(128) - biExp2(128 - pf - 1))
+ checkBigInt2(biExp2(128))
+
+ checkBigInt2(biExp2(1023))
+ checkBigInt2(biExp2(1024) - biExp2(1024 - pd))
+ checkBigInt2(biExp2(1024) - biExp2(1024 - pd - 1))
+ checkBigInt2(biExp2(1024))
+ }
+
+ def testNonWholeDoubles() {
+ checkNonWholeDouble(0.5)
+ checkNonWholeDouble(-math.E)
+ checkNonWholeDouble((1L << 51).toDouble + 0.5)
+ checkNonWholeDouble((1L << 23).toDouble + 0.5)
+ checkNonWholeDouble(Double.PositiveInfinity)
+ checkNonWholeDouble(Double.NegativeInfinity)
}
- def biExp2(e: Int) = BigInt(1) << e
+ def testNaNs() {
+ assert(!Double.NaN.isWhole, Double.NaN)
+// assert(!Double.NaN.isValidDouble, Double.NaN)
+// assert(!Double.NaN.isValidFloat, Double.NaN)
+// assert(!Double.NaN.isValidLong, Double.NaN)
+ assert(!Double.NaN.isValidInt, Double.NaN)
+ assert(!Double.NaN.isValidChar, Double.NaN)
+ assert(!Double.NaN.isValidShort, Double.NaN)
+ assert(!Double.NaN.isValidByte, Double.NaN)
- def testBigIntIsFloat() {
- val prec = 24
- def checkFloatT(x: BigInt) = {
- assert(x.isValidFloat, x)
- assert((-x).isValidFloat, -x)
+ assert(!Float.NaN.isWhole, Float.NaN)
+// assert(!Float.NaN.isValidDouble, Float.NaN)
+// assert(!Float.NaN.isValidFloat, Float.NaN)
+// assert(!Float.NaN.isValidLong, Float.NaN)
+ assert(!Float.NaN.isValidInt, Float.NaN)
+ assert(!Float.NaN.isValidChar, Float.NaN)
+ assert(!Float.NaN.isValidShort, Float.NaN)
+ assert(!Float.NaN.isValidByte, Float.NaN)
+ }
+
+ def checkNonWholeDouble(d: Double) {
+ val f = d.toFloat
+ val isFloat = f == d
+
+ if (!d.isInfinity) {
+ val bd = BigDecimal(new java.math.BigDecimal(d))
+// assert(!bd.isWhole, bd)
+ assert(bd.isValidDouble, bd)
+ assert(bd.isValidFloat == isFloat, bd)
+ assert(!bd.isValidLong, bd)
+ assert(!bd.isValidInt, bd)
+ assert(!bd.isValidChar, bd)
+ assert(!bd.isValidShort, bd)
+ assert(!bd.isValidByte, bd)
+ }
+
+ assert(!d.isWhole, d)
+// assert(d.isValidDouble, d)
+// assert(d.isValidFloat == isFloat, d)
+// assert(!d.isValidLong, d)
+ assert(!d.isValidInt, d)
+ assert(!d.isValidChar, d)
+ assert(!d.isValidShort, d)
+ assert(!d.isValidByte, d)
+
+ if (isFloat) {
+ assert(!f.isWhole, f)
+// assert(f.isValidDouble, f)
+// assert(f.isValidFloat == isFloat, f)
+// assert(!f.isValidLong, f)
+ assert(!f.isValidInt, f)
+ assert(!f.isValidChar, f)
+ assert(!f.isValidShort, f)
+ assert(!f.isValidByte, f)
}
- def checkFloatF(x: BigInt) = {
- assert(!x.isValidFloat, x)
- assert(!(-x).isValidFloat, -x)
- }
- checkFloatT(biExp2(prec) - 1)
- checkFloatT(biExp2(prec))
- checkFloatF(biExp2(prec) + 1)
- checkFloatT(biExp2(prec) + 2)
- checkFloatT(biExp2(prec) - 2)
- checkFloatF(biExp2(prec + 1) - 1)
- checkFloatT(biExp2(prec + 1))
- checkFloatF(biExp2(prec + 1) + 1)
- checkFloatF(biExp2(prec + 1) + 2)
- checkFloatF(biExp2(prec + 1) + 3)
- checkFloatT(biExp2(prec + 1) + 4)
- checkFloatT(biExp2(64))
- checkFloatF(biExp2(64) + biExp2(64 - prec))
- checkFloatT(biExp2(64) + biExp2(64 - prec + 1))
- checkFloatT(biExp2(127))
- checkFloatT(biExp2(128) - biExp2(128 - prec))
- checkFloatF(biExp2(128) - biExp2(128 - prec - 1))
- checkFloatF(biExp2(128))
}
- def testBigIntIsDouble() {
- val prec = 53
- def checkDoubleT(x: BigInt) = {
- assert(x.isValidDouble, x)
- assert((-x).isValidDouble, -x)
+ def checkBigInt(bi: BigInt) {
+ val bd = BigDecimal(bi, java.math.MathContext.UNLIMITED)
+ val isByte = bi >= Byte.MinValue && bi <= Byte.MaxValue
+ val isShort = bi >= Short.MinValue && bi <= Short.MaxValue
+ val isChar = bi >= Char.MinValue && bi <= Char.MaxValue
+ val isInt = bi >= Int.MinValue && bi <= Int.MaxValue
+ val isLong = bi >= Long.MinValue && bi <= Long.MaxValue
+ val isFloat = !bi.toFloat.isInfinity && bd.compare(BigDecimal(new java.math.BigDecimal(bi.toFloat))) == 0
+ val isDouble = !bi.toDouble.isInfinity && bd.compare(BigDecimal(new java.math.BigDecimal(bi.toDouble))) == 0
+
+// assert(bd.isWhole, bd)
+ assert(bd.isValidDouble == isDouble, bd)
+ assert(bd.isValidFloat == isFloat, bd)
+ assert(bd.isValidLong == isLong, bd)
+ assert(bd.isValidInt == isInt, bd)
+ assert(bd.isValidChar == isChar, bd)
+ assert(bd.isValidShort == isShort, bd)
+ assert(bd.isValidByte == isByte, bd)
+
+// assert(bi.isWhole, bi)
+ assert(bi.isValidDouble == isDouble, bi)
+ assert(bi.isValidFloat == isFloat, bi)
+ assert(bi.isValidLong == isLong, bi)
+ assert(bi.isValidInt == isInt, bi)
+ assert(bi.isValidChar == isChar, bi)
+ assert(bi.isValidShort == isShort, bi)
+ assert(bi.isValidByte == isByte, bi)
+
+ if (isDouble) {
+ val d = bi.toDouble
+ assert(d.isWhole, d)
+// assert(d.isValidDouble == isDouble, d)
+// assert(d.isValidFloat == isFloat, d)
+// assert(d.isValidLong == isLong, d)
+ assert(d.isValidInt == isInt, d)
+ assert(d.isValidChar == isChar, d)
+ assert(d.isValidShort == isShort, d)
+ assert(d.isValidByte == isByte, d)
+ }
+
+ if (isFloat) {
+ val f = bi.toFloat
+ assert(f.isWhole, f)
+// assert(f.isValidDouble == isDouble, f)
+// assert(f.isValidFloat == isFloat, f)
+// assert(f.isValidLong == isLong, f)
+ assert(f.isValidInt == isInt, f)
+ assert(f.isValidChar == isChar, f)
+ assert(f.isValidShort == isShort, f)
+ assert(f.isValidByte == isByte, f)
+ }
+
+ if (isLong) {
+ val l = bi.toLong
+ assert(l.isWhole, l)
+// assert(l.isValidDouble == isDouble, l)
+// assert(l.isValidFloat == isFloat, l)
+// assert(l.isValidLong == isLong, l)
+ assert(l.isValidInt == isInt, l)
+ assert(l.isValidChar == isChar, l)
+ assert(l.isValidShort == isShort, l)
+ assert(l.isValidByte == isByte, l)
+ }
+
+ if (isInt) {
+ val i = bi.toInt
+ assert(i.isWhole, i)
+// assert(i.isValidDouble == isDouble, i)
+// assert(i.isValidFloat == isFloat, i)
+// assert(i.isValidLong == isLong, i)
+ assert(i.isValidInt == isInt, i)
+ assert(i.isValidChar == isChar, i)
+ assert(i.isValidShort == isShort, i)
+ assert(i.isValidByte == isByte, i)
}
- def checkDoubleF(x: BigInt) = {
- assert(!x.isValidDouble, x)
- assert(!(-x).isValidDouble, -x)
+
+ if (isChar) {
+ val c = bi.toChar
+ assert(c.isWhole, c)
+// assert(c.isValidDouble == isDouble, c)
+// assert(c.isValidFloat == isFloat, c)
+// assert(c.isValidLong == isLong, c)
+ assert(c.isValidInt == isInt, c)
+ assert(c.isValidChar == isChar, c)
+ assert(c.isValidShort == isShort, c)
+ assert(c.isValidByte == isByte, c)
+ }
+
+ if (isShort) {
+ val s = bi.toShort
+ assert(s.isWhole, s)
+// assert(s.isValidDouble == isDouble, s)
+// assert(s.isValidFloat == isFloat, s)
+// assert(s.isValidLong == isLong, s)
+ assert(s.isValidInt == isInt, s)
+ assert(s.isValidChar == isChar, s)
+ assert(s.isValidShort == isShort, s)
+ assert(s.isValidByte == isByte, s)
+ }
+
+ if (isByte) {
+ val b = bi.toByte
+ assert(b.isWhole, b)
+// assert(b.isValidDouble == isDouble, b)
+// assert(b.isValidFloat == isFloat, b)
+// assert(b.isValidLong == isLong, b)
+ assert(b.isValidInt == isInt, b)
+ assert(b.isValidChar == isChar, b)
+ assert(b.isValidShort == isShort, b)
+ assert(b.isValidByte == isByte, b)
}
- checkDoubleT(biExp2(prec) - 1)
- checkDoubleT(biExp2(prec))
- checkDoubleF(biExp2(prec) + 1)
- checkDoubleT(biExp2(prec) + 2)
- checkDoubleT(biExp2(prec + 1) - 2)
- checkDoubleF(biExp2(prec + 1) - 1)
- checkDoubleT(biExp2(prec + 1))
- checkDoubleF(biExp2(prec + 1) + 1)
- checkDoubleF(biExp2(prec + 1) + 2)
- checkDoubleF(biExp2(prec + 1) + 3)
- checkDoubleT(biExp2(prec + 1) + 4)
- checkDoubleT(biExp2(64))
- checkDoubleF(biExp2(64) + biExp2(64 - prec))
- checkDoubleT(biExp2(64) + biExp2(64 - prec + 1))
- checkDoubleT(biExp2(1023))
- checkDoubleT(biExp2(1024) - biExp2(1024 - prec))
- checkDoubleF(biExp2(1024) - biExp2(1024 - prec - 1))
- checkDoubleF(biExp2(1024))
}
}
diff --git a/test/files/run/lazy-locals.check b/test/files/run/lazy-locals.check
index 7d14da243b..d1cc754f2c 100644
--- a/test/files/run/lazy-locals.check
+++ b/test/files/run/lazy-locals.check
@@ -36,30 +36,19 @@ forced lazy val t02
forced lazy val t01
forced lazy val t00
Sum is: 496
-forced lazy val t32
-forced lazy val t31
-forced lazy val t30
-forced lazy val t29
-forced lazy val t28
-forced lazy val t27
-forced lazy val t26
-forced lazy val t25
-forced lazy val t24
-forced lazy val t23
-forced lazy val t22
-forced lazy val t21
-forced lazy val t20
-forced lazy val t19
-forced lazy val t18
-forced lazy val t17
-forced lazy val t16
-forced lazy val t15
-forced lazy val t14
-forced lazy val t13
-forced lazy val t12
-forced lazy val t11
-forced lazy val t10
-forced lazy val t09
+Sum again is: 496
+Sum again again is: 496
+forced lazy val t07
+forced lazy val t06
+forced lazy val t05
+forced lazy val t04
+forced lazy val t03
+forced lazy val t02
+forced lazy val t01
+forced lazy val t00
+Sum is: 28
+Sum again is: 28
+Sum again again is: 28
forced lazy val t08
forced lazy val t07
forced lazy val t06
@@ -69,7 +58,9 @@ forced lazy val t03
forced lazy val t02
forced lazy val t01
forced lazy val t00
-Sum is: 528
+Sum is: 36
+Sum again is: 36
+Sum again again is: 36
forced lazy val t at n = 0
42
forced lazy val t at n = 0
diff --git a/test/files/run/lazy-locals.scala b/test/files/run/lazy-locals.scala
index 696aeeba96..aca15d0357 100644
--- a/test/files/run/lazy-locals.scala
+++ b/test/files/run/lazy-locals.scala
@@ -13,7 +13,7 @@ object Test extends App {
1 + t + t
}
- /** test 32 lazy vals, which fills one bitmap int. */
+ /** test 32 lazy vals, which should spill over multiple byte bitmaps. */
def testLazy32 = {
lazy val t00 = { Console.println("forced lazy val t00"); 0 }
lazy val t01 = { Console.println("forced lazy val t01"); 1 }
@@ -51,12 +51,25 @@ object Test extends App {
val sum = t31 + t30 + t29 + t28 + t27 + t26 + t25 + t24 + t23 +
t22 + t21 + t20 + t19 + t18 + t17 + t16 + t15 + t14 +
t13 + t12 + t11 + t10 + t09 + t08 + t07 + t06 + t05 +
- t04 + t03 + t02 + t01 + t00;
- println("Sum is: " + sum);
+ t04 + t03 + t02 + t01 + t00
+ val sum2 = t31 + t30 + t29 + t28 + t27 + t26 + t25 + t24 + t23 +
+ t22 + t21 + t20 + t19 + t18 + t17 + t16 + t15 + t14 +
+ t13 + t12 + t11 + t10 + t09 + t08 + t07 + t06 + t05 +
+ t04 + t03 + t02 + t01 + t00
+ val sum3 = t00 + t01 + t02 + t03 + t04 + t05 + t06 + t07 + t08 +
+ t09 + t10 + t11 + t12 + t13 + t14 + t15 + t16 + t17 +
+ t18 + t19 + t20 + t21 + t22 + t23 + t24 + t25 + t26 +
+ t27 + t28 + t29 + t30 + t31
+
+
+
+ println("Sum is: " + sum)
+ println("Sum again is: " + sum2)
+ println("Sum again again is: " + sum3)
}
- /** test 32 lazy vals, which needs two bitmap ints. */
- def testLazy33 = {
+ /** test 8 lazy vals, which should fit one byte bitmap. */
+ def testLazy8 = {
lazy val t00 = { Console.println("forced lazy val t00"); 0 }
lazy val t01 = { Console.println("forced lazy val t01"); 1 }
lazy val t02 = { Console.println("forced lazy val t02"); 2 }
@@ -65,39 +78,38 @@ object Test extends App {
lazy val t05 = { Console.println("forced lazy val t05"); 5 }
lazy val t06 = { Console.println("forced lazy val t06"); 6 }
lazy val t07 = { Console.println("forced lazy val t07"); 7 }
- lazy val t08 = { Console.println("forced lazy val t08"); 8 }
- lazy val t09 = { Console.println("forced lazy val t09"); 9 }
- lazy val t10 = { Console.println("forced lazy val t10"); 10 }
- lazy val t11 = { Console.println("forced lazy val t11"); 11 }
- lazy val t12 = { Console.println("forced lazy val t12"); 12 }
- lazy val t13 = { Console.println("forced lazy val t13"); 13 }
- lazy val t14 = { Console.println("forced lazy val t14"); 14 }
- lazy val t15 = { Console.println("forced lazy val t15"); 15 }
- lazy val t16 = { Console.println("forced lazy val t16"); 16 }
- lazy val t17 = { Console.println("forced lazy val t17"); 17 }
- lazy val t18 = { Console.println("forced lazy val t18"); 18 }
- lazy val t19 = { Console.println("forced lazy val t19"); 19 }
- lazy val t20 = { Console.println("forced lazy val t20"); 20 }
- lazy val t21 = { Console.println("forced lazy val t21"); 21 }
- lazy val t22 = { Console.println("forced lazy val t22"); 22 }
- lazy val t23 = { Console.println("forced lazy val t23"); 23 }
- lazy val t24 = { Console.println("forced lazy val t24"); 24 }
- lazy val t25 = { Console.println("forced lazy val t25"); 25 }
- lazy val t26 = { Console.println("forced lazy val t26"); 26 }
- lazy val t27 = { Console.println("forced lazy val t27"); 27 }
- lazy val t28 = { Console.println("forced lazy val t28"); 28 }
- lazy val t29 = { Console.println("forced lazy val t29"); 29 }
- lazy val t30 = { Console.println("forced lazy val t30"); 30 }
- lazy val t31 = { Console.println("forced lazy val t31"); 31 }
- lazy val t32 = { Console.println("forced lazy val t32"); 32 }
- val sum = t32 + t31 + t30 + t29 + t28 + t27 + t26 + t25 + t24 + t23 +
- t22 + t21 + t20 + t19 + t18 + t17 + t16 + t15 + t14 +
- t13 + t12 + t11 + t10 + t09 + t08 + t07 + t06 + t05 +
- t04 + t03 + t02 + t01 + t00;
- println("Sum is: " + sum);
+ val sum = t07 + t06 + t05 + t04 + t03 + t02 + t01 + t00
+ val sum2 = t07 + t06 + t05 + t04 + t03 + t02 + t01 + t00
+ val sum3 = t00 + t01 + t02 + t03 + t04 + t05 + t06 + t07
+
+
+
+ println("Sum is: " + sum)
+ println("Sum again is: " + sum2)
+ println("Sum again again is: " + sum3)
}
+ /** test 9 lazy vals, which should spill over two bitmaps. */
+ def testLazy9 = {
+ lazy val t00 = { Console.println("forced lazy val t00"); 0 }
+ lazy val t01 = { Console.println("forced lazy val t01"); 1 }
+ lazy val t02 = { Console.println("forced lazy val t02"); 2 }
+ lazy val t03 = { Console.println("forced lazy val t03"); 3 }
+ lazy val t04 = { Console.println("forced lazy val t04"); 4 }
+ lazy val t05 = { Console.println("forced lazy val t05"); 5 }
+ lazy val t06 = { Console.println("forced lazy val t06"); 6 }
+ lazy val t07 = { Console.println("forced lazy val t07"); 7 }
+ lazy val t08 = { Console.println("forced lazy val t08"); 8 }
+
+ val sum = t08 + t07 + t06 + t05 + t04 + t03 + t02 + t01 + t00
+ val sum2 = t08 + t07 + t06 + t05 + t04 + t03 + t02 + t01 + t00
+ val sum3 = t00 + t01 + t02 + t03 + t04 + t05 + t06 + t07 + t08
+
+ println("Sum is: " + sum)
+ println("Sum again is: " + sum2)
+ println("Sum again again is: " + sum3)
+ }
/** test recursive method with lazy vals and a single forced */
def testLazyRec(n: Int): Int = {
@@ -185,7 +197,8 @@ object Test extends App {
println(testLazy)
testLazy32
- testLazy33
+ testLazy8
+ testLazy9
println(testLazyRec(5))
println(testLazyRecMany(5))
testRecVal
diff --git a/test/files/run/macro-abort-fresh.check b/test/files/run/macro-abort-fresh.check
new file mode 100644
index 0000000000..28057c2883
--- /dev/null
+++ b/test/files/run/macro-abort-fresh.check
@@ -0,0 +1,6 @@
+$1$
+qwe1
+qwe2
+reflective compilation has failed:
+
+blargh
diff --git a/test/files/run/macro-abort-fresh.flags b/test/files/run/macro-abort-fresh.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-abort-fresh.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-abort-fresh/Macros_1.scala b/test/files/run/macro-abort-fresh/Macros_1.scala
new file mode 100644
index 0000000000..4186c4c4a6
--- /dev/null
+++ b/test/files/run/macro-abort-fresh/Macros_1.scala
@@ -0,0 +1,15 @@
+import scala.reflect.makro.Context
+
+object Impls {
+ def impl(c: Context) = {
+ import c.mirror._
+ println(c.fresh())
+ println(c.fresh("qwe"))
+ println(c.fresh(newTypeName("qwe")))
+ c.abort(NoPosition, "blargh")
+ }
+}
+
+object Macros {
+ def foo = macro Impls.impl
+} \ No newline at end of file
diff --git a/test/files/run/macro-abort-fresh/Test_2.scala b/test/files/run/macro-abort-fresh/Test_2.scala
new file mode 100644
index 0000000000..ecf48b9752
--- /dev/null
+++ b/test/files/run/macro-abort-fresh/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Select(Ident("Macros"), newTermName("foo"))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+} \ No newline at end of file
diff --git a/test/files/run/macro-basic-ma-md-mi.check b/test/files/run/macro-basic-ma-md-mi.check
new file mode 100644
index 0000000000..b74e882ae3
--- /dev/null
+++ b/test/files/run/macro-basic-ma-md-mi.check
@@ -0,0 +1 @@
+31 \ No newline at end of file
diff --git a/test/files/run/macro-basic-ma-md-mi.flags b/test/files/run/macro-basic-ma-md-mi.flags
new file mode 100644
index 0000000000..5e5dd6ce79
--- /dev/null
+++ b/test/files/run/macro-basic-ma-md-mi.flags
@@ -0,0 +1 @@
+-language:experimental.macros
diff --git a/test/files/run/macro-basic-ma-md-mi/Impls_1.scala b/test/files/run/macro-basic-ma-md-mi/Impls_1.scala
new file mode 100644
index 0000000000..3f23e349d5
--- /dev/null
+++ b/test/files/run/macro-basic-ma-md-mi/Impls_1.scala
@@ -0,0 +1,21 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1))))
+ Expr[Int](body)
+ }
+
+ def bar(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2))))
+ Expr[Int](body)
+ }
+
+ def quux(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3))))
+ Expr[Int](body)
+ }
+}
diff --git a/test/files/run/macro-basic-ma-md-mi/Macros_2.scala b/test/files/run/macro-basic-ma-md-mi/Macros_2.scala
new file mode 100644
index 0000000000..5279043746
--- /dev/null
+++ b/test/files/run/macro-basic-ma-md-mi/Macros_2.scala
@@ -0,0 +1,10 @@
+object Macros {
+ object Shmacros {
+ def foo(x: Int): Int = macro Impls.foo
+ }
+ def bar(x: Int): Int = macro Impls.bar
+}
+
+class Macros {
+ def quux(x: Int): Int = macro Impls.quux
+} \ No newline at end of file
diff --git a/test/files/run/macro-basic-ma-md-mi/Test_3.scala b/test/files/run/macro-basic-ma-md-mi/Test_3.scala
new file mode 100644
index 0000000000..e9a10e20c9
--- /dev/null
+++ b/test/files/run/macro-basic-ma-md-mi/Test_3.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros.Shmacros._
+ println(foo(2) + Macros.bar(2) * new Macros().quux(4))
+} \ No newline at end of file
diff --git a/test/files/run/macro-basic-ma-mdmi.check b/test/files/run/macro-basic-ma-mdmi.check
new file mode 100644
index 0000000000..b74e882ae3
--- /dev/null
+++ b/test/files/run/macro-basic-ma-mdmi.check
@@ -0,0 +1 @@
+31 \ No newline at end of file
diff --git a/test/files/run/macro-basic-ma-mdmi.flags b/test/files/run/macro-basic-ma-mdmi.flags
new file mode 100644
index 0000000000..5e5dd6ce79
--- /dev/null
+++ b/test/files/run/macro-basic-ma-mdmi.flags
@@ -0,0 +1 @@
+-language:experimental.macros
diff --git a/test/files/run/macro-basic-ma-mdmi/Impls_Macros_1.scala b/test/files/run/macro-basic-ma-mdmi/Impls_Macros_1.scala
new file mode 100644
index 0000000000..44bfe861e3
--- /dev/null
+++ b/test/files/run/macro-basic-ma-mdmi/Impls_Macros_1.scala
@@ -0,0 +1,32 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1))))
+ Expr[Int](body)
+ }
+
+ def bar(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2))))
+ Expr[Int](body)
+ }
+
+ def quux(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3))))
+ Expr[Int](body)
+ }
+}
+
+object Macros {
+ object Shmacros {
+ def foo(x: Int): Int = macro Impls.foo
+ }
+ def bar(x: Int): Int = macro Impls.bar
+}
+
+class Macros {
+ def quux(x: Int): Int = macro Impls.quux
+} \ No newline at end of file
diff --git a/test/files/run/macro-basic-ma-mdmi/Test_2.scala b/test/files/run/macro-basic-ma-mdmi/Test_2.scala
new file mode 100644
index 0000000000..e9a10e20c9
--- /dev/null
+++ b/test/files/run/macro-basic-ma-mdmi/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros.Shmacros._
+ println(foo(2) + Macros.bar(2) * new Macros().quux(4))
+} \ No newline at end of file
diff --git a/test/files/run/macro-basic-mamd-mi.check b/test/files/run/macro-basic-mamd-mi.check
new file mode 100644
index 0000000000..b74e882ae3
--- /dev/null
+++ b/test/files/run/macro-basic-mamd-mi.check
@@ -0,0 +1 @@
+31 \ No newline at end of file
diff --git a/test/files/run/macro-basic-mamd-mi.flags b/test/files/run/macro-basic-mamd-mi.flags
new file mode 100644
index 0000000000..5e5dd6ce79
--- /dev/null
+++ b/test/files/run/macro-basic-mamd-mi.flags
@@ -0,0 +1 @@
+-language:experimental.macros
diff --git a/test/files/run/macro-basic-mamd-mi/Impls_1.scala b/test/files/run/macro-basic-mamd-mi/Impls_1.scala
new file mode 100644
index 0000000000..82d2cce2f5
--- /dev/null
+++ b/test/files/run/macro-basic-mamd-mi/Impls_1.scala
@@ -0,0 +1,19 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1)))))
+ }
+
+ def bar(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2)))))
+ }
+
+ def quux(c: Ctx)(x: c.Expr[Int]): c.Expr[Int] = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3))))
+ Expr[Int](body)
+ }
+}
diff --git a/test/files/run/macro-basic-mamd-mi/Macros_Test_2.scala b/test/files/run/macro-basic-mamd-mi/Macros_Test_2.scala
new file mode 100644
index 0000000000..d3746894f0
--- /dev/null
+++ b/test/files/run/macro-basic-mamd-mi/Macros_Test_2.scala
@@ -0,0 +1,15 @@
+object Macros {
+ object Shmacros {
+ def foo(x: Int): Int = macro Impls.foo
+ }
+ def bar(x: Int): Int = macro Impls.bar
+}
+
+class Macros {
+ def quux(x: Int): Int = macro Impls.quux
+}
+
+object Test extends App {
+ import Macros.Shmacros._
+ println(foo(2) + Macros.bar(2) * new Macros().quux(4))
+} \ No newline at end of file
diff --git a/test/files/run/macro-basic.check b/test/files/run/macro-basic.check
deleted file mode 100644
index d434014897..0000000000
--- a/test/files/run/macro-basic.check
+++ /dev/null
@@ -1 +0,0 @@
-10
diff --git a/test/files/run/macro-basic.flags b/test/files/run/macro-basic.flags
deleted file mode 100644
index 06a7b31f11..0000000000
--- a/test/files/run/macro-basic.flags
+++ /dev/null
@@ -1 +0,0 @@
--Xmacros
diff --git a/test/files/run/macro-basic/Macros_1.scala b/test/files/run/macro-basic/Macros_1.scala
deleted file mode 100644
index c2ea183abe..0000000000
--- a/test/files/run/macro-basic/Macros_1.scala
+++ /dev/null
@@ -1,10 +0,0 @@
-object Macros {
- object Shmacros {
- def macro foo(x: Int): Int = x
- }
- def macro bar(x: Int): Int = x
-}
-
-class Macros {
- def macro quux(x: Int): Int = x
-} \ No newline at end of file
diff --git a/test/files/run/macro-bodyexpandstoimpl.check b/test/files/run/macro-bodyexpandstoimpl.check
new file mode 100644
index 0000000000..f70d7bba4a
--- /dev/null
+++ b/test/files/run/macro-bodyexpandstoimpl.check
@@ -0,0 +1 @@
+42 \ No newline at end of file
diff --git a/test/files/run/macro-bodyexpandstoimpl.flags b/test/files/run/macro-bodyexpandstoimpl.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-bodyexpandstoimpl.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-bodyexpandstoimpl/Impls_1.scala b/test/files/run/macro-bodyexpandstoimpl/Impls_1.scala
new file mode 100644
index 0000000000..5c5ec2c999
--- /dev/null
+++ b/test/files/run/macro-bodyexpandstoimpl/Impls_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = x
+
+ def refToFoo(dummy: Int) = macro refToFoo_impl
+ def refToFoo_impl(c: Ctx)(dummy: c.Expr[Int]) = {
+ import c.mirror._
+ val body = Select(Ident(newTermName("Impls")), newTermName("foo"))
+ Expr[Int](body)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-bodyexpandstoimpl/Macros_Test_2.scala b/test/files/run/macro-bodyexpandstoimpl/Macros_Test_2.scala
new file mode 100644
index 0000000000..2934201a16
--- /dev/null
+++ b/test/files/run/macro-bodyexpandstoimpl/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo(x: Int) = macro Impls.refToFoo(42)
+}
+
+object Test extends App {
+ import Macros._
+ println(foo(42))
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-annotation.check b/test/files/run/macro-declared-in-annotation.check
new file mode 100644
index 0000000000..1ea14b4e20
--- /dev/null
+++ b/test/files/run/macro-declared-in-annotation.check
@@ -0,0 +1 @@
+it works
diff --git a/test/files/run/macro-declared-in-annotation.flags b/test/files/run/macro-declared-in-annotation.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-annotation.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-annotation/Impls_1.scala b/test/files/run/macro-declared-in-annotation/Impls_1.scala
new file mode 100644
index 0000000000..a1234a7374
--- /dev/null
+++ b/test/files/run/macro-declared-in-annotation/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(List(printPrefix), Literal(Constant("this is deprecated")))
+ Expr[String](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-annotation/Macros_2.scala b/test/files/run/macro-declared-in-annotation/Macros_2.scala
new file mode 100644
index 0000000000..40d71c62fb
--- /dev/null
+++ b/test/files/run/macro-declared-in-annotation/Macros_2.scala
@@ -0,0 +1,8 @@
+class foo(val bar: String) extends annotation.StaticAnnotation
+
+object Api {
+ // foo in ann must have a different name
+ // otherwise, we get bitten by https://issues.scala-lang.org/browse/SI-5544
+ @foo({def fooInAnn = macro Impls.foo; fooInAnn})
+ def foo = println("it works")
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-annotation/Test_3.scala b/test/files/run/macro-declared-in-annotation/Test_3.scala
new file mode 100644
index 0000000000..866487f028
--- /dev/null
+++ b/test/files/run/macro-declared-in-annotation/Test_3.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ Api.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-anonymous.check b/test/files/run/macro-declared-in-anonymous.check
new file mode 100644
index 0000000000..09b8d015a6
--- /dev/null
+++ b/test/files/run/macro-declared-in-anonymous.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](Test.this.macros)
+it works
diff --git a/test/files/run/macro-declared-in-anonymous.flags b/test/files/run/macro-declared-in-anonymous.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-anonymous.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-anonymous/Impls_1.scala b/test/files/run/macro-declared-in-anonymous/Impls_1.scala
new file mode 100644
index 0000000000..c0827ace31
--- /dev/null
+++ b/test/files/run/macro-declared-in-anonymous/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-anonymous/Macros_Test_2.scala b/test/files/run/macro-declared-in-anonymous/Macros_Test_2.scala
new file mode 100644
index 0000000000..8bd8c172c9
--- /dev/null
+++ b/test/files/run/macro-declared-in-anonymous/Macros_Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ val macros = new { def foo = macro Impls.foo }
+ macros.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-block.check b/test/files/run/macro-declared-in-block.check
new file mode 100644
index 0000000000..a61fd13087
--- /dev/null
+++ b/test/files/run/macro-declared-in-block.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](<empty>)
+it works
diff --git a/test/files/run/macro-declared-in-block.flags b/test/files/run/macro-declared-in-block.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-block.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-block/Impls_1.scala b/test/files/run/macro-declared-in-block/Impls_1.scala
new file mode 100644
index 0000000000..c0827ace31
--- /dev/null
+++ b/test/files/run/macro-declared-in-block/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(List(printPrefix), Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-block/Macros_Test_2.scala b/test/files/run/macro-declared-in-block/Macros_Test_2.scala
new file mode 100644
index 0000000000..69088e24bc
--- /dev/null
+++ b/test/files/run/macro-declared-in-block/Macros_Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ {
+ def foo = macro Impls.foo
+ foo
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-class-class.check b/test/files/run/macro-declared-in-class-class.check
new file mode 100644
index 0000000000..480c2f906f
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-class.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](new Test.this.outer.Macros())
+it works
diff --git a/test/files/run/macro-declared-in-class-class.flags b/test/files/run/macro-declared-in-class-class.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-class.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-class-class/Impls_1.scala b/test/files/run/macro-declared-in-class-class/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-class/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-class-class/Macros_Test_2.scala b/test/files/run/macro-declared-in-class-class/Macros_Test_2.scala
new file mode 100644
index 0000000000..871857a97f
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-class/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+class Macros {
+ class Macros {
+ def foo = macro Impls.foo
+ }
+}
+
+object Test extends App {
+ val outer = new Macros()
+ new outer.Macros().foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-class-object.check b/test/files/run/macro-declared-in-class-object.check
new file mode 100644
index 0000000000..f7ba5a53cb
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-object.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](Test.this.outer.Macros)
+it works
diff --git a/test/files/run/macro-declared-in-class-object.flags b/test/files/run/macro-declared-in-class-object.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-object.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-class-object/Impls_1.scala b/test/files/run/macro-declared-in-class-object/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-object/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-class-object/Macros_Test_2.scala b/test/files/run/macro-declared-in-class-object/Macros_Test_2.scala
new file mode 100644
index 0000000000..994f9fe935
--- /dev/null
+++ b/test/files/run/macro-declared-in-class-object/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+class Macros {
+ object Macros {
+ def foo = macro Impls.foo
+ }
+}
+
+object Test extends App {
+ val outer = new Macros()
+ outer.Macros.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-class.check b/test/files/run/macro-declared-in-class.check
new file mode 100644
index 0000000000..946851e4bb
--- /dev/null
+++ b/test/files/run/macro-declared-in-class.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](new Macros())
+it works
diff --git a/test/files/run/macro-declared-in-class.flags b/test/files/run/macro-declared-in-class.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-class.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-class/Impls_1.scala b/test/files/run/macro-declared-in-class/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-class/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-class/Macros_Test_2.scala b/test/files/run/macro-declared-in-class/Macros_Test_2.scala
new file mode 100644
index 0000000000..1b9d13e775
--- /dev/null
+++ b/test/files/run/macro-declared-in-class/Macros_Test_2.scala
@@ -0,0 +1,7 @@
+class Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ new Macros().foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-default-param.check b/test/files/run/macro-declared-in-default-param.check
new file mode 100644
index 0000000000..00052ad018
--- /dev/null
+++ b/test/files/run/macro-declared-in-default-param.check
@@ -0,0 +1,5 @@
+prefix = Expr[Nothing](<empty>)
+it works
+it works
+prefix = Expr[Nothing](<empty>)
+it works
diff --git a/test/files/run/macro-declared-in-default-param.flags b/test/files/run/macro-declared-in-default-param.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-default-param.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-default-param/Impls_1.scala b/test/files/run/macro-declared-in-default-param/Impls_1.scala
new file mode 100644
index 0000000000..e45095812a
--- /dev/null
+++ b/test/files/run/macro-declared-in-default-param/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(List(printPrefix), Literal(Constant("it works")))
+ Expr[String](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-default-param/Macros_Test_2.scala b/test/files/run/macro-declared-in-default-param/Macros_Test_2.scala
new file mode 100644
index 0000000000..356029e63e
--- /dev/null
+++ b/test/files/run/macro-declared-in-default-param/Macros_Test_2.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ def foo(bar: String = { def foo = macro Impls.foo; foo }) = println(bar)
+
+ foo()
+ foo("it works")
+ foo()
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-implicit-class.check b/test/files/run/macro-declared-in-implicit-class.check
new file mode 100644
index 0000000000..b3640ceaa7
--- /dev/null
+++ b/test/files/run/macro-declared-in-implicit-class.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](Macros.foo("2"))
+Some(2)
diff --git a/test/files/run/macro-declared-in-implicit-class.flags b/test/files/run/macro-declared-in-implicit-class.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-implicit-class.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala b/test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala
new file mode 100644
index 0000000000..8605d4a8be
--- /dev/null
+++ b/test/files/run/macro-declared-in-implicit-class/Impls_Macros_1.scala
@@ -0,0 +1,19 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def toOptionOfInt(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Ident(definitions.SomeModule), List(Select(Select(prefix.tree, newTermName("x")), newTermName("toInt")))))
+ Expr[Option[Int]](body)
+ }
+}
+
+object Macros {
+ implicit def foo(x: String): Foo = new Foo(x)
+
+ class Foo(val x: String) {
+ def toOptionOfInt = macro Impls.toOptionOfInt
+ }
+}
diff --git a/test/files/run/macro-declared-in-implicit-class/Test_2.scala b/test/files/run/macro-declared-in-implicit-class/Test_2.scala
new file mode 100644
index 0000000000..d0bc9cc38c
--- /dev/null
+++ b/test/files/run/macro-declared-in-implicit-class/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros._
+ println("2".toOptionOfInt)
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-method.check b/test/files/run/macro-declared-in-method.check
new file mode 100644
index 0000000000..a61fd13087
--- /dev/null
+++ b/test/files/run/macro-declared-in-method.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](<empty>)
+it works
diff --git a/test/files/run/macro-declared-in-method.flags b/test/files/run/macro-declared-in-method.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-method.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-method/Impls_1.scala b/test/files/run/macro-declared-in-method/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-method/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-method/Macros_Test_2.scala b/test/files/run/macro-declared-in-method/Macros_Test_2.scala
new file mode 100644
index 0000000000..ed5c8b7c43
--- /dev/null
+++ b/test/files/run/macro-declared-in-method/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Test extends App {
+ def bar() = {
+ def foo = macro Impls.foo
+ foo
+ }
+
+ bar()
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-object-class.check b/test/files/run/macro-declared-in-object-class.check
new file mode 100644
index 0000000000..480c2f906f
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-class.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](new Test.this.outer.Macros())
+it works
diff --git a/test/files/run/macro-declared-in-object-class.flags b/test/files/run/macro-declared-in-object-class.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-class.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-object-class/Impls_1.scala b/test/files/run/macro-declared-in-object-class/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-class/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-object-class/Macros_Test_2.scala b/test/files/run/macro-declared-in-object-class/Macros_Test_2.scala
new file mode 100644
index 0000000000..204deed61c
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-class/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+object Macros {
+ class Macros {
+ def foo = macro Impls.foo
+ }
+}
+
+object Test extends App {
+ val outer = Macros
+ new outer.Macros().foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-object-object.check b/test/files/run/macro-declared-in-object-object.check
new file mode 100644
index 0000000000..f7ba5a53cb
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-object.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](Test.this.outer.Macros)
+it works
diff --git a/test/files/run/macro-declared-in-object-object.flags b/test/files/run/macro-declared-in-object-object.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-object.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-object-object/Impls_1.scala b/test/files/run/macro-declared-in-object-object/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-object/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-object-object/Macros_Test_2.scala b/test/files/run/macro-declared-in-object-object/Macros_Test_2.scala
new file mode 100644
index 0000000000..e261a50f3d
--- /dev/null
+++ b/test/files/run/macro-declared-in-object-object/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+object Macros {
+ object Macros {
+ def foo = macro Impls.foo
+ }
+}
+
+object Test extends App {
+ val outer = Macros
+ outer.Macros.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-object.check b/test/files/run/macro-declared-in-object.check
new file mode 100644
index 0000000000..05a8cc48ea
--- /dev/null
+++ b/test/files/run/macro-declared-in-object.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](Macros)
+it works
diff --git a/test/files/run/macro-declared-in-object.flags b/test/files/run/macro-declared-in-object.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-object.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-object/Impls_1.scala b/test/files/run/macro-declared-in-object/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-object/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-object/Macros_Test_2.scala b/test/files/run/macro-declared-in-object/Macros_Test_2.scala
new file mode 100644
index 0000000000..a5a4862ba0
--- /dev/null
+++ b/test/files/run/macro-declared-in-object/Macros_Test_2.scala
@@ -0,0 +1,7 @@
+object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ Macros.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-package-object.check b/test/files/run/macro-declared-in-package-object.check
new file mode 100644
index 0000000000..6f797f3c68
--- /dev/null
+++ b/test/files/run/macro-declared-in-package-object.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](Macros.`package`)
+it works
diff --git a/test/files/run/macro-declared-in-package-object.flags b/test/files/run/macro-declared-in-package-object.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-package-object.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-package-object/Impls_1.scala b/test/files/run/macro-declared-in-package-object/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-package-object/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-package-object/Macros_Test_2.scala b/test/files/run/macro-declared-in-package-object/Macros_Test_2.scala
new file mode 100644
index 0000000000..54a5962e80
--- /dev/null
+++ b/test/files/run/macro-declared-in-package-object/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+package object Macros {
+ def foo = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-refinement.check b/test/files/run/macro-declared-in-refinement.check
new file mode 100644
index 0000000000..861cd43b01
--- /dev/null
+++ b/test/files/run/macro-declared-in-refinement.check
@@ -0,0 +1,2 @@
+prefix = Expr[Nothing](Test.this.macros)
+it works
diff --git a/test/files/run/macro-declared-in-refinement.flags b/test/files/run/macro-declared-in-refinement.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-refinement.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-refinement/Impls_1.scala b/test/files/run/macro-declared-in-refinement/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-refinement/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-refinement/Macros_Test_2.scala b/test/files/run/macro-declared-in-refinement/Macros_Test_2.scala
new file mode 100644
index 0000000000..f746c2da57
--- /dev/null
+++ b/test/files/run/macro-declared-in-refinement/Macros_Test_2.scala
@@ -0,0 +1,6 @@
+class Base
+
+object Test extends App {
+ val macros = new Base { def foo = macro Impls.foo }
+ macros.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-trait.check b/test/files/run/macro-declared-in-trait.check
new file mode 100644
index 0000000000..d5d9e4e457
--- /dev/null
+++ b/test/files/run/macro-declared-in-trait.check
@@ -0,0 +1,15 @@
+prefix = Expr[Nothing]({
+ final class $anon extends Object with Base {
+ def <init>(): anonymous class $anon = {
+ $anon.super.<init>();
+ ()
+ };
+ <empty>
+ };
+ new $anon()
+})
+it works
+prefix = Expr[Nothing](Macros)
+it works
+prefix = Expr[Nothing](new Macros())
+it works
diff --git a/test/files/run/macro-declared-in-trait.flags b/test/files/run/macro-declared-in-trait.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-declared-in-trait.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-declared-in-trait/Impls_1.scala b/test/files/run/macro-declared-in-trait/Impls_1.scala
new file mode 100644
index 0000000000..c2e6933582
--- /dev/null
+++ b/test/files/run/macro-declared-in-trait/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val printPrefix = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("prefix = " + prefix))))
+ val body = Block(printPrefix, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works")))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-declared-in-trait/Macros_Test_2.scala b/test/files/run/macro-declared-in-trait/Macros_Test_2.scala
new file mode 100644
index 0000000000..f75906b636
--- /dev/null
+++ b/test/files/run/macro-declared-in-trait/Macros_Test_2.scala
@@ -0,0 +1,13 @@
+trait Base {
+ def foo = macro Impls.foo
+}
+
+object Macros extends Base
+
+class Macros extends Base
+
+object Test extends App {
+ (new Base {}).foo
+ Macros.foo
+ new Macros().foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-a.check b/test/files/run/macro-def-infer-return-type-a.check
new file mode 100644
index 0000000000..f70d7bba4a
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-a.check
@@ -0,0 +1 @@
+42 \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-a.flags b/test/files/run/macro-def-infer-return-type-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-a/Impls_1.scala b/test/files/run/macro-def-infer-return-type-a/Impls_1.scala
new file mode 100644
index 0000000000..2346a6106d
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-a/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = x
+}
diff --git a/test/files/run/macro-def-infer-return-type-a/Macros_Test_2.scala b/test/files/run/macro-def-infer-return-type-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..60fe9dc1c2
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-a/Macros_Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo(x: Int) = macro Impls.foo
+ println(foo(42))
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-b.check b/test/files/run/macro-def-infer-return-type-b.check
new file mode 100644
index 0000000000..f34d257c82
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-b.check
@@ -0,0 +1,6 @@
+reflective compilation has failed:
+
+exception during macro expansion:
+java.lang.Error: an implementation is missing
+ at Impls$.foo(Impls_Macros_1.scala:5)
+
diff --git a/test/files/run/macro-def-infer-return-type-b.flags b/test/files/run/macro-def-infer-return-type-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-b/Impls_Macros_1.scala b/test/files/run/macro-def-infer-return-type-b/Impls_Macros_1.scala
new file mode 100644
index 0000000000..8640713846
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-b/Impls_Macros_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T](c: Ctx)(x: c.Expr[T]) =
+ throw new Error("an implementation is missing")
+}
+
+object Macros {
+ def foo[T](x: T) = macro Impls.foo[T]
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-b/Test_2.scala b/test/files/run/macro-def-infer-return-type-b/Test_2.scala
new file mode 100644
index 0000000000..f8f15b4224
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-b/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42))))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-c.check b/test/files/run/macro-def-infer-return-type-c.check
new file mode 100644
index 0000000000..f70d7bba4a
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-c.check
@@ -0,0 +1 @@
+42 \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-c.flags b/test/files/run/macro-def-infer-return-type-c.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-c.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-def-infer-return-type-c/Impls_1.scala b/test/files/run/macro-def-infer-return-type-c/Impls_1.scala
new file mode 100644
index 0000000000..f3e53bbea7
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-c/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T](c: Ctx)(x: c.Expr[T]): c.Expr[T] = x
+}
diff --git a/test/files/run/macro-def-infer-return-type-c/Macros_Test_2.scala b/test/files/run/macro-def-infer-return-type-c/Macros_Test_2.scala
new file mode 100644
index 0000000000..967d16f6de
--- /dev/null
+++ b/test/files/run/macro-def-infer-return-type-c/Macros_Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo[T](x: T) = macro Impls.foo[T]
+ println(foo(42))
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-a.check b/test/files/run/macro-def-path-dependent-a.check
new file mode 100644
index 0000000000..1ea14b4e20
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-a.check
@@ -0,0 +1 @@
+it works
diff --git a/test/files/run/macro-def-path-dependent-a.flags b/test/files/run/macro-def-path-dependent-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-a/Impls_Macros_1.scala b/test/files/run/macro-def-path-dependent-a/Impls_Macros_1.scala
new file mode 100644
index 0000000000..d7167e671c
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-a/Impls_Macros_1.scala
@@ -0,0 +1,21 @@
+import scala.reflect.makro.{Context => Ctx}
+
+trait Exprs {
+ self: Universe =>
+
+ class Expr[T]
+}
+
+trait Reifiers {
+ self: Universe =>
+
+ type Expr[T]
+
+ def reify[T](expr: T) = macro Impls.reify[T]
+}
+
+trait Universe extends Exprs with Reifiers
+
+object Impls {
+ def reify[T](cc: Ctx{ type PrefixType = Reifiers })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = ???
+}
diff --git a/test/files/run/macro-def-path-dependent-a/Test_2.scala b/test/files/run/macro-def-path-dependent-a/Test_2.scala
new file mode 100644
index 0000000000..7dffc5107d
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-a/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ println("it works")
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-b.check b/test/files/run/macro-def-path-dependent-b.check
new file mode 100644
index 0000000000..1ea14b4e20
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-b.check
@@ -0,0 +1 @@
+it works
diff --git a/test/files/run/macro-def-path-dependent-b.flags b/test/files/run/macro-def-path-dependent-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-b/Impls_Macros_1.scala b/test/files/run/macro-def-path-dependent-b/Impls_Macros_1.scala
new file mode 100644
index 0000000000..44af6949a7
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-b/Impls_Macros_1.scala
@@ -0,0 +1,20 @@
+import scala.reflect.makro.{Context => Ctx}
+
+trait Exprs {
+ self: Universe =>
+
+ class Expr[T]
+}
+
+trait Reifiers {
+ self: Universe =>
+
+}
+
+trait Universe extends Exprs with Reifiers {
+ def reify[T](expr: T) = macro Impls.reify[T]
+}
+
+object Impls {
+ def reify[T](cc: Ctx{ type PrefixType = Universe })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = ???
+}
diff --git a/test/files/run/macro-def-path-dependent-b/Test_2.scala b/test/files/run/macro-def-path-dependent-b/Test_2.scala
new file mode 100644
index 0000000000..7dffc5107d
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-b/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ println("it works")
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-c.check b/test/files/run/macro-def-path-dependent-c.check
new file mode 100644
index 0000000000..1ea14b4e20
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-c.check
@@ -0,0 +1 @@
+it works
diff --git a/test/files/run/macro-def-path-dependent-c.flags b/test/files/run/macro-def-path-dependent-c.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-c.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-c/Impls_Macros_1.scala b/test/files/run/macro-def-path-dependent-c/Impls_Macros_1.scala
new file mode 100644
index 0000000000..305146c48b
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-c/Impls_Macros_1.scala
@@ -0,0 +1,20 @@
+import scala.reflect.makro.{Context => Ctx}
+
+trait Exprs {
+ self: Universe =>
+
+ class Expr[T]
+}
+
+trait Reifiers {
+ self: Universe =>
+
+}
+
+trait Universe extends Exprs with Reifiers {
+ def reify[T](expr: T): Expr[T] = macro Impls.reify[T]
+}
+
+object Impls {
+ def reify[T](cc: Ctx{ type PrefixType = Universe })(expr: cc.Expr[T]): cc.Expr[cc.prefix.value.Expr[T]] = ???
+}
diff --git a/test/files/run/macro-def-path-dependent-c/Test_2.scala b/test/files/run/macro-def-path-dependent-c/Test_2.scala
new file mode 100644
index 0000000000..7dffc5107d
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-c/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ println("it works")
+} \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-d.check b/test/files/run/macro-def-path-dependent-d.check
new file mode 100644
index 0000000000..1ea14b4e20
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-d.check
@@ -0,0 +1 @@
+it works
diff --git a/test/files/run/macro-def-path-dependent-d.flags b/test/files/run/macro-def-path-dependent-d.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-d.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-def-path-dependent-d/Impls_Macros_1.scala b/test/files/run/macro-def-path-dependent-d/Impls_Macros_1.scala
new file mode 100644
index 0000000000..32f03e778e
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-d/Impls_Macros_1.scala
@@ -0,0 +1,8 @@
+import scala.reflect.makro.Context
+import scala.reflect.api.Universe
+
+object Test {
+ def materializeTypeTag[T](u: Universe)(e: T) = macro materializeTypeTag_impl[T]
+
+ def materializeTypeTag_impl[T: c.TypeTag](c: Context)(u: c.Expr[Universe])(e: c.Expr[T]): c.Expr[u.value.TypeTag[T]] = ???
+}
diff --git a/test/files/run/macro-def-path-dependent-d/Test_2.scala b/test/files/run/macro-def-path-dependent-d/Test_2.scala
new file mode 100644
index 0000000000..7dffc5107d
--- /dev/null
+++ b/test/files/run/macro-def-path-dependent-d/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ println("it works")
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-has-implicit.check b/test/files/run/macro-expand-implicit-macro-has-implicit.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-has-implicit.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/macro-expand-implicit-macro-has-implicit.flags b/test/files/run/macro-expand-implicit-macro-has-implicit.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-has-implicit.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-has-implicit/Impls_1.scala b/test/files/run/macro-expand-implicit-macro-has-implicit/Impls_1.scala
new file mode 100644
index 0000000000..39db275e1c
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-has-implicit/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(x.tree))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-implicit-macro-has-implicit/Macros_Test_2.scala b/test/files/run/macro-expand-implicit-macro-has-implicit/Macros_Test_2.scala
new file mode 100644
index 0000000000..ffb04dc80b
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-has-implicit/Macros_Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ implicit val x = 42
+ def foo(implicit x: Int) = macro Impls.foo
+ foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-is-implicit.check b/test/files/run/macro-expand-implicit-macro-is-implicit.check
new file mode 100644
index 0000000000..42abf4579b
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-implicit.check
@@ -0,0 +1,2 @@
+Some(2)
+2
diff --git a/test/files/run/macro-expand-implicit-macro-is-implicit.flags b/test/files/run/macro-expand-implicit-macro-is-implicit.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-implicit.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-is-implicit/Impls_1.scala b/test/files/run/macro-expand-implicit-macro-is-implicit/Impls_1.scala
new file mode 100644
index 0000000000..0262485994
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-implicit/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[String]): c.Expr[Option[Int]] = {
+ import c.mirror._
+ val body = Apply(Ident(definitions.SomeModule), List(Select(x.tree, newTermName("toInt"))))
+ Expr[Option[Int]](body)
+ }
+}
diff --git a/test/files/run/macro-expand-implicit-macro-is-implicit/Macros_Test_2.scala b/test/files/run/macro-expand-implicit-macro-is-implicit/Macros_Test_2.scala
new file mode 100644
index 0000000000..81ebd63c5f
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-implicit/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+object Macros {
+ implicit def foo(x: String): Option[Int] = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ println("2": Option[Int])
+ val s: Int = "2" getOrElse 0
+ println(s)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-is-val.check b/test/files/run/macro-expand-implicit-macro-is-val.check
new file mode 100644
index 0000000000..78c6baefdd
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-val.check
@@ -0,0 +1 @@
+2
diff --git a/test/files/run/macro-expand-implicit-macro-is-val.flags b/test/files/run/macro-expand-implicit-macro-is-val.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-val.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-is-val/Impls_1.scala b/test/files/run/macro-expand-implicit-macro-is-val/Impls_1.scala
new file mode 100644
index 0000000000..510d8502f6
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-val/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.mirror._
+ val body = Literal(Constant(2))
+ Expr[Int](body)
+ }
+}
diff --git a/test/files/run/macro-expand-implicit-macro-is-val/Macros_Test_2.scala b/test/files/run/macro-expand-implicit-macro-is-val/Macros_Test_2.scala
new file mode 100644
index 0000000000..b91b1016c9
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-val/Macros_Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ implicit def foo = macro Impls.foo
+ def bar(implicit x: Int) = println(x)
+ bar
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-is-view.check b/test/files/run/macro-expand-implicit-macro-is-view.check
new file mode 100644
index 0000000000..78c6baefdd
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-view.check
@@ -0,0 +1 @@
+2
diff --git a/test/files/run/macro-expand-implicit-macro-is-view.flags b/test/files/run/macro-expand-implicit-macro-is-view.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-view.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-implicit-macro-is-view/Impls_1.scala b/test/files/run/macro-expand-implicit-macro-is-view/Impls_1.scala
new file mode 100644
index 0000000000..0262485994
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-view/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[String]): c.Expr[Option[Int]] = {
+ import c.mirror._
+ val body = Apply(Ident(definitions.SomeModule), List(Select(x.tree, newTermName("toInt"))))
+ Expr[Option[Int]](body)
+ }
+}
diff --git a/test/files/run/macro-expand-implicit-macro-is-view/Macros_Test_2.scala b/test/files/run/macro-expand-implicit-macro-is-view/Macros_Test_2.scala
new file mode 100644
index 0000000000..0ff1fb80ca
--- /dev/null
+++ b/test/files/run/macro-expand-implicit-macro-is-view/Macros_Test_2.scala
@@ -0,0 +1,9 @@
+object Macros {
+ implicit def foo(x: String): Option[Int] = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ def bar[T <% Option[Int]](x: T) = println(x)
+ println("2")
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-multiple-arglists.check b/test/files/run/macro-expand-multiple-arglists.check
new file mode 100644
index 0000000000..c24b6ae77d
--- /dev/null
+++ b/test/files/run/macro-expand-multiple-arglists.check
@@ -0,0 +1 @@
+38 \ No newline at end of file
diff --git a/test/files/run/macro-expand-multiple-arglists.flags b/test/files/run/macro-expand-multiple-arglists.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-multiple-arglists.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-multiple-arglists/Impls_1.scala b/test/files/run/macro-expand-multiple-arglists/Impls_1.scala
new file mode 100644
index 0000000000..ae1c50eace
--- /dev/null
+++ b/test/files/run/macro-expand-multiple-arglists/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int])(y: c.Expr[Int]) = {
+ import c.mirror._
+ val sum = Apply(Select(x.tree, newTermName("$minus")), List(y.tree))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(sum))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-multiple-arglists/Macros_Test_2.scala b/test/files/run/macro-expand-multiple-arglists/Macros_Test_2.scala
new file mode 100644
index 0000000000..fa4504b0ea
--- /dev/null
+++ b/test/files/run/macro-expand-multiple-arglists/Macros_Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo(x: Int)(y: Int) = macro Impls.foo
+ foo(40)(2)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-nullary-generic.check b/test/files/run/macro-expand-nullary-generic.check
new file mode 100644
index 0000000000..6dfe04af12
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-generic.check
@@ -0,0 +1,6 @@
+it works ConcreteTypeTag[Int]
+it works ConcreteTypeTag[Int]
+it works ConcreteTypeTag[Int]
+it works ConcreteTypeTag[Int]
+it works ConcreteTypeTag[Int]
+kkthxbai
diff --git a/test/files/run/macro-expand-nullary-generic.flags b/test/files/run/macro-expand-nullary-generic.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-generic.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-nullary-generic/Impls_1.scala b/test/files/run/macro-expand-nullary-generic/Impls_1.scala
new file mode 100644
index 0000000000..10352594f5
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-generic/Impls_1.scala
@@ -0,0 +1,14 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def impl[T: c.TypeTag](c: Ctx) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works " + implicitly[c.TypeTag[T]]))))
+ Expr[Unit](body)
+ }
+
+ def fooNullary[T: c.TypeTag](c: Ctx) = impl[T](c)
+ def fooEmpty[T: c.TypeTag](c: Ctx)() = impl[T](c)
+ def barNullary[T: c.TypeTag](c: Ctx)(x: c.Expr[Int]) = impl[T](c)
+ def barEmpty[T: c.TypeTag](c: Ctx)(x: c.Expr[Int])() = impl[T](c)
+}
diff --git a/test/files/run/macro-expand-nullary-generic/Macros_Test_2.scala b/test/files/run/macro-expand-nullary-generic/Macros_Test_2.scala
new file mode 100644
index 0000000000..2d5cf53c3c
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-generic/Macros_Test_2.scala
@@ -0,0 +1,15 @@
+object Macros {
+ def foo1[T] = macro Impls.fooNullary[T]
+ def foo2[T]() = macro Impls.fooEmpty[T]
+ def bar1[T](x: Int) = macro Impls.barNullary[T]
+ def bar2[T](x: Int)() = macro Impls.barEmpty[T]
+}
+
+object Test extends App {
+ Macros.foo1[Int]
+ Macros.foo2[Int]
+ Macros.foo2[Int]()
+ Macros.bar1[Int](42)
+ Macros.bar2[Int](42)()
+ println("kkthxbai")
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-nullary-nongeneric.check b/test/files/run/macro-expand-nullary-nongeneric.check
new file mode 100644
index 0000000000..9ab5f3a2bc
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-nongeneric.check
@@ -0,0 +1,6 @@
+it works
+it works
+it works
+it works
+it works
+kkthxbai
diff --git a/test/files/run/macro-expand-nullary-nongeneric.flags b/test/files/run/macro-expand-nullary-nongeneric.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-nongeneric.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-nullary-nongeneric/Impls_1.scala b/test/files/run/macro-expand-nullary-nongeneric/Impls_1.scala
new file mode 100644
index 0000000000..7dc58abba8
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-nongeneric/Impls_1.scala
@@ -0,0 +1,14 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def impl(c: Ctx) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))
+ Expr[Unit](body)
+ }
+
+ def fooNullary(c: Ctx) = impl(c)
+ def fooEmpty(c: Ctx)() = impl(c)
+ def barNullary(c: Ctx)(x: c.Expr[Int]) = impl(c)
+ def barEmpty(c: Ctx)(x: c.Expr[Int])() = impl(c)
+}
diff --git a/test/files/run/macro-expand-nullary-nongeneric/Macros_Test_2.scala b/test/files/run/macro-expand-nullary-nongeneric/Macros_Test_2.scala
new file mode 100644
index 0000000000..1f6d717956
--- /dev/null
+++ b/test/files/run/macro-expand-nullary-nongeneric/Macros_Test_2.scala
@@ -0,0 +1,15 @@
+object Macros {
+ def foo1 = macro Impls.fooNullary
+ def foo2() = macro Impls.fooEmpty
+ def bar1(x: Int) = macro Impls.barNullary
+ def bar2(x: Int)() = macro Impls.barEmpty
+}
+
+object Test extends App {
+ Macros.foo1
+ Macros.foo2
+ Macros.foo2()
+ Macros.bar1(42)
+ Macros.bar2(42)()
+ println("kkthxbai")
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-overload.check b/test/files/run/macro-expand-overload.check
new file mode 100644
index 0000000000..9d9989d85f
--- /dev/null
+++ b/test/files/run/macro-expand-overload.check
@@ -0,0 +1,6 @@
+(fooObjectString,Expr[Nothing](Macros),42)
+(fooObjectInt,Expr[Nothing](Macros),42)
+fooObjectBoolean
+(fooClassString,Expr[Nothing](new Macros()),42)
+(fooClassInt,Expr[Nothing](new Macros()),42)
+fooClassBoolean
diff --git a/test/files/run/macro-expand-overload.flags b/test/files/run/macro-expand-overload.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-overload.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-overload/Impls_1.scala b/test/files/run/macro-expand-overload/Impls_1.scala
new file mode 100644
index 0000000000..1dc4adc20e
--- /dev/null
+++ b/test/files/run/macro-expand-overload/Impls_1.scala
@@ -0,0 +1,15 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def impl(c: Ctx)(tag: String, x: c.Expr[_]) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(tag)), Literal(Constant(prefix.toString)), x.tree))
+ Expr[Unit](body)
+ }
+
+ def fooObjectString(c: Ctx)(x: c.Expr[_]) = impl(c)("fooObjectString", x)
+ def fooObjectInt(c: Ctx)(x: c.Expr[_]) = impl(c)("fooObjectInt", x)
+ def fooClassString(c: Ctx)(x: c.Expr[_]) = impl(c)("fooClassString", x)
+ def fooClassInt(c: Ctx)(x: c.Expr[_]) = impl(c)("fooClassInt", x)
+}
diff --git a/test/files/run/macro-expand-overload/Macros_Test_2.scala b/test/files/run/macro-expand-overload/Macros_Test_2.scala
new file mode 100644
index 0000000000..7f61f85184
--- /dev/null
+++ b/test/files/run/macro-expand-overload/Macros_Test_2.scala
@@ -0,0 +1,20 @@
+object Macros {
+ def foo(x: String) = macro Impls.fooObjectString
+ def foo(x: Int) = macro Impls.fooObjectInt
+ def foo(x: Boolean) = println("fooObjectBoolean")
+}
+
+class Macros {
+ def foo(x: String) = macro Impls.fooClassString
+ def foo(x: Int) = macro Impls.fooClassInt
+ def foo(x: Boolean) = println("fooClassBoolean")
+}
+
+object Test extends App {
+ Macros.foo("42")
+ Macros.foo(42)
+ Macros.foo(true)
+ new Macros().foo("42")
+ new Macros().foo(42)
+ new Macros().foo(true)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-override.check b/test/files/run/macro-expand-override.check
new file mode 100644
index 0000000000..486bec7098
--- /dev/null
+++ b/test/files/run/macro-expand-override.check
@@ -0,0 +1,15 @@
+(fooBString,Expr[Nothing](Test.this.dd),42)
+(fooDInt,Expr[Nothing](Test.this.dd),42)
+fooBBoolean
+(fooBString,Expr[Nothing](Test.this.db),42)
+(fooBInt,Expr[Nothing](Test.this.db),42)
+fooBBoolean
+(fooZString,Expr[Nothing](Test.this.zz),42)
+(fooDInt,Expr[Nothing](Test.this.zz),42)
+fooZBoolean
+(fooBString,Expr[Nothing](Test.this.zd),42)
+(fooDInt,Expr[Nothing](Test.this.zd),42)
+fooZBoolean
+(fooBString,Expr[Nothing](Test.this.zb),42)
+(fooBInt,Expr[Nothing](Test.this.zb),42)
+fooZBoolean
diff --git a/test/files/run/macro-expand-override.flags b/test/files/run/macro-expand-override.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-override.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-override/Impls_1.scala b/test/files/run/macro-expand-override/Impls_1.scala
new file mode 100644
index 0000000000..0b127f5a59
--- /dev/null
+++ b/test/files/run/macro-expand-override/Impls_1.scala
@@ -0,0 +1,15 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def impl(c: Ctx)(tag: String, x: c.Expr[_]) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(tag)), Literal(Constant(prefix.toString)), x.tree))
+ Expr[Unit](body)
+ }
+
+ def fooBString(c: Ctx)(x: c.Expr[_]) = impl(c)("fooBString", x)
+ def fooBInt(c: Ctx)(x: c.Expr[_]) = impl(c)("fooBInt", x)
+ def fooDInt(c: Ctx)(x: c.Expr[_]) = impl(c)("fooDInt", x)
+ def fooZString(c: Ctx)(x: c.Expr[_]) = impl(c)("fooZString", x)
+}
diff --git a/test/files/run/macro-expand-override/Macros_Test_2.scala b/test/files/run/macro-expand-override/Macros_Test_2.scala
new file mode 100644
index 0000000000..f162773c95
--- /dev/null
+++ b/test/files/run/macro-expand-override/Macros_Test_2.scala
@@ -0,0 +1,43 @@
+class B {
+ def foo(x: String) = macro Impls.fooBString
+ def foo(x: Int) = macro Impls.fooBInt
+ def foo(x: Boolean) = println("fooBBoolean")
+}
+
+class D extends B {
+ //override def foo(x: String) = println("fooDString") => method cannot override a macro
+ override def foo(x: Int) = macro Impls.fooDInt
+}
+
+class Z extends D {
+ override def foo(x: String) = macro Impls.fooZString
+ override def foo(x: Boolean) = println("fooZBoolean")
+}
+
+object Test extends App {
+
+ val dd: D = new D()
+ dd.foo("42")
+ dd.foo(42)
+ dd.foo(true)
+
+ val db: B = new D()
+ db.foo("42")
+ db.foo(42)
+ db.foo(true)
+
+ val zz: Z = new Z()
+ zz.foo("42")
+ zz.foo(42)
+ zz.foo(true)
+
+ val zd: D = new Z()
+ zd.foo("42")
+ zd.foo(42)
+ zd.foo(true)
+
+ val zb: B = new Z()
+ zb.foo("42")
+ zb.foo(42)
+ zb.foo(true)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-recursive.check b/test/files/run/macro-expand-recursive.check
new file mode 100644
index 0000000000..1ea14b4e20
--- /dev/null
+++ b/test/files/run/macro-expand-recursive.check
@@ -0,0 +1 @@
+it works
diff --git a/test/files/run/macro-expand-recursive.flags b/test/files/run/macro-expand-recursive.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-recursive.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-recursive/Impls_1.scala b/test/files/run/macro-expand-recursive/Impls_1.scala
new file mode 100644
index 0000000000..6eff805989
--- /dev/null
+++ b/test/files/run/macro-expand-recursive/Impls_1.scala
@@ -0,0 +1,15 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("it works"))))
+ Expr[Unit](body)
+ }
+
+ def fooFoo(c: Ctx) = {
+ import c.mirror._
+ val body = Select(Ident(newTermName("Macros")), newTermName("foo"))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-recursive/Macros_Test_2.scala b/test/files/run/macro-expand-recursive/Macros_Test_2.scala
new file mode 100644
index 0000000000..6ff691bdb1
--- /dev/null
+++ b/test/files/run/macro-expand-recursive/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo
+ def fooFoo = macro Impls.fooFoo
+}
+
+object Test extends App {
+ Macros.fooFoo
+} \ No newline at end of file
diff --git a/test/pending/run/t5271_1.check b/test/files/run/macro-expand-tparams-bounds-a.check
index e69de29bb2..e69de29bb2 100644
--- a/test/pending/run/t5271_1.check
+++ b/test/files/run/macro-expand-tparams-bounds-a.check
diff --git a/test/files/run/macro-expand-tparams-bounds-a.flags b/test/files/run/macro-expand-tparams-bounds-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-bounds-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-bounds-a/Impls_1.scala b/test/files/run/macro-expand-tparams-bounds-a/Impls_1.scala
new file mode 100644
index 0000000000..5019d5d4a7
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-bounds-a/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U <: String](c: Ctx): c.Expr[Unit] = c.literalUnit
+}
diff --git a/test/files/run/macro-expand-tparams-bounds-a/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-bounds-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..b498e6f65b
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-bounds-a/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo[U <: String] = macro Impls.foo[U]
+}
+
+object Test extends App {
+ import Macros._
+ foo[String]
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-bounds-b.check b/test/files/run/macro-expand-tparams-bounds-b.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-bounds-b.check
diff --git a/test/files/run/macro-expand-tparams-bounds-b.flags b/test/files/run/macro-expand-tparams-bounds-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-bounds-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-bounds-b/Impls_1.scala b/test/files/run/macro-expand-tparams-bounds-b/Impls_1.scala
new file mode 100644
index 0000000000..abd68696b6
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-bounds-b/Impls_1.scala
@@ -0,0 +1,7 @@
+import scala.reflect.makro.{Context => Ctx}
+
+class C
+
+object Impls {
+ def foo[U <: C](c: Ctx): c.Expr[Unit] = c.literalUnit
+}
diff --git a/test/files/run/macro-expand-tparams-bounds-b/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-bounds-b/Macros_Test_2.scala
new file mode 100644
index 0000000000..1a261e9f73
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-bounds-b/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+class D extends C
+
+object Macros {
+ def foo[T <: D] = macro Impls.foo[T]
+}
+
+object Test extends App {
+ import Macros._
+ foo[D]
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-explicit.check b/test/files/run/macro-expand-tparams-explicit.check
new file mode 100644
index 0000000000..5670e27c4e
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-explicit.check
@@ -0,0 +1 @@
+ConcreteTypeTag[Int]
diff --git a/test/files/run/macro-expand-tparams-explicit.flags b/test/files/run/macro-expand-tparams-explicit.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-explicit.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-explicit/Impls_1.scala b/test/files/run/macro-expand-tparams-explicit/Impls_1.scala
new file mode 100644
index 0000000000..957d8331fc
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-explicit/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U: c.TypeTag](c: Ctx) = {
+ import c.mirror._
+ val U = implicitly[c.TypeTag[U]]
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(U.toString))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-explicit/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-explicit/Macros_Test_2.scala
new file mode 100644
index 0000000000..e72c27881a
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-explicit/Macros_Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo[U] = macro Impls.foo[U]
+ foo[Int]
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-implicit.check b/test/files/run/macro-expand-tparams-implicit.check
new file mode 100644
index 0000000000..e57fc1217b
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-implicit.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[String]
diff --git a/test/files/run/macro-expand-tparams-implicit.flags b/test/files/run/macro-expand-tparams-implicit.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-implicit.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-implicit/Impls_1.scala b/test/files/run/macro-expand-tparams-implicit/Impls_1.scala
new file mode 100644
index 0000000000..c25d12be60
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-implicit/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U: c.TypeTag](c: Ctx)(x: c.Expr[U]) = {
+ import c.mirror._
+ val U = implicitly[c.TypeTag[U]]
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(U.toString))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-implicit/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-implicit/Macros_Test_2.scala
new file mode 100644
index 0000000000..f8c573f509
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-implicit/Macros_Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ def foo[U](x: U) = macro Impls.foo[U]
+ foo(42)
+ foo("42")
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-only-in-impl.flags b/test/files/run/macro-expand-tparams-only-in-impl.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-only-in-impl.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-only-in-impl/Impls_1.scala b/test/files/run/macro-expand-tparams-only-in-impl/Impls_1.scala
new file mode 100644
index 0000000000..5019d5d4a7
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-only-in-impl/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U <: String](c: Ctx): c.Expr[Unit] = c.literalUnit
+}
diff --git a/test/files/run/macro-expand-tparams-only-in-impl/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-only-in-impl/Macros_Test_2.scala
new file mode 100644
index 0000000000..218c7aec7f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-only-in-impl/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo = macro Impls.foo[String]
+}
+
+object Test extends App {
+ import Macros._
+ foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-optional.check b/test/files/run/macro-expand-tparams-optional.check
new file mode 100644
index 0000000000..3bacd7a4e0
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-optional.check
@@ -0,0 +1 @@
+don't know U
diff --git a/test/files/run/macro-expand-tparams-optional.flags b/test/files/run/macro-expand-tparams-optional.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-optional.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-optional/Impls_1.scala b/test/files/run/macro-expand-tparams-optional/Impls_1.scala
new file mode 100644
index 0000000000..37efb009c4
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-optional/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U](c: Ctx) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("don't know U"))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-optional/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-optional/Macros_Test_2.scala
new file mode 100644
index 0000000000..e72c27881a
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-optional/Macros_Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo[U] = macro Impls.foo[U]
+ foo[Int]
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-a.check b/test/files/run/macro-expand-tparams-prefix-a.check
new file mode 100644
index 0000000000..922be1a6dd
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-a.check
@@ -0,0 +1,4 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[Int]
+ConcreteTypeTag[String]
+ConcreteTypeTag[Boolean]
diff --git a/test/files/run/macro-expand-tparams-prefix-a.flags b/test/files/run/macro-expand-tparams-prefix-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-a/Impls_1.scala b/test/files/run/macro-expand-tparams-prefix-a/Impls_1.scala
new file mode 100644
index 0000000000..c25d12be60
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-a/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U: c.TypeTag](c: Ctx)(x: c.Expr[U]) = {
+ import c.mirror._
+ val U = implicitly[c.TypeTag[U]]
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(U.toString))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-prefix-a/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-prefix-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..81ccb7ff42
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-a/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ class C[T] {
+ def foo[U](x: U) = macro Impls.foo[U]
+ }
+
+ new C[Int]().foo(42)
+ new C[Boolean]().foo(42)
+ new C[Int]().foo("42")
+ new C[String]().foo(true)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-b.check b/test/files/run/macro-expand-tparams-prefix-b.check
new file mode 100644
index 0000000000..a336bb51ec
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-b.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Boolean] ConcreteTypeTag[Int]
+ConcreteTypeTag[Boolean] ConcreteTypeTag[String]
diff --git a/test/files/run/macro-expand-tparams-prefix-b.flags b/test/files/run/macro-expand-tparams-prefix-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-b/Impls_1.scala b/test/files/run/macro-expand-tparams-prefix-b/Impls_1.scala
new file mode 100644
index 0000000000..8af3ecc9ae
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-b/Impls_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T: c.TypeTag, U: c.TypeTag](c: Ctx)(x: c.Expr[U]) = {
+ import c.mirror._
+ val T = implicitly[c.TypeTag[T]]
+ val U = implicitly[c.TypeTag[U]]
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(T.toString + " " + U.toString))))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-prefix-b/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-prefix-b/Macros_Test_2.scala
new file mode 100644
index 0000000000..a4a0acfe8b
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-b/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ class C[T] {
+ def foo[U](x: U) = macro Impls.foo[T, U]
+ }
+
+ object D extends C[Boolean]
+
+ D.foo(42)
+ D.foo("42")
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-c1.check b/test/files/run/macro-expand-tparams-prefix-c1.check
new file mode 100644
index 0000000000..87f295aa49
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c1.check
@@ -0,0 +1,3 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[String]
+ConcreteTypeTag[Boolean]
diff --git a/test/files/run/macro-expand-tparams-prefix-c1.flags b/test/files/run/macro-expand-tparams-prefix-c1.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c1.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-c1/Impls_1.scala b/test/files/run/macro-expand-tparams-prefix-c1/Impls_1.scala
new file mode 100644
index 0000000000..4da5a9b823
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c1/Impls_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T, U: c.TypeTag, V](c: Ctx)(implicit T: c.TypeTag[T], V: c.TypeTag[V]): c.Expr[Unit] = {
+ import c.mirror._
+ Expr(Block(List(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(T.toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(implicitly[c.TypeTag[U]].toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(V.toString))))),
+ Literal(Constant(()))))
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-prefix-c1/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-prefix-c1/Macros_Test_2.scala
new file mode 100644
index 0000000000..4fa0c8cb33
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c1/Macros_Test_2.scala
@@ -0,0 +1,11 @@
+class D[T] {
+ class C[U] {
+ def foo[V] = macro Impls.foo[T, U, V]
+ }
+}
+
+object Test extends App {
+ val outer1 = new D[Int]
+ val outer2 = new outer1.C[String]
+ outer2.foo[Boolean]
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-c2.check b/test/files/run/macro-expand-tparams-prefix-c2.check
new file mode 100644
index 0000000000..87f295aa49
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c2.check
@@ -0,0 +1,3 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[String]
+ConcreteTypeTag[Boolean]
diff --git a/test/files/run/macro-expand-tparams-prefix-c2.flags b/test/files/run/macro-expand-tparams-prefix-c2.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c2.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-c2/Impls_Macros_1.scala b/test/files/run/macro-expand-tparams-prefix-c2/Impls_Macros_1.scala
new file mode 100644
index 0000000000..4d137a4aef
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c2/Impls_Macros_1.scala
@@ -0,0 +1,18 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T, U: c.TypeTag, V](c: Ctx)(implicit T: c.TypeTag[T], V: c.TypeTag[V]): c.Expr[Unit] = {
+ import c.mirror._
+ Expr(Block(List(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(T.toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(implicitly[c.TypeTag[U]].toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(V.toString))))),
+ Literal(Constant(()))))
+ }
+}
+
+class D[T] {
+ class C[U] {
+ def foo[V] = macro Impls.foo[T, U, V]
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-prefix-c2/Test_2.scala b/test/files/run/macro-expand-tparams-prefix-c2/Test_2.scala
new file mode 100644
index 0000000000..e729d4a536
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-c2/Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ val outer1 = new D[Int]
+ val outer2 = new outer1.C[String]
+ outer2.foo[Boolean]
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-d1.check b/test/files/run/macro-expand-tparams-prefix-d1.check
new file mode 100644
index 0000000000..ca7a220475
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-d1.check
@@ -0,0 +1,3 @@
+TypeTag[T]
+TypeTag[U]
+ConcreteTypeTag[Boolean]
diff --git a/test/files/run/macro-expand-tparams-prefix-d1.flags b/test/files/run/macro-expand-tparams-prefix-d1.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-d1.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-tparams-prefix-d1/Impls_1.scala b/test/files/run/macro-expand-tparams-prefix-d1/Impls_1.scala
new file mode 100644
index 0000000000..4da5a9b823
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-d1/Impls_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T, U: c.TypeTag, V](c: Ctx)(implicit T: c.TypeTag[T], V: c.TypeTag[V]): c.Expr[Unit] = {
+ import c.mirror._
+ Expr(Block(List(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(T.toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(implicitly[c.TypeTag[U]].toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(V.toString))))),
+ Literal(Constant(()))))
+ }
+}
diff --git a/test/files/run/macro-expand-tparams-prefix-d1/Macros_Test_2.scala b/test/files/run/macro-expand-tparams-prefix-d1/Macros_Test_2.scala
new file mode 100644
index 0000000000..8222a6d1e8
--- /dev/null
+++ b/test/files/run/macro-expand-tparams-prefix-d1/Macros_Test_2.scala
@@ -0,0 +1,11 @@
+object Test extends App {
+ class D[T] {
+ class C[U] {
+ def foo[V] = macro Impls.foo[T, U, V]
+ foo[Boolean]
+ }
+ }
+
+ val outer1 = new D[Int]
+ new outer1.C[String]
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.check b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.check
new file mode 100644
index 0000000000..fd1d654cf8
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.check
@@ -0,0 +1,4 @@
+reflective compilation has failed:
+
+no `: _*' annotation allowed here
+(such annotations are only allowed in arguments to *-parameters)
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.flags b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Impls_1.scala b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Impls_1.scala
new file mode 100644
index 0000000000..d97f0af786
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(xs: c.Expr[Int]*) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), xs.map(_.tree).toList)
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala
new file mode 100644
index 0000000000..01fc9d4462
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-bad/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+object Macros {
+ def foo(xs: Int*) = macro Impls.foo
+}
+
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Typed(Apply(Ident(definitions.ListModule), List(Literal(Constant(1)), Literal(Constant(2)))), Ident(tpnme.WILDCARD_STAR))))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.check b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.check
new file mode 100644
index 0000000000..835137b4a2
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.check
@@ -0,0 +1 @@
+List(1, 2, 3, 4, 5)
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.flags b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Impls_1.scala b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Impls_1.scala
new file mode 100644
index 0000000000..f9667d78b8
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Impls_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(xs: c.Expr[Int]*) = {
+ import c.mirror._
+ val stripped_xs = xs map (_.tree) toList match {
+ case List(Typed(stripped, Ident(wildstar))) if wildstar == tpnme.WILDCARD_STAR => List(stripped)
+ case _ => ???
+ }
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), stripped_xs)
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Macros_Test_2.scala b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Macros_Test_2.scala
new file mode 100644
index 0000000000..f127ebcde7
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-nonvarargs-good/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(xs: Int*) = macro Impls.foo
+}
+
+object Test extends App {
+ val numbers = List(1, 2, 3, 4, 5)
+ Macros.foo(numbers: _*)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-explicit-over-varargs.check b/test/files/run/macro-expand-varargs-explicit-over-varargs.check
new file mode 100644
index 0000000000..835137b4a2
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-varargs.check
@@ -0,0 +1 @@
+List(1, 2, 3, 4, 5)
diff --git a/test/files/run/macro-expand-varargs-explicit-over-varargs.flags b/test/files/run/macro-expand-varargs-explicit-over-varargs.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-varargs.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-explicit-over-varargs/Impls_1.scala b/test/files/run/macro-expand-varargs-explicit-over-varargs/Impls_1.scala
new file mode 100644
index 0000000000..8c609daa0e
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-varargs/Impls_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def myprintln(xs: Int*) = {
+ println(xs)
+ }
+
+ def foo(c: Ctx)(xs: c.Expr[Int]*) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(newTermName("Impls")), newTermName("myprintln")), xs.map(_.tree).toList)
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-varargs-explicit-over-varargs/Macros_Test_2.scala b/test/files/run/macro-expand-varargs-explicit-over-varargs/Macros_Test_2.scala
new file mode 100644
index 0000000000..f127ebcde7
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-explicit-over-varargs/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Macros {
+ def foo(xs: Int*) = macro Impls.foo
+}
+
+object Test extends App {
+ val numbers = List(1, 2, 3, 4, 5)
+ Macros.foo(numbers: _*)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-implicit-over-nonvarargs.check b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs.check
new file mode 100644
index 0000000000..0a6596858c
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs.check
@@ -0,0 +1 @@
+(1,2,3,4,5)
diff --git a/test/files/run/macro-expand-varargs-implicit-over-nonvarargs.flags b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Impls_1.scala b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Impls_1.scala
new file mode 100644
index 0000000000..d97f0af786
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(xs: c.Expr[Int]*) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), xs.map(_.tree).toList)
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Macros_Test_2.scala b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Macros_Test_2.scala
new file mode 100644
index 0000000000..2311ca0b95
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-nonvarargs/Macros_Test_2.scala
@@ -0,0 +1,7 @@
+object Macros {
+ def foo(xs: Int*) = macro Impls.foo
+}
+
+object Test extends App {
+ Macros.foo(1, 2, 3, 4, 5)
+} \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-implicit-over-varargs.check b/test/files/run/macro-expand-varargs-implicit-over-varargs.check
new file mode 100644
index 0000000000..f25fa141d3
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-varargs.check
@@ -0,0 +1 @@
+WrappedArray(1, 2, 3, 4, 5)
diff --git a/test/files/run/macro-expand-varargs-implicit-over-varargs.flags b/test/files/run/macro-expand-varargs-implicit-over-varargs.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-varargs.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-expand-varargs-implicit-over-varargs/Impls_1.scala b/test/files/run/macro-expand-varargs-implicit-over-varargs/Impls_1.scala
new file mode 100644
index 0000000000..8c609daa0e
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-varargs/Impls_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def myprintln(xs: Int*) = {
+ println(xs)
+ }
+
+ def foo(c: Ctx)(xs: c.Expr[Int]*) = {
+ import c.mirror._
+ val body = Apply(Select(Ident(newTermName("Impls")), newTermName("myprintln")), xs.map(_.tree).toList)
+ Expr[Unit](body)
+ }
+}
diff --git a/test/files/run/macro-expand-varargs-implicit-over-varargs/Macros_Test_2.scala b/test/files/run/macro-expand-varargs-implicit-over-varargs/Macros_Test_2.scala
new file mode 100644
index 0000000000..2311ca0b95
--- /dev/null
+++ b/test/files/run/macro-expand-varargs-implicit-over-varargs/Macros_Test_2.scala
@@ -0,0 +1,7 @@
+object Macros {
+ def foo(xs: Int*) = macro Impls.foo
+}
+
+object Test extends App {
+ Macros.foo(1, 2, 3, 4, 5)
+} \ No newline at end of file
diff --git a/test/files/run/macro-impl-default-params.check b/test/files/run/macro-impl-default-params.check
new file mode 100644
index 0000000000..eaf94458e6
--- /dev/null
+++ b/test/files/run/macro-impl-default-params.check
@@ -0,0 +1,5 @@
+foo_targs:
+invoking foo_targs...
+type of prefix is: Nothing
+type of prefix tree is: Macros[Int]
+U is: String
diff --git a/test/files/run/macro-impl-default-params.flags b/test/files/run/macro-impl-default-params.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-impl-default-params.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-impl-default-params/Impls_Macros_1.scala b/test/files/run/macro-impl-default-params/Impls_Macros_1.scala
new file mode 100644
index 0000000000..cece1c09e4
--- /dev/null
+++ b/test/files/run/macro-impl-default-params/Impls_Macros_1.scala
@@ -0,0 +1,20 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo_targs[T, U: c.TypeTag](c: Ctx = null)(x: c.Expr[Int] = null) = {
+ import c.{prefix => prefix}
+ import c.mirror._
+ val U = implicitly[c.TypeTag[U]]
+ val body = Block(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("invoking foo_targs...")))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("type of prefix is: " + prefix.tpe)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("type of prefix tree is: " + prefix.tree.tpe)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("U is: " + U.tpe)))),
+ Literal(Constant(())))
+ Expr[Unit](body)
+ }
+}
+
+class Macros[T] {
+ def foo_targs[U](x: Int) = macro Impls.foo_targs[T, U]
+}
diff --git a/test/files/run/macro-impl-default-params/Test_2.scala b/test/files/run/macro-impl-default-params/Test_2.scala
new file mode 100644
index 0000000000..90e850df21
--- /dev/null
+++ b/test/files/run/macro-impl-default-params/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println("foo_targs:")
+ new Macros[Int]().foo_targs[String](42)
+} \ No newline at end of file
diff --git a/test/files/run/macro-impl-rename-context.check b/test/files/run/macro-impl-rename-context.check
new file mode 100644
index 0000000000..753edcd970
--- /dev/null
+++ b/test/files/run/macro-impl-rename-context.check
@@ -0,0 +1,2 @@
+foo
+invoking foo...
diff --git a/test/files/run/macro-impl-rename-context.flags b/test/files/run/macro-impl-rename-context.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-impl-rename-context.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-impl-rename-context/Impls_Macros_1.scala b/test/files/run/macro-impl-rename-context/Impls_Macros_1.scala
new file mode 100644
index 0000000000..000e351f4d
--- /dev/null
+++ b/test/files/run/macro-impl-rename-context/Impls_Macros_1.scala
@@ -0,0 +1,15 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(unconventionalName: Ctx)(x: unconventionalName.Expr[Int]) = {
+ import unconventionalName.mirror._
+ val body = Block(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant("invoking foo...")))),
+ Literal(Constant(())))
+ Expr[Unit](body)
+ }
+}
+
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
diff --git a/test/files/run/macro-impl-rename-context/Test_2.scala b/test/files/run/macro-impl-rename-context/Test_2.scala
new file mode 100644
index 0000000000..bd9c493544
--- /dev/null
+++ b/test/files/run/macro-impl-rename-context/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println("foo")
+ Macros.foo(42)
+} \ No newline at end of file
diff --git a/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.check b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.check
new file mode 100644
index 0000000000..e21e05157a
--- /dev/null
+++ b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.check
@@ -0,0 +1,5 @@
+reflective compilation has failed:
+
+type mismatch;
+ found : String("42")
+ required: Int
diff --git a/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.flags b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Impls_Macros_1.scala b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Impls_Macros_1.scala
new file mode 100644
index 0000000000..828ccf34e2
--- /dev/null
+++ b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Impls_Macros_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx): c.Expr[Int] = {
+ import c.mirror._
+ Expr(Literal(Constant("42")))
+ }
+}
+
+object Macros {
+ def foo: Int = macro Impls.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala
new file mode 100644
index 0000000000..ecf48b9752
--- /dev/null
+++ b/test/files/run/macro-invalidret-doesnt-conform-to-def-rettype/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Select(Ident("Macros"), newTermName("foo"))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+} \ No newline at end of file
diff --git a/test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.check b/test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.check
diff --git a/test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.flags b/test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-invalidret-doesnt-conform-to-impl-rettype.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-invalidret-nontypeable.check b/test/files/run/macro-invalidret-nontypeable.check
new file mode 100644
index 0000000000..eee08528e2
--- /dev/null
+++ b/test/files/run/macro-invalidret-nontypeable.check
@@ -0,0 +1,3 @@
+reflective compilation has failed:
+
+not found: value IDoNotExist
diff --git a/test/files/run/macro-invalidret-nontypeable.flags b/test/files/run/macro-invalidret-nontypeable.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-invalidret-nontypeable.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala b/test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala
new file mode 100644
index 0000000000..f3a0476a35
--- /dev/null
+++ b/test/files/run/macro-invalidret-nontypeable/Impls_Macros_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx) = {
+ import c.mirror._
+ val body = Ident("IDoNotExist")
+ Expr[Int](body)
+ }
+}
+
+object Macros {
+ def foo = macro Impls.foo
+}
diff --git a/test/files/run/macro-invalidret-nontypeable/Test_2.scala b/test/files/run/macro-invalidret-nontypeable/Test_2.scala
new file mode 100644
index 0000000000..ecf48b9752
--- /dev/null
+++ b/test/files/run/macro-invalidret-nontypeable/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Select(Ident("Macros"), newTermName("foo"))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+} \ No newline at end of file
diff --git a/test/files/run/macro-invalidusage-badret.check b/test/files/run/macro-invalidusage-badret.check
new file mode 100644
index 0000000000..5bdc484644
--- /dev/null
+++ b/test/files/run/macro-invalidusage-badret.check
@@ -0,0 +1,5 @@
+reflective compilation has failed:
+
+type mismatch;
+ found : Int(42)
+ required: String
diff --git a/test/files/run/macro-invalidusage-badret.flags b/test/files/run/macro-invalidusage-badret.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-invalidusage-badret.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-invalidusage-badret/Impls_Macros_1.scala b/test/files/run/macro-invalidusage-badret/Impls_Macros_1.scala
new file mode 100644
index 0000000000..c63ad01677
--- /dev/null
+++ b/test/files/run/macro-invalidusage-badret/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = x
+}
+
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
diff --git a/test/files/run/macro-invalidusage-badret/Test_2.scala b/test/files/run/macro-invalidusage-badret/Test_2.scala
new file mode 100644
index 0000000000..aeb3c26eaa
--- /dev/null
+++ b/test/files/run/macro-invalidusage-badret/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Typed(Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42)))), Ident(newTypeName("String")))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+} \ No newline at end of file
diff --git a/test/files/run/macro-invalidusage-partialapplication.check b/test/files/run/macro-invalidusage-partialapplication.check
new file mode 100644
index 0000000000..73f57b0b81
--- /dev/null
+++ b/test/files/run/macro-invalidusage-partialapplication.check
@@ -0,0 +1,3 @@
+reflective compilation has failed:
+
+macros cannot be partially applied
diff --git a/test/files/run/macro-invalidusage-partialapplication.flags b/test/files/run/macro-invalidusage-partialapplication.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-invalidusage-partialapplication.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-invalidusage-partialapplication/Impls_Macros_1.scala b/test/files/run/macro-invalidusage-partialapplication/Impls_Macros_1.scala
new file mode 100644
index 0000000000..449b91d074
--- /dev/null
+++ b/test/files/run/macro-invalidusage-partialapplication/Impls_Macros_1.scala
@@ -0,0 +1,14 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int])(y: c.Expr[Int]) = {
+ import c.mirror._
+ val sum = Apply(Select(x.tree, newTermName("$plus")), List(y.tree))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(sum))
+ Expr[Unit](body)
+ }
+}
+
+object Macros {
+ def foo(x: Int)(y: Int) = macro Impls.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-invalidusage-partialapplication/Test_2.scala b/test/files/run/macro-invalidusage-partialapplication/Test_2.scala
new file mode 100644
index 0000000000..293d906048
--- /dev/null
+++ b/test/files/run/macro-invalidusage-partialapplication/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(40))))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+}
diff --git a/test/files/run/macro-openmacros.check b/test/files/run/macro-openmacros.check
new file mode 100644
index 0000000000..a4b06a1e1a
--- /dev/null
+++ b/test/files/run/macro-openmacros.check
@@ -0,0 +1,3 @@
+List(MacroContext(foo@source-Test_2.scala,line-2,offset=35 +0))
+List(MacroContext(foo@source-Test_2.scala,line-2,offset=35 +1), MacroContext(foo@source-Test_2.scala,line-2,offset=35 +0))
+List(MacroContext(foo@source-Test_2.scala,line-2,offset=35 +2), MacroContext(foo@source-Test_2.scala,line-2,offset=35 +1), MacroContext(foo@source-Test_2.scala,line-2,offset=35 +0))
diff --git a/test/files/run/macro-openmacros.flags b/test/files/run/macro-openmacros.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-openmacros.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-openmacros/Impls_Macros_1.scala b/test/files/run/macro-openmacros/Impls_Macros_1.scala
new file mode 100644
index 0000000000..9fd658656e
--- /dev/null
+++ b/test/files/run/macro-openmacros/Impls_Macros_1.scala
@@ -0,0 +1,26 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl(c: Context): c.Expr[Unit] = {
+ // we're macros, so we can reflect against our source path
+ // so we don't need any partests to clean up after us!
+ val c.CompilationUnit(file, _, _) = c.enclosingUnit
+ val dir = file.getParentFile
+ def normalizePaths(s: String) = {
+ val base = (dir.getCanonicalPath + java.io.File.separator).replace('\\', '/')
+ var regex = """\Q%s\E""" format base
+ val isWin = System.getProperty("os.name", "") startsWith "Windows"
+ if (isWin) regex = "(?i)" + regex
+ s.replace('\\', '/').replaceAll(regex, "")
+ }
+
+ import c.mirror._
+ val next = if (c.enclosingMacros.length < 3) Expr[Unit](Select(Ident(staticModule("Macros")), newTermName("foo"))) else c.literalUnit
+ c.reify {
+ println(c.literal(normalizePaths(c.enclosingMacros.toString)).eval)
+ next.eval
+ }
+ }
+
+ def foo = macro impl
+} \ No newline at end of file
diff --git a/test/files/run/macro-openmacros/Test_2.scala b/test/files/run/macro-openmacros/Test_2.scala
new file mode 100644
index 0000000000..5d19639cdd
--- /dev/null
+++ b/test/files/run/macro-openmacros/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ Macros.foo
+}
diff --git a/test/files/run/macro-quasiinvalidbody-c.check b/test/files/run/macro-quasiinvalidbody-c.check
new file mode 100644
index 0000000000..f70d7bba4a
--- /dev/null
+++ b/test/files/run/macro-quasiinvalidbody-c.check
@@ -0,0 +1 @@
+42 \ No newline at end of file
diff --git a/test/files/run/macro-quasiinvalidbody-c.flags b/test/files/run/macro-quasiinvalidbody-c.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-quasiinvalidbody-c.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-quasiinvalidbody-c/Impls_Macros_1.scala b/test/files/run/macro-quasiinvalidbody-c/Impls_Macros_1.scala
new file mode 100644
index 0000000000..7cb810c86b
--- /dev/null
+++ b/test/files/run/macro-quasiinvalidbody-c/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = x
+ }
+
+ def foo(x: Any) = macro Impls.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-quasiinvalidbody-c/Test_2.scala b/test/files/run/macro-quasiinvalidbody-c/Test_2.scala
new file mode 100644
index 0000000000..dec29aa857
--- /dev/null
+++ b/test/files/run/macro-quasiinvalidbody-c/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ import Macros._
+ println(foo(42))
+} \ No newline at end of file
diff --git a/test/files/run/macro-range.flags b/test/files/run/macro-range.flags
index 06a7b31f11..5e5dd6ce79 100644
--- a/test/files/run/macro-range.flags
+++ b/test/files/run/macro-range.flags
@@ -1 +1 @@
--Xmacros
+-language:experimental.macros
diff --git a/test/files/run/macro-range/Common_1.scala b/test/files/run/macro-range/Common_1.scala
new file mode 100644
index 0000000000..bd46e1f529
--- /dev/null
+++ b/test/files/run/macro-range/Common_1.scala
@@ -0,0 +1,48 @@
+import reflect.api.Modifier
+import reflect.makro.Context
+
+abstract class RangeDefault {
+ val from, to: Int
+ def foreach(f: Int => Unit) = {
+ var i = from
+ while (i < to) { f(i); i += 1 }
+ }
+}
+
+/** This class should go into reflect.macro once it is a bit more stable. */
+abstract class Utils {
+ val context: Context
+ import context.mirror._
+
+ class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer {
+ override def transform(tree: Tree): Tree = tree match {
+ case Ident(_) =>
+ def subst(from: List[Symbol], to: List[Tree]): Tree =
+ if (from.isEmpty) tree
+ else if (tree.symbol == from.head) to.head.duplicate // TODO: does it ever make sense *not* to perform a shallowDuplicate on `to.head`?
+ else subst(from.tail, to.tail);
+ subst(from, to)
+ case _ =>
+ val tree1 = super.transform(tree)
+ if (tree1 ne tree) tree1.tpe = null
+ tree1
+ }
+ }
+ def makeApply(fn: Tree, args: List[Tree]): Tree = fn match {
+ case Function(vparams, body) =>
+ new TreeSubstituter(vparams map (_.symbol), args) transform body
+ case Block(stats, expr) =>
+ Block(stats, makeApply(expr, args))
+ case _ =>
+ // todo. read the compiler config and print if -Ydebug is set
+ //println("no beta on "+fn+" "+fn.getClass)
+ Apply(fn, args)
+ }
+ def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = {
+ val continu = Apply(Ident(lname), Nil)
+ val rhs = If(cond, Block(List(body), continu), Literal(Constant()))
+ LabelDef(lname, Nil, rhs)
+ }
+ def makeBinop(left: Tree, op: String, right: Tree): Tree =
+ Apply(Select(left, newTermName(op)), List(right))
+}
diff --git a/test/files/run/macro-range/Expansion_Impossible_2.scala b/test/files/run/macro-range/Expansion_Impossible_2.scala
new file mode 100644
index 0000000000..051afff99c
--- /dev/null
+++ b/test/files/run/macro-range/Expansion_Impossible_2.scala
@@ -0,0 +1,53 @@
+import reflect.api.Modifier
+import reflect.makro.Context
+
+object Impls {
+ def foreach(c: Context)(f: c.Expr[Int => Unit]): c.Expr[Unit] = {
+ // todo. read the compiler config and print if -Ydebug is set
+ //println("macro-expand, _this = "+ _this)
+ object utils extends Utils { val context: c.type = c }
+ import utils._
+ import c.mirror._
+
+ val initName = newTermName("<init>")
+ // Either:
+ // scala"{ var i = $low; val h = $hi; while (i < h) { $f(i); i = i + 1 } }
+ // or:
+ // scala"($_this: RangeDefault).foreach($f)"
+ Expr(c.prefix.tree match {
+ case Apply(Select(New(tpt), initName), List(lo, hi)) if tpt.symbol.fullName == "Range" =>
+ val iname = newTermName("$i")
+ val hname = newTermName("$h")
+ def iref = Ident(iname)
+ def href = Ident(hname)
+ val labelname = newTermName("$while")
+ val cond = makeBinop(iref, "$less", href)
+ val body = Block(
+ List(makeApply(f.tree, List(iref))),
+ Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1)))))
+ val generated =
+ Block(
+ List(
+ ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo),
+ ValDef(Modifiers(), hname, TypeTree(), hi)),
+ makeWhile(labelname, cond, body))
+ // todo. read the compiler config and print if -Ydebug is set
+ //tools.nsc.util.trace("generated: ")(generated)
+ generated
+ case _ =>
+ Apply(
+ Select(
+ Typed(c.prefix.tree, Ident(newTypeName("RangeDefault"))),
+ newTermName("foreach")),
+ List(f.tree))
+ })
+ }
+}
+
+class Range(val from: Int, val to: Int) extends RangeDefault {
+ override def foreach(f: Int => Unit): Unit = macro Impls.foreach
+}
+
+object Test extends App {
+ new Range(1, 10) foreach println
+} \ No newline at end of file
diff --git a/test/files/run/macro-range/Expansion_Possible_3.scala b/test/files/run/macro-range/Expansion_Possible_3.scala
new file mode 100644
index 0000000000..e7ecbcc362
--- /dev/null
+++ b/test/files/run/macro-range/Expansion_Possible_3.scala
@@ -0,0 +1,7 @@
+class Range(val from: Int, val to: Int) extends RangeDefault {
+ override def foreach(f: Int => Unit): Unit = macro Impls.foreach
+}
+
+object Test extends App {
+ new Range(1, 10) foreach println
+} \ No newline at end of file
diff --git a/test/files/run/macro-range/macro_range_1.scala b/test/files/run/macro-range/macro_range_1.scala
deleted file mode 100644
index fdfe7169ad..0000000000
--- a/test/files/run/macro-range/macro_range_1.scala
+++ /dev/null
@@ -1,99 +0,0 @@
-import reflect.api.Modifier
-import reflect.macro.Context
-
-abstract class RangeDefault {
- val from, to: Int
- def foreach(f: Int => Unit) = {
- var i = from
- while (i < to) { f(i); i += 1 }
- }
-}
-
-/** This class should go into reflect.macro once it is a bit more stable. */
-abstract class Utils {
- val context: Context
- import context._
-
- class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer {
- override def transform(tree: Tree): Tree = tree match {
- case Ident(_) =>
- def subst(from: List[Symbol], to: List[Tree]): Tree =
- if (from.isEmpty) tree
- else if (tree.symbol == from.head) to.head.duplicate // TODO: does it ever make sense *not* to perform a shallowDuplicate on `to.head`?
- else subst(from.tail, to.tail);
- subst(from, to)
- case _ =>
- val tree1 = super.transform(tree)
- if (tree1 ne tree) tree1.tpe = null
- tree1
- }
- }
- def makeApply(fn: Tree, args: List[Tree]): Tree = fn match {
- case Function(vparams, body) =>
- new TreeSubstituter(vparams map (_.symbol), args) transform body
- case Block(stats, expr) =>
- Block(stats, makeApply(expr, args))
- case _ =>
- // todo. read the compiler config and print if -Ydebug is set
- //println("no beta on "+fn+" "+fn.getClass)
- Apply(fn, args)
- }
- def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = {
- val continu = Apply(Ident(lname), Nil)
- val rhs = If(cond, Block(List(body), continu), Literal(Constant()))
- LabelDef(lname, Nil, rhs)
- }
- def makeBinop(left: Tree, op: String, right: Tree): Tree =
- Apply(Select(left, newTermName(op)), List(right))
-}
-
-class Range(val from: Int, val to: Int) extends RangeDefault {
- override def macro foreach(f: Int => Unit): Unit = {
- // todo. read the compiler config and print if -Ydebug is set
- //println("macro-expand, _this = "+ _this)
- import _context._
- object utils extends Utils {
- val context: _context.type = _context
- }
- import utils._
-
- val initName = newTermName("<init>")
- // Either:
- // scala"{ var i = $low; val h = $hi; while (i < h) { $f(i); i = i + 1 } }
- // or:
- // scala"($_this: RangeDefault).foreach($f)"
- _this match {
- case Apply(Select(New(tpt), initName), List(lo, hi)) if tpt.symbol.fullName == "Range" =>
- val iname = newTermName("$i")
- val hname = newTermName("$h")
- def iref = Ident(iname)
- def href = Ident(hname)
- val labelname = newTermName("$while")
- val cond = makeBinop(iref, "$less", href)
- val body = Block(
- List(makeApply(f, List(iref))),
- Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1)))))
- val generated =
- Block(
- List(
- ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo),
- ValDef(Modifiers(), hname, TypeTree(), hi)),
- makeWhile(labelname, cond, body))
- // todo. read the compiler config and print if -Ydebug is set
- //tools.nsc.util.trace("generated: ")(generated)
- generated
- case _ =>
- Apply(
- Select(
- Typed(_this, Ident(newTypeName("RangeDefault"))),
- newTermName("foreach")),
- List(f))
- }
- }
-}
-
-object Test extends App {
-
- new Range(1, 10) foreach println
-
-}
diff --git a/test/files/run/macro-range/macro_range_2.scala b/test/files/run/macro-range/macro_range_2.scala
deleted file mode 100644
index fdfe7169ad..0000000000
--- a/test/files/run/macro-range/macro_range_2.scala
+++ /dev/null
@@ -1,99 +0,0 @@
-import reflect.api.Modifier
-import reflect.macro.Context
-
-abstract class RangeDefault {
- val from, to: Int
- def foreach(f: Int => Unit) = {
- var i = from
- while (i < to) { f(i); i += 1 }
- }
-}
-
-/** This class should go into reflect.macro once it is a bit more stable. */
-abstract class Utils {
- val context: Context
- import context._
-
- class TreeSubstituter(from: List[Symbol], to: List[Tree]) extends Transformer {
- override def transform(tree: Tree): Tree = tree match {
- case Ident(_) =>
- def subst(from: List[Symbol], to: List[Tree]): Tree =
- if (from.isEmpty) tree
- else if (tree.symbol == from.head) to.head.duplicate // TODO: does it ever make sense *not* to perform a shallowDuplicate on `to.head`?
- else subst(from.tail, to.tail);
- subst(from, to)
- case _ =>
- val tree1 = super.transform(tree)
- if (tree1 ne tree) tree1.tpe = null
- tree1
- }
- }
- def makeApply(fn: Tree, args: List[Tree]): Tree = fn match {
- case Function(vparams, body) =>
- new TreeSubstituter(vparams map (_.symbol), args) transform body
- case Block(stats, expr) =>
- Block(stats, makeApply(expr, args))
- case _ =>
- // todo. read the compiler config and print if -Ydebug is set
- //println("no beta on "+fn+" "+fn.getClass)
- Apply(fn, args)
- }
- def makeWhile(lname: TermName, cond: Tree, body: Tree): Tree = {
- val continu = Apply(Ident(lname), Nil)
- val rhs = If(cond, Block(List(body), continu), Literal(Constant()))
- LabelDef(lname, Nil, rhs)
- }
- def makeBinop(left: Tree, op: String, right: Tree): Tree =
- Apply(Select(left, newTermName(op)), List(right))
-}
-
-class Range(val from: Int, val to: Int) extends RangeDefault {
- override def macro foreach(f: Int => Unit): Unit = {
- // todo. read the compiler config and print if -Ydebug is set
- //println("macro-expand, _this = "+ _this)
- import _context._
- object utils extends Utils {
- val context: _context.type = _context
- }
- import utils._
-
- val initName = newTermName("<init>")
- // Either:
- // scala"{ var i = $low; val h = $hi; while (i < h) { $f(i); i = i + 1 } }
- // or:
- // scala"($_this: RangeDefault).foreach($f)"
- _this match {
- case Apply(Select(New(tpt), initName), List(lo, hi)) if tpt.symbol.fullName == "Range" =>
- val iname = newTermName("$i")
- val hname = newTermName("$h")
- def iref = Ident(iname)
- def href = Ident(hname)
- val labelname = newTermName("$while")
- val cond = makeBinop(iref, "$less", href)
- val body = Block(
- List(makeApply(f, List(iref))),
- Assign(iref, makeBinop(iref, "$plus", Literal(Constant(1)))))
- val generated =
- Block(
- List(
- ValDef(Modifiers(Set(Modifier.mutable)), iname, TypeTree(), lo),
- ValDef(Modifiers(), hname, TypeTree(), hi)),
- makeWhile(labelname, cond, body))
- // todo. read the compiler config and print if -Ydebug is set
- //tools.nsc.util.trace("generated: ")(generated)
- generated
- case _ =>
- Apply(
- Select(
- Typed(_this, Ident(newTypeName("RangeDefault"))),
- newTermName("foreach")),
- List(f))
- }
- }
-}
-
-object Test extends App {
-
- new Range(1, 10) foreach println
-
-}
diff --git a/test/files/run/macro-reflective-ma-normal-mdmi.check b/test/files/run/macro-reflective-ma-normal-mdmi.check
new file mode 100644
index 0000000000..ac4213d6e9
--- /dev/null
+++ b/test/files/run/macro-reflective-ma-normal-mdmi.check
@@ -0,0 +1 @@
+43 \ No newline at end of file
diff --git a/test/files/run/macro-reflective-ma-normal-mdmi.flags b/test/files/run/macro-reflective-ma-normal-mdmi.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reflective-ma-normal-mdmi.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reflective-ma-normal-mdmi/Impls_Macros_1.scala b/test/files/run/macro-reflective-ma-normal-mdmi/Impls_Macros_1.scala
new file mode 100644
index 0000000000..f6caf89dca
--- /dev/null
+++ b/test/files/run/macro-reflective-ma-normal-mdmi/Impls_Macros_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1))))
+ Expr[Int](body)
+ }
+}
+
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala b/test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala
new file mode 100644
index 0000000000..632708a125
--- /dev/null
+++ b/test/files/run/macro-reflective-ma-normal-mdmi/Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42))))
+ println(Expr(tree).eval)
+}
diff --git a/test/files/run/macro-reflective-mamd-normal-mi.check b/test/files/run/macro-reflective-mamd-normal-mi.check
new file mode 100644
index 0000000000..ac4213d6e9
--- /dev/null
+++ b/test/files/run/macro-reflective-mamd-normal-mi.check
@@ -0,0 +1 @@
+43 \ No newline at end of file
diff --git a/test/files/run/macro-reflective-mamd-normal-mi/Impls_1.scala b/test/files/run/macro-reflective-mamd-normal-mi/Impls_1.scala
new file mode 100644
index 0000000000..dc7d42d23e
--- /dev/null
+++ b/test/files/run/macro-reflective-mamd-normal-mi/Impls_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1))))
+ Expr[Int](body)
+ }
+}
diff --git a/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala
new file mode 100644
index 0000000000..cf34f1685d
--- /dev/null
+++ b/test/files/run/macro-reflective-mamd-normal-mi/Macros_Test_2.scala
@@ -0,0 +1,17 @@
+//object Macros {
+// def foo(x: Int) = macro Impls.foo
+//}
+
+object Test extends App {
+ import scala.reflect.mirror._
+
+ val macrobody = Select(Ident(newTermName("Impls")), newTermName("foo"))
+ val macroparam = ValDef(NoMods, newTermName("x"), TypeTree(definitions.IntClass.asType), EmptyTree)
+ val macrodef = DefDef(Modifiers(Set(scala.reflect.api.Modifier.`macro`)), newTermName("foo"), Nil, List(List(macroparam)), TypeTree(), macrobody)
+ val modulector = DefDef(NoMods, nme.CONSTRUCTOR, Nil, List(List()), TypeTree(), Block(Apply(Select(Super(This(EmptyTypeName), EmptyTypeName), nme.CONSTRUCTOR), List())))
+ val module = ModuleDef(NoMods, newTermName("Macros"), Template(Nil, emptyValDef, List(modulector, macrodef)))
+ val macroapp = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42))))
+ val tree = Block(macrodef, module, macroapp)
+ val toolbox = mkToolBox(options = "-language:experimental.macros")
+ println(toolbox.runExpr(tree))
+}
diff --git a/test/files/run/macro-reify-basic.check b/test/files/run/macro-reify-basic.check
new file mode 100644
index 0000000000..f35d3e67b4
--- /dev/null
+++ b/test/files/run/macro-reify-basic.check
@@ -0,0 +1 @@
+hello world
diff --git a/test/files/run/macro-reify-basic.flags b/test/files/run/macro-reify-basic.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-basic.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-basic/Macros_1.scala b/test/files/run/macro-reify-basic/Macros_1.scala
new file mode 100644
index 0000000000..b2243d131c
--- /dev/null
+++ b/test/files/run/macro-reify-basic/Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo(s: String) = macro Impls.foo
+
+ object Impls {
+ def foo(c: Ctx)(s: c.Expr[String]) = c.reify {
+ println("hello " + s.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-basic/Test_2.scala b/test/files/run/macro-reify-basic/Test_2.scala
new file mode 100644
index 0000000000..0a762f7ad7
--- /dev/null
+++ b/test/files/run/macro-reify-basic/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ Macros.foo("world")
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-eval-eval.check b/test/files/run/macro-reify-eval-eval.check
new file mode 100644
index 0000000000..f35d3e67b4
--- /dev/null
+++ b/test/files/run/macro-reify-eval-eval.check
@@ -0,0 +1 @@
+hello world
diff --git a/test/files/run/macro-reify-eval-eval.flags b/test/files/run/macro-reify-eval-eval.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-eval-eval.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-eval-eval/Macros_1.scala b/test/files/run/macro-reify-eval-eval/Macros_1.scala
new file mode 100644
index 0000000000..6b8ac94f0e
--- /dev/null
+++ b/test/files/run/macro-reify-eval-eval/Macros_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+import scala.reflect.{mirror => mr}
+
+object Macros {
+ def foo = macro Impls.foo
+
+ object Impls {
+ def foo(c: Ctx) = c.reify {
+ { c.reify(c.reify("hello world")) }.eval.eval
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-eval-eval/Test_2.scala b/test/files/run/macro-reify-eval-eval/Test_2.scala
new file mode 100644
index 0000000000..f697da6020
--- /dev/null
+++ b/test/files/run/macro-reify-eval-eval/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ println(Macros.foo)
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-eval-outside-reify.check b/test/files/run/macro-reify-eval-outside-reify.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/macro-reify-eval-outside-reify.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/macro-reify-eval-outside-reify.flags b/test/files/run/macro-reify-eval-outside-reify.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-eval-outside-reify.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-eval-outside-reify/Impls_Macros_1.scala b/test/files/run/macro-reify-eval-outside-reify/Impls_Macros_1.scala
new file mode 100644
index 0000000000..086f9aeef2
--- /dev/null
+++ b/test/files/run/macro-reify-eval-outside-reify/Impls_Macros_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = {
+ val x1 = c.Expr[Int](c.resetAllAttrs(x.tree))
+ c.literal(x1.eval)
+ }
+}
+
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
diff --git a/test/files/run/macro-reify-eval-outside-reify/Test_2.scala b/test/files/run/macro-reify-eval-outside-reify/Test_2.scala
new file mode 100644
index 0000000000..632708a125
--- /dev/null
+++ b/test/files/run/macro-reify-eval-outside-reify/Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42))))
+ println(Expr(tree).eval)
+}
diff --git a/test/files/run/macro-reify-freevars.check b/test/files/run/macro-reify-freevars.check
new file mode 100644
index 0000000000..068742f0b6
--- /dev/null
+++ b/test/files/run/macro-reify-freevars.check
@@ -0,0 +1,3 @@
+reflective compilation has failed:
+
+Macro expansion contains free term variable code defined by map in Macros_1.scala:8:9. Have you forgotten to use eval when splicing this variable into a reifee? If you have troubles tracking free term variables, consider using -Xlog-free-terms
diff --git a/test/files/run/macro-reify-freevars.flags b/test/files/run/macro-reify-freevars.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-freevars.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-freevars/Macros_1.scala b/test/files/run/macro-reify-freevars/Macros_1.scala
new file mode 100644
index 0000000000..3cc559a0af
--- /dev/null
+++ b/test/files/run/macro-reify-freevars/Macros_1.scala
@@ -0,0 +1,19 @@
+package scala.collection.slick
+object QueryableMacros{
+ def map[T:c.TypeTag, S:c.TypeTag]
+ (c: scala.reflect.makro.Context)
+ (projection: c.mirror.Expr[T => S])
+ : c.mirror.Expr[scala.collection.slick.Queryable[S]] = {
+ import c.mirror._
+ val code = EmptyTree
+ c.reify{
+ Queryable.factory[S]( code.asInstanceOf[reflect.mirror.Tree] )
+ }
+ }
+}
+class Queryable[T]{
+ def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]
+}
+object Queryable{
+ def factory[S]( projection:scala.reflect.mirror.Tree ) : Queryable[S] = null
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-freevars/Test_2.scala b/test/files/run/macro-reify-freevars/Test_2.scala
new file mode 100644
index 0000000000..e7077f9c7f
--- /dev/null
+++ b/test/files/run/macro-reify-freevars/Test_2.scala
@@ -0,0 +1,9 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val q = New(AppliedTypeTree(Select(Select(Select(Ident("scala"), newTermName("collection")), newTermName("slick")), newTypeName("Queryable")), List(Ident("Int"))))
+ val x = ValDef(NoMods, newTermName("x"), Ident("Int"), EmptyTree)
+ val fn = Function(List(x), Apply(Select(Ident(newTermName("x")), newTermName("$plus")), List(Literal(Constant("5")))))
+ val tree = Apply(Select(q, newTermName("map")), List(fn))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-groundtypetag-notypeparams.check b/test/files/run/macro-reify-groundtypetag-notypeparams.check
new file mode 100644
index 0000000000..d75b3c72b2
--- /dev/null
+++ b/test/files/run/macro-reify-groundtypetag-notypeparams.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[List[Int]]
diff --git a/test/files/run/macro-reify-groundtypetag-notypeparams/Test.scala b/test/files/run/macro-reify-groundtypetag-notypeparams/Test.scala
new file mode 100644
index 0000000000..d2f8fab5ec
--- /dev/null
+++ b/test/files/run/macro-reify-groundtypetag-notypeparams/Test.scala
@@ -0,0 +1,6 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ println(implicitly[ConcreteTypeTag[Int]])
+ println(implicitly[ConcreteTypeTag[List[Int]]])
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-groundtypetag-typeparams-tags.check b/test/files/run/macro-reify-groundtypetag-typeparams-tags.check
new file mode 100644
index 0000000000..d75b3c72b2
--- /dev/null
+++ b/test/files/run/macro-reify-groundtypetag-typeparams-tags.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[List[Int]]
diff --git a/test/files/run/macro-reify-groundtypetag-typeparams-tags/Test.scala b/test/files/run/macro-reify-groundtypetag-typeparams-tags/Test.scala
new file mode 100644
index 0000000000..6d7eab5f9a
--- /dev/null
+++ b/test/files/run/macro-reify-groundtypetag-typeparams-tags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooTypeTag[T: ConcreteTypeTag] = {
+ println(implicitly[ConcreteTypeTag[T]])
+ println(implicitly[ConcreteTypeTag[List[T]]])
+ }
+ fooTypeTag[Int]
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-a.check b/test/files/run/macro-reify-nested-a.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/macro-reify-nested-a.check
diff --git a/test/files/run/macro-reify-nested-a.flags b/test/files/run/macro-reify-nested-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-nested-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala
new file mode 100644
index 0000000000..1ce8f44671
--- /dev/null
+++ b/test/files/run/macro-reify-nested-a/Impls_Macros_1.scala
@@ -0,0 +1,43 @@
+import scala.reflect.makro.Context
+
+case class Utils[C <: Context]( c:C ) {
+ import c.mirror._
+ import c.{Tree=>_}
+ object removeDoubleReify extends c.mirror.Transformer {
+ def apply( tree:Tree ) = transform(tree)
+ override def transform(tree: Tree): Tree = {
+ super.transform {
+ tree match {
+ case Apply(TypeApply(Select(_this, termname), _), reified::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reified)
+ case Apply(Select(_this, termname), reified::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reified)
+ case _ => tree
+ }
+ }
+ }
+ }
+}
+object QueryableMacros{
+ def _helper[C <: Context,S:c.TypeTag]( c:C )( name:String, projection:c.mirror.Expr[_] ) = {
+ import c.mirror._
+ val element_type = implicitly[c.TypeTag[S]].tpe
+ val foo = Expr[reflect.mirror.Expr[Queryable[S]]](
+ c.reifyTree( c.reflectMirrorPrefix, c.typeCheck(
+ Utils[c.type](c).removeDoubleReify(
+ Apply(Select(c.prefix.tree, newTermName( name )), List( projection.tree ))
+ ).asInstanceOf[Tree]
+ )))
+ c.reify{ Queryable.factory[S]( foo.eval )}
+ }
+ def map[T:c.TypeTag, S:c.TypeTag]
+ (c: scala.reflect.makro.Context)
+ (projection: c.mirror.Expr[T => S]): c.mirror.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
+}
+class Queryable[T]{
+ def _map[S]( projection: T => S ) : Queryable[S] = ???
+ def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]
+}
+object Queryable{
+ def factory[S]( projection:scala.reflect.mirror.Expr[Queryable[S]] ) : Queryable[S] = null
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-a/Test_2.scala b/test/files/run/macro-reify-nested-a/Test_2.scala
new file mode 100644
index 0000000000..fa0eb378af
--- /dev/null
+++ b/test/files/run/macro-reify-nested-a/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App{
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1))
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b.check b/test/files/run/macro-reify-nested-b.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/macro-reify-nested-b.check
diff --git a/test/files/run/macro-reify-nested-b.flags b/test/files/run/macro-reify-nested-b.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-nested-b.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala b/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala
new file mode 100644
index 0000000000..1ce8f44671
--- /dev/null
+++ b/test/files/run/macro-reify-nested-b/Impls_Macros_1.scala
@@ -0,0 +1,43 @@
+import scala.reflect.makro.Context
+
+case class Utils[C <: Context]( c:C ) {
+ import c.mirror._
+ import c.{Tree=>_}
+ object removeDoubleReify extends c.mirror.Transformer {
+ def apply( tree:Tree ) = transform(tree)
+ override def transform(tree: Tree): Tree = {
+ super.transform {
+ tree match {
+ case Apply(TypeApply(Select(_this, termname), _), reified::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reified)
+ case Apply(Select(_this, termname), reified::Nil )
+ if termname.toString == "factory" => c.unreifyTree(reified)
+ case _ => tree
+ }
+ }
+ }
+ }
+}
+object QueryableMacros{
+ def _helper[C <: Context,S:c.TypeTag]( c:C )( name:String, projection:c.mirror.Expr[_] ) = {
+ import c.mirror._
+ val element_type = implicitly[c.TypeTag[S]].tpe
+ val foo = Expr[reflect.mirror.Expr[Queryable[S]]](
+ c.reifyTree( c.reflectMirrorPrefix, c.typeCheck(
+ Utils[c.type](c).removeDoubleReify(
+ Apply(Select(c.prefix.tree, newTermName( name )), List( projection.tree ))
+ ).asInstanceOf[Tree]
+ )))
+ c.reify{ Queryable.factory[S]( foo.eval )}
+ }
+ def map[T:c.TypeTag, S:c.TypeTag]
+ (c: scala.reflect.makro.Context)
+ (projection: c.mirror.Expr[T => S]): c.mirror.Expr[Queryable[S]] = _helper[c.type,S]( c )( "_map", projection )
+}
+class Queryable[T]{
+ def _map[S]( projection: T => S ) : Queryable[S] = ???
+ def map[S]( projection: T => S ) : Queryable[S] = macro QueryableMacros.map[T,S]
+}
+object Queryable{
+ def factory[S]( projection:scala.reflect.mirror.Expr[Queryable[S]] ) : Queryable[S] = null
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-nested-b/Test_2.scala b/test/files/run/macro-reify-nested-b/Test_2.scala
new file mode 100644
index 0000000000..fa13f57ffb
--- /dev/null
+++ b/test/files/run/macro-reify-nested-b/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App{
+ val q : Queryable[Any] = new Queryable[Any]
+ q.map(e1 => q.map(e2=>e1).map(e2=>e1))
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-ref-to-packageless.check b/test/files/run/macro-reify-ref-to-packageless.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/macro-reify-ref-to-packageless.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/macro-reify-ref-to-packageless.flags b/test/files/run/macro-reify-ref-to-packageless.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-ref-to-packageless.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-ref-to-packageless/Impls_1.scala b/test/files/run/macro-reify-ref-to-packageless/Impls_1.scala
new file mode 100644
index 0000000000..2f2d05678d
--- /dev/null
+++ b/test/files/run/macro-reify-ref-to-packageless/Impls_1.scala
@@ -0,0 +1,6 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ val `Answer to the Ultimate Question of Life, the Universe, and Everything` = 42
+ def foo(c: Ctx) = c.reify { `Answer to the Ultimate Question of Life, the Universe, and Everything` }
+}
diff --git a/test/files/run/macro-reify-ref-to-packageless/Test_2.scala b/test/files/run/macro-reify-ref-to-packageless/Test_2.scala
new file mode 100644
index 0000000000..9d475f756d
--- /dev/null
+++ b/test/files/run/macro-reify-ref-to-packageless/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo = macro Impls.foo
+ println(foo)
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-tagful-a.check b/test/files/run/macro-reify-tagful-a.check
new file mode 100644
index 0000000000..8a701df6a5
--- /dev/null
+++ b/test/files/run/macro-reify-tagful-a.check
@@ -0,0 +1 @@
+List(hello world)
diff --git a/test/files/run/macro-reify-tagful-a.flags b/test/files/run/macro-reify-tagful-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-tagful-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-tagful-a/Macros_1.scala b/test/files/run/macro-reify-tagful-a/Macros_1.scala
new file mode 100644
index 0000000000..2ff12091a1
--- /dev/null
+++ b/test/files/run/macro-reify-tagful-a/Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo[T](s: T) = macro Impls.foo[T]
+
+ object Impls {
+ def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.reify {
+ List(s.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-tagful-a/Test_2.scala b/test/files/run/macro-reify-tagful-a/Test_2.scala
new file mode 100644
index 0000000000..4d27166341
--- /dev/null
+++ b/test/files/run/macro-reify-tagful-a/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ val list: List[String] = Macros.foo("hello world")
+ println(list)
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-tagless-a.check b/test/files/run/macro-reify-tagless-a.check
new file mode 100644
index 0000000000..4ee11190d6
--- /dev/null
+++ b/test/files/run/macro-reify-tagless-a.check
@@ -0,0 +1,3 @@
+reflective compilation has failed:
+
+Macro expansion contains free type variable T defined by foo in Impls_Macros_1.scala:7:13. Have you forgotten to use c.TypeTag annotation for this type parameter? If you have troubles tracking free type variables, consider using -Xlog-free-types
diff --git a/test/files/run/macro-reify-tagless-a.flags b/test/files/run/macro-reify-tagless-a.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-tagless-a.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala b/test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala
new file mode 100644
index 0000000000..45e39d7d1c
--- /dev/null
+++ b/test/files/run/macro-reify-tagless-a/Impls_Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo[T](s: T) = macro Impls.foo[T]
+
+ object Impls {
+ def foo[T](c: Ctx)(s: c.Expr[T]) = c.reify {
+ List[T](s.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-tagless-a/Test_2.scala b/test/files/run/macro-reify-tagless-a/Test_2.scala
new file mode 100644
index 0000000000..94efbd0c37
--- /dev/null
+++ b/test/files/run/macro-reify-tagless-a/Test_2.scala
@@ -0,0 +1,12 @@
+object Test extends App {
+ //val list: List[String] = Macros.foo("hello world")
+ //println(list)
+
+ import scala.reflect.mirror._
+ val tpt = AppliedTypeTree(Ident(definitions.ListClass), List(Ident(definitions.StringClass)))
+ val rhs = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant("hello world"))))
+ val list = ValDef(NoMods, newTermName("list"), tpt, rhs)
+ val tree = Block(list, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Ident(list.name))))
+ try Expr(tree).eval
+ catch { case ex: Throwable => println(ex.getMessage) }
+}
diff --git a/test/files/run/macro-reify-typetag-notypeparams.check b/test/files/run/macro-reify-typetag-notypeparams.check
new file mode 100644
index 0000000000..d75b3c72b2
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-notypeparams.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[List[Int]]
diff --git a/test/files/run/macro-reify-typetag-notypeparams/Test.scala b/test/files/run/macro-reify-typetag-notypeparams/Test.scala
new file mode 100644
index 0000000000..041a44273d
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-notypeparams/Test.scala
@@ -0,0 +1,6 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ println(implicitly[TypeTag[Int]])
+ println(implicitly[TypeTag[List[Int]]])
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-typetag-typeparams-notags.check b/test/files/run/macro-reify-typetag-typeparams-notags.check
new file mode 100644
index 0000000000..11d78ece41
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-typeparams-notags.check
@@ -0,0 +1,2 @@
+TypeTag[T]
+TypeTag[List[T]]
diff --git a/test/files/run/macro-reify-typetag-typeparams-notags/Test.scala b/test/files/run/macro-reify-typetag-typeparams-notags/Test.scala
new file mode 100644
index 0000000000..a89499e7fe
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-typeparams-notags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooNoTypeTag[T] = {
+ println(implicitly[TypeTag[T]])
+ println(implicitly[TypeTag[List[T]]])
+ }
+ fooNoTypeTag[Int]
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-typetag-typeparams-tags.check b/test/files/run/macro-reify-typetag-typeparams-tags.check
new file mode 100644
index 0000000000..458593c449
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-typeparams-tags.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Int]
+*ConcreteTypeTag[List[Int]]
diff --git a/test/files/run/macro-reify-typetag-typeparams-tags/Test.scala b/test/files/run/macro-reify-typetag-typeparams-tags/Test.scala
new file mode 100644
index 0000000000..b32680a4b8
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-typeparams-tags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooTypeTag[T: TypeTag] = {
+ println(implicitly[TypeTag[T]])
+ println(implicitly[TypeTag[List[T]]])
+ }
+ fooTypeTag[Int]
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-typetag-usegroundtypetag.check b/test/files/run/macro-reify-typetag-usegroundtypetag.check
new file mode 100644
index 0000000000..458593c449
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-usegroundtypetag.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Int]
+*ConcreteTypeTag[List[Int]]
diff --git a/test/files/run/macro-reify-typetag-usegroundtypetag/Test.scala b/test/files/run/macro-reify-typetag-usegroundtypetag/Test.scala
new file mode 100644
index 0000000000..de235f51cc
--- /dev/null
+++ b/test/files/run/macro-reify-typetag-usegroundtypetag/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooTypeTag[T: ConcreteTypeTag] = {
+ println(implicitly[TypeTag[T]])
+ println(implicitly[TypeTag[List[T]]])
+ }
+ fooTypeTag[Int]
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-unreify.check b/test/files/run/macro-reify-unreify.check
new file mode 100644
index 0000000000..a5334cc355
--- /dev/null
+++ b/test/files/run/macro-reify-unreify.check
@@ -0,0 +1 @@
+hello world = Expr[String("hello world")]("hello world")
diff --git a/test/files/run/macro-reify-unreify.flags b/test/files/run/macro-reify-unreify.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-unreify.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-unreify/Macros_1.scala b/test/files/run/macro-reify-unreify/Macros_1.scala
new file mode 100644
index 0000000000..1b0b9c6421
--- /dev/null
+++ b/test/files/run/macro-reify-unreify/Macros_1.scala
@@ -0,0 +1,19 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo(s: String) = macro Impls.foo
+
+ object Impls {
+ def foo(c: Ctx)(s: c.Expr[String]) = {
+ import c.mirror._
+
+ val world = c.reifyTree(c.reflectMirrorPrefix, s.tree)
+ val greeting = c.reifyTree(c.reflectMirrorPrefix, c.typeCheck(Apply(Select(Literal(Constant("hello ")), newTermName("$plus")), List(c.unreifyTree(world)))))
+ val typedGreeting = Expr[String](greeting)
+
+ c.reify {
+ println("hello " + s.eval + " = " + typedGreeting.eval)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-unreify/Test_2.scala b/test/files/run/macro-reify-unreify/Test_2.scala
new file mode 100644
index 0000000000..0a762f7ad7
--- /dev/null
+++ b/test/files/run/macro-reify-unreify/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ Macros.foo("world")
+} \ No newline at end of file
diff --git a/test/files/run/macro-reify-value-outside-reify.check b/test/files/run/macro-reify-value-outside-reify.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/macro-reify-value-outside-reify.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/macro-reify-value-outside-reify.flags b/test/files/run/macro-reify-value-outside-reify.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-reify-value-outside-reify.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-reify-value-outside-reify/Impls_Macros_1.scala b/test/files/run/macro-reify-value-outside-reify/Impls_Macros_1.scala
new file mode 100644
index 0000000000..109e19e44a
--- /dev/null
+++ b/test/files/run/macro-reify-value-outside-reify/Impls_Macros_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = {
+ val x1 = c.Expr[Int](c.resetAllAttrs(x.tree))
+ c.literal(x1.value)
+ }
+}
+
+object Macros {
+ def foo(x: Int) = macro Impls.foo
+}
diff --git a/test/files/run/macro-reify-value-outside-reify/Test_2.scala b/test/files/run/macro-reify-value-outside-reify/Test_2.scala
new file mode 100644
index 0000000000..128cad4510
--- /dev/null
+++ b/test/files/run/macro-reify-value-outside-reify/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import scala.reflect.mirror._
+ val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(42))))
+ try println(Expr(tree).eval)
+ catch { case ex: Throwable => println(ex.getMessage) }
+}
diff --git a/test/files/run/macro-repl-basic.check b/test/files/run/macro-repl-basic.check
index f8f0d3ad29..9e0f9aa1a2 100644
--- a/test/files/run/macro-repl-basic.check
+++ b/test/files/run/macro-repl-basic.check
@@ -1,25 +1,54 @@
-Type in expressions to have them evaluated.
-Type :help for more information.
-
-scala>
-
-scala> object Macros {
- object Shmacros {
- def macro foo(x: Int): Int = x
- }
- def macro bar(x: Int): Int = x
-}; class Macros {
- def macro quux(x: Int): Int = x
-}
-defined module Macros
-defined class Macros
-
-scala>
-
-scala> import Macros.Shmacros._
-import Macros.Shmacros._
-
-scala> println(foo(2) + Macros.bar(2) * new Macros().quux(4))
-10
-
-scala>
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import language.experimental.macros
+import language.experimental.macros
+
+scala> import scala.reflect.makro.{Context => Ctx}
+import scala.reflect.makro.{Context=>Ctx}
+
+scala>
+
+scala> object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int]) = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1))))
+ Expr[Int](body)
+ }
+
+ def bar(c: Ctx)(x: c.Expr[Int]) = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2))))
+ Expr[Int](body)
+ }
+
+ def quux(c: Ctx)(x: c.Expr[Int]) = {
+ import c.mirror._
+ val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3))))
+ Expr[Int](body)
+ }
+}
+defined module Impls
+
+scala> object Macros {
+ object Shmacros {
+ def foo(x: Int): Int = macro Impls.foo
+ }
+ def bar(x: Int): Int = macro Impls.bar
+}; class Macros {
+ def quux(x: Int): Int = macro Impls.quux
+}
+defined module Macros
+defined class Macros
+
+scala>
+
+scala> import Macros.Shmacros._
+import Macros.Shmacros._
+
+scala> println(foo(2) + Macros.bar(2) * new Macros().quux(4))
+31
+
+scala>
diff --git a/test/files/run/macro-repl-basic.scala b/test/files/run/macro-repl-basic.scala
index 9b1a53343b..e8849b4b56 100644
--- a/test/files/run/macro-repl-basic.scala
+++ b/test/files/run/macro-repl-basic.scala
@@ -1,18 +1,39 @@
import scala.tools.partest.ReplTest
object Test extends ReplTest {
- override def extraSettings = "-Xmacros"
def code = """
+ |import language.experimental.macros
+ |import scala.reflect.makro.{Context => Ctx}
+ |
+ |object Impls {
+ | def foo(c: Ctx)(x: c.Expr[Int]) = {
+ | import c.mirror._
+ | val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(1))))
+ | Expr[Int](body)
+ | }
+ |
+ | def bar(c: Ctx)(x: c.Expr[Int]) = {
+ | import c.mirror._
+ | val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(2))))
+ | Expr[Int](body)
+ | }
+ |
+ | def quux(c: Ctx)(x: c.Expr[Int]) = {
+ | import c.mirror._
+ | val body = Apply(Select(x.tree, newTermName("$plus")), List(Literal(Constant(3))))
+ | Expr[Int](body)
+ | }
+ |}
|object Macros {
| object Shmacros {
- | def macro foo(x: Int): Int = x
+ | def foo(x: Int): Int = macro Impls.foo
| }
- | def macro bar(x: Int): Int = x
+ | def bar(x: Int): Int = macro Impls.bar
|}; class Macros {
- | def macro quux(x: Int): Int = x
+ | def quux(x: Int): Int = macro Impls.quux
|}
|
|import Macros.Shmacros._
|println(foo(2) + Macros.bar(2) * new Macros().quux(4))
|""".stripMargin
-} \ No newline at end of file
+}
diff --git a/test/files/run/macro-repl-dontexpand.check b/test/files/run/macro-repl-dontexpand.check
index d2bb89b6f7..35845f0cff 100644
--- a/test/files/run/macro-repl-dontexpand.check
+++ b/test/files/run/macro-repl-dontexpand.check
@@ -3,7 +3,10 @@ Type :help for more information.
scala>
-scala> def macro foo = ???
+scala> def bar(c: scala.reflect.makro.Context) = ???
+bar: (c: scala.reflect.makro.Context)Nothing
+
+scala> def foo = macro bar
foo: Any
scala>
diff --git a/test/files/run/macro-repl-dontexpand.scala b/test/files/run/macro-repl-dontexpand.scala
index 254bce894c..cd1b2e1969 100644
--- a/test/files/run/macro-repl-dontexpand.scala
+++ b/test/files/run/macro-repl-dontexpand.scala
@@ -1,8 +1,9 @@
import scala.tools.partest.ReplTest
object Test extends ReplTest {
- override def extraSettings = "-Xmacros"
+ override def extraSettings = "-language:experimental.macros"
def code = """
- |def macro foo = ???
+ |def bar(c: scala.reflect.makro.Context) = ???
+ |def foo = macro bar
|""".stripMargin
-} \ No newline at end of file
+}
diff --git a/test/files/run/macro-rettype-mismatch.flags b/test/files/run/macro-rettype-mismatch.flags
index 7fea2ff901..cd66464f2f 100644
--- a/test/files/run/macro-rettype-mismatch.flags
+++ b/test/files/run/macro-rettype-mismatch.flags
@@ -1 +1 @@
--Xmacros \ No newline at end of file
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-rettype-mismatch/Macros_1.scala b/test/files/run/macro-rettype-mismatch/Macros_1.scala
deleted file mode 100644
index 64e5b93468..0000000000
--- a/test/files/run/macro-rettype-mismatch/Macros_1.scala
+++ /dev/null
@@ -1,3 +0,0 @@
-object Macros {
- def macro foo(x: Int): String = x
-} \ No newline at end of file
diff --git a/test/files/run/macro-rettype-mismatch/Test_2.scala b/test/files/run/macro-rettype-mismatch/Test_2.scala
deleted file mode 100644
index 39a7c7ad1a..0000000000
--- a/test/files/run/macro-rettype-mismatch/Test_2.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
-object Test extends App {
- import scala.reflect.mirror._
- val tree = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant(2))))
-
- val stderr = new java.io.ByteArrayOutputStream()
- Console.setErr(new java.io.PrintStream(stderr))
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- try { toolbox.runExpr(tree) }
- catch { case ex: Throwable => println(stderr); println(ex) }
-}
diff --git a/test/files/run/macro-settings.check b/test/files/run/macro-settings.check
new file mode 100644
index 0000000000..33784d1c15
--- /dev/null
+++ b/test/files/run/macro-settings.check
@@ -0,0 +1 @@
+List(hello=1)
diff --git a/test/files/run/macro-settings.flags b/test/files/run/macro-settings.flags
new file mode 100644
index 0000000000..15479e30b8
--- /dev/null
+++ b/test/files/run/macro-settings.flags
@@ -0,0 +1 @@
+-language:experimental.macros -Xmacro-settings:hello=1 \ No newline at end of file
diff --git a/test/files/run/macro-settings/Impls_Macros_1.scala b/test/files/run/macro-settings/Impls_Macros_1.scala
new file mode 100644
index 0000000000..8c7254c79a
--- /dev/null
+++ b/test/files/run/macro-settings/Impls_Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.Context
+
+object Impls {
+ def impl(c: Context) = c.reify {
+ println(c.literal(c.settings.toString).eval)
+ }
+}
+
+object Macros {
+ def foo = macro Impls.impl
+} \ No newline at end of file
diff --git a/test/files/run/macro-settings/Test_2.scala b/test/files/run/macro-settings/Test_2.scala
new file mode 100644
index 0000000000..acfddae942
--- /dev/null
+++ b/test/files/run/macro-settings/Test_2.scala
@@ -0,0 +1,3 @@
+object Test extends App {
+ Macros.foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-sip19-revised.check b/test/files/run/macro-sip19-revised.check
new file mode 100644
index 0000000000..aa2fbd11d3
--- /dev/null
+++ b/test/files/run/macro-sip19-revised.check
@@ -0,0 +1,5 @@
+hey, i've been called from SourceLocation1(null,Test_2.scala,11,251)
+hey, i've been called from SourceLocation1(SourceLocation1(null,Test_2.scala,11,251),Test_2.scala,8,222)
+hey, i've been called from SourceLocation1(SourceLocation1(SourceLocation1(null,Test_2.scala,11,251),Test_2.scala,8,222),Test_2.scala,8,222)
+hey, i've been called from SourceLocation1(SourceLocation1(SourceLocation1(SourceLocation1(null,Test_2.scala,11,251),Test_2.scala,8,222),Test_2.scala,8,222),Test_2.scala,6,180)
+2
diff --git a/test/files/run/macro-sip19-revised.flags b/test/files/run/macro-sip19-revised.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-sip19-revised.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-sip19-revised/Impls_Macros_1.scala b/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
new file mode 100644
index 0000000000..e8f6e1df85
--- /dev/null
+++ b/test/files/run/macro-sip19-revised/Impls_Macros_1.scala
@@ -0,0 +1,34 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl(c: Context) = {
+ import c.mirror._
+
+ val inscope = c.inferImplicitValue(staticClass("SourceLocation").asType)
+ val outer = Expr[SourceLocation](if (!inscope.isEmpty) inscope else Literal(Constant(null)))
+
+ val Apply(fun, args) = c.enclosingImplicits(0)._2
+ val fileName = fun.pos.fileInfo.getName
+ val line = fun.pos.line
+ val charOffset = fun.pos.point
+ c.reify { SourceLocation1(outer.eval, c.literal(fileName).eval, c.literal(line).eval, c.literal(charOffset).eval) }
+ }
+
+ implicit def sourceLocation: SourceLocation1 = macro impl
+}
+
+trait SourceLocation {
+ /** Source location of the outermost call */
+ val outer: SourceLocation
+
+ /** The name of the source file */
+ val fileName: String
+
+ /** The line number */
+ val line: Int
+
+ /** The character offset */
+ val charOffset: Int
+}
+
+case class SourceLocation1(val outer: SourceLocation, val fileName: String, val line: Int, val charOffset: Int) extends SourceLocation
diff --git a/test/files/run/macro-sip19-revised/Test_2.scala b/test/files/run/macro-sip19-revised/Test_2.scala
new file mode 100644
index 0000000000..d9a4d7d4fc
--- /dev/null
+++ b/test/files/run/macro-sip19-revised/Test_2.scala
@@ -0,0 +1,12 @@
+import Macros._
+
+object Test extends App {
+ def foo(x: Int, y: Int)(implicit loc: SourceLocation): Int = {
+ println("hey, i've been called from %s".format(loc))
+ if (x < y) foo(y, x)
+ else if (y == 0) x
+ else foo(x - y, y)
+ }
+
+ println(foo(4, 2))
+}
diff --git a/test/files/run/macro-sip19.check b/test/files/run/macro-sip19.check
new file mode 100644
index 0000000000..6b317ccb47
--- /dev/null
+++ b/test/files/run/macro-sip19.check
@@ -0,0 +1,5 @@
+hey, i've been called from SourceLocation(Test_2.scala,15,366)
+hey, i've been called from SourceLocation(Test_2.scala,11,331)
+hey, i've been called from SourceLocation(Test_2.scala,11,331)
+hey, i've been called from SourceLocation(Test_2.scala,9,285)
+2
diff --git a/test/files/run/macro-sip19.flags b/test/files/run/macro-sip19.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-sip19.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-sip19/Impls_Macros_1.scala b/test/files/run/macro-sip19/Impls_Macros_1.scala
new file mode 100644
index 0000000000..39b29ad64c
--- /dev/null
+++ b/test/files/run/macro-sip19/Impls_Macros_1.scala
@@ -0,0 +1,25 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl(c: Context) = {
+ import c.mirror._
+ val Apply(fun, args) = c.enclosingImplicits(0)._2
+ val fileName = fun.pos.fileInfo.getName
+ val line = fun.pos.line
+ val charOffset = fun.pos.point
+ c.reify { SourceLocation(c.literal(fileName).eval, c.literal(line).eval, c.literal(charOffset).eval) }
+ }
+
+ implicit def sourceLocation: SourceLocation = macro impl
+}
+
+case class SourceLocation(
+ /** The name of the source file */
+ val fileName: String,
+
+ /** The line number */
+ val line: Int,
+
+ /** The character offset */
+ val charOffset: Int
+)
diff --git a/test/files/run/macro-sip19/Test_2.scala b/test/files/run/macro-sip19/Test_2.scala
new file mode 100644
index 0000000000..32326e6352
--- /dev/null
+++ b/test/files/run/macro-sip19/Test_2.scala
@@ -0,0 +1,16 @@
+import Macros._
+
+object Test extends App {
+ def foo(x: Int, y: Int)(implicit loc0: SourceLocation): Int = {
+ var loc = loc0;
+ {
+ var loc0 = 0 // shadow loc0 to disambiguate with the implicit macro
+ println("hey, i've been called from %s".format(loc))
+ if (x < y) foo(y, x)
+ else if (y == 0) x
+ else foo(x - y, y)
+ }
+ }
+
+ println(foo(4, 2))
+}
diff --git a/test/files/run/macro-typecheck-implicitsdisabled.check b/test/files/run/macro-typecheck-implicitsdisabled.check
new file mode 100644
index 0000000000..aa6c8e1f07
--- /dev/null
+++ b/test/files/run/macro-typecheck-implicitsdisabled.check
@@ -0,0 +1,2 @@
+scala.this.Predef.any2ArrowAssoc[Int](1).->[Int](2)
+scala.reflect.internal.Types$TypeError: value -> is not a member of Int
diff --git a/test/files/run/macro-typecheck-implicitsdisabled.flags b/test/files/run/macro-typecheck-implicitsdisabled.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-typecheck-implicitsdisabled.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-implicitsdisabled/Impls_Macros_1.scala b/test/files/run/macro-typecheck-implicitsdisabled/Impls_Macros_1.scala
new file mode 100644
index 0000000000..4f0f76aed6
--- /dev/null
+++ b/test/files/run/macro-typecheck-implicitsdisabled/Impls_Macros_1.scala
@@ -0,0 +1,28 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl_with_implicits_enabled(c: Context) = {
+ import c.mirror._
+
+ val tree1 = Apply(Select(Literal(Constant(1)), newTermName("$minus$greater")), List(Literal(Constant(2))))
+ val ttree1 = c.typeCheck(tree1, withImplicitViewsDisabled = false)
+ c.literal(ttree1.toString)
+ }
+
+ def foo_with_implicits_enabled = macro impl_with_implicits_enabled
+
+ def impl_with_implicits_disabled(c: Context) = {
+ import c.mirror._
+
+ try {
+ val tree2 = Apply(Select(Literal(Constant(1)), newTermName("$minus$greater")), List(Literal(Constant(2))))
+ val ttree2 = c.typeCheck(tree2, withImplicitViewsDisabled = true)
+ c.literal(ttree2.toString)
+ } catch {
+ case ex: Throwable =>
+ c.literal(ex.toString)
+ }
+ }
+
+ def foo_with_implicits_disabled = macro impl_with_implicits_disabled
+} \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-implicitsdisabled/Test_2.scala b/test/files/run/macro-typecheck-implicitsdisabled/Test_2.scala
new file mode 100644
index 0000000000..127e955f0e
--- /dev/null
+++ b/test/files/run/macro-typecheck-implicitsdisabled/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println(Macros.foo_with_implicits_enabled)
+ println(Macros.foo_with_implicits_disabled)
+} \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-macrosdisabled.check b/test/files/run/macro-typecheck-macrosdisabled.check
new file mode 100644
index 0000000000..3e1057520b
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled.check
@@ -0,0 +1,5 @@
+{
+ val $mr: reflect.mirror.type = scala.reflect.`package`.mirror;
+ $mr.Expr.apply[Int(2)]($mr.Literal.apply($mr.Constant.apply(2)))($mr.ConcreteTypeTag.apply[Int(2)]($mr.ConstantType.apply($mr.Constant.apply(2)), classOf[scala.Int]))
+}
+mr.reify[Int](2)
diff --git a/test/files/run/macro-typecheck-macrosdisabled.flags b/test/files/run/macro-typecheck-macrosdisabled.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala b/test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala
new file mode 100644
index 0000000000..3de9367994
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled/Impls_Macros_1.scala
@@ -0,0 +1,29 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl_with_macros_enabled(c: Context) = {
+ import c.mirror._
+
+ val mr = Select(Select(Select(Ident(newTermName("scala")), newTermName("reflect")), newTermName("package")), newTermName("mirror"))
+ val tree1 = Apply(Select(mr, newTermName("reify")), List(Literal(Constant(2))))
+ val ttree1 = c.typeCheck(tree1, withMacrosDisabled = false)
+ c.literal(ttree1.toString)
+ }
+
+ def foo_with_macros_enabled = macro impl_with_macros_enabled
+
+ def impl_with_macros_disabled(c: Context) = {
+ import c.mirror._
+
+ val mrPkg = staticModule("scala.reflect.package")
+ val mrSym = selectTerm(mrPkg, "mirror")
+ val NullaryMethodType(mrTpe) = mrSym.typeSignature
+ val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror)
+
+ val tree2 = Apply(Select(Ident(mr), newTermName("reify")), List(Literal(Constant(2))))
+ val ttree2 = c.typeCheck(tree2, withMacrosDisabled = true)
+ c.literal(ttree2.toString)
+ }
+
+ def foo_with_macros_disabled = macro impl_with_macros_disabled
+} \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-macrosdisabled/Test_2.scala b/test/files/run/macro-typecheck-macrosdisabled/Test_2.scala
new file mode 100644
index 0000000000..bdba39195b
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println(Macros.foo_with_macros_enabled)
+ println(Macros.foo_with_macros_disabled)
+} \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-macrosdisabled2.check b/test/files/run/macro-typecheck-macrosdisabled2.check
new file mode 100644
index 0000000000..02da6ad0c7
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled2.check
@@ -0,0 +1,5 @@
+{
+ val $mr: reflect.mirror.type = scala.reflect.`package`.mirror;
+ $mr.Expr.apply[Array[Int]]($mr.Apply.apply($mr.Select.apply($mr.Select.apply($mr.Ident($mr.staticModule("scala")), $mr.newTermName("Array")), $mr.newTermName("apply")), scala.collection.immutable.List.apply[$mr.Literal]($mr.Literal.apply($mr.Constant.apply(2)))))($mr.ConcreteTypeTag.apply[Array[Int]]($mr.TypeRef.apply($mr.thisModuleType("scala"), $mr.staticClass("scala.Array"), scala.collection.immutable.List.apply[$mr.Type]($mr.staticClass("scala.Int").asTypeConstructor)), ScalaRunTime.this.arrayClass(classOf[scala.Int])))
+}
+mr.reify[Array[Int]](scala.Array.apply(2))
diff --git a/test/files/run/macro-typecheck-macrosdisabled2.flags b/test/files/run/macro-typecheck-macrosdisabled2.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled2.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-macrosdisabled2/Impls_Macros_1.scala b/test/files/run/macro-typecheck-macrosdisabled2/Impls_Macros_1.scala
new file mode 100644
index 0000000000..1b840a6204
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled2/Impls_Macros_1.scala
@@ -0,0 +1,29 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl_with_macros_enabled(c: Context) = {
+ import c.mirror._
+
+ val mr = Select(Select(Select(Ident(newTermName("scala")), newTermName("reflect")), newTermName("package")), newTermName("mirror"))
+ val tree1 = Apply(Select(mr, newTermName("reify")), List(Apply(Select(Ident(newTermName("scala")), newTermName("Array")), List(Literal(Constant(2))))))
+ val ttree1 = c.typeCheck(tree1, withMacrosDisabled = false)
+ c.literal(ttree1.toString)
+ }
+
+ def foo_with_macros_enabled = macro impl_with_macros_enabled
+
+ def impl_with_macros_disabled(c: Context) = {
+ import c.mirror._
+
+ val mrPkg = staticModule("scala.reflect.package")
+ val mrSym = selectTerm(mrPkg, "mirror")
+ val NullaryMethodType(mrTpe) = mrSym.typeSignature
+ val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror)
+
+ val tree2 = Apply(Select(Ident(mr), newTermName("reify")), List(Apply(Select(Ident(newTermName("scala")), newTermName("Array")), List(Literal(Constant(2))))))
+ val ttree2 = c.typeCheck(tree2, withMacrosDisabled = true)
+ c.literal(ttree2.toString)
+ }
+
+ def foo_with_macros_disabled = macro impl_with_macros_disabled
+} \ No newline at end of file
diff --git a/test/files/run/macro-typecheck-macrosdisabled2/Test_2.scala b/test/files/run/macro-typecheck-macrosdisabled2/Test_2.scala
new file mode 100644
index 0000000000..bdba39195b
--- /dev/null
+++ b/test/files/run/macro-typecheck-macrosdisabled2/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ println(Macros.foo_with_macros_enabled)
+ println(Macros.foo_with_macros_disabled)
+} \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-consfromsls.check b/test/files/run/macro-undetparams-consfromsls.check
new file mode 100644
index 0000000000..49e9140d5a
--- /dev/null
+++ b/test/files/run/macro-undetparams-consfromsls.check
@@ -0,0 +1,5 @@
+A = ConcreteTypeTag[Int]
+B = ConcreteTypeTag[Nothing]
+List(1)
+A = ConcreteTypeTag[Any]
+List(abc, 1)
diff --git a/test/files/run/macro-undetparams-consfromsls.flags b/test/files/run/macro-undetparams-consfromsls.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-undetparams-consfromsls.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala b/test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala
new file mode 100644
index 0000000000..c22ff96028
--- /dev/null
+++ b/test/files/run/macro-undetparams-consfromsls/Impls_Macros_1.scala
@@ -0,0 +1,17 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def cons_impl[A: c.TypeTag](c: Context)(x: c.Expr[A], xs: c.Expr[List[A]]): c.Expr[List[A]] = c.reify {
+ println("A = " + c.literal(implicitly[c.TypeTag[A]].toString).eval)
+ x.eval :: xs.eval
+ }
+
+ def nil_impl[B: c.TypeTag](c: Context): c.Expr[List[B]] = c.reify {
+ println("B = " + c.literal(implicitly[c.TypeTag[B]].toString).eval)
+ Nil
+ }
+
+ def cons[A](x: A, xs: List[A]): List[A] = macro cons_impl[A]
+
+ def nil[B]: List[B] = macro nil_impl[B]
+} \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-consfromsls/Test_2.scala b/test/files/run/macro-undetparams-consfromsls/Test_2.scala
new file mode 100644
index 0000000000..f2c2ce0051
--- /dev/null
+++ b/test/files/run/macro-undetparams-consfromsls/Test_2.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ import Macros._
+ val xs = cons(1, nil)
+ println(xs)
+ val ys = cons("abc", xs)
+ println(ys)
+} \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-implicitval.check b/test/files/run/macro-undetparams-implicitval.check
new file mode 100644
index 0000000000..6c2b601aa5
--- /dev/null
+++ b/test/files/run/macro-undetparams-implicitval.check
@@ -0,0 +1 @@
+ConcreteTypeTag[Nothing]
diff --git a/test/files/run/macro-undetparams-implicitval.flags b/test/files/run/macro-undetparams-implicitval.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-undetparams-implicitval.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-implicitval/Test.scala b/test/files/run/macro-undetparams-implicitval/Test.scala
new file mode 100644
index 0000000000..5278295451
--- /dev/null
+++ b/test/files/run/macro-undetparams-implicitval/Test.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo[T: TypeTag] = println(implicitly[TypeTag[T]])
+ foo
+} \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-macroitself.check b/test/files/run/macro-undetparams-macroitself.check
new file mode 100644
index 0000000000..e57fc1217b
--- /dev/null
+++ b/test/files/run/macro-undetparams-macroitself.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[String]
diff --git a/test/files/run/macro-undetparams-macroitself.flags b/test/files/run/macro-undetparams-macroitself.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/macro-undetparams-macroitself.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala b/test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala
new file mode 100644
index 0000000000..9d65e8b0da
--- /dev/null
+++ b/test/files/run/macro-undetparams-macroitself/Impls_Macros_1.scala
@@ -0,0 +1,7 @@
+import scala.reflect.makro.Context
+
+object Macros {
+ def impl[T: c.TypeTag](c: Context)(foo: c.Expr[T]): c.Expr[Unit] = c.reify { println(c.literal(implicitly[c.TypeTag[T]].toString).eval) }
+
+ def foo[T](foo: T) = macro impl[T]
+} \ No newline at end of file
diff --git a/test/files/run/macro-undetparams-macroitself/Test_2.scala b/test/files/run/macro-undetparams-macroitself/Test_2.scala
new file mode 100644
index 0000000000..1a93ff1304
--- /dev/null
+++ b/test/files/run/macro-undetparams-macroitself/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ Macros.foo(42)
+ Macros.foo("42")
+} \ No newline at end of file
diff --git a/test/files/run/manifests-new.scala b/test/files/run/manifests-new.scala
new file mode 100644
index 0000000000..4485ce9124
--- /dev/null
+++ b/test/files/run/manifests-new.scala
@@ -0,0 +1,147 @@
+object Test
+{
+ object Variances extends Enumeration {
+ val CO, IN, CONTRA = Value
+ }
+ import Variances.{ CO, IN, CONTRA }
+
+ object SubtypeRelationship extends Enumeration {
+ val NONE, SAME, SUB, SUPER = Value
+ }
+ import SubtypeRelationship.{ NONE, SAME, SUB, SUPER }
+
+ class VarianceTester[T, U, CC[_]](expected: Variances.Value)(
+ implicit ev1: TypeTag[T], ev2: TypeTag[U], ev3: TypeTag[CC[T]], ev4: TypeTag[CC[U]]) {
+
+ def elements = List(ev1.tpe <:< ev2.tpe, ev2.tpe <:< ev1.tpe)
+ def containers = List(ev3.tpe <:< ev4.tpe, ev4.tpe <:< ev3.tpe)
+
+ def isUnrelated = typeCompare[T, U] == NONE
+ def isSame = typeCompare[T, U] == SAME
+ def isSub = typeCompare[T, U] == SUB
+ def isSuper = typeCompare[T, U] == SUPER
+
+ def showsCovariance = (elements == containers)
+ def showsContravariance = (elements == containers.reverse)
+ def showsInvariance = containers forall (_ == isSame)
+
+ def allContainerVariances = List(showsCovariance, showsInvariance, showsContravariance)
+
+ def showsExpectedVariance =
+ if (isUnrelated) allContainerVariances forall (_ == false)
+ else if (isSame) allContainerVariances forall (_ == true)
+ else expected match {
+ case CO => showsCovariance && !showsContravariance && !showsInvariance
+ case IN => showsInvariance && !showsCovariance && !showsContravariance
+ case CONTRA => showsContravariance && !showsCovariance && !showsInvariance
+ }
+ }
+
+ def showsCovariance[T, U, CC[_]](implicit ev1: TypeTag[T], ev2: TypeTag[U], ev3: TypeTag[CC[T]], ev4: TypeTag[CC[U]]) =
+ new VarianceTester[T, U, CC](CO) showsExpectedVariance
+
+ def showsInvariance[T, U, CC[_]](implicit ev1: TypeTag[T], ev2: TypeTag[U], ev3: TypeTag[CC[T]], ev4: TypeTag[CC[U]]) =
+ new VarianceTester[T, U, CC](IN) showsExpectedVariance
+
+ def showsContravariance[T, U, CC[_]](implicit ev1: TypeTag[T], ev2: TypeTag[U], ev3: TypeTag[CC[T]], ev4: TypeTag[CC[U]]) =
+ new VarianceTester[T, U, CC](CONTRA) showsExpectedVariance
+
+ def typeCompare[T, U](implicit ev1: TypeTag[T], ev2: TypeTag[U]) = (ev1.tpe <:< ev2.tpe, ev2.tpe <:< ev1.tpe) match {
+ case (true, true) => SAME
+ case (true, false) => SUB
+ case (false, true) => SUPER
+ case (false, false) => NONE
+ }
+
+ def assertAnyRef[T: TypeTag] = List(
+ typeTag[T].tpe <:< typeTag[Any].tpe,
+ typeTag[T].tpe <:< typeTag[AnyRef].tpe,
+ !(typeTag[T].tpe <:< typeTag[AnyVal].tpe)
+ ) foreach (assert(_, "assertAnyRef"))
+
+ def assertAnyVal[T: TypeTag] = List(
+ typeTag[T].tpe <:< typeTag[Any].tpe,
+ !(typeTag[T].tpe <:< typeTag[AnyRef].tpe),
+ typeTag[T].tpe <:< typeTag[AnyVal].tpe
+ ) foreach (assert(_, "assertAnyVal"))
+
+ def assertSameType[T: TypeTag, U: TypeTag] = assert(typeCompare[T, U] == SAME, "assertSameType")
+ def assertSuperType[T: TypeTag, U: TypeTag] = assert(typeCompare[T, U] == SUPER, "assertSuperType")
+ def assertSubType[T: TypeTag, U: TypeTag] = assert(typeCompare[T, U] == SUB, "assertSubType")
+ def assertNoRelationship[T: TypeTag, U: TypeTag] = assert(typeCompare[T, U] == NONE, "assertNoRelationship")
+
+ def testVariancesVia[T: TypeTag, U: TypeTag] = assert(
+ typeCompare[T, U] == SUB &&
+ showsCovariance[T, U, List] &&
+ showsInvariance[T, U, Set],
+ "testVariancesVia"
+ )
+
+ def runAllTests = {
+ assertAnyVal[AnyVal]
+ assertAnyVal[Unit]
+ assertAnyVal[Int]
+ assertAnyVal[Double]
+ assertAnyVal[Boolean]
+ assertAnyVal[Char]
+
+ assertAnyRef[AnyRef]
+ assertAnyRef[java.lang.Object]
+ assertAnyRef[java.lang.Integer]
+ assertAnyRef[java.lang.Double]
+ assertAnyRef[java.lang.Boolean]
+ assertAnyRef[java.lang.Character]
+ assertAnyRef[String]
+ assertAnyRef[scala.List[String]]
+ assertAnyRef[scala.List[_]]
+
+ // variance doesn't work yet
+ // testVariancesVia[String, Any]
+ // testVariancesVia[String, AnyRef]
+
+ assertSubType[List[String], List[Any]]
+ assertSubType[List[String], List[AnyRef]]
+ assertNoRelationship[List[String], List[AnyVal]]
+
+ assertSubType[List[Int], List[Any]]
+ assertSubType[List[Int], List[AnyVal]]
+ assertNoRelationship[List[Int], List[AnyRef]]
+
+ // Nothing
+ assertSubType[Nothing, Any]
+ assertSubType[Nothing, AnyVal]
+ assertSubType[Nothing, AnyRef]
+ assertSubType[Nothing, String]
+ assertSubType[Nothing, List[String]]
+ assertSubType[Nothing, Null]
+ assertSameType[Nothing, Nothing]
+
+ // Null
+ assertSubType[Null, Any]
+ assertNoRelationship[Null, AnyVal]
+ assertSubType[Null, AnyRef]
+ assertSubType[Null, String]
+ assertSubType[Null, List[String]]
+ assertSameType[Null, Null]
+ assertSuperType[Null, Nothing]
+
+ // Any
+ assertSameType[Any, Any]
+ assertSuperType[Any, AnyVal]
+ assertSuperType[Any, AnyRef]
+ assertSuperType[Any, String]
+ assertSuperType[Any, List[String]]
+ assertSuperType[Any, Null]
+ assertSuperType[Any, Nothing]
+
+ // Misc unrelated types
+ assertNoRelationship[Unit, AnyRef]
+ assertNoRelationship[Unit, Int]
+ assertNoRelationship[Int, Long]
+ assertNoRelationship[Boolean, String]
+ assertNoRelationship[List[Boolean], List[String]]
+ assertNoRelationship[Set[Boolean], Set[String]]
+ }
+
+ def main(args: Array[String]): Unit = runAllTests
+}
diff --git a/test/files/run/manifests.scala b/test/files/run/manifests-old.scala
index 6b6ea80b34..621689a254 100644
--- a/test/files/run/manifests.scala
+++ b/test/files/run/manifests-old.scala
@@ -4,15 +4,15 @@ object Test
val CO, IN, CONTRA = Value
}
import Variances.{ CO, IN, CONTRA }
-
+
object SubtypeRelationship extends Enumeration {
val NONE, SAME, SUB, SUPER = Value
}
import SubtypeRelationship.{ NONE, SAME, SUB, SUPER }
-
+
class VarianceTester[T, U, CC[_]](expected: Variances.Value)(
implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) {
-
+
def elements = List(ev1 <:< ev2, ev2 <:< ev1)
def containers = List(ev3 <:< ev4, ev4 <:< ev3)
@@ -20,13 +20,13 @@ object Test
def isSame = typeCompare[T, U] == SAME
def isSub = typeCompare[T, U] == SUB
def isSuper = typeCompare[T, U] == SUPER
-
+
def showsCovariance = (elements == containers)
def showsContravariance = (elements == containers.reverse)
def showsInvariance = containers forall (_ == isSame)
def allContainerVariances = List(showsCovariance, showsInvariance, showsContravariance)
-
+
def showsExpectedVariance =
if (isUnrelated) allContainerVariances forall (_ == false)
else if (isSame) allContainerVariances forall (_ == true)
@@ -36,64 +36,55 @@ object Test
case CONTRA => showsContravariance && !showsCovariance && !showsInvariance
}
}
-
+
def showsCovariance[T, U, CC[_]](implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) =
new VarianceTester[T, U, CC](CO) showsExpectedVariance
def showsInvariance[T, U, CC[_]](implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) =
new VarianceTester[T, U, CC](IN) showsExpectedVariance
-
+
def showsContravariance[T, U, CC[_]](implicit ev1: Manifest[T], ev2: Manifest[U], ev3: Manifest[CC[T]], ev4: Manifest[CC[U]]) =
new VarianceTester[T, U, CC](CONTRA) showsExpectedVariance
-
- def typeCompare[T, U](implicit ev1: Manifest[T], ev2: Manifest[U]) = {
- // checking types as well
- if ((ev1 <:< ev2) != (ev1.tpe <:< ev2.tpe))
- println("Failed! " + ((ev1, ev2)))
-
- if ((ev2 <:< ev1) != (ev2.tpe <:< ev1.tpe))
- println("Failed! " + ((ev2, ev1)))
-
- (ev1 <:< ev2, ev2 <:< ev1) match {
- case (true, true) => SAME
- case (true, false) => SUB
- case (false, true) => SUPER
- case (false, false) => NONE
- }
+
+ def typeCompare[T, U](implicit ev1: Manifest[T], ev2: Manifest[U]) = (ev1 <:< ev2, ev2 <:< ev1) match {
+ case (true, true) => SAME
+ case (true, false) => SUB
+ case (false, true) => SUPER
+ case (false, false) => NONE
}
-
+
def assertAnyRef[T: Manifest] = List(
manifest[T] <:< manifest[Any],
manifest[T] <:< manifest[AnyRef],
!(manifest[T] <:< manifest[AnyVal])
) foreach (assert(_, "assertAnyRef"))
-
+
def assertAnyVal[T: Manifest] = List(
manifest[T] <:< manifest[Any],
!(manifest[T] <:< manifest[AnyRef]),
manifest[T] <:< manifest[AnyVal]
) foreach (assert(_, "assertAnyVal"))
-
+
def assertSameType[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == SAME, "assertSameType")
def assertSuperType[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == SUPER, "assertSuperType")
def assertSubType[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == SUB, "assertSubType")
def assertNoRelationship[T: Manifest, U: Manifest] = assert(typeCompare[T, U] == NONE, "assertNoRelationship")
-
+
def testVariancesVia[T: Manifest, U: Manifest] = assert(
- typeCompare[T, U] == SUB &&
+ typeCompare[T, U] == SUB &&
showsCovariance[T, U, List] &&
showsInvariance[T, U, Set],
"testVariancesVia"
)
-
+
def runAllTests = {
assertAnyVal[AnyVal]
assertAnyVal[Unit]
- assertAnyVal[Int]
- assertAnyVal[Double]
+ assertAnyVal[Int]
+ assertAnyVal[Double]
assertAnyVal[Boolean]
assertAnyVal[Char]
-
+
assertAnyRef[AnyRef]
assertAnyRef[java.lang.Object]
assertAnyRef[java.lang.Integer]
@@ -103,7 +94,7 @@ object Test
assertAnyRef[String]
assertAnyRef[scala.List[String]]
assertAnyRef[scala.List[_]]
-
+
// variance doesn't work yet
// testVariancesVia[String, Any]
// testVariancesVia[String, AnyRef]
@@ -111,11 +102,11 @@ object Test
assertSubType[List[String], List[Any]]
assertSubType[List[String], List[AnyRef]]
assertNoRelationship[List[String], List[AnyVal]]
-
+
assertSubType[List[Int], List[Any]]
assertSubType[List[Int], List[AnyVal]]
assertNoRelationship[List[Int], List[AnyRef]]
-
+
// Nothing
assertSubType[Nothing, Any]
assertSubType[Nothing, AnyVal]
@@ -124,7 +115,7 @@ object Test
assertSubType[Nothing, List[String]]
assertSubType[Nothing, Null]
assertSameType[Nothing, Nothing]
-
+
// Null
assertSubType[Null, Any]
assertNoRelationship[Null, AnyVal]
@@ -133,7 +124,7 @@ object Test
assertSubType[Null, List[String]]
assertSameType[Null, Null]
assertSuperType[Null, Nothing]
-
+
// Any
assertSameType[Any, Any]
assertSuperType[Any, AnyVal]
@@ -142,7 +133,7 @@ object Test
assertSuperType[Any, List[String]]
assertSuperType[Any, Null]
assertSuperType[Any, Nothing]
-
+
// Misc unrelated types
assertNoRelationship[Unit, AnyRef]
assertNoRelationship[Unit, Int]
@@ -153,4 +144,4 @@ object Test
}
def main(args: Array[String]): Unit = runAllTests
-}
+} \ No newline at end of file
diff --git a/test/files/run/nonlocalreturn.check b/test/files/run/nonlocalreturn.check
new file mode 100644
index 0000000000..aeb2d5e239
--- /dev/null
+++ b/test/files/run/nonlocalreturn.check
@@ -0,0 +1 @@
+Some(1)
diff --git a/test/files/run/nonlocalreturn.scala b/test/files/run/nonlocalreturn.scala
new file mode 100644
index 0000000000..3c1e7420ed
--- /dev/null
+++ b/test/files/run/nonlocalreturn.scala
@@ -0,0 +1,15 @@
+object Test {
+ def wrap[K](body: => K): K = body
+
+ def f(): Option[Int] = {
+ wrap({ return Some(1) ; None })
+ }
+
+ def main(args: Array[String]) {
+ println(f())
+ }
+}
+// java.lang.ClassCastException: scala.Some cannot be cast to scala.None$
+// at Test$$anonfun$f$1.apply(nonlocalreturn.scala:5)
+// at Test$$anonfun$f$1.apply(nonlocalreturn.scala:5)
+// at Test$.wrap(nonlocalreturn.scala:2)
diff --git a/test/files/run/option-fold.check b/test/files/run/option-fold.check
new file mode 100644
index 0000000000..4e3fe99f98
--- /dev/null
+++ b/test/files/run/option-fold.check
@@ -0,0 +1,5 @@
+List()
+List(5)
+-1
+0
+1
diff --git a/test/files/run/option-fold.scala b/test/files/run/option-fold.scala
new file mode 100644
index 0000000000..d554ba4f9b
--- /dev/null
+++ b/test/files/run/option-fold.scala
@@ -0,0 +1,19 @@
+object Test {
+ sealed class A
+ case object B extends A
+ case class C(x: Int) extends A
+
+ def f[T](x: Option[T]) = x.fold(List.empty[T])(List(_))
+ def g(x: Option[A]) = x.fold(-1) {
+ case B => 0
+ case C(x) => x
+ }
+
+ def main(args: Array[String]): Unit = {
+ println(f(None))
+ println(f(Some(5)))
+ println(g(None))
+ println(g(Some(B)))
+ println(g(Some(C(1))))
+ }
+}
diff --git a/test/files/run/packrat3.check b/test/files/run/packrat3.check
index 4d84623ce6..8c10626751 100644
--- a/test/files/run/packrat3.check
+++ b/test/files/run/packrat3.check
@@ -4,4 +4,4 @@
(((List(a, a, a, a, b, b, b, b)~())~List(a, a, a, a))~List(b, b, b, b, c, c, c, c))
Expected failure
``b'' expected but `c' found
-``c'' expected but EOF found
+end of input
diff --git a/test/files/run/patmat_unapp_abstype.check b/test/files/run/patmat_unapp_abstype-new.check
index ac28ccdb95..72239d16cd 100644
--- a/test/files/run/patmat_unapp_abstype.check
+++ b/test/files/run/patmat_unapp_abstype-new.check
@@ -1,2 +1,4 @@
TypeRef
none of the above
+Bar
+Foo
diff --git a/test/files/run/patmat_unapp_abstype-new.flags b/test/files/run/patmat_unapp_abstype-new.flags
new file mode 100644
index 0000000000..ba80cad69b
--- /dev/null
+++ b/test/files/run/patmat_unapp_abstype-new.flags
@@ -0,0 +1 @@
+-Xoldpatmat
diff --git a/test/files/run/patmat_unapp_abstype-new.scala b/test/files/run/patmat_unapp_abstype-new.scala
new file mode 100644
index 0000000000..45496f08a2
--- /dev/null
+++ b/test/files/run/patmat_unapp_abstype-new.scala
@@ -0,0 +1,83 @@
+// abstract types and extractors, oh my!
+trait TypesAPI {
+ trait Type
+
+ // an alternative fix (implemented in the virtual pattern matcher, is to replace the isInstanceOf by a manifest-based run-time test)
+ // that's what typeRefMani is for
+ type TypeRef <: Type //; implicit def typeRefMani: Manifest[TypeRef]
+ val TypeRef: TypeRefExtractor; trait TypeRefExtractor {
+ def apply(x: Int): TypeRef
+ def unapply(x: TypeRef): Option[(Int)]
+ }
+
+ // just for illustration, should follow the same pattern as TypeRef
+ case class MethodType(n: Int) extends Type
+}
+
+// user should not be exposed to the implementation
+trait TypesUser extends TypesAPI {
+ def shouldNotCrash(tp: Type): Unit = {
+ tp match {
+ case TypeRef(x) => println("TypeRef")
+ // the above checks tp.isInstanceOf[TypeRef], which is erased to tp.isInstanceOf[Type]
+ // before calling TypeRef.unapply(tp), which will then crash unless tp.isInstanceOf[TypesImpl#TypeRef] (which is not implied by tp.isInstanceOf[Type])
+ // tp.isInstanceOf[TypesImpl#TypeRef] is equivalent to classOf[TypesImpl#TypeRef].isAssignableFrom(tp.getClass)
+ // this is equivalent to manifest
+ // it is NOT equivalent to manifest[Type] <:< typeRefMani
+ case MethodType(x) => println("MethodType")
+ case _ => println("none of the above")
+ }
+ }
+}
+
+trait TypesImpl extends TypesAPI {
+ object TypeRef extends TypeRefExtractor // this will have a bridged unapply(x: Type) = unapply(x.asInstanceOf[TypeRef])
+ case class TypeRef(n: Int) extends Type // this has a bridge from TypesAPI#Type to TypesImpl#TypeRef
+ // --> the cast in the bridge will fail because the pattern matcher can't type test against the abstract types in TypesUser
+ //lazy val typeRefMani = manifest[TypeRef]
+}
+
+trait Foos {
+ trait Bar
+ type Foo <: Bar
+ trait FooExtractor {
+ def unapply(foo: Foo): Option[Int]
+ }
+ val Foo: FooExtractor
+}
+
+trait RealFoos extends Foos {
+ class Foo(val x: Int) extends Bar
+ object Foo extends FooExtractor {
+ def unapply(foo: Foo): Option[Int] = Some(foo.x)
+ }
+}
+
+trait Intermed extends Foos {
+ def crash(bar: Bar): Unit =
+ bar match {
+ case Foo(x) => println("Foo")
+ case _ => println("Bar")
+ }
+}
+
+object TestUnappStaticallyKnownSynthetic extends TypesImpl with TypesUser {
+ def test() = {
+ shouldNotCrash(TypeRef(10)) // should and does print "TypeRef"
+ // once #1697/#2337 are fixed, this should generate the correct output
+ shouldNotCrash(MethodType(10)) // should print "MethodType" but prints "none of the above" -- good one, pattern matcher!
+ }
+}
+
+object TestUnappDynamicSynth extends RealFoos with Intermed {
+ case class FooToo(n: Int) extends Bar
+ def test() = {
+ crash(FooToo(10))
+ crash(new Foo(5))
+ }
+}
+
+object Test extends App {
+ TestUnappStaticallyKnownSynthetic.test()
+ TestUnappDynamicSynth.test()
+}
diff --git a/test/files/run/patmat_unapp_abstype-old.check b/test/files/run/patmat_unapp_abstype-old.check
new file mode 100644
index 0000000000..72239d16cd
--- /dev/null
+++ b/test/files/run/patmat_unapp_abstype-old.check
@@ -0,0 +1,4 @@
+TypeRef
+none of the above
+Bar
+Foo
diff --git a/test/files/run/patmat_unapp_abstype-old.flags b/test/files/run/patmat_unapp_abstype-old.flags
new file mode 100644
index 0000000000..ba80cad69b
--- /dev/null
+++ b/test/files/run/patmat_unapp_abstype-old.flags
@@ -0,0 +1 @@
+-Xoldpatmat
diff --git a/test/files/run/patmat_unapp_abstype-old.scala b/test/files/run/patmat_unapp_abstype-old.scala
new file mode 100644
index 0000000000..45496f08a2
--- /dev/null
+++ b/test/files/run/patmat_unapp_abstype-old.scala
@@ -0,0 +1,83 @@
+// abstract types and extractors, oh my!
+trait TypesAPI {
+ trait Type
+
+ // an alternative fix (implemented in the virtual pattern matcher, is to replace the isInstanceOf by a manifest-based run-time test)
+ // that's what typeRefMani is for
+ type TypeRef <: Type //; implicit def typeRefMani: Manifest[TypeRef]
+ val TypeRef: TypeRefExtractor; trait TypeRefExtractor {
+ def apply(x: Int): TypeRef
+ def unapply(x: TypeRef): Option[(Int)]
+ }
+
+ // just for illustration, should follow the same pattern as TypeRef
+ case class MethodType(n: Int) extends Type
+}
+
+// user should not be exposed to the implementation
+trait TypesUser extends TypesAPI {
+ def shouldNotCrash(tp: Type): Unit = {
+ tp match {
+ case TypeRef(x) => println("TypeRef")
+ // the above checks tp.isInstanceOf[TypeRef], which is erased to tp.isInstanceOf[Type]
+ // before calling TypeRef.unapply(tp), which will then crash unless tp.isInstanceOf[TypesImpl#TypeRef] (which is not implied by tp.isInstanceOf[Type])
+ // tp.isInstanceOf[TypesImpl#TypeRef] is equivalent to classOf[TypesImpl#TypeRef].isAssignableFrom(tp.getClass)
+ // this is equivalent to manifest
+ // it is NOT equivalent to manifest[Type] <:< typeRefMani
+ case MethodType(x) => println("MethodType")
+ case _ => println("none of the above")
+ }
+ }
+}
+
+trait TypesImpl extends TypesAPI {
+ object TypeRef extends TypeRefExtractor // this will have a bridged unapply(x: Type) = unapply(x.asInstanceOf[TypeRef])
+ case class TypeRef(n: Int) extends Type // this has a bridge from TypesAPI#Type to TypesImpl#TypeRef
+ // --> the cast in the bridge will fail because the pattern matcher can't type test against the abstract types in TypesUser
+ //lazy val typeRefMani = manifest[TypeRef]
+}
+
+trait Foos {
+ trait Bar
+ type Foo <: Bar
+ trait FooExtractor {
+ def unapply(foo: Foo): Option[Int]
+ }
+ val Foo: FooExtractor
+}
+
+trait RealFoos extends Foos {
+ class Foo(val x: Int) extends Bar
+ object Foo extends FooExtractor {
+ def unapply(foo: Foo): Option[Int] = Some(foo.x)
+ }
+}
+
+trait Intermed extends Foos {
+ def crash(bar: Bar): Unit =
+ bar match {
+ case Foo(x) => println("Foo")
+ case _ => println("Bar")
+ }
+}
+
+object TestUnappStaticallyKnownSynthetic extends TypesImpl with TypesUser {
+ def test() = {
+ shouldNotCrash(TypeRef(10)) // should and does print "TypeRef"
+ // once #1697/#2337 are fixed, this should generate the correct output
+ shouldNotCrash(MethodType(10)) // should print "MethodType" but prints "none of the above" -- good one, pattern matcher!
+ }
+}
+
+object TestUnappDynamicSynth extends RealFoos with Intermed {
+ case class FooToo(n: Int) extends Bar
+ def test() = {
+ crash(FooToo(10))
+ crash(new Foo(5))
+ }
+}
+
+object Test extends App {
+ TestUnappStaticallyKnownSynthetic.test()
+ TestUnappDynamicSynth.test()
+}
diff --git a/test/files/run/patmat_unapp_abstype.scala b/test/files/run/patmat_unapp_abstype.scala
deleted file mode 100644
index e5adec5c16..0000000000
--- a/test/files/run/patmat_unapp_abstype.scala
+++ /dev/null
@@ -1,39 +0,0 @@
-// abstract types and extractors, oh my!
-trait TypesAPI {
- trait Type
-
- // an alternative fix (implemented in the virtual pattern matcher, is to replace the isInstanceOf by a manifest-based run-time test)
- // that's what typeRefMani is for
- type TypeRef <: Type //; implicit def typeRefMani: Manifest[TypeRef]
- val TypeRef: TypeRefExtractor; trait TypeRefExtractor {
- def apply(x: Int): TypeRef
- def unapply(x: TypeRef): Option[(Int)]
- }
-
- // just for illustration, should follow the same pattern as TypeRef
- case class MethodType(n: Int) extends Type
-}
-
-// user should not be exposed to the implementation
-trait TypesUser extends TypesAPI {
- def shouldNotCrash(tp: Type): Unit = {
- tp match {
- case TypeRef(x) => println("TypeRef")
- case MethodType(x) => println("MethodType")
- case _ => println("none of the above")
- }
- }
-}
-
-trait TypesImpl extends TypesAPI {
- object TypeRef extends TypeRefExtractor // this will have a bridged unapply(x: Type) = unapply(x.asInstanceOf[TypeRef])
- case class TypeRef(n: Int) extends Type // this has a bridge from TypesAPI#Type to TypesImpl#TypeRef
- // --> the cast in the bridge will fail because the pattern matcher can't type test against the abstract types in TypesUser
- //lazy val typeRefMani = manifest[TypeRef]
-}
-
-object Test extends TypesImpl with TypesUser with App {
- shouldNotCrash(TypeRef(10)) // should and does print "TypeRef"
- // once #1697/#2337 are fixed, this should generate the correct output
- shouldNotCrash(MethodType(10)) // should print "MethodType" but prints "none of the above" -- good one, pattern matcher!
-} \ No newline at end of file
diff --git a/test/files/run/phantomValueClass.check b/test/files/run/phantomValueClass.check
new file mode 100644
index 0000000000..323fae03f4
--- /dev/null
+++ b/test/files/run/phantomValueClass.check
@@ -0,0 +1 @@
+foobar
diff --git a/test/files/run/phantomValueClass.scala b/test/files/run/phantomValueClass.scala
new file mode 100644
index 0000000000..f6509f2189
--- /dev/null
+++ b/test/files/run/phantomValueClass.scala
@@ -0,0 +1,10 @@
+final class Phantom[A](val s: String) extends AnyVal {
+ def compose(p: Phantom[A]): Phantom[A] = new Phantom[A](s+p.s)
+}
+
+object Test extends App {
+ val x = new Phantom[Int]("foo")
+ val y = new Phantom[Int]("bar")
+ val z = x compose y
+ println(z.s)
+}
diff --git a/test/files/run/primitive-sigs-2-new.check b/test/files/run/primitive-sigs-2-new.check
new file mode 100644
index 0000000000..b82ddbeaff
--- /dev/null
+++ b/test/files/run/primitive-sigs-2-new.check
@@ -0,0 +1,7 @@
+T<java.lang.Object>
+List(A, char, class java.lang.Object)
+a
+public <T> java.lang.Object Arr.arr4(java.lang.Object[],scala.reflect.ArrayTag<T>)
+public float[] Arr.arr3(float[][])
+public scala.collection.immutable.List<java.lang.Character> Arr.arr2(java.lang.Character[])
+public scala.collection.immutable.List<java.lang.Object> Arr.arr1(int[])
diff --git a/test/files/run/primitive-sigs-2-new.scala b/test/files/run/primitive-sigs-2-new.scala
new file mode 100644
index 0000000000..7e13014cb2
--- /dev/null
+++ b/test/files/run/primitive-sigs-2-new.scala
@@ -0,0 +1,31 @@
+import java.{ lang => jl }
+
+trait T[A] {
+ def f(): A
+}
+class C extends T[Char] {
+ def f(): Char = 'a'
+}
+class Arr {
+ def arr1(xs: Array[Int]): List[Int] = xs.toList
+ def arr2(xs: Array[jl.Character]): List[jl.Character] = xs.toList
+ def arr3(xss: Array[Array[Float]]): Array[Float] = xss map (_.sum)
+ def arr4[T: ArrayTag](xss: Array[Array[T]]): Array[T] = xss map (_.head)
+}
+
+object Test {
+ val c1: Class[_] = classOf[T[_]]
+ val c2: Class[_] = classOf[C]
+ val c3: Class[_] = classOf[Arr]
+
+ val c1m = c1.getMethods.toList filter (_.getName == "f") map (_.getGenericReturnType.toString)
+ val c2m = c2.getMethods.toList filter (_.getName == "f") map (_.getGenericReturnType.toString)
+ val c3m = c3.getDeclaredMethods.toList map (_.toGenericString)
+
+ def main(args: Array[String]): Unit = {
+ println(c2.getGenericInterfaces.map(_.toString).sorted mkString " ")
+ println(c1m ++ c2m sorted)
+ println(new C f)
+ c3m.sorted foreach println
+ }
+}
diff --git a/test/files/run/primitive-sigs-2.check b/test/files/run/primitive-sigs-2-old.check
index feb0619525..9132b4d8ae 100644
--- a/test/files/run/primitive-sigs-2.check
+++ b/test/files/run/primitive-sigs-2-old.check
@@ -1,7 +1,7 @@
-T<java.lang.Object>
-List(A, char, class java.lang.Object)
-a
-public <T> java.lang.Object Arr.arr4(java.lang.Object[],scala.reflect.Manifest<T>)
-public float[] Arr.arr3(float[][])
-public scala.collection.immutable.List<java.lang.Character> Arr.arr2(java.lang.Character[])
-public scala.collection.immutable.List<java.lang.Object> Arr.arr1(int[])
+T<java.lang.Object>
+List(A, char, class java.lang.Object)
+a
+public <T> java.lang.Object Arr.arr4(java.lang.Object[],scala.reflect.Manifest<T>)
+public float[] Arr.arr3(float[][])
+public scala.collection.immutable.List<java.lang.Character> Arr.arr2(java.lang.Character[])
+public scala.collection.immutable.List<java.lang.Object> Arr.arr1(int[])
diff --git a/test/files/run/primitive-sigs-2.scala b/test/files/run/primitive-sigs-2-old.scala
index b7152f7e3d..b7152f7e3d 100644
--- a/test/files/run/primitive-sigs-2.scala
+++ b/test/files/run/primitive-sigs-2-old.scala
diff --git a/test/files/run/programmatic-main.check b/test/files/run/programmatic-main.check
index d16e2c5178..bdf76ddce1 100644
--- a/test/files/run/programmatic-main.check
+++ b/test/files/run/programmatic-main.check
@@ -4,27 +4,28 @@
namer 2 resolve names, attach symbols to named trees
packageobjects 3 load package objects
typer 4 the meat and potatoes: type the trees
- superaccessors 5 add super accessors in traits and nested classes
- extmethods 6 add extension methods for inline classes
- pickler 7 serialize symbol tables
- refchecks 8 reference/override checking, translate nested objects
- uncurry 9 uncurry, translate function values to anonymous classes
- tailcalls 10 replace tail calls by jumps
- specialize 11 @specialized-driven class and method specialization
- explicitouter 12 this refs to outer pointers, translate patterns
- erasure 13 erase types, add interfaces for traits
- posterasure 14 clean up erased inline classes
- lazyvals 15 allocate bitmaps, translate lazy vals into lazified defs
- lambdalift 16 move nested functions to top level
- constructors 17 move field definitions into constructors
- flatten 18 eliminate inner classes
- mixin 19 mixin composition
- cleanup 20 platform-specific cleanups, generate reflective calls
- icode 21 generate portable intermediate code
- inliner 22 optimization: do inlining
-inlineExceptionHandlers 23 optimization: inline exception handlers
- closelim 24 optimization: eliminate uncalled closures
- dce 25 optimization: eliminate dead code
- jvm 26 generate JVM bytecode
- terminal 27 The last phase in the compiler chain
+ patmat 5 translate match expressions
+ superaccessors 6 add super accessors in traits and nested classes
+ extmethods 7 add extension methods for inline classes
+ pickler 8 serialize symbol tables
+ refchecks 9 reference/override checking, translate nested objects
+ uncurry 10 uncurry, translate function values to anonymous classes
+ tailcalls 11 replace tail calls by jumps
+ specialize 12 @specialized-driven class and method specialization
+ explicitouter 13 this refs to outer pointers, translate patterns
+ erasure 14 erase types, add interfaces for traits
+ posterasure 15 clean up erased inline classes
+ lazyvals 16 allocate bitmaps, translate lazy vals into lazified defs
+ lambdalift 17 move nested functions to top level
+ constructors 18 move field definitions into constructors
+ flatten 19 eliminate inner classes
+ mixin 20 mixin composition
+ cleanup 21 platform-specific cleanups, generate reflective calls
+ icode 22 generate portable intermediate code
+ inliner 23 optimization: do inlining
+inlineExceptionHandlers 24 optimization: inline exception handlers
+ closelim 25 optimization: eliminate uncalled closures
+ dce 26 optimization: eliminate dead code
+ jvm 27 generate JVM bytecode
+ terminal 28 The last phase in the compiler chain
diff --git a/test/files/run/reflect-overload.scala b/test/files/run/reflect-overload.scala
new file mode 100644
index 0000000000..af82a1948d
--- /dev/null
+++ b/test/files/run/reflect-overload.scala
@@ -0,0 +1,16 @@
+object Test extends App {
+ import reflect.mirror._
+
+ val s = "hello world"
+ val sc = symbolOfInstance(s)
+ val st = sc.asType
+ val m = st member newTermName("indexOf")
+ val IntType = definitions.IntClass.asType
+ val indexOf = m resolveOverloaded(actuals = List(IntType))
+ assert(invoke(s, indexOf)('w') == 6)
+ assert((invoke(s, indexOf)('w') match { case x: Int => x }) == 6)
+
+ val m2 = st member newTermName("substring")
+ val substring = m2 resolveOverloaded(actuals = List(IntType, IntType))
+ assert(invoke(s, substring)(2, 6) == "llo ")
+}
diff --git a/test/files/run/reflection-implClass-new.scala b/test/files/run/reflection-implClass-new.scala
new file mode 100644
index 0000000000..27374f2106
--- /dev/null
+++ b/test/files/run/reflection-implClass-new.scala
@@ -0,0 +1,38 @@
+/**
+ * Tries to load a symbol for the `Foo$class` using Scala reflection.
+ * Since trait implementation classes do not get pickling information
+ * symbol for them should be created using fallback mechanism
+ * that exposes Java reflection information dressed up in
+ * a Scala symbol.
+ */
+object Test extends App with Outer {
+ import scala.reflect.mirror
+
+ assert(mirror.classToSymbol(classTag[Foo].erasure).typeSignature.declaration(mirror.newTermName("bar")).typeSignature ==
+ mirror.classToSymbol(classTag[Bar].erasure).typeSignature.declaration(mirror.newTermName("foo")).typeSignature)
+
+ val s1 = implClass(classTag[Foo].erasure)
+ assert(s1 != mirror.NoSymbol)
+ assert(s1.typeSignature != mirror.NoType)
+ assert(s1.companionSymbol.typeSignature != mirror.NoType)
+ assert(s1.companionSymbol.typeSignature.declaration(mirror.newTermName("bar")) != mirror.NoSymbol)
+ val s2 = implClass(classTag[Bar].erasure)
+ assert(s2 != mirror.NoSymbol)
+ assert(s2.typeSignature != mirror.NoType)
+ assert(s2.companionSymbol.typeSignature != mirror.NoType)
+ assert(s2.companionSymbol.typeSignature.declaration(mirror.newTermName("foo")) != mirror.NoSymbol)
+ def implClass(clazz: Class[_]) = {
+ val implClass = Class.forName(clazz.getName + "$class")
+ mirror.classToSymbol(implClass)
+ }
+}
+
+trait Foo {
+ def bar = 1
+}
+
+trait Outer {
+ trait Bar {
+ def foo = 1
+ }
+}
diff --git a/test/files/run/reflection-implClass.scala b/test/files/run/reflection-implClass-old.scala
index 7718b52f33..6583624d8b 100644
--- a/test/files/run/reflection-implClass.scala
+++ b/test/files/run/reflection-implClass-old.scala
@@ -1,5 +1,5 @@
-/**
- * Tries to load a symbol for the `Foo$class` using Scala reflection.
+/**
+ * Tries to load a symbol for the `Foo$class` using Scala reflection.
* Since trait implementation classes do not get pickling information
* symbol for them should be created using fallback mechanism
* that exposes Java reflection information dressed up in
diff --git a/test/files/run/reflection-simple.check b/test/files/run/reflection-simple.check
new file mode 100644
index 0000000000..671d9d2716
--- /dev/null
+++ b/test/files/run/reflection-simple.check
@@ -0,0 +1,45 @@
+Running
+constructor Foo$3
+constructor Object
+method !=
+method !=
+method ##
+method $asInstanceOf
+method $init$
+method $isInstanceOf
+method ==
+method ==
+method _1
+method _2
+method _3
+method a
+method asInstanceOf
+method b
+method c
+method canEqual
+method clone
+method copy
+method copy$default$1
+method copy$default$2
+method copy$default$3
+method eq
+method equals
+method finalize
+method getClass
+method hashCode
+method isInstanceOf
+method ne
+method notify
+method notifyAll
+method productArity
+method productElement
+method productIterator
+method productPrefix
+method synchronized
+method toString
+method wait
+method wait
+method wait
+value a
+value b
+value c
diff --git a/test/files/run/reflection-simple.scala b/test/files/run/reflection-simple.scala
new file mode 100644
index 0000000000..fb3feec3cb
--- /dev/null
+++ b/test/files/run/reflection-simple.scala
@@ -0,0 +1,11 @@
+// a.scala
+// Wed May 2 01:01:22 PDT 2012
+
+object Test {
+ def main(args: Array[String]) {
+ System.out.println("Running")
+ case class Foo(a: Int, b: Int, c: Int)
+ val props = reflect.mirror.classToType(classOf[Foo]).members.filter(_.isTerm).map(_.toString)
+ props.toList.sorted foreach System.out.println
+ }
+}
diff --git a/test/files/run/reify-repl-fail-gracefully.check b/test/files/run/reify-repl-fail-gracefully.check
new file mode 100644
index 0000000000..680db12667
--- /dev/null
+++ b/test/files/run/reify-repl-fail-gracefully.check
@@ -0,0 +1,21 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import language.experimental.macros
+import language.experimental.macros
+
+scala> import scala.reflect.mirror._
+import scala.reflect.mirror._
+
+scala>
+
+scala> reify
+<console>:12: error: macros cannot be partially applied
+ reify
+ ^
+
+scala>
+
+scala>
diff --git a/test/files/run/reify-repl-fail-gracefully.scala b/test/files/run/reify-repl-fail-gracefully.scala
new file mode 100644
index 0000000000..d7a06e8da8
--- /dev/null
+++ b/test/files/run/reify-repl-fail-gracefully.scala
@@ -0,0 +1,10 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |import language.experimental.macros
+ |import scala.reflect.mirror._
+ |
+ |reify
+ """.stripMargin
+}
diff --git a/test/files/run/reify_ann1a.check b/test/files/run/reify_ann1a.check
index 66dce778a8..a3944ae1ee 100644
--- a/test/files/run/reify_ann1a.check
+++ b/test/files/run/reify_ann1a.check
@@ -1,30 +1,30 @@
-{
- @new ann(immutable.this.List.apply[String]("1a")) @new ann(immutable.this.List.apply[String]("1b")) class C[@new ann(immutable.this.List.apply[String]("2a")) @new ann(immutable.this.List.apply[String]("2b")) T] extends scala.AnyRef {
- @new ann(immutable.this.List.apply[String]("3a")) @new ann(immutable.this.List.apply[String]("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply[String]("4a")) @ann(immutable.this.List.apply[String]("4b")) = _;
- def <init>(@new ann(immutable.this.List.apply[String]("3a")) @new ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4a")) @ann(immutable.this.List.apply[String]("4b"))) = {
- super.<init>();
- ()
- };
- @new ann(immutable.this.List.apply[String]("5a")) @new ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = {
- @new ann(immutable.this.List.apply[String]("7a")) @new ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.$plus(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")));
- val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")));
- r.$plus(s)
- }
- };
- ()
-}
-{
- @ann(immutable.this.List.apply[String]("1a")) @ann(immutable.this.List.apply[String]("1b")) class C[@ann(immutable.this.List.apply[String]("2a")) @ann(immutable.this.List.apply[String]("2b")) T] extends scala.AnyRef {
- @ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a")) = _;
- def <init>(@ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a"))): C[T] = {
- C.super.<init>();
- ()
- };
- @ann(immutable.this.List.apply[String]("5a")) @ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = {
- @ann(immutable.this.List.apply[String]("7a")) @ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.+(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")));
- val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")));
- r.+(s)
- }
- };
- ()
-}
+{
+ @new ann(immutable.this.List.apply("1a")) @new ann(immutable.this.List.apply("1b")) class C[@new ann(immutable.this.List.apply("2a")) @new ann(immutable.this.List.apply("2b")) T >: Nothing <: Any] extends Object {
+ @new ann(immutable.this.List.apply("3a")) @new ann(immutable.this.List.apply("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply("4a")) @ann(immutable.this.List.apply("4b")) = _;
+ def <init>(@new ann(immutable.this.List.apply("3a")) @new ann(immutable.this.List.apply("3b")) x: T @ann(immutable.this.List.apply("4a")) @ann(immutable.this.List.apply("4b"))) = {
+ super.<init>();
+ ()
+ };
+ @new ann(immutable.this.List.apply("5a")) @new ann(immutable.this.List.apply("5b")) def f(x: Int @ann(immutable.this.List.apply("6a")) @ann(immutable.this.List.apply("6b"))) = {
+ @new ann(immutable.this.List.apply("7a")) @new ann(immutable.this.List.apply("7b")) val r = x.$plus(3): @ann(immutable.this.List.apply("8a")): @ann(immutable.this.List.apply("8b"));
+ val s = (4: Int @ann(immutable.this.List.apply("9a")) @ann(immutable.this.List.apply("9b")));
+ r.$plus(s)
+ }
+ };
+ ()
+}
+{
+ @ann(immutable.this.List.apply[String]("1a")) @ann(immutable.this.List.apply[String]("1b")) class C[@ann(immutable.this.List.apply[String]("2a")) @ann(immutable.this.List.apply[String]("2b")) T] extends Object {
+ @ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a")) = _;
+ def <init>(@ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a"))): C[T] = {
+ C.super.<init>();
+ ()
+ };
+ @ann(immutable.this.List.apply[String]("5a")) @ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = {
+ @ann(immutable.this.List.apply[String]("7a")) @ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.+(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")));
+ val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")));
+ r.+(s)
+ }
+ };
+ ()
+}
diff --git a/test/files/run/reify_ann1a.scala b/test/files/run/reify_ann1a.scala
index 1ca170904b..6c062ca2c2 100644
--- a/test/files/run/reify_ann1a.scala
+++ b/test/files/run/reify_ann1a.scala
@@ -1,14 +1,10 @@
-import scala.reflect._
-import scala.reflect.api._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
-class ann(bar: List[String]) extends StaticAnnotation
+class ann(bar: List[String]) extends annotation.StaticAnnotation
object Test extends App {
// test 1: reify
- val tree = scala.reflect.Code.lift{
+ val tree = reify{
@ann(bar=List("1a")) @ann(bar=List("1b")) class C[@ann(bar=List("2a")) @ann(bar=List("2b")) T](@ann(bar=List("3a")) @ann(bar=List("3b")) x: T @ann(bar=List("4a")) @ann(bar=List("4b"))) {
@ann(bar=List("5a")) @ann(bar=List("5b")) def f(x: Int @ann(bar=List("6a")) @ann(bar=List("6b"))) = {
@ann(bar=List("7a")) @ann(bar=List("7b")) val r = (x + 3): @ann(bar=List("8a")) @ann(bar=List("8b"))
@@ -20,8 +16,7 @@ object Test extends App {
println(tree.toString)
// test 2: import and typecheck
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val ttree = toolbox.typeCheck(tree)
println(ttree.toString)
diff --git a/test/files/run/reify_ann1b.check b/test/files/run/reify_ann1b.check
index 9bc65a422e..bae838f15f 100644
--- a/test/files/run/reify_ann1b.check
+++ b/test/files/run/reify_ann1b.check
@@ -1,30 +1,30 @@
-{
- @new ann(bar = "1a") @new ann(bar = "1b") class C[@new ann(bar = "2a") @new ann(bar = "2b") T] extends scala.AnyRef {
- @new ann(bar = "3a") @new ann(bar = "3b") <paramaccessor> private[this] val x: T @ann(bar = "4a") @ann(bar = "4b") = _;
- def <init>(@new ann(bar = "3a") @new ann(bar = "3b") x: T @ann(bar = "4a") @ann(bar = "4b")) = {
- super.<init>();
- ()
- };
- @new ann(bar = "5a") @new ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = {
- @new ann(bar = "7a") @new ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.$plus(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a"));
- val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a"));
- r.$plus(s)
- }
- };
- ()
-}
-{
- @ann(bar = "1a") @ann(bar = "1b") class C[@ann(bar = "2a") @ann(bar = "2b") T] extends scala.AnyRef {
- @ann(bar = "3a") @ann(bar = "3b") <paramaccessor> private[this] val x: T @ann(bar = "4b") @ann(bar = "4a") = _;
- def <init>(@ann(bar = "3a") @ann(bar = "3b") x: T @ann(bar = "4b") @ann(bar = "4a")): C[T] = {
- C.super.<init>();
- ()
- };
- @ann(bar = "5a") @ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = {
- @ann(bar = "7a") @ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.+(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a"));
- val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a"));
- r.+(s)
- }
- };
- ()
-}
+{
+ @new ann(bar = "1a") @new ann(bar = "1b") class C[@new ann(bar = "2a") @new ann(bar = "2b") T >: Nothing <: Any] extends Object {
+ @new ann(bar = "3a") @new ann(bar = "3b") <paramaccessor> private[this] val x: T @ann(bar = "4a") @ann(bar = "4b") = _;
+ def <init>(@new ann(bar = "3a") @new ann(bar = "3b") x: T @ann(bar = "4a") @ann(bar = "4b")) = {
+ super.<init>();
+ ()
+ };
+ @new ann(bar = "5a") @new ann(bar = "5b") def f(x: Int @ann(bar = "6a") @ann(bar = "6b")) = {
+ @new ann(bar = "7a") @new ann(bar = "7b") val r = x.$plus(3): @ann(bar = "8a"): @ann(bar = "8b");
+ val s = (4: Int @ann(bar = "9a") @ann(bar = "9b"));
+ r.$plus(s)
+ }
+ };
+ ()
+}
+{
+ @ann(bar = "1a") @ann(bar = "1b") class C[@ann(bar = "2a") @ann(bar = "2b") T] extends Object {
+ @ann(bar = "3a") @ann(bar = "3b") <paramaccessor> private[this] val x: T @ann(bar = "4b") @ann(bar = "4a") = _;
+ def <init>(@ann(bar = "3a") @ann(bar = "3b") x: T @ann(bar = "4b") @ann(bar = "4a")): C[T] = {
+ C.super.<init>();
+ ()
+ };
+ @ann(bar = "5a") @ann(bar = "5b") def f(x: Int @ann(bar = "6b") @ann(bar = "6a")): Int = {
+ @ann(bar = "7a") @ann(bar = "7b") val r: Int @ann(bar = "8b") @ann(bar = "8a") = ((x.+(3): Int @ann(bar = "8a")): Int @ann(bar = "8b") @ann(bar = "8a"));
+ val s: Int @ann(bar = "9b") @ann(bar = "9a") = (4: Int @ann(bar = "9b") @ann(bar = "9a"));
+ r.+(s)
+ }
+ };
+ ()
+}
diff --git a/test/files/run/reify_ann1b.scala b/test/files/run/reify_ann1b.scala
index 9bdc712227..4faddef72c 100644
--- a/test/files/run/reify_ann1b.scala
+++ b/test/files/run/reify_ann1b.scala
@@ -1,14 +1,10 @@
-import scala.reflect._
-import scala.reflect.api._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
-class ann(bar: String) extends ClassfileAnnotation
+class ann(bar: String) extends annotation.ClassfileAnnotation
object Test extends App {
// test 1: reify
- val tree = scala.reflect.Code.lift{
+ val tree = reify{
@ann(bar="1a") @ann(bar="1b") class C[@ann(bar="2a") @ann(bar="2b") T](@ann(bar="3a") @ann(bar="3b") x: T @ann(bar="4a") @ann(bar="4b")) {
@ann(bar="5a") @ann(bar="5b") def f(x: Int @ann(bar="6a") @ann(bar="6b")) = {
@ann(bar="7a") @ann(bar="7b") val r = (x + 3): @ann(bar="8a") @ann(bar="8b")
@@ -20,8 +16,7 @@ object Test extends App {
println(tree.toString)
// test 2: import and typecheck
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val ttree = toolbox.typeCheck(tree)
println(ttree.toString)
diff --git a/test/files/run/reify_ann2a.check b/test/files/run/reify_ann2a.check
new file mode 100644
index 0000000000..5022c50ca8
--- /dev/null
+++ b/test/files/run/reify_ann2a.check
@@ -0,0 +1,44 @@
+{
+ class ann extends StaticAnnotation {
+ <paramaccessor> private[this] val bar: List[String] = _;
+ def <init>(bar: List[String]) = {
+ super.<init>();
+ ()
+ }
+ };
+ @new ann(immutable.this.List.apply("1a")) @new ann(immutable.this.List.apply("1b")) class C[@new ann(immutable.this.List.apply("2a")) @new ann(immutable.this.List.apply("2b")) T >: Nothing <: Any] extends Object {
+ @new ann(immutable.this.List.apply("3a")) @new ann(immutable.this.List.apply("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply("4a")) @ann(immutable.this.List.apply("4b")) = _;
+ def <init>(@new ann(immutable.this.List.apply("3a")) @new ann(immutable.this.List.apply("3b")) x: T @ann(immutable.this.List.apply("4a")) @ann(immutable.this.List.apply("4b"))) = {
+ super.<init>();
+ ()
+ };
+ @new ann(immutable.this.List.apply("5a")) @new ann(immutable.this.List.apply("5b")) def f(x: Int @ann(immutable.this.List.apply("6a")) @ann(immutable.this.List.apply("6b"))) = {
+ @new ann(immutable.this.List.apply("7a")) @new ann(immutable.this.List.apply("7b")) val r = x.$plus(3): @ann(immutable.this.List.apply("8a")): @ann(immutable.this.List.apply("8b"));
+ val s = (4: Int @ann(immutable.this.List.apply("9a")) @ann(immutable.this.List.apply("9b")));
+ r.$plus(s)
+ }
+ };
+ ()
+}
+{
+ class ann extends scala.annotation.Annotation with scala.annotation.StaticAnnotation {
+ <paramaccessor> private[this] val bar: List[String] = _;
+ def <init>(bar: List[String]): ann = {
+ ann.super.<init>();
+ ()
+ }
+ };
+ @ann(immutable.this.List.apply[String]("1a")) @ann(immutable.this.List.apply[String]("1b")) class C[@ann(immutable.this.List.apply[String]("2a")) @ann(immutable.this.List.apply[String]("2b")) T] extends Object {
+ @ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) <paramaccessor> private[this] val x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a")) = _;
+ def <init>(@ann(immutable.this.List.apply[String]("3a")) @ann(immutable.this.List.apply[String]("3b")) x: T @ann(immutable.this.List.apply[String]("4b")) @ann(immutable.this.List.apply[String]("4a"))): C[T] = {
+ C.super.<init>();
+ ()
+ };
+ @ann(immutable.this.List.apply[String]("5a")) @ann(immutable.this.List.apply[String]("5b")) def f(x: Int @ann(immutable.this.List.apply[String]("6b")) @ann(immutable.this.List.apply[String]("6a"))): Int = {
+ @ann(immutable.this.List.apply[String]("7a")) @ann(immutable.this.List.apply[String]("7b")) val r: Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")) = ((x.+(3): Int @ann(immutable.this.List.apply[String]("8a"))): Int @ann(immutable.this.List.apply[String]("8b")) @ann(immutable.this.List.apply[String]("8a")));
+ val s: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")) = (4: Int @ann(immutable.this.List.apply[String]("9b")) @ann(immutable.this.List.apply[String]("9a")));
+ r.+(s)
+ }
+ };
+ ()
+}
diff --git a/test/files/neg/reify_ann2a.scala b/test/files/run/reify_ann2a.scala
index 8de0984074..a1723c221d 100644
--- a/test/files/neg/reify_ann2a.scala
+++ b/test/files/run/reify_ann2a.scala
@@ -1,13 +1,9 @@
-import scala.reflect._
-import scala.reflect.api._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
// test 1: reify
- val tree = scala.reflect.Code.lift{
- class ann(bar: List[String]) extends StaticAnnotation
+ val tree = reify{
+ class ann(bar: List[String]) extends annotation.StaticAnnotation
@ann(bar=List("1a")) @ann(bar=List("1b")) class C[@ann(bar=List("2a")) @ann(bar=List("2b")) T](@ann(bar=List("3a")) @ann(bar=List("3b")) x: T @ann(bar=List("4a")) @ann(bar=List("4b"))) {
@ann(bar=List("5a")) @ann(bar=List("5b")) def f(x: Int @ann(bar=List("6a")) @ann(bar=List("6b"))) = {
@@ -20,8 +16,7 @@ object Test extends App {
println(tree.toString)
// test 2: import and typecheck
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val ttree = toolbox.typeCheck(tree)
println(ttree.toString)
diff --git a/test/files/run/reify_ann3.check b/test/files/run/reify_ann3.check
new file mode 100644
index 0000000000..9452a9701e
--- /dev/null
+++ b/test/files/run/reify_ann3.check
@@ -0,0 +1,21 @@
+{
+ class Tree[A >: Nothing <: Any, B >: Nothing <: Any] extends Object {
+ @new inline @getter() final <paramaccessor> val key: A = _;
+ def <init>(key: A) = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+}
+{
+ class Tree[A, B] extends Object {
+ final <paramaccessor> private[this] val key: A = _;
+ @inline @scala.annotation.meta.getter final <stable> <accessor> <paramaccessor> def key: A = Tree.this.key;
+ def <init>(key: A): Tree[A,B] = {
+ Tree.super.<init>();
+ ()
+ }
+ };
+ ()
+}
diff --git a/test/files/run/reify_ann3.scala b/test/files/run/reify_ann3.scala
new file mode 100644
index 0000000000..d65e641619
--- /dev/null
+++ b/test/files/run/reify_ann3.scala
@@ -0,0 +1,19 @@
+import scala.reflect.mirror._
+import scala.annotation._
+import scala.annotation.meta._
+
+object Test extends App {
+ // test 1: reify
+ val tree = reify{
+ class Tree[A, +B](@(inline @getter) final val key: A)
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val toolbox = mkToolBox()
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(tree)
+}
diff --git a/test/files/run/reify_ann4.check b/test/files/run/reify_ann4.check
new file mode 100644
index 0000000000..406ee7bc08
--- /dev/null
+++ b/test/files/run/reify_ann4.check
@@ -0,0 +1,32 @@
+{
+ class D extends StaticAnnotation {
+ def <init>() = {
+ super.<init>();
+ ()
+ }
+ };
+ class C extends Object {
+ def <init>() = {
+ super.<init>();
+ ()
+ }
+ };
+ val c1 = new C @D();
+ ()
+}
+{
+ class D extends scala.annotation.Annotation with scala.annotation.StaticAnnotation {
+ def <init>(): D = {
+ D.super.<init>();
+ ()
+ }
+ };
+ class C extends Object {
+ def <init>(): C = {
+ C.super.<init>();
+ ()
+ }
+ };
+ val c1: C = new C @D();
+ ()
+}
diff --git a/test/files/run/reify_ann4.scala b/test/files/run/reify_ann4.scala
new file mode 100644
index 0000000000..5655812689
--- /dev/null
+++ b/test/files/run/reify_ann4.scala
@@ -0,0 +1,23 @@
+import scala.reflect.mirror._
+import scala.annotation._
+import scala.annotation.meta._
+
+object Test extends App {
+ // test 1: reify
+ val tree = reify{
+ class D extends StaticAnnotation
+ class C
+ val c1 = new C @D
+ //val c2 = (new C) @D // illegal syntax
+ //val c3 = c1 @D // illegal syntax
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val toolbox = mkToolBox()
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(tree)
+}
diff --git a/test/files/run/reify_ann5.check b/test/files/run/reify_ann5.check
new file mode 100644
index 0000000000..ecf08eebb2
--- /dev/null
+++ b/test/files/run/reify_ann5.check
@@ -0,0 +1,22 @@
+{
+ class C extends Object {
+ @new inline @beanGetter() @new BeanProperty() <paramaccessor> val x: Int = _;
+ def <init>(x: Int) = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+}
+{
+ class C extends Object {
+ @scala.beans.BeanProperty <paramaccessor> private[this] val x: Int = _;
+ <stable> <accessor> <paramaccessor> def x: Int = C.this.x;
+ def <init>(x: Int): C = {
+ C.super.<init>();
+ ()
+ };
+ @inline @scala.annotation.meta.beanGetter def getX(): Int = C.this.x
+ };
+ ()
+}
diff --git a/test/files/run/reify_ann5.scala b/test/files/run/reify_ann5.scala
new file mode 100644
index 0000000000..aecc61de46
--- /dev/null
+++ b/test/files/run/reify_ann5.scala
@@ -0,0 +1,20 @@
+import scala.reflect.mirror._
+import scala.annotation._
+import scala.annotation.meta._
+import scala.beans._
+
+object Test extends App {
+ // test 1: reify
+ val tree = reify{
+ class C(@BeanProperty @(inline @beanGetter) val x: Int)
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val toolbox = mkToolBox()
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(tree)
+}
diff --git a/test/files/run/reify_anonymous.scala b/test/files/run/reify_anonymous.scala
index af16f2f8fd..cd740f0190 100644
--- a/test/files/run/reify_anonymous.scala
+++ b/test/files/run/reify_anonymous.scala
@@ -1,13 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
println(new {def x = 2; def y = x * x}.y)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_classfileann_a.check b/test/files/run/reify_classfileann_a.check
index 419d916907..685ecf5de6 100644
--- a/test/files/run/reify_classfileann_a.check
+++ b/test/files/run/reify_classfileann_a.check
@@ -1,18 +1,18 @@
-{
- @new ann(bar = "1", quux = Array("2", "3"), baz = new ann(bar = "4")) class C extends scala.AnyRef {
- def <init>() = {
- super.<init>();
- ()
- }
- };
- ()
-}
-{
- @ann(bar = "1", quux = ["2", "3"], baz = ann(bar = "4")) class C extends scala.AnyRef {
- def <init>(): C = {
- C.super.<init>();
- ()
- }
- };
- ()
-}
+{
+ @new ann(bar = "1", quux = Array("2", "3"), baz = new ann(bar = "4")) class C extends Object {
+ def <init>() = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+}
+{
+ @ann(bar = "1", quux = ["2", "3"], baz = ann(bar = "4")) class C extends Object {
+ def <init>(): C = {
+ C.super.<init>();
+ ()
+ }
+ };
+ ()
+}
diff --git a/test/files/run/reify_classfileann_a.scala b/test/files/run/reify_classfileann_a.scala
index c77bd3b8a2..9aec69b4a3 100644
--- a/test/files/run/reify_classfileann_a.scala
+++ b/test/files/run/reify_classfileann_a.scala
@@ -1,21 +1,16 @@
-import scala.reflect._
-import scala.reflect.api._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
-class ann(bar: String, quux: Array[String] = Array(), baz: ann = null) extends ClassfileAnnotation
+class ann(bar: String, quux: Array[String] = Array(), baz: ann = null) extends annotation.ClassfileAnnotation
object Test extends App {
// test 1: reify
- val tree = scala.reflect.Code.lift{
+ val tree = reify{
@ann(bar="1", quux=Array("2", "3"), baz = new ann(bar = "4")) class C
}.tree
println(tree.toString)
// test 2: import and typecheck
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val ttree = toolbox.typeCheck(tree)
println(ttree.toString)
diff --git a/test/files/run/reify_classfileann_b.check b/test/files/run/reify_classfileann_b.check
new file mode 100644
index 0000000000..0aac9aeb2a
--- /dev/null
+++ b/test/files/run/reify_classfileann_b.check
@@ -0,0 +1,20 @@
+{
+ class C extends Object {
+ def <init>() = {
+ super.<init>();
+ ()
+ };
+ def x: Int = 2: @ann(bar = "1",quux = Array("2", "3"),baz = new ann(bar = "4"))
+ };
+ ()
+}
+{
+ class C extends Object {
+ def <init>(): C = {
+ C.super.<init>();
+ ()
+ };
+ def x: Int = (2: Int(2) @ann(bar = "1", quux = ["2", "3"], baz = ann(bar = "4")))
+ };
+ ()
+}
diff --git a/test/files/run/reify_classfileann_b.scala b/test/files/run/reify_classfileann_b.scala
new file mode 100644
index 0000000000..a37f20e72e
--- /dev/null
+++ b/test/files/run/reify_classfileann_b.scala
@@ -0,0 +1,23 @@
+import scala.reflect.mirror._
+
+class ann(bar: String, quux: Array[String] = Array(), baz: ann = null) extends annotation.ClassfileAnnotation
+
+object Test extends App {
+ // test 1: reify
+ val tree = reify{
+ class C {
+ def x: Int = {
+ 2: @ann(bar="1", quux=Array("2", "3"), baz = new ann(bar = "4"))
+ }
+ }
+ }.tree
+ println(tree.toString)
+
+ // test 2: import and typecheck
+ val toolbox = mkToolBox()
+ val ttree = toolbox.typeCheck(tree)
+ println(ttree.toString)
+
+ // test 3: import and compile
+ toolbox.runExpr(tree)
+} \ No newline at end of file
diff --git a/test/files/run/reify_closure1.scala b/test/files/run/reify_closure1.scala
index 7cb3aff17d..3f5c8a8724 100644
--- a/test/files/run/reify_closure1.scala
+++ b/test/files/run/reify_closure1.scala
@@ -1,15 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
def foo[T](ys: List[T]): Int => Int = {
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reify{(x: Int) => {
x
}}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/files/run/reify_closure2a.scala b/test/files/run/reify_closure2a.scala
index cf367aa63f..f5669a0e2c 100644
--- a/test/files/run/reify_closure2a.scala
+++ b/test/files/run/reify_closure2a.scala
@@ -1,15 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
def foo(y: Int): Int => Int = {
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reify{(x: Int) => {
x + y
}}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/files/run/reify_closure3a.scala b/test/files/run/reify_closure3a.scala
index d322b970b6..056a705d7d 100644
--- a/test/files/run/reify_closure3a.scala
+++ b/test/files/run/reify_closure3a.scala
@@ -1,17 +1,14 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
def foo(y: Int): Int => Int = {
def y1 = y
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reify{(x: Int) => {
x + y1
}}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/files/run/reify_closure4a.scala b/test/files/run/reify_closure4a.scala
index bbedd7e092..a63d20e561 100644
--- a/test/files/run/reify_closure4a.scala
+++ b/test/files/run/reify_closure4a.scala
@@ -1,17 +1,14 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
def foo(y: Int): Int => Int = {
val y1 = y
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reify{(x: Int) => {
x + y1
}}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/files/run/reify_closure5a.scala b/test/files/run/reify_closure5a.scala
index 193e18103a..2e8b413f4c 100644
--- a/test/files/run/reify_closure5a.scala
+++ b/test/files/run/reify_closure5a.scala
@@ -1,19 +1,18 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- def foo[T](ys: List[T]): Int => Int = {
- val fun = reflect.Code.lift{(x: Int) => {
+ def foo[T: TypeTag](ys: List[T]): Int => Int = {
+ val fun = reify{(x: Int) => {
x + ys.length
}}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun.tree)
dyn.asInstanceOf[Int => Int]
}
- println(foo(List(1, 2, 3))(10))
- println(foo(List(1, 2, 3, 4))(10))
+ var fun1 = foo(List(1, 2, 3))
+ println(fun1(10))
+ var fun2 = foo(List(1, 2, 3, 4))
+ println(fun2(10))
}
diff --git a/test/files/run/reify_closure6.scala b/test/files/run/reify_closure6.scala
index 6aff83cb94..2cbd4ce819 100644
--- a/test/files/run/reify_closure6.scala
+++ b/test/files/run/reify_closure6.scala
@@ -1,13 +1,11 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
var q = 0
- def foo[T](ys: List[T]): Int => Int = {
+ def foo[T: TypeTag](ys: List[T]): Int => Int = {
val z = 1
var y = 0
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reify{(x: Int) => {
y += 1
q += 1
println("q = " + q)
@@ -15,13 +13,14 @@ object Test extends App {
x + ys.length * z + q + y
}}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun.tree)
dyn.asInstanceOf[Int => Int]
}
- println("first invocation = " + foo(List(1, 2, 3))(10))
- println("second invocation = " + foo(List(1, 2, 3, 4))(10))
+ val fun1 = foo(List(1, 2, 3))
+ println("first invocation = " + fun1(10))
+ val fun2 = foo(List(1, 2, 3, 4))
+ println("second invocation = " + fun2(10))
println("q after second invocation = " + q)
} \ No newline at end of file
diff --git a/test/files/run/reify_closure7.scala b/test/files/run/reify_closure7.scala
index 46002d8d6c..b9f87dbdeb 100644
--- a/test/files/run/reify_closure7.scala
+++ b/test/files/run/reify_closure7.scala
@@ -1,14 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
var q = 0
var clo: Int => Int = null
- def foo[T](ys: List[T]): Int => Int = {
+ def foo[T: TypeTag](ys: List[T]): Int => Int = {
val z = 1
var y = 0
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reify{(x: Int) => {
y += 1
q += 1
println("q = " + q)
@@ -17,8 +15,7 @@ object Test extends App {
}}
if (clo == null) {
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun.tree)
clo = dyn.asInstanceOf[Int => Int]
}
@@ -26,6 +23,8 @@ object Test extends App {
clo
}
- println("first invocation = " + foo(List(1, 2, 3))(10))
- println("second invocation = " + foo(List(1, 2, 3, 4))(10))
+ val fun1 = foo(List(1, 2, 3))
+ println("first invocation = " + fun1(10))
+ val fun2 = foo(List(1, 2, 3, 4))
+ println("second invocation = " + fun2(10))
}
diff --git a/test/files/run/reify_closure8a.scala b/test/files/run/reify_closure8a.scala
index 805d8ff855..9de121b42f 100644
--- a/test/files/run/reify_closure8a.scala
+++ b/test/files/run/reify_closure8a.scala
@@ -1,15 +1,11 @@
-import scala.reflect.Code._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
class Foo(val y: Int) {
- def fun = lift{y}
+ def fun = reify{y}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(new Foo(10).fun.tree)
val foo = dyn.asInstanceOf[Int]
println(foo)
diff --git a/test/files/run/reify_closure8b.check b/test/files/run/reify_closure8b.check
new file mode 100644
index 0000000000..e0ec7d2c8f
--- /dev/null
+++ b/test/files/run/reify_closure8b.check
@@ -0,0 +1,3 @@
+scala.reflect.runtime.ToolBoxes$ToolBox$ToolBoxError: reflective compilation has failed:
+
+value y is not a member of Test.Foo
diff --git a/test/files/run/reify_closure8b.scala b/test/files/run/reify_closure8b.scala
new file mode 100644
index 0000000000..431da3230e
--- /dev/null
+++ b/test/files/run/reify_closure8b.scala
@@ -0,0 +1,18 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ // will fail because y is a private field
+ // reification doesn't magically make unavailable stuff available
+ class Foo(y: Int) {
+ def fun = reify{y}
+ }
+
+ try {
+ val dyn = mkToolBox().runExpr(new Foo(10).fun.tree)
+ val foo = dyn.asInstanceOf[Int]
+ println(foo)
+ } catch {
+ case ex: Throwable =>
+ println(ex)
+ }
+}
diff --git a/test/files/run/reify_closures10.scala b/test/files/run/reify_closures10.scala
index b6ec8e8911..0ccce77a94 100644
--- a/test/files/run/reify_closures10.scala
+++ b/test/files/run/reify_closures10.scala
@@ -1,14 +1,10 @@
-import scala.reflect.Code._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
val x = 2
val y = 3
- val code = lift{println(x + y); x + y}
+ val code = reify{println(x + y); x + y}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
println(toolbox.runExpr(code.tree))
}
diff --git a/test/files/run/reify_complex.scala b/test/files/run/reify_complex.scala
index 0d9aeb28c5..ecc25ffca5 100644
--- a/test/files/run/reify_complex.scala
+++ b/test/files/run/reify_complex.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class Complex(val re: Double, val im: Double) {
def + (that: Complex) =
new Complex(re + that.re, im + that.im)
@@ -22,9 +20,5 @@ object Test extends App {
}
val x = new Complex(2, 1); val y = new Complex(1, 3)
println(x + y)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/pending/run/reify_csv.check b/test/files/run/reify_csv.check
index b56f4bb50b..b56f4bb50b 100644
--- a/test/pending/run/reify_csv.check
+++ b/test/files/run/reify_csv.check
diff --git a/test/pending/run/reify_csv.scala b/test/files/run/reify_csv.scala
index a6a616fab0..966521575c 100644
--- a/test/pending/run/reify_csv.scala
+++ b/test/files/run/reify_csv.scala
@@ -1,6 +1,4 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
val csv = """
@@ -18,7 +16,7 @@ object Test extends App {
val fields = csv.head.split(";").map{_.trim()}.toList
println(fields)
- val code = scala.reflect.Code.lift({
+ reify({
object Csv {
case class record(`phase name`: String, id: String, description: String)
@@ -33,9 +31,5 @@ object Test extends App {
}
Csv.record.parse(csv) foreach println
- })
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }).eval
}
diff --git a/test/files/run/reify_extendbuiltins.scala b/test/files/run/reify_extendbuiltins.scala
index 0aaec7cdf2..f95e9ab6ec 100644
--- a/test/files/run/reify_extendbuiltins.scala
+++ b/test/files/run/reify_extendbuiltins.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
def fact(n: Int): BigInt =
if (n == 0) 1 else fact(n-1) * n
class Factorizer(n: Int) {
@@ -12,9 +10,5 @@ object Test extends App {
implicit def int2fact(n: Int) = new Factorizer(n)
println("10! = " + (10!))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_for1.scala b/test/files/run/reify_for1.scala
index d1b60d878b..9d1e32f7e5 100644
--- a/test/files/run/reify_for1.scala
+++ b/test/files/run/reify_for1.scala
@@ -1,15 +1,9 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
val sumOfSquares1 = (for (i <- 1 to 100; if (i % 3 == 0)) yield Math.pow(i, 2)).sum
val sumOfSquares2 = (1 to 100).filter(_ % 3 == 0).map(Math.pow(_, 2)).sum
assert(sumOfSquares1 == sumOfSquares2)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_fors.flags b/test/files/run/reify_fors.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/reify_fors.flags
diff --git a/test/files/run/reify_fors.scala b/test/files/run/reify_fors.scala
index 27ee85d18b..635fce049e 100644
--- a/test/files/run/reify_fors.scala
+++ b/test/files/run/reify_fors.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
object Persons {
/** A list of persons. To create a list, we use Predef.List
* which takes a variable number of arguments and constructs
@@ -98,9 +96,5 @@ object Test extends App {
val ys = List(2.0, 1.0, 3.0)
println("scalProd(" + xs + ", " + ys +") = " + scalProd(xs, ys))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_generic.scala b/test/files/run/reify_generic.scala
index 6a4ff148c4..7033c4e237 100644
--- a/test/files/run/reify_generic.scala
+++ b/test/files/run/reify_generic.scala
@@ -1,14 +1,8 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
val product = List(1, 2, 3).head * List[Any](4, 2, 0).head.asInstanceOf[Int]
println(product)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_generic2.scala b/test/files/run/reify_generic2.scala
index 9413f41eb5..8f9def318e 100644
--- a/test/files/run/reify_generic2.scala
+++ b/test/files/run/reify_generic2.scala
@@ -1,15 +1,9 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C
val product = List(new C, new C).length * List[C](new C, new C).length
println(product)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_getter.scala b/test/files/run/reify_getter.scala
index 33f36888a7..8bae293e72 100644
--- a/test/files/run/reify_getter.scala
+++ b/test/files/run/reify_getter.scala
@@ -1,18 +1,15 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
class C {
val x = 2
}
new C().x
- };
+ }
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val evaluated = toolbox.runExpr(code.tree)
println("evaluated = " + evaluated)
}
diff --git a/test/files/run/reify_implicits.check b/test/files/run/reify_implicits-new.check
index e3aeb20f6b..e3aeb20f6b 100644
--- a/test/files/run/reify_implicits.check
+++ b/test/files/run/reify_implicits-new.check
diff --git a/test/files/run/reify_implicits-new.scala b/test/files/run/reify_implicits-new.scala
new file mode 100644
index 0000000000..69198391d1
--- /dev/null
+++ b/test/files/run/reify_implicits-new.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ reify {
+ implicit def arrayWrapper[A : ArrayTag](x: Array[A]) =
+ new {
+ def sort(p: (A, A) => Boolean) = {
+ util.Sorting.stableSort(x, p); x
+ }
+ }
+ val x = Array(2, 3, 1, 4)
+ println("x = "+ x.sort((x: Int, y: Int) => x < y).toList)
+ }.eval
+}
diff --git a/test/files/run/reify_implicits-old.check b/test/files/run/reify_implicits-old.check
new file mode 100644
index 0000000000..e3aeb20f6b
--- /dev/null
+++ b/test/files/run/reify_implicits-old.check
@@ -0,0 +1 @@
+x = List(1, 2, 3, 4)
diff --git a/test/files/run/reify_implicits.scala b/test/files/run/reify_implicits-old.scala
index 953eabe6c2..60971c3cfb 100644
--- a/test/files/run/reify_implicits.scala
+++ b/test/files/run/reify_implicits-old.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
implicit def arrayWrapper[A : ClassManifest](x: Array[A]) =
new {
def sort(p: (A, A) => Boolean) = {
@@ -12,9 +10,5 @@ object Test extends App {
}
val x = Array(2, 3, 1, 4)
println("x = "+ x.sort((x: Int, y: Int) => x < y).toList)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_inheritance.scala b/test/files/run/reify_inheritance.scala
index 78a64c264e..dd86c355a3 100644
--- a/test/files/run/reify_inheritance.scala
+++ b/test/files/run/reify_inheritance.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C {
def x = 2
def y = x * x
@@ -14,9 +12,5 @@ object Test extends App {
}
println(new D().y * new C().x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_inner1.scala b/test/files/run/reify_inner1.scala
index 546fe36d16..ea77ece6df 100644
--- a/test/files/run/reify_inner1.scala
+++ b/test/files/run/reify_inner1.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C {
class D {
val x = 2
@@ -13,9 +11,5 @@ object Test extends App {
val outer = new C()
val inner = new outer.D()
println(inner.x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_inner2.scala b/test/files/run/reify_inner2.scala
index 613614b989..67c403f7e5 100644
--- a/test/files/run/reify_inner2.scala
+++ b/test/files/run/reify_inner2.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C {
object D {
val x = 2
@@ -13,9 +11,5 @@ object Test extends App {
val outer = new C()
val inner = outer.D
println(inner.x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_inner3.scala b/test/files/run/reify_inner3.scala
index e9fb636dce..ad401d81da 100644
--- a/test/files/run/reify_inner3.scala
+++ b/test/files/run/reify_inner3.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
object C {
class D {
val x = 2
@@ -13,9 +11,5 @@ object Test extends App {
val outer = C
val inner = new outer.D
println(inner.x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_inner4.scala b/test/files/run/reify_inner4.scala
index 33870b0983..140c8e9ed4 100644
--- a/test/files/run/reify_inner4.scala
+++ b/test/files/run/reify_inner4.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
object C {
object D {
val x = 2
@@ -13,9 +11,5 @@ object Test extends App {
val outer = C
val inner = outer.D
println(inner.x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/pending/run/reify_lazyevaluation.check b/test/files/run/reify_lazyevaluation.check
index 1c7f96cd96..1c7f96cd96 100644
--- a/test/pending/run/reify_lazyevaluation.check
+++ b/test/files/run/reify_lazyevaluation.check
diff --git a/test/pending/run/reify_lazyevaluation.scala b/test/files/run/reify_lazyevaluation.scala
index 0720a7c979..1a0c858914 100644
--- a/test/pending/run/reify_lazyevaluation.scala
+++ b/test/files/run/reify_lazyevaluation.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
object lazyLib {
/** Delay the evaluation of an expression until it is needed. */
@@ -56,9 +54,5 @@ object Test extends App {
println("sl2 = " + sl2)
println("sl2() = " + sl2())
println("sl2 = " + sl2)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_maps.flags b/test/files/run/reify_maps.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/reify_maps.flags
diff --git a/test/files/run/reify_maps.scala b/test/files/run/reify_maps.scala
index d3d95ffa24..3fcc21892f 100644
--- a/test/files/run/reify_maps.scala
+++ b/test/files/run/reify_maps.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
val colors = Map("red" -> 0xFF0000,
"turquoise" -> 0x00FFFF,
"black" -> 0x000000,
@@ -17,9 +15,5 @@ object Test extends App {
"Unknown color: " + name
}
)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_metalevel_breach_+0_refers_to_1.check b/test/files/run/reify_metalevel_breach_+0_refers_to_1.check
new file mode 100644
index 0000000000..5bfed17f8e
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_+0_refers_to_1.check
@@ -0,0 +1 @@
+evaluated = 2 \ No newline at end of file
diff --git a/test/files/run/reify_metalevel_breach_+0_refers_to_1.scala b/test/files/run/reify_metalevel_breach_+0_refers_to_1.scala
new file mode 100644
index 0000000000..fe23bc8438
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_+0_refers_to_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val code = reify{
+ val x = 2
+ val inner = reify{x}
+ inner.eval
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_metalevel_breach_-1_refers_to_0_a.check b/test/files/run/reify_metalevel_breach_-1_refers_to_0_a.check
new file mode 100644
index 0000000000..5bfed17f8e
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_-1_refers_to_0_a.check
@@ -0,0 +1 @@
+evaluated = 2 \ No newline at end of file
diff --git a/test/files/run/reify_metalevel_breach_-1_refers_to_0_a.scala b/test/files/run/reify_metalevel_breach_-1_refers_to_0_a.scala
new file mode 100644
index 0000000000..5d98a38592
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_-1_refers_to_0_a.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val x = 2
+ val outer = reify{reify{x}}
+ val code = reify{outer.eval.eval}
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_metalevel_breach_-1_refers_to_0_b.check b/test/files/run/reify_metalevel_breach_-1_refers_to_0_b.check
new file mode 100644
index 0000000000..5bfed17f8e
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_-1_refers_to_0_b.check
@@ -0,0 +1 @@
+evaluated = 2 \ No newline at end of file
diff --git a/test/files/run/reify_metalevel_breach_-1_refers_to_0_b.scala b/test/files/run/reify_metalevel_breach_-1_refers_to_0_b.scala
new file mode 100644
index 0000000000..ca31d83acd
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_-1_refers_to_0_b.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val x = 2
+ val code = reify{
+ {
+ val inner = reify{reify{x}}
+ inner.eval
+ }.eval
+ }
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_metalevel_breach_-1_refers_to_1.check b/test/files/run/reify_metalevel_breach_-1_refers_to_1.check
new file mode 100644
index 0000000000..5bfed17f8e
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_-1_refers_to_1.check
@@ -0,0 +1 @@
+evaluated = 2 \ No newline at end of file
diff --git a/test/files/run/reify_metalevel_breach_-1_refers_to_1.scala b/test/files/run/reify_metalevel_breach_-1_refers_to_1.scala
new file mode 100644
index 0000000000..56d85c6ba1
--- /dev/null
+++ b/test/files/run/reify_metalevel_breach_-1_refers_to_1.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val code = reify{
+ val x = 2
+ val inner = reify{reify{x}}
+ inner.eval.eval
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_nested_inner_refers_to_global.check b/test/files/run/reify_nested_inner_refers_to_global.check
new file mode 100644
index 0000000000..7ff4c83d37
--- /dev/null
+++ b/test/files/run/reify_nested_inner_refers_to_global.check
@@ -0,0 +1 @@
+evaluated = 2
diff --git a/test/files/run/reify_nested_inner_refers_to_global.scala b/test/files/run/reify_nested_inner_refers_to_global.scala
new file mode 100644
index 0000000000..14899bcf99
--- /dev/null
+++ b/test/files/run/reify_nested_inner_refers_to_global.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val code = {
+ val x = 2
+ reify{
+ reify{x}.eval
+ }
+ }
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_nested_inner_refers_to_local.check b/test/files/run/reify_nested_inner_refers_to_local.check
new file mode 100644
index 0000000000..5bfed17f8e
--- /dev/null
+++ b/test/files/run/reify_nested_inner_refers_to_local.check
@@ -0,0 +1 @@
+evaluated = 2 \ No newline at end of file
diff --git a/test/files/run/reify_nested_inner_refers_to_local.scala b/test/files/run/reify_nested_inner_refers_to_local.scala
new file mode 100644
index 0000000000..fd56585f72
--- /dev/null
+++ b/test/files/run/reify_nested_inner_refers_to_local.scala
@@ -0,0 +1,12 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val code = reify{
+ val x = 2
+ reify{x}.eval
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_nested_outer_refers_to_global.check b/test/files/run/reify_nested_outer_refers_to_global.check
new file mode 100644
index 0000000000..7ff4c83d37
--- /dev/null
+++ b/test/files/run/reify_nested_outer_refers_to_global.check
@@ -0,0 +1 @@
+evaluated = 2
diff --git a/test/files/run/reify_nested_outer_refers_to_global.scala b/test/files/run/reify_nested_outer_refers_to_global.scala
new file mode 100644
index 0000000000..f34e4fe04b
--- /dev/null
+++ b/test/files/run/reify_nested_outer_refers_to_global.scala
@@ -0,0 +1,16 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val code = {
+ val x = 2
+ val outer = reify{x}
+ reify{
+ val x = 42
+ outer.eval
+ };
+ }
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_nested_outer_refers_to_local.check b/test/files/run/reify_nested_outer_refers_to_local.check
new file mode 100644
index 0000000000..7ff4c83d37
--- /dev/null
+++ b/test/files/run/reify_nested_outer_refers_to_local.check
@@ -0,0 +1 @@
+evaluated = 2
diff --git a/test/files/run/reify_nested_outer_refers_to_local.scala b/test/files/run/reify_nested_outer_refers_to_local.scala
new file mode 100644
index 0000000000..e16c851d8d
--- /dev/null
+++ b/test/files/run/reify_nested_outer_refers_to_local.scala
@@ -0,0 +1,16 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val outer = {
+ val x = 2
+ reify{x}
+ }
+ val code = reify{
+ val x = 42
+ outer.eval
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_newimpl_01.check b/test/files/run/reify_newimpl_01.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/files/run/reify_newimpl_01.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_01.scala b/test/files/run/reify_newimpl_01.scala
new file mode 100644
index 0000000000..f7539a15b0
--- /dev/null
+++ b/test/files/run/reify_newimpl_01.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val x = 2
+ val code = reify {
+ x
+ }
+ println(code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_02.check b/test/files/run/reify_newimpl_02.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/files/run/reify_newimpl_02.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_02.scala b/test/files/run/reify_newimpl_02.scala
new file mode 100644
index 0000000000..2c085efa04
--- /dev/null
+++ b/test/files/run/reify_newimpl_02.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var x = 2
+ val code = reify {
+ x
+ }
+ println(code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_03.check b/test/files/run/reify_newimpl_03.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/files/run/reify_newimpl_03.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_03.scala b/test/files/run/reify_newimpl_03.scala
new file mode 100644
index 0000000000..361cfc50bb
--- /dev/null
+++ b/test/files/run/reify_newimpl_03.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val code = reify {
+ val x = 2
+ reify{x}.eval
+ }
+ println(code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_04.check b/test/files/run/reify_newimpl_04.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/files/run/reify_newimpl_04.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_04.scala b/test/files/run/reify_newimpl_04.scala
new file mode 100644
index 0000000000..d80a7c9ffd
--- /dev/null
+++ b/test/files/run/reify_newimpl_04.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val code = reify {
+ var x = 2
+ reify{x}.eval
+ }
+ println(code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_05.check b/test/files/run/reify_newimpl_05.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/files/run/reify_newimpl_05.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_05.scala b/test/files/run/reify_newimpl_05.scala
new file mode 100644
index 0000000000..85c1711bdb
--- /dev/null
+++ b/test/files/run/reify_newimpl_05.scala
@@ -0,0 +1,12 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val code = reify {
+ var x = 2
+ def y = x // forcibly captures x
+ reify{x}.eval
+ }
+ println(code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_06.check b/test/files/run/reify_newimpl_06.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/files/run/reify_newimpl_06.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_06.scala b/test/files/run/reify_newimpl_06.scala
new file mode 100644
index 0000000000..257b54167a
--- /dev/null
+++ b/test/files/run/reify_newimpl_06.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C(val y: Int) {
+ val code = reify {
+ reify{y}.eval
+ }
+ }
+
+ println(new C(2).code.eval)
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_09.check b/test/files/run/reify_newimpl_09.check
new file mode 100644
index 0000000000..220bd6875a
--- /dev/null
+++ b/test/files/run/reify_newimpl_09.check
@@ -0,0 +1 @@
+List(2) \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_09.scala b/test/files/run/reify_newimpl_09.scala
new file mode 100644
index 0000000000..2c81945a2a
--- /dev/null
+++ b/test/files/run/reify_newimpl_09.scala
@@ -0,0 +1,11 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ type T = Int
+ val code = reify {
+ List[T](2)
+ }
+ println(code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_10.check b/test/files/run/reify_newimpl_10.check
new file mode 100644
index 0000000000..220bd6875a
--- /dev/null
+++ b/test/files/run/reify_newimpl_10.check
@@ -0,0 +1 @@
+List(2) \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_10.scala b/test/files/run/reify_newimpl_10.scala
new file mode 100644
index 0000000000..6e70b4d216
--- /dev/null
+++ b/test/files/run/reify_newimpl_10.scala
@@ -0,0 +1,12 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ type T = Int
+ implicit val tt = implicitly[TypeTag[String]].asInstanceOf[TypeTag[T]] // this "mistake" is made for a reason!
+ val code = reify {
+ List[T](2)
+ }
+ println(code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_11.check b/test/files/run/reify_newimpl_11.check
new file mode 100644
index 0000000000..e2a8206132
--- /dev/null
+++ b/test/files/run/reify_newimpl_11.check
@@ -0,0 +1,2 @@
+scala.reflect.runtime.ToolBoxes$ToolBox$ToolBoxError: reflective toolbox has failed:
+unresolved free type variables (namely: T defined by C in reify_newimpl_11.scala:4:11). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types
diff --git a/test/files/run/reify_newimpl_11.scala b/test/files/run/reify_newimpl_11.scala
new file mode 100644
index 0000000000..4e91c7a457
--- /dev/null
+++ b/test/files/run/reify_newimpl_11.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C[T] {
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ try {
+ new C[Int]
+ } catch {
+ case ex: Throwable =>
+ println(ex)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_12.check b/test/files/run/reify_newimpl_12.check
new file mode 100644
index 0000000000..220bd6875a
--- /dev/null
+++ b/test/files/run/reify_newimpl_12.check
@@ -0,0 +1 @@
+List(2) \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_12.scala b/test/files/run/reify_newimpl_12.scala
new file mode 100644
index 0000000000..433168ce28
--- /dev/null
+++ b/test/files/run/reify_newimpl_12.scala
@@ -0,0 +1,12 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C[T: TypeTag] {
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ new C[Int]
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_13.check b/test/files/run/reify_newimpl_13.check
new file mode 100644
index 0000000000..7c47310cf2
--- /dev/null
+++ b/test/files/run/reify_newimpl_13.check
@@ -0,0 +1,2 @@
+scala.reflect.runtime.ToolBoxes$ToolBox$ToolBoxError: reflective toolbox has failed:
+unresolved free type variables (namely: T defined by C in reify_newimpl_13.scala:5:13). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types
diff --git a/test/files/run/reify_newimpl_13.scala b/test/files/run/reify_newimpl_13.scala
new file mode 100644
index 0000000000..dd1980b74f
--- /dev/null
+++ b/test/files/run/reify_newimpl_13.scala
@@ -0,0 +1,19 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ class C[T] {
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ try {
+ new C[Int]
+ } catch {
+ case ex: Throwable =>
+ println(ex)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_14.check b/test/files/run/reify_newimpl_14.check
new file mode 100644
index 0000000000..220bd6875a
--- /dev/null
+++ b/test/files/run/reify_newimpl_14.check
@@ -0,0 +1 @@
+List(2) \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_14.scala b/test/files/run/reify_newimpl_14.scala
new file mode 100644
index 0000000000..3f52f19cfb
--- /dev/null
+++ b/test/files/run/reify_newimpl_14.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ class C[T: TypeTag] {
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ new C[Int]
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_15.check b/test/files/run/reify_newimpl_15.check
new file mode 100644
index 0000000000..220bd6875a
--- /dev/null
+++ b/test/files/run/reify_newimpl_15.check
@@ -0,0 +1 @@
+List(2) \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_15.scala b/test/files/run/reify_newimpl_15.scala
new file mode 100644
index 0000000000..b707b2583d
--- /dev/null
+++ b/test/files/run/reify_newimpl_15.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C {
+ type T = Int
+ val code = reify {
+ List[T](2)
+ }
+ println(code.eval)
+ }
+
+ new C
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_16.check b/test/files/run/reify_newimpl_16.check
new file mode 100644
index 0000000000..220bd6875a
--- /dev/null
+++ b/test/files/run/reify_newimpl_16.check
@@ -0,0 +1 @@
+List(2) \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_16.scala b/test/files/run/reify_newimpl_16.scala
new file mode 100644
index 0000000000..98fc15878c
--- /dev/null
+++ b/test/files/run/reify_newimpl_16.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ class C {
+ type T = Int
+ val code = reify {
+ List[T](2)
+ }
+ println(code.eval)
+ }
+
+ new C
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_17.check b/test/files/run/reify_newimpl_17.check
new file mode 100644
index 0000000000..0fb9ddfc2d
--- /dev/null
+++ b/test/files/run/reify_newimpl_17.check
@@ -0,0 +1,2 @@
+scala.reflect.runtime.ToolBoxes$ToolBox$ToolBoxError: reflective toolbox has failed:
+unresolved free type variables (namely: U defined by C in reify_newimpl_17.scala:4:11). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types
diff --git a/test/files/run/reify_newimpl_17.scala b/test/files/run/reify_newimpl_17.scala
new file mode 100644
index 0000000000..331777fcfb
--- /dev/null
+++ b/test/files/run/reify_newimpl_17.scala
@@ -0,0 +1,18 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C[U] {
+ type T = U
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ try {
+ new C[Int]
+ } catch {
+ case ex: Throwable =>
+ println(ex)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_18.check b/test/files/run/reify_newimpl_18.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_18.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_18.scala b/test/files/run/reify_newimpl_18.scala
new file mode 100644
index 0000000000..704e54928a
--- /dev/null
+++ b/test/files/run/reify_newimpl_18.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C[U: TypeTag] {
+ type T = U
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ new C[Int]
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_19.check b/test/files/run/reify_newimpl_19.check
new file mode 100644
index 0000000000..32f9300f53
--- /dev/null
+++ b/test/files/run/reify_newimpl_19.check
@@ -0,0 +1,2 @@
+scala.reflect.runtime.ToolBoxes$ToolBox$ToolBoxError: reflective toolbox has failed:
+unresolved free type variables (namely: T defined by C in reify_newimpl_19.scala:5:10). have you forgot to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types
diff --git a/test/files/run/reify_newimpl_19.scala b/test/files/run/reify_newimpl_19.scala
new file mode 100644
index 0000000000..0ea8ae6992
--- /dev/null
+++ b/test/files/run/reify_newimpl_19.scala
@@ -0,0 +1,18 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C {
+ type T
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ try {
+ new C { val T = Int }
+ } catch {
+ case ex: Throwable =>
+ println(ex)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_20.check b/test/files/run/reify_newimpl_20.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_20.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_20.scala b/test/files/run/reify_newimpl_20.scala
new file mode 100644
index 0000000000..16895a449e
--- /dev/null
+++ b/test/files/run/reify_newimpl_20.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C {
+ type T
+ implicit val tt: TypeTag[T] = implicitly[TypeTag[Int]].asInstanceOf[TypeTag[T]]
+ val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ println(code.eval)
+ }
+
+ new C { type T = String } // this "mistake" is made for a reason!
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_21.check b/test/files/run/reify_newimpl_21.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_21.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_21.scala b/test/files/run/reify_newimpl_21.scala
new file mode 100644
index 0000000000..99f9ac9089
--- /dev/null
+++ b/test/files/run/reify_newimpl_21.scala
@@ -0,0 +1,18 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ trait C {
+ type T
+ implicit val tt: TypeTag[T]
+ lazy val code = reify {
+ List[T](2.asInstanceOf[T])
+ }
+ }
+
+ class D extends C {
+ type T = String // this "mistake" is made for a reason!
+ override val tt: TypeTag[T] = implicitly[TypeTag[Int]].asInstanceOf[TypeTag[T]]
+ }
+
+ println((new D).code.eval)
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_22.check b/test/files/run/reify_newimpl_22.check
new file mode 100644
index 0000000000..51699cbc29
--- /dev/null
+++ b/test/files/run/reify_newimpl_22.check
@@ -0,0 +1,23 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.reflect.mirror._
+import scala.reflect.mirror._
+
+scala> {
+ val x = 2
+ val code = reify {
+ x
+ }
+ println(code.eval)
+}
+<console>:13: free term: Ident(newTermName("x")) defined by res0 in <console>:12:21
+ val code = reify {
+ ^
+2
+
+scala>
+
+scala>
diff --git a/test/files/run/reify_newimpl_22.scala b/test/files/run/reify_newimpl_22.scala
new file mode 100644
index 0000000000..a211ad360c
--- /dev/null
+++ b/test/files/run/reify_newimpl_22.scala
@@ -0,0 +1,15 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ override def extraSettings = "-Xlog-free-terms"
+ def code = """
+import scala.reflect.mirror._
+{
+ val x = 2
+ val code = reify {
+ x
+ }
+ println(code.eval)
+}
+ """
+}
diff --git a/test/files/run/reify_newimpl_23.check b/test/files/run/reify_newimpl_23.check
new file mode 100644
index 0000000000..33d15190fb
--- /dev/null
+++ b/test/files/run/reify_newimpl_23.check
@@ -0,0 +1,22 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.reflect.mirror._
+import scala.reflect.mirror._
+
+scala> def foo[T]{
+ val code = reify {
+ List[T]()
+ }
+ println(code.eval)
+}
+<console>:11: free type: Ident(newTypeName("T")) defined by foo in <console>:10:16
+ val code = reify {
+ ^
+foo: [T]=> Unit
+
+scala>
+
+scala>
diff --git a/test/files/run/reify_newimpl_23.scala b/test/files/run/reify_newimpl_23.scala
new file mode 100644
index 0000000000..15da4e497e
--- /dev/null
+++ b/test/files/run/reify_newimpl_23.scala
@@ -0,0 +1,14 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ override def extraSettings = "-Xlog-free-types"
+ def code = """
+import scala.reflect.mirror._
+def foo[T]{
+ val code = reify {
+ List[T]()
+ }
+ println(code.eval)
+}
+ """
+}
diff --git a/test/files/run/reify_newimpl_24.check b/test/files/run/reify_newimpl_24.check
new file mode 100644
index 0000000000..66b18c790e
--- /dev/null
+++ b/test/files/run/reify_newimpl_24.check
@@ -0,0 +1,24 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.reflect.mirror._
+import scala.reflect.mirror._
+
+scala> {
+ val x = 2
+ val code = reify {
+ val y = reify { x }
+ y.eval
+ }
+ println(code.eval)
+}
+<console>:15: this splice cannot be resolved statically
+ y.eval
+ ^
+2
+
+scala>
+
+scala>
diff --git a/test/files/run/reify_newimpl_24.scala b/test/files/run/reify_newimpl_24.scala
new file mode 100644
index 0000000000..7b21eeeb10
--- /dev/null
+++ b/test/files/run/reify_newimpl_24.scala
@@ -0,0 +1,16 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ override def extraSettings = "-Xlog-runtime-splices"
+ def code = """
+import scala.reflect.mirror._
+{
+ val x = 2
+ val code = reify {
+ val y = reify { x }
+ y.eval
+ }
+ println(code.eval)
+}
+ """
+}
diff --git a/test/files/run/reify_newimpl_25.check b/test/files/run/reify_newimpl_25.check
new file mode 100644
index 0000000000..37ff83c9ee
--- /dev/null
+++ b/test/files/run/reify_newimpl_25.check
@@ -0,0 +1,21 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.reflect.mirror._
+import scala.reflect.mirror._
+
+scala> {
+ val x = "2"
+ val tt = implicitly[TypeTag[x.type]]
+ println(tt)
+}
+<console>:13: free term: Ident(newTermName("x")) defined by res0 in <console>:12:21
+ val tt = implicitly[TypeTag[x.type]]
+ ^
+ConcreteTypeTag[x.type]
+
+scala>
+
+scala>
diff --git a/test/files/run/reify_newimpl_25.scala b/test/files/run/reify_newimpl_25.scala
new file mode 100644
index 0000000000..1f66f5e681
--- /dev/null
+++ b/test/files/run/reify_newimpl_25.scala
@@ -0,0 +1,13 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ override def extraSettings = "-Xlog-free-terms"
+ def code = """
+import scala.reflect.mirror._
+{
+ val x = "2"
+ val tt = implicitly[TypeTag[x.type]]
+ println(tt)
+}
+ """
+}
diff --git a/test/files/run/reify_newimpl_26.check b/test/files/run/reify_newimpl_26.check
new file mode 100644
index 0000000000..d92b3bd817
--- /dev/null
+++ b/test/files/run/reify_newimpl_26.check
@@ -0,0 +1,23 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> import scala.reflect.mirror._
+import scala.reflect.mirror._
+
+scala> def foo[T]{
+ val tt = implicitly[TypeTag[List[T]]]
+ println(tt)
+}
+<console>:11: free type: Ident(newTypeName("T")) defined by foo in <console>:10:16
+ val tt = implicitly[TypeTag[List[T]]]
+ ^
+foo: [T]=> Unit
+
+scala> foo[Int]
+TypeTag[List[T]]
+
+scala>
+
+scala>
diff --git a/test/files/run/reify_newimpl_26.scala b/test/files/run/reify_newimpl_26.scala
new file mode 100644
index 0000000000..f2dd1bfc4e
--- /dev/null
+++ b/test/files/run/reify_newimpl_26.scala
@@ -0,0 +1,13 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ override def extraSettings = "-Xlog-free-types"
+ def code = """
+import scala.reflect.mirror._
+def foo[T]{
+ val tt = implicitly[TypeTag[List[T]]]
+ println(tt)
+}
+foo[Int]
+ """
+}
diff --git a/test/files/run/reify_newimpl_27.check b/test/files/run/reify_newimpl_27.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_27.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_27.scala b/test/files/run/reify_newimpl_27.scala
new file mode 100644
index 0000000000..b3d6d5c865
--- /dev/null
+++ b/test/files/run/reify_newimpl_27.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ object C {
+ type T = Int
+ val code = reify {
+ List[T](2)
+ }
+ println(code.eval)
+ }
+
+ C
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_28.check b/test/files/run/reify_newimpl_28.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_28.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_28.scala b/test/files/run/reify_newimpl_28.scala
new file mode 100644
index 0000000000..f7874b8548
--- /dev/null
+++ b/test/files/run/reify_newimpl_28.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ object C {
+ type T = Int
+ val code = reify {
+ List[T](2)
+ }
+ println(code.eval)
+ }
+
+ C
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_29.check b/test/files/run/reify_newimpl_29.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_29.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_29.scala b/test/files/run/reify_newimpl_29.scala
new file mode 100644
index 0000000000..e32762f335
--- /dev/null
+++ b/test/files/run/reify_newimpl_29.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C {
+ type T = Int
+ val code = reify {
+ List[C#T](2)
+ }
+ println(code.eval)
+ }
+
+ new C
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_30.check b/test/files/run/reify_newimpl_30.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_30.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_30.scala b/test/files/run/reify_newimpl_30.scala
new file mode 100644
index 0000000000..e4ba3221e1
--- /dev/null
+++ b/test/files/run/reify_newimpl_30.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ class C {
+ type T = Int
+ val code = reify {
+ List[C#T](2)
+ }
+ println(code.eval)
+ }
+
+ new C
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_31.check b/test/files/run/reify_newimpl_31.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_31.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_31.scala b/test/files/run/reify_newimpl_31.scala
new file mode 100644
index 0000000000..20a851e32e
--- /dev/null
+++ b/test/files/run/reify_newimpl_31.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ object C {
+ type T = Int
+ val code = reify {
+ List[C.T](2)
+ }
+ println(code.eval)
+ }
+
+ C
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_32.check b/test/files/run/reify_newimpl_32.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_32.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_32.scala b/test/files/run/reify_newimpl_32.scala
new file mode 100644
index 0000000000..788486ec00
--- /dev/null
+++ b/test/files/run/reify_newimpl_32.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ object C {
+ type T = Int
+ val code = reify {
+ List[C.T](2)
+ }
+ println(code.eval)
+ }
+
+ C
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_33.check b/test/files/run/reify_newimpl_33.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_33.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_33.scala b/test/files/run/reify_newimpl_33.scala
new file mode 100644
index 0000000000..84a8258256
--- /dev/null
+++ b/test/files/run/reify_newimpl_33.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ object C {
+ type T = Int
+ val c = C
+ val code = reify {
+ List[c.T](2)
+ }
+ println(code.eval)
+ }
+
+ C
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_34.check b/test/files/run/reify_newimpl_34.check
new file mode 100644
index 0000000000..a7029974a4
--- /dev/null
+++ b/test/files/run/reify_newimpl_34.check
@@ -0,0 +1 @@
+List(2)
diff --git a/test/files/run/reify_newimpl_34.scala b/test/files/run/reify_newimpl_34.scala
new file mode 100644
index 0000000000..5935ab385c
--- /dev/null
+++ b/test/files/run/reify_newimpl_34.scala
@@ -0,0 +1,16 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ object C {
+ type T = Int
+ lazy val c = C
+ val code = reify {
+ List[c.T](2)
+ }
+ println(code.eval)
+ }
+
+ C
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_36.check b/test/files/run/reify_newimpl_36.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/reify_newimpl_36.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/reify_newimpl_36.scala b/test/files/run/reify_newimpl_36.scala
new file mode 100644
index 0000000000..c76efce27a
--- /dev/null
+++ b/test/files/run/reify_newimpl_36.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val x = 42
+ def foo() = reify(reify(x));
+ {
+ val x = 2
+ val code1 = foo()
+ val code2 = code1.eval
+ println(code2.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_37.check b/test/files/run/reify_newimpl_37.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/reify_newimpl_37.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/reify_newimpl_37.scala b/test/files/run/reify_newimpl_37.scala
new file mode 100644
index 0000000000..e83d35dbe1
--- /dev/null
+++ b/test/files/run/reify_newimpl_37.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val x = 42
+ def foo() = reify(reify(reify(x)));
+ {
+ val x = 2
+ val code1 = foo()
+ val code2 = code1.eval
+ val code3 = code2.eval
+ println(code3.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_38.check b/test/files/run/reify_newimpl_38.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/reify_newimpl_38.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/reify_newimpl_38.scala b/test/files/run/reify_newimpl_38.scala
new file mode 100644
index 0000000000..70ef49ecf7
--- /dev/null
+++ b/test/files/run/reify_newimpl_38.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val x = 42
+ def foo() = reify{ val y = x; reify(y) };
+ {
+ val x = 2
+ val code1 = foo()
+ val code2 = code1.eval
+ println(code2.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_39.check b/test/files/run/reify_newimpl_39.check
new file mode 100644
index 0000000000..2f562a182f
--- /dev/null
+++ b/test/files/run/reify_newimpl_39.check
@@ -0,0 +1 @@
+42
diff --git a/test/files/run/reify_newimpl_39.scala b/test/files/run/reify_newimpl_39.scala
new file mode 100644
index 0000000000..faa45d917d
--- /dev/null
+++ b/test/files/run/reify_newimpl_39.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val x = 42
+ def foo() = reify{ val y = x; reify{ val z = y; reify(z) } };
+ {
+ val x = 2
+ val code1 = foo()
+ val code2 = code1.eval
+ val code3 = code2.eval
+ println(code3.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_40.check b/test/files/run/reify_newimpl_40.check
new file mode 100644
index 0000000000..94c5a65fe0
--- /dev/null
+++ b/test/files/run/reify_newimpl_40.check
@@ -0,0 +1 @@
+74088
diff --git a/test/files/run/reify_newimpl_40.scala b/test/files/run/reify_newimpl_40.scala
new file mode 100644
index 0000000000..a983a92324
--- /dev/null
+++ b/test/files/run/reify_newimpl_40.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ val x = 42
+ def foo() = reify{ val y = x; reify{ val z = y * x; reify(z * x) } };
+ {
+ val x = 2
+ val code1 = foo()
+ val code2 = code1.eval
+ val code3 = code2.eval
+ println(code3.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_41.check b/test/files/run/reify_newimpl_41.check
new file mode 100644
index 0000000000..0b427f2ee6
--- /dev/null
+++ b/test/files/run/reify_newimpl_41.check
@@ -0,0 +1,3 @@
+42
+44
+43 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_41.scala b/test/files/run/reify_newimpl_41.scala
new file mode 100644
index 0000000000..9aedccc98a
--- /dev/null
+++ b/test/files/run/reify_newimpl_41.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var _x = 42
+ def x = { val x0 = _x; _x += 1; x0 }
+ var _y = 1
+ def y = { val y0 = _y + _x; _y += y0; y0 }
+ val code = reify {
+ def foo = y // ensures that y is the first freevar we find
+ println(x)
+ println(y)
+ println(x)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_42.check b/test/files/run/reify_newimpl_42.check
new file mode 100644
index 0000000000..0b427f2ee6
--- /dev/null
+++ b/test/files/run/reify_newimpl_42.check
@@ -0,0 +1,3 @@
+42
+44
+43 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_42.scala b/test/files/run/reify_newimpl_42.scala
new file mode 100644
index 0000000000..1e21bd59bc
--- /dev/null
+++ b/test/files/run/reify_newimpl_42.scala
@@ -0,0 +1,16 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var _x = 42
+ def x = { val x0 = _x; _x += 1; x0 }
+ var _y = 1
+ def y = { val y0 = _y + _x; _y += y0; y0 }
+ val code = reify {
+ println(x)
+ println(y)
+ println(x)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_43.check b/test/files/run/reify_newimpl_43.check
new file mode 100644
index 0000000000..7a754f414c
--- /dev/null
+++ b/test/files/run/reify_newimpl_43.check
@@ -0,0 +1,2 @@
+1
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_43.scala b/test/files/run/reify_newimpl_43.scala
new file mode 100644
index 0000000000..962461db8b
--- /dev/null
+++ b/test/files/run/reify_newimpl_43.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var counter = 0
+ lazy val x = { counter += 1; counter }
+ lazy val y = { counter += 1; counter }
+ val code = reify {
+ def foo = y // ensures that y is the first freevar we find
+ println(x)
+ println(y)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_44.check b/test/files/run/reify_newimpl_44.check
new file mode 100644
index 0000000000..7a754f414c
--- /dev/null
+++ b/test/files/run/reify_newimpl_44.check
@@ -0,0 +1,2 @@
+1
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_44.scala b/test/files/run/reify_newimpl_44.scala
new file mode 100644
index 0000000000..962461db8b
--- /dev/null
+++ b/test/files/run/reify_newimpl_44.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var counter = 0
+ lazy val x = { counter += 1; counter }
+ lazy val y = { counter += 1; counter }
+ val code = reify {
+ def foo = y // ensures that y is the first freevar we find
+ println(x)
+ println(y)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_45.check b/test/files/run/reify_newimpl_45.check
new file mode 100644
index 0000000000..6e14f71e26
--- /dev/null
+++ b/test/files/run/reify_newimpl_45.check
@@ -0,0 +1,2 @@
+List(free type T)
+ima worx: 2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_45.scala b/test/files/run/reify_newimpl_45.scala
new file mode 100644
index 0000000000..b2b52eaf5b
--- /dev/null
+++ b/test/files/run/reify_newimpl_45.scala
@@ -0,0 +1,12 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C[T >: Null] {
+ val code = reify{val x: T = "2".asInstanceOf[T]; println("ima worx: %s".format(x)); x}
+ println(freeTypes(code.tree))
+ val T = freeTypes(code.tree)(0)
+ mkToolBox().runExpr(code.tree, Map(T -> definitions.StringClass.asType))
+ }
+
+ new C[String]
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_47.check b/test/files/run/reify_newimpl_47.check
new file mode 100644
index 0000000000..d8263ee986
--- /dev/null
+++ b/test/files/run/reify_newimpl_47.check
@@ -0,0 +1 @@
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_47.scala b/test/files/run/reify_newimpl_47.scala
new file mode 100644
index 0000000000..bd1bd1fe65
--- /dev/null
+++ b/test/files/run/reify_newimpl_47.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val outer = {
+ val x = 2
+ reify{x}
+ }
+
+ val code = reify{
+ val x = 42
+ outer.eval
+ }
+
+ println(code.eval)
+}
diff --git a/test/files/run/reify_newimpl_48.check b/test/files/run/reify_newimpl_48.check
new file mode 100644
index 0000000000..f11c82a4cb
--- /dev/null
+++ b/test/files/run/reify_newimpl_48.check
@@ -0,0 +1 @@
+9 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_48.scala b/test/files/run/reify_newimpl_48.scala
new file mode 100644
index 0000000000..1522509907
--- /dev/null
+++ b/test/files/run/reify_newimpl_48.scala
@@ -0,0 +1,20 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val outer1 = {
+ val x = 2
+ reify{x}
+ }
+
+ val outer2 = {
+ val x = 3
+ reify{x}
+ }
+
+ val code = reify{
+ val x = 4
+ x + outer1.eval + outer2.eval
+ }
+
+ println(code.eval)
+}
diff --git a/test/files/run/reify_newimpl_49.check b/test/files/run/reify_newimpl_49.check
new file mode 100644
index 0000000000..d8a621df00
--- /dev/null
+++ b/test/files/run/reify_newimpl_49.check
@@ -0,0 +1,3 @@
+3
+3
+5 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_49.scala b/test/files/run/reify_newimpl_49.scala
new file mode 100644
index 0000000000..68d968e28b
--- /dev/null
+++ b/test/files/run/reify_newimpl_49.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var y = 1
+ def x = { y += 2; y }
+ val code = reify {
+ def foo = y // ensures that y is the first freevar we find
+ println(x)
+ println(y)
+ println(x)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_50.check b/test/files/run/reify_newimpl_50.check
new file mode 100644
index 0000000000..d8a621df00
--- /dev/null
+++ b/test/files/run/reify_newimpl_50.check
@@ -0,0 +1,3 @@
+3
+3
+5 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_50.scala b/test/files/run/reify_newimpl_50.scala
new file mode 100644
index 0000000000..b81d72a4eb
--- /dev/null
+++ b/test/files/run/reify_newimpl_50.scala
@@ -0,0 +1,14 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var y = 1
+ def x = { y += 2; y }
+ val code = reify {
+ println(x)
+ println(y)
+ println(x)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_51.check b/test/files/run/reify_newimpl_51.check
new file mode 100644
index 0000000000..9a4ddeacd3
--- /dev/null
+++ b/test/files/run/reify_newimpl_51.check
@@ -0,0 +1,3 @@
+2
+1
+2 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_51.scala b/test/files/run/reify_newimpl_51.scala
new file mode 100644
index 0000000000..ccbae2e160
--- /dev/null
+++ b/test/files/run/reify_newimpl_51.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var counter = 0
+ lazy val x = { counter += 1; counter }
+ lazy val y = { counter += 1; counter }
+ val code = reify {
+ def foo = y // ensures that y is the first freevar we find
+ val bar = reify { println(x * y) }
+ bar.eval
+ println(x)
+ println(y)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_52.check b/test/files/run/reify_newimpl_52.check
new file mode 100644
index 0000000000..9359a2b211
--- /dev/null
+++ b/test/files/run/reify_newimpl_52.check
@@ -0,0 +1,3 @@
+2
+2
+1 \ No newline at end of file
diff --git a/test/files/run/reify_newimpl_52.scala b/test/files/run/reify_newimpl_52.scala
new file mode 100644
index 0000000000..60b16d3618
--- /dev/null
+++ b/test/files/run/reify_newimpl_52.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ var counter = 0
+ lazy val x = { counter += 1; counter }
+ lazy val y = { counter += 1; counter }
+ val code = reify {
+ def foo = y // ensures that y is the first freevar we find
+ val bar = reify { println(y * x) }
+ bar.eval
+ println(x)
+ println(y)
+ }
+ code.eval
+ }
+} \ No newline at end of file
diff --git a/test/files/run/reify_printf.scala b/test/files/run/reify_printf.scala
index cd6052bc5e..dc092c1a85 100644
--- a/test/files/run/reify_printf.scala
+++ b/test/files/run/reify_printf.scala
@@ -1,19 +1,15 @@
import java.io.{ ByteArrayOutputStream, PrintStream }
-import scala.reflect.Code
import scala.reflect.mirror._
import scala.reflect.api._
import scala.reflect.api.Trees
import scala.reflect.internal.Types
-import reflect.runtime.Mirror.ToolBox
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
import scala.util.matching.Regex
object Test extends App {
- val tree = tree_printf(Code.lift("hello %s").tree, Code.lift("world").tree)
+ val tree = tree_printf(reify("hello %s").tree, reify("world").tree)
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter, args mkString " ")
+ import scala.reflect.mirror._
+ val toolbox = mkToolBox()
val output = new ByteArrayOutputStream()
Console.setOut(new PrintStream(output))
@@ -22,6 +18,7 @@ object Test extends App {
assert(output.toString() == "hello world", output.toString() +" == hello world")
/*
+ // upd. Oh, good old times, our very-very first experiments with macros :)
macro def printf(format: String, params: Any*) : String = tree_printf(format: Tree, (params: Seq[Tree]): _*)
*/
diff --git a/test/pending/run/reify_properties.check b/test/files/run/reify_properties.check
index d769bea4b0..d769bea4b0 100644
--- a/test/pending/run/reify_properties.check
+++ b/test/files/run/reify_properties.check
diff --git a/test/pending/run/reify_properties.scala b/test/files/run/reify_properties.scala
index 265c344b8e..5cacc262ac 100644
--- a/test/pending/run/reify_properties.scala
+++ b/test/files/run/reify_properties.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
/** A mutable property whose getter and setter may be customized. */
case class Property[T](init: T) {
private var value: T = init
@@ -54,9 +52,5 @@ object Test extends App {
println("user1: " + user1)
println("user2: " + user2)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_sort.scala b/test/files/run/reify_sort.scala
index 5984a64967..0b373b358f 100644
--- a/test/files/run/reify_sort.scala
+++ b/test/files/run/reify_sort.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
/** Nested methods can use and even update everything
* visible in their scope (including local variables or
* arguments of enclosing methods).
@@ -48,9 +46,5 @@ object Test extends App {
println(ar)
sort(ar)
println(ar)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_sort1.scala b/test/files/run/reify_sort1.scala
index 6f365dea26..56125619e9 100644
--- a/test/files/run/reify_sort1.scala
+++ b/test/files/run/reify_sort1.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
def sort(a: List[Int]): List[Int] = {
if (a.length < 2)
a
@@ -18,9 +16,5 @@ object Test extends App {
val xs = List(6, 2, 8, 5, 1)
println(xs)
println(sort(xs))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_this.scala b/test/files/run/reify_this.scala
index ee1f116013..280d735ab6 100644
--- a/test/files/run/reify_this.scala
+++ b/test/files/run/reify_this.scala
@@ -1,30 +1,19 @@
-import scala.reflect._
-import scala.reflect.Code._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
trait Eval {
- def eval(code: Code): Any = eval(code.tree)
-
- def eval(tree: Tree): Any = {
- val settings = new Settings
- val reporter = new ConsoleReporter(settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(tree)
- }
+ def eval(tree: Expr[_]) = tree.eval
}
object Test extends App with Eval {
// select a value from package
- eval(lift{println("foo")})
- eval(lift{println((new Object).toString == (new Object).toString)})
+ eval(reify{println("foo")})
+ eval(reify{println((new Object).toString == (new Object).toString)})
// select a type from package
- eval(lift{val x: Any = 2; println(x)})
- eval(lift{val x: Object = "bar"; println(x)})
+ eval(reify{val x: Any = 2; println(x)})
+ eval(reify{val x: Object = "bar"; println(x)})
// select a value from module
val x = 2
- eval(lift{println(x)})
+ eval(reify{println(x)})
}
diff --git a/test/files/run/reify_timeofday.scala b/test/files/run/reify_timeofday.scala
index 122d7a6d52..481ab04df5 100644
--- a/test/files/run/reify_timeofday.scala
+++ b/test/files/run/reify_timeofday.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class DateError extends Exception
/** Simulating properties in Scala
@@ -39,9 +37,5 @@ object Test extends App {
case de: DateError => println("DateError")
case e: Exception => println("Exception")
}
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/reify_typerefs_1a.check b/test/files/run/reify_typerefs_1a.check
new file mode 100644
index 0000000000..919c298ba3
--- /dev/null
+++ b/test/files/run/reify_typerefs_1a.check
@@ -0,0 +1 @@
+evaluated = List(Expression, Expression) \ No newline at end of file
diff --git a/test/files/run/reify_typerefs_1a.scala b/test/files/run/reify_typerefs_1a.scala
new file mode 100644
index 0000000000..15d8d17835
--- /dev/null
+++ b/test/files/run/reify_typerefs_1a.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+class Expression {
+ override def toString = "Expression"
+}
+
+object Test extends App {
+ val code = reify {
+ List(new Expression, new Expression)
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_typerefs_1b.check b/test/files/run/reify_typerefs_1b.check
new file mode 100644
index 0000000000..919c298ba3
--- /dev/null
+++ b/test/files/run/reify_typerefs_1b.check
@@ -0,0 +1 @@
+evaluated = List(Expression, Expression) \ No newline at end of file
diff --git a/test/files/run/reify_typerefs_1b.scala b/test/files/run/reify_typerefs_1b.scala
new file mode 100644
index 0000000000..06ce1e35ac
--- /dev/null
+++ b/test/files/run/reify_typerefs_1b.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Expression {
+ override def toString = "Expression"
+}
+
+object Test extends App {
+ val code = reify {
+ List(Expression, Expression)
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_typerefs_2a.check b/test/files/run/reify_typerefs_2a.check
new file mode 100644
index 0000000000..919c298ba3
--- /dev/null
+++ b/test/files/run/reify_typerefs_2a.check
@@ -0,0 +1 @@
+evaluated = List(Expression, Expression) \ No newline at end of file
diff --git a/test/files/run/reify_typerefs_2a.scala b/test/files/run/reify_typerefs_2a.scala
new file mode 100644
index 0000000000..d03efea222
--- /dev/null
+++ b/test/files/run/reify_typerefs_2a.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+package foo {
+ class Expression {
+ override def toString = "Expression"
+ }
+}
+
+object Test extends App {
+ val code = reify {
+ List(new foo.Expression, new foo.Expression)
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_typerefs_2b.check b/test/files/run/reify_typerefs_2b.check
new file mode 100644
index 0000000000..919c298ba3
--- /dev/null
+++ b/test/files/run/reify_typerefs_2b.check
@@ -0,0 +1 @@
+evaluated = List(Expression, Expression) \ No newline at end of file
diff --git a/test/files/run/reify_typerefs_2b.scala b/test/files/run/reify_typerefs_2b.scala
new file mode 100644
index 0000000000..3d9f7d61b8
--- /dev/null
+++ b/test/files/run/reify_typerefs_2b.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+package foo {
+ object Expression {
+ override def toString = "Expression"
+ }
+}
+
+object Test extends App {
+ val code = reify {
+ List(foo.Expression, foo.Expression)
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_typerefs_3a.check b/test/files/run/reify_typerefs_3a.check
new file mode 100644
index 0000000000..919c298ba3
--- /dev/null
+++ b/test/files/run/reify_typerefs_3a.check
@@ -0,0 +1 @@
+evaluated = List(Expression, Expression) \ No newline at end of file
diff --git a/test/files/run/reify_typerefs_3a.scala b/test/files/run/reify_typerefs_3a.scala
new file mode 100644
index 0000000000..4128073f60
--- /dev/null
+++ b/test/files/run/reify_typerefs_3a.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object foo {
+ class Expression {
+ override def toString = "Expression"
+ }
+}
+
+object Test extends App {
+ val code = reify {
+ List(new foo.Expression, new foo.Expression)
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_typerefs_3b.check b/test/files/run/reify_typerefs_3b.check
new file mode 100644
index 0000000000..919c298ba3
--- /dev/null
+++ b/test/files/run/reify_typerefs_3b.check
@@ -0,0 +1 @@
+evaluated = List(Expression, Expression) \ No newline at end of file
diff --git a/test/files/run/reify_typerefs_3b.scala b/test/files/run/reify_typerefs_3b.scala
new file mode 100644
index 0000000000..a7ede00c9c
--- /dev/null
+++ b/test/files/run/reify_typerefs_3b.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object foo {
+ object Expression {
+ override def toString = "Expression"
+ }
+}
+
+object Test extends App {
+ val code = reify {
+ List(foo.Expression, foo.Expression)
+ };
+
+ val toolbox = mkToolBox()
+ val evaluated = toolbox.runExpr(code.tree)
+ println("evaluated = " + evaluated)
+}
diff --git a/test/files/run/reify_varargs.scala b/test/files/run/reify_varargs.scala
index 175cfb5db0..fe8f03b702 100644
--- a/test/files/run/reify_varargs.scala
+++ b/test/files/run/reify_varargs.scala
@@ -1,16 +1,10 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
val msg = java.text.MessageFormat.format(
"On {1} there was {2} on planet {0}.",
"Hoth", "the fifth of August", "a disturbance in the Force")
println("Message="+msg)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check
index 66c2fcc77f..cb0b9a6c8b 100644
--- a/test/files/run/repl-colon-type.check
+++ b/test/files/run/repl-colon-type.check
@@ -7,6 +7,12 @@ scala> :type List[1, 2, 3]
<console>:2: error: identifier expected but integer literal found.
List[1, 2, 3]
^
+<console>:3: error: ']' expected but '}' found.
+ }
+ ^
+<console>:1: error: identifier expected but integer literal found.
+ List[1, 2, 3]
+ ^
scala> :type List(1, 2, 3)
@@ -25,7 +31,7 @@ scala> :type def f[T >: Null, U <: String](x: T, y: U) = Set(x, y)
[T >: Null, U <: String](x: T, y: U)scala.collection.immutable.Set[Any]
scala> :type def x = 1 ; def bar[T >: Null <: AnyRef](xyz: T) = 5
-[T >: Null <: AnyRef](xyz: T)Int
+=> Int <and> [T >: Null <: AnyRef](xyz: T)Int
scala>
@@ -39,10 +45,19 @@ scala> :type lazy val f = 5
Int
scala> :type protected lazy val f = 5
-Int
+<console>:2: error: illegal start of statement (no modifiers allowed here)
+ protected lazy val f = 5
+ ^
+<console>:5: error: lazy value f cannot be accessed in object $iw
+ Access to protected value f not permitted because
+ enclosing object $eval in package $line19 is not a subclass of
+ object $iw where target is defined
+ lazy val $result = `f`
+ ^
+
scala> :type def f = 5
-Int
+=> Int
scala> :type def f() = 5
()Int
@@ -54,4 +69,156 @@ scala> :type def g[T](xs: Set[_ <: T]) = Some(xs.head)
scala>
+scala> // verbose!
+
+scala> :type -v List(1,2,3) filter _
+// Type signature
+(Int => Boolean) => List[Int]
+
+// Internal Type structure
+TypeRef(
+ TypeSymbol(abstract trait Function1[-T1, +R] extends Object)
+ args = List(
+ TypeRef(
+ TypeSymbol(abstract trait Function1[-T1, +R] extends Object)
+ args = List(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ TypeRef(TypeSymbol(final class Boolean extends AnyVal))
+ )
+ )
+ TypeRef(
+ TypeSymbol(
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]]
+
+ )
+ args = List(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+ )
+ )
+)
+
+scala> :type -v def f[T >: Null, U <: String](x: T, y: U) = Set(x, y)
+// Type signature
+[T >: Null, U <: String](x: T, y: U)scala.collection.immutable.Set[Any]
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T >: Null), TypeParam(U <: String))
+ resultType = MethodType(
+ params = List(TermSymbol(x: T), TermSymbol(y: U))
+ resultType = TypeRef(
+ TypeSymbol(
+ abstract trait Set[A] extends Iterable[A] with Set[A] with GenericSetTemplate[A,scala.collection.immutable.Set] with SetLike[A,scala.collection.immutable.Set[A]] with Parallelizable[A,scala.collection.parallel.immutable.ParSet[A]]
+
+ )
+ args = List(TypeRef(TypeSymbol(abstract class Any extends )))
+ )
+ )
+)
+
+scala> :type -v def x = 1 ; def bar[T >: Null <: AnyRef](xyz: T) = 5
+// Type signature
+=> Int <and> [T >: Null <: AnyRef](xyz: T)Int
+
+// Internal Type structure
+OverloadedType(
+ alts = List(
+ NullaryMethodType(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+ PolyType(
+ typeParams = List(TypeParam(T >: Null <: AnyRef))
+ resultType = MethodType(
+ params = List(TermSymbol(xyz: T))
+ resultType = TypeRef(
+ TypeSymbol(final class Int extends AnyVal)
+ )
+ )
+ )
+ )
+)
+
+scala> :type -v Nil.combinations _
+// Type signature
+Int => Iterator[List[Nothing]]
+
+// Internal Type structure
+TypeRef(
+ TypeSymbol(abstract trait Function1[-T1, +R] extends Object)
+ args = List(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ TypeRef(
+ TypeSymbol(
+ abstract trait Iterator[+A] extends TraversableOnce[A]
+ )
+ args = List(
+ TypeRef(
+ TypeSymbol(
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]]
+
+ )
+ args = List(
+ TypeRef(
+ TypeSymbol(final abstract class Nothing extends Any)
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
+scala> :type -v def f[T <: AnyVal] = List[T]().combinations _
+// Type signature
+[T <: AnyVal]=> Int => Iterator[List[T]]
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T <: AnyVal))
+ resultType = NullaryMethodType(
+ TypeRef(
+ TypeSymbol(abstract trait Function1[-T1, +R] extends Object)
+ args = List(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ TypeRef(
+ TypeSymbol(
+ abstract trait Iterator[+A] extends TraversableOnce[A]
+ )
+ args = List(
+ TypeRef(
+ TypeSymbol(
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]]
+
+ )
+ args = List(TypeParamTypeRef(TypeParam(T <: AnyVal)))
+ )
+ )
+ )
+ )
+ )
+ )
+)
+
+scala> :type -v def f[T, U >: T](x: T, y: List[U]) = x :: y
+// Type signature
+[T, U >: T](x: T, y: List[U])List[U]
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T), TypeParam(U >: T))
+ resultType = MethodType(
+ params = List(TermSymbol(x: T), TermSymbol(y: List[U]))
+ resultType = TypeRef(
+ TypeSymbol(
+ sealed abstract class List[+A] extends AbstractSeq[A] with LinearSeq[A] with Product with GenericTraversableTemplate[A,List] with LinearSeqOptimized[A,List[A]]
+
+ )
+ args = List(TypeParamTypeRef(TypeParam(U >: T)))
+ )
+ )
+)
+
+scala>
+
scala>
diff --git a/test/files/run/repl-colon-type.scala b/test/files/run/repl-colon-type.scala
index 39ab580d2a..c055b215c2 100644
--- a/test/files/run/repl-colon-type.scala
+++ b/test/files/run/repl-colon-type.scala
@@ -18,6 +18,14 @@ object Test extends ReplTest {
|:type def f() = 5
|
|:type def g[T](xs: Set[_ <: T]) = Some(xs.head)
+ |
+ |// verbose!
+ |:type -v List(1,2,3) filter _
+ |:type -v def f[T >: Null, U <: String](x: T, y: U) = Set(x, y)
+ |:type -v def x = 1 ; def bar[T >: Null <: AnyRef](xyz: T) = 5
+ |:type -v Nil.combinations _
+ |:type -v def f[T <: AnyVal] = List[T]().combinations _
+ |:type -v def f[T, U >: T](x: T, y: List[U]) = x :: y
""".stripMargin
}
diff --git a/test/files/run/repl-parens.check b/test/files/run/repl-parens.check
index 69f0a9ce30..4b7ce6b059 100644
--- a/test/files/run/repl-parens.check
+++ b/test/files/run/repl-parens.check
@@ -34,7 +34,7 @@ res7: (Int, Int) = (4,4)
scala> (((2 + 2)), ((2 + 2)), 2)
res8: (Int, Int, Int) = (4,4,2)
-scala> ((((2 + 2)), ((2 + 2)), 2).productIterator ++ Iterator(3) mkString)
+scala> (((((2 + 2)), ((2 + 2)), 2).productIterator ++ Iterator(3)).mkString)
res9: String = 4423
scala>
diff --git a/test/files/run/repl-parens.scala b/test/files/run/repl-parens.scala
index c1cf9b50e1..e25933b1a2 100644
--- a/test/files/run/repl-parens.scala
+++ b/test/files/run/repl-parens.scala
@@ -11,7 +11,7 @@ object Test extends ReplTest {
5 ; ( (2 + 2 ) ) ; ((5))
(((2 + 2)), ((2 + 2)))
(((2 + 2)), ((2 + 2)), 2)
-((((2 + 2)), ((2 + 2)), 2).productIterator ++ Iterator(3) mkString)
+(((((2 + 2)), ((2 + 2)), 2).productIterator ++ Iterator(3)).mkString)
55 ; ((2 + 2)) ; (1, 2, 3)
55 ; (x: Int) => x + 1 ; () => ((5))
@@ -26,4 +26,4 @@ foo(5)(10)(15)+foo(5)(10)(15)
List(1) ++ List('a')
""".trim
-} \ No newline at end of file
+}
diff --git a/test/files/run/repl-power.check b/test/files/run/repl-power.check
index 1e7b6f0cd8..c509434116 100644
--- a/test/files/run/repl-power.check
+++ b/test/files/run/repl-power.check
@@ -1,32 +1,32 @@
-Type in expressions to have them evaluated.
-Type :help for more information.
-
-scala> :power
-** Power User mode enabled - BEEP WHIR GYVE **
-** :phase has been set to 'typer'. **
-** scala.tools.nsc._ has been imported **
-** global._, definitions._ also imported **
-** Try :help, :vals, power.<tab> **
-
-scala> // guarding against "error: reference to global is ambiguous"
-
-scala> global.emptyValDef // "it is imported twice in the same scope by ..."
-res0: $r.global.emptyValDef.type = private val _ = _
-
-scala> val tp = ArrayClass[scala.util.Random] // magic with manifests
-tp: $r.global.Type = Array[scala.util.Random]
-
-scala> tp.memberType(Array_apply) // evidence
-res1: $r.global.Type = (i: Int)scala.util.Random
-
-scala> val m = LIT(10) MATCH (CASE(LIT(5)) ==> FALSE, DEFAULT ==> TRUE) // treedsl
-m: $r.treedsl.global.Match =
-10 match {
- case 5 => false
- case _ => true
-}
-
-scala> typed(m).tpe // typed is in scope
-res2: $r.treedsl.global.Type = Boolean
-
-scala>
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala> :power
+** Power User mode enabled - BEEP WHIR GYVE **
+** :phase has been set to 'typer'. **
+** scala.tools.nsc._ has been imported **
+** global._, definitions._ also imported **
+** Try :help, :vals, power.<tab> **
+
+scala> // guarding against "error: reference to global is ambiguous"
+
+scala> global.emptyValDef // "it is imported twice in the same scope by ..."
+res0: $r.global.emptyValDef.type = private val _ = _
+
+scala> val tp = ArrayClass[scala.util.Random] // magic with tags
+tp: $r.global.Type = Array[scala.util.Random]
+
+scala> tp.memberType(Array_apply) // evidence
+res1: $r.global.Type = (i: Int)scala.util.Random
+
+scala> val m = LIT(10) MATCH (CASE(LIT(5)) ==> FALSE, DEFAULT ==> TRUE) // treedsl
+m: $r.treedsl.global.Match =
+10 match {
+ case 5 => false
+ case _ => true
+}
+
+scala> typed(m).tpe // typed is in scope
+res2: $r.treedsl.global.Type = Boolean
+
+scala>
diff --git a/test/files/run/repl-power.scala b/test/files/run/repl-power.scala
index 27da3df106..f7c88c63ff 100644
--- a/test/files/run/repl-power.scala
+++ b/test/files/run/repl-power.scala
@@ -5,10 +5,9 @@ object Test extends ReplTest {
:power
// guarding against "error: reference to global is ambiguous"
global.emptyValDef // "it is imported twice in the same scope by ..."
-val tp = ArrayClass[scala.util.Random] // magic with manifests
+val tp = ArrayClass[scala.util.Random] // magic with tags
tp.memberType(Array_apply) // evidence
val m = LIT(10) MATCH (CASE(LIT(5)) ==> FALSE, DEFAULT ==> TRUE) // treedsl
typed(m).tpe // typed is in scope
""".trim
}
-
diff --git a/test/files/run/repl-reset.check b/test/files/run/repl-reset.check
index 8c21ab067a..7256b851bb 100644
--- a/test/files/run/repl-reset.check
+++ b/test/files/run/repl-reset.check
@@ -28,7 +28,7 @@ val x3 = 3
case class BippyBungus()
x1 + x2 + x3
-Forgetting all expression results and named terms: BippyBungus, x1, x2, x3
+Forgetting all expression results and named terms: $intp, BippyBungus, x1, x2, x3
Forgetting defined types: BippyBungus
scala> x1 + x2 + x3
diff --git a/test/files/run/repl-suppressed-warnings.scala b/test/files/run/repl-suppressed-warnings.scala
index a78b00f36e..1a51afe34f 100644
--- a/test/files/run/repl-suppressed-warnings.scala
+++ b/test/files/run/repl-suppressed-warnings.scala
@@ -1,6 +1,7 @@
import scala.tools.partest.ReplTest
object Test extends ReplTest {
+ override def extraSettings = ""
def code = """
// "Is this thing on?" Not working on first couple
diff --git a/test/files/run/repl-type-verbose.check b/test/files/run/repl-type-verbose.check
new file mode 100644
index 0000000000..103ac3e64d
--- /dev/null
+++ b/test/files/run/repl-type-verbose.check
@@ -0,0 +1,186 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> // verbose!
+
+scala> :type -v def f = 5
+// Type signature
+=> Int
+
+// Internal Type structure
+NullaryMethodType(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+)
+
+scala> :type -v def f() = 5
+// Type signature
+()Int
+
+// Internal Type structure
+NullaryMethodType(
+ resultType = TypeRef(TypeSymbol(final class Int extends AnyVal))
+)
+
+scala> :type -v def f[T] = 5
+// Type signature
+[T]=> Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T))
+ resultType = NullaryMethodType(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala> :type -v def f[T >: Null] = 5
+// Type signature
+[T >: Null]=> Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T >: Null))
+ resultType = NullaryMethodType(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala> :type -v def f[T <: String] = 5
+// Type signature
+[T <: String]=> Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T <: String))
+ resultType = NullaryMethodType(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala> :type -v def f[T]() = 5
+// Type signature
+[T]()Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T))
+ resultType = NullaryMethodType(
+ resultType = TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala> :type -v def f[T, U]() = 5
+// Type signature
+[T, U]()Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T), TypeParam(U))
+ resultType = NullaryMethodType(
+ resultType = TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala> :type -v def f[T, U]()() = 5
+// Type signature
+[T, U]()()Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T), TypeParam(U))
+ resultType = NullaryMethodType(
+ resultType = NullaryMethodType(
+ resultType = TypeRef(
+ TypeSymbol(final class Int extends AnyVal)
+ )
+ )
+ )
+)
+
+scala> :type -v def f[T, U <: T] = 5
+// Type signature
+[T, U <: T]=> Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T), TypeParam(U <: T))
+ resultType = NullaryMethodType(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala> :type -v def f[T, U <: T](x: T)(y: U) = 5
+// Type signature
+[T, U <: T](x: T)(y: U)Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T), TypeParam(U <: T))
+ resultType = MethodType(
+ params = List(TermSymbol(x: T))
+ resultType = MethodType(
+ params = List(TermSymbol(y: U))
+ resultType = TypeRef(
+ TypeSymbol(final class Int extends AnyVal)
+ )
+ )
+ )
+)
+
+scala> :type -v def f[T: Ordering] = 5
+// Type signature
+[T](implicit evidence$1: Ordering[T])Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T))
+ resultType = MethodType(
+ params = List(TermSymbol(implicit evidence$1: Ordering[T]))
+ resultType = TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala> :type -v def f[T: Ordering] = implicitly[Ordering[T]]
+// Type signature
+[T](implicit evidence$1: Ordering[T])Ordering[T]
+
+// Internal Type structure
+PolyType(
+ typeParams = List(TypeParam(T))
+ resultType = MethodType(
+ params = List(TermSymbol(implicit evidence$1: Ordering[T]))
+ resultType = AliasTypeRef(
+ Alias(type Ordering[T] = scala.math.Ordering[T])
+ args = List(TypeParamTypeRef(TypeParam(T)))
+ normalize = TypeRef(
+ TypeSymbol(
+ abstract trait Ordering[T] extends Comparator[T] with PartialOrdering[T] with Serializable
+
+ )
+ args = List(TypeParamTypeRef(TypeParam(T)))
+ )
+ )
+ )
+)
+
+scala> :type -v def f[T <: { type Bippy = List[Int] ; def g(): Bippy }] = 5
+// Type signature
+[T <: AnyRef{type Bippy = List[Int]; def g(): this.Bippy}]=> Int
+
+// Internal Type structure
+PolyType(
+ typeParams = List(
+ TypeParam(
+ T <: AnyRef{type Bippy = List[Int]; def g(): this.Bippy}
+ )
+ )
+ resultType = NullaryMethodType(
+ TypeRef(TypeSymbol(final class Int extends AnyVal))
+ )
+)
+
+scala>
+
+scala>
diff --git a/test/files/run/repl-type-verbose.scala b/test/files/run/repl-type-verbose.scala
new file mode 100644
index 0000000000..10c390550a
--- /dev/null
+++ b/test/files/run/repl-type-verbose.scala
@@ -0,0 +1,20 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+ |// verbose!
+ |:type -v def f = 5
+ |:type -v def f() = 5
+ |:type -v def f[T] = 5
+ |:type -v def f[T >: Null] = 5
+ |:type -v def f[T <: String] = 5
+ |:type -v def f[T]() = 5
+ |:type -v def f[T, U]() = 5
+ |:type -v def f[T, U]()() = 5
+ |:type -v def f[T, U <: T] = 5
+ |:type -v def f[T, U <: T](x: T)(y: U) = 5
+ |:type -v def f[T: Ordering] = 5
+ |:type -v def f[T: Ordering] = implicitly[Ordering[T]]
+ |:type -v def f[T <: { type Bippy = List[Int] ; def g(): Bippy }] = 5
+ """.stripMargin
+}
diff --git a/test/files/run/si5045.check b/test/files/run/si5045.check
new file mode 100644
index 0000000000..7e9c1961b7
--- /dev/null
+++ b/test/files/run/si5045.check
@@ -0,0 +1,6 @@
+ extract an exact match 2011-07-15 2011-07-15
+ extract from middle of string 2011-07-15 2011-07-15
+ extract from middle of string (P2) 2011-07-15 2011-07-15
+ extract from middle of string (P3) 2011-07-15 2011-07-15
+ copyright example has date Copyright 2011 Copyright 2011
+ copyright example missing date No copyright No copyright
diff --git a/test/files/run/si5045.scala b/test/files/run/si5045.scala
new file mode 100644
index 0000000000..e198b101f3
--- /dev/null
+++ b/test/files/run/si5045.scala
@@ -0,0 +1,46 @@
+object Test extends App {
+
+ import scala.util.matching.{ Regex, UnanchoredRegex }
+
+ val dateP1 = """(\d\d\d\d)-(\d\d)-(\d\d)""".r.unanchored
+ val dateP2 = """(\d\d\d\d)-(\d\d)-(\d\d)""" r ("year", "month", "day") unanchored
+ val dateP3 = new Regex("""(\d\d\d\d)-(\d\d)-(\d\d)""", "year", "month", "day") with UnanchoredRegex
+
+ val yearStr = "2011"
+ val dateStr = List(yearStr,"07","15").mkString("-")
+
+ def test(msg: String)(strs: Seq[String]): Unit = println("%40s %s".format(msg, strs mkString " "))
+
+ test("extract an exact match") {
+ val dateP1(y,m,d) = dateStr
+ Seq(List(y,m,d).mkString("-"), dateStr)
+ }
+
+ test("extract from middle of string") {
+ val dateP1(y,m,d) = "Tested on "+dateStr+"."
+ Seq(List(y,m,d).mkString("-"), dateStr)
+ }
+
+ test("extract from middle of string (P2)") {
+ val dateP2(y,m,d) = "Tested on "+dateStr+"."
+ Seq(List(y,m,d).mkString("-"), dateStr)
+ }
+
+ test("extract from middle of string (P3)") {
+ val dateP2(y,m,d) = "Tested on "+dateStr+"."
+ Seq(List(y,m,d).mkString("-"), dateStr)
+ }
+
+ def copyright(in: String): String = in match {
+ case dateP1(year, month, day) => "Copyright "+year
+ case _ => "No copyright"
+ }
+
+ test("copyright example has date") {
+ Seq(copyright("Date of this document: "+dateStr), "Copyright "+yearStr)
+ }
+
+ test("copyright example missing date") {
+ Seq(copyright("Date of this document: unknown"), "No copyright")
+ }
+}
diff --git a/test/files/run/t0421.check b/test/files/run/t0421-new.check
index cdcf042f19..cdcf042f19 100644
--- a/test/files/run/t0421.check
+++ b/test/files/run/t0421-new.check
diff --git a/test/files/run/t0421-new.scala b/test/files/run/t0421-new.scala
new file mode 100644
index 0000000000..7de6b7f2c4
--- /dev/null
+++ b/test/files/run/t0421-new.scala
@@ -0,0 +1,30 @@
+// ticket #421
+object Test extends App {
+
+ def transpose[A: ArrayTag](xss: Array[Array[A]]) = {
+ for (i <- Array.range(0, xss(0).length)) yield
+ for (xs <- xss) yield xs(i)
+ }
+
+ def scalprod(xs: Array[Double], ys: Array[Double]) = {
+ var acc = 0.0
+ for ((x, y) <- xs zip ys) acc = acc + x * y
+ acc
+ }
+
+ def matmul(xss: Array[Array[Double]], yss: Array[Array[Double]]) = {
+ val ysst = transpose(yss)
+ val ysst1: Array[Array[Double]] = yss.transpose
+ assert(ysst.deep == ysst1.deep)
+ for (xs <- xss) yield
+ for (yst <- ysst) yield
+ scalprod(xs, yst)
+ }
+
+ val a1 = Array(Array(0, 2, 4), Array(1, 3, 5))
+ println(transpose(a1).deep.mkString("[", ",", "]"))
+
+ println(matmul(Array(Array(2, 3)), Array(Array(5), Array(7))).deep.mkString("[", ",", "]"))
+
+ println(matmul(Array(Array(4)), Array(Array(6, 8))).deep.mkString("[", ",", "]"))
+}
diff --git a/test/files/run/t0421-old.check b/test/files/run/t0421-old.check
new file mode 100644
index 0000000000..cdcf042f19
--- /dev/null
+++ b/test/files/run/t0421-old.check
@@ -0,0 +1,3 @@
+[Array(0, 1),Array(2, 3),Array(4, 5)]
+[Array(31.0)]
+[Array(24.0, 32.0)]
diff --git a/test/files/run/t0421.scala b/test/files/run/t0421-old.scala
index 8d51013924..8d51013924 100644
--- a/test/files/run/t0421.scala
+++ b/test/files/run/t0421-old.scala
diff --git a/test/files/run/t0677-new.scala b/test/files/run/t0677-new.scala
new file mode 100644
index 0000000000..bf7a3971dc
--- /dev/null
+++ b/test/files/run/t0677-new.scala
@@ -0,0 +1,8 @@
+object Test extends App {
+ class X[T: ArrayTag] {
+ val a = Array.ofDim[T](3, 4)
+ }
+ val x = new X[String]
+ x.a(1)(2) = "hello"
+ assert(x.a(1)(2) == "hello")
+}
diff --git a/test/files/run/t0677.scala b/test/files/run/t0677-old.scala
index 6c8a3a7e99..6c8a3a7e99 100644
--- a/test/files/run/t0677.scala
+++ b/test/files/run/t0677-old.scala
diff --git a/test/files/run/t1195-new.check b/test/files/run/t1195-new.check
new file mode 100644
index 0000000000..554e3fd03d
--- /dev/null
+++ b/test/files/run/t1195-new.check
@@ -0,0 +1,6 @@
+ConcreteTypeTag[Bar.type], underlying = <: scala.runtime.AbstractFunction1[Int,Bar] with Serializable{case def unapply(x$0: Bar): Option[Int]} with Singleton
+ConcreteTypeTag[Bar], underlying = <: Product with Serializable{val x: Int; def copy(x: Int): Bar; def copy$default$1: Int; def _1: Int}
+ConcreteTypeTag[Product with Serializable], underlying = Product with Serializable
+ConcreteTypeTag[Bar.type], underlying = <: scala.runtime.AbstractFunction1[Int,Bar] with Serializable{case def unapply(x$0: Bar): Option[Int]} with Singleton
+ConcreteTypeTag[Bar], underlying = <: Product with Serializable{val x: Int; def copy(x: Int): Bar; def copy$default$1: Int; def _1: Int}
+ConcreteTypeTag[Product with Serializable], underlying = Product with Serializable
diff --git a/test/files/run/t1195-new.scala b/test/files/run/t1195-new.scala
new file mode 100644
index 0000000000..6f28a4a167
--- /dev/null
+++ b/test/files/run/t1195-new.scala
@@ -0,0 +1,26 @@
+object Test {
+ def f() = { case class Bar(x: Int); Bar }
+ def g() = { case class Bar(x: Int); Bar(5) }
+ def h() = { case object Bar ; Bar }
+
+ val f1 = f()
+ val g1 = g()
+ val h1 = h()
+
+ def m[T: TypeTag](x: T) = println(typeTag[T] + ", underlying = " + typeTag[T].sym.typeSignature)
+
+ def main(args: Array[String]): Unit = {
+ m(f)
+ m(g)
+ m(h)
+ m(f1)
+ m(g1)
+ m(h1)
+ }
+}
+
+class A1[T] {
+ class B1[U] {
+ def f = { case class D(x: Int) extends A1[String] ; new D(5) }
+ }
+}
diff --git a/test/files/run/t1195.check b/test/files/run/t1195-old.check
index d023bc91f7..eb60eceb17 100644
--- a/test/files/run/t1195.check
+++ b/test/files/run/t1195-old.check
@@ -1,6 +1,6 @@
-_ <: scala.runtime.AbstractFunction1[Int, _ <: Object with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object
-_ <: Object with scala.Product with scala.Serializable
-Object with scala.Product with scala.Serializable
-_ <: scala.runtime.AbstractFunction1[Int, _ <: Object with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object
-_ <: Object with scala.Product with scala.Serializable
-Object with scala.Product with scala.Serializable
+_ <: scala.runtime.AbstractFunction1[Int, _ <: Object with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object
+_ <: Object with scala.Product with scala.Serializable
+Object with scala.Product with scala.Serializable
+_ <: scala.runtime.AbstractFunction1[Int, _ <: Object with scala.Product with scala.Serializable] with scala.Serializable with java.lang.Object
+_ <: Object with scala.Product with scala.Serializable
+Object with scala.Product with scala.Serializable
diff --git a/test/files/run/t1195.scala b/test/files/run/t1195-old.scala
index 81ef5bdb0e..b46a3b70f5 100644
--- a/test/files/run/t1195.scala
+++ b/test/files/run/t1195-old.scala
@@ -6,7 +6,7 @@ object Test {
val f1 = f()
val g1 = g()
val h1 = h()
-
+
def m[T: Manifest](x: T) = println(manifest[T])
def main(args: Array[String]): Unit = {
diff --git a/test/files/run/t1247.check b/test/files/run/t1247.check
new file mode 100644
index 0000000000..ce123032fd
--- /dev/null
+++ b/test/files/run/t1247.check
@@ -0,0 +1 @@
+Is same closure class: true is same closure: true
diff --git a/test/files/run/t1247.scala b/test/files/run/t1247.scala
new file mode 100644
index 0000000000..c709b73bc8
--- /dev/null
+++ b/test/files/run/t1247.scala
@@ -0,0 +1,11 @@
+object Test extends App {
+ val f = () => 5
+ def test(g: => Int) {
+ val gFunc = g _
+ val isSameClosureClass = gFunc.getClass == f.getClass
+ val isSame = gFunc eq f
+ println("Is same closure class: "+isSameClosureClass+" is same closure: "+isSame)
+ }
+
+ test(f())
+}
diff --git a/test/files/run/t1500.scala b/test/files/run/t1500.scala
index c312a9a883..586a2666ad 100644
--- a/test/files/run/t1500.scala
+++ b/test/files/run/t1500.scala
@@ -8,7 +8,7 @@ object Test {
val testCode = <code>
- class posingAs[A] extends TypeConstraint
+ class posingAs[A] extends annotation.TypeConstraint
def resolve[A,B](x: A @posingAs[B]): B = x.asInstanceOf[B]
diff --git a/test/files/run/t1501.scala b/test/files/run/t1501.scala
index 05e4da8c7a..dee6e0c68e 100644
--- a/test/files/run/t1501.scala
+++ b/test/files/run/t1501.scala
@@ -8,7 +8,7 @@ object Test {
val testCode = <code>
- class xyz[A] extends TypeConstraint
+ class xyz[A] extends annotation.TypeConstraint
def loopWhile[T](cond: =>Boolean)(body: =>(Unit @xyz[T])): Unit @ xyz[T] = {{
if (cond) {{
diff --git a/test/pending/run/t1697.scala b/test/files/run/t1697.scala
index 01590dd405..01590dd405 100644
--- a/test/pending/run/t1697.scala
+++ b/test/files/run/t1697.scala
diff --git a/test/files/run/t2236-new.scala b/test/files/run/t2236-new.scala
new file mode 100644
index 0000000000..bbabe8e7d9
--- /dev/null
+++ b/test/files/run/t2236-new.scala
@@ -0,0 +1,17 @@
+class T[A](implicit val m:TypeTag[A])
+class Foo
+class Bar extends T[Foo]
+object Test extends App {
+ new Bar
+}
+
+object EvidenceTest {
+ trait E[T]
+ trait A[T] { implicit val e: E[T] = null }
+ class B[T : E] extends A[T] { override val e = null }
+
+ def f[T] {
+ implicit val e: E[T] = null
+ new B[T]{}
+ }
+}
diff --git a/test/files/run/t2236.scala b/test/files/run/t2236-old.scala
index 64ed18c805..64ed18c805 100755..100644
--- a/test/files/run/t2236.scala
+++ b/test/files/run/t2236-old.scala
diff --git a/test/files/run/t2337.check b/test/files/run/t2337.check
new file mode 100644
index 0000000000..18f1f66fc3
--- /dev/null
+++ b/test/files/run/t2337.check
@@ -0,0 +1,4 @@
+(Both Int,-1,-1)
+(Both Float,1,1)
+(Float then Int,0,0)
+(Int then Float,0,0)
diff --git a/test/files/run/t2337.scala b/test/files/run/t2337.scala
new file mode 100644
index 0000000000..86a372ce56
--- /dev/null
+++ b/test/files/run/t2337.scala
@@ -0,0 +1,21 @@
+
+object Test {
+
+ def compare(first: Any, second: Any): Any = {
+ (first, second) match {
+ case (k: Int, o: Int) => k compare o
+ //why the next case matches (Float, Int) but does not match (Int, Float) ???
+ case (k: Number, o: Number) => k.doubleValue() compare o.doubleValue()
+ case _ => "BOGON"
+ // throw new Exception("Unsupported compare " + first + "; " + second)
+ }
+ }
+
+ def main(args: Array[String]): Unit = {
+ println("Both Int", -1, compare(0, 1))
+ println("Both Float", 1, compare(1.0, 0.0))
+ println("Float then Int", 0, compare(10.0, 10))
+ println("Int then Float", 0, compare(10, 10.0)) //this fails with an exception
+ }
+}
+
diff --git a/test/files/run/t2386-new.check b/test/files/run/t2386-new.check
new file mode 100644
index 0000000000..98e226f946
--- /dev/null
+++ b/test/files/run/t2386-new.check
@@ -0,0 +1,2 @@
+a(0) = Array(1, 2)
+a(1) = Array("a", "b")
diff --git a/test/files/run/t2386-new.scala b/test/files/run/t2386-new.scala
new file mode 100644
index 0000000000..15d1859759
--- /dev/null
+++ b/test/files/run/t2386-new.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ val a = Array(Array(1, 2), Array("a","b"))
+ println("a(0) = Array(" + (a(0) mkString ", ") + ")")
+ println("a(1) = Array(" + (a(1) map (s => "\"" + s + "\"") mkString ", ") + ")")
+}
diff --git a/test/files/run/t2886.check b/test/files/run/t2886.check
index 5fe1e73a45..8d97a82799 100644
--- a/test/files/run/t2886.check
+++ b/test/files/run/t2886.check
@@ -1,5 +1,5 @@
-((x: scala.Predef.String) => {
- val x$1 = x;
- val x$2 = x;
- Test.test(x$2, x$1)
-})
+((x: String) => {
+ val x$1 = x;
+ val x$2 = x;
+ Test.this.test(x$2, x$1)
+})
diff --git a/test/files/run/t2886.scala b/test/files/run/t2886.scala
new file mode 100644
index 0000000000..e0835a0a44
--- /dev/null
+++ b/test/files/run/t2886.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test {
+ def test(name: String, address: String) = null
+ def main(args: Array[String]) = {
+ val tree = reify((x:String) => test(address=x,name=x)).tree
+ println(tree)
+ }
+}
diff --git a/test/files/run/t3507-new.check b/test/files/run/t3507-new.check
new file mode 100644
index 0000000000..6e4fa4170e
--- /dev/null
+++ b/test/files/run/t3507-new.check
@@ -0,0 +1 @@
+ConcreteTypeTag[_1.b.c.type]
diff --git a/test/files/run/t3507-new.scala b/test/files/run/t3507-new.scala
new file mode 100644
index 0000000000..c7a529e8b8
--- /dev/null
+++ b/test/files/run/t3507-new.scala
@@ -0,0 +1,15 @@
+class A {
+ object b {
+ object c
+ }
+ def m = b.c
+}
+
+object Test extends App {
+ var a: A = new A // mutable
+ val c /*: object _1.b.c forSome { val _1: A } */ = a.m // widening using existential
+
+ def mani[T: TypeTag](x: T) = println(typeTag[T])
+ mani/*[object _1.b.c]*/(c) // kaboom in manifestOfType / TreeGen.mkAttributedQualifier
+ // --> _1 is not in scope here
+} \ No newline at end of file
diff --git a/test/files/run/t3569.check b/test/files/run/t3569.check
index 24cee4bf00..a9fb5ff32e 100644
--- a/test/files/run/t3569.check
+++ b/test/files/run/t3569.check
@@ -8,10 +8,9 @@ private int Test$X.lval3
private int Test$X.var1
private int Test$X.var2
private int Test$X.var3
-private volatile int Test$X.bitmap$priv$0
-public int Test$X.x
-public volatile int Test$X.bitmap$0
-public final int Test$Y.z1
-public final int Test$Y.z2
-public int Test$Y.x
-public int Test$Y.y
+private int Test$X.x
+private volatile byte Test$X.bitmap$0
+private final int Test$Y.z1
+private final int Test$Y.z2
+private int Test$Y.x
+private int Test$Y.y
diff --git a/test/pending/run/t3705.scala b/test/files/run/t3705.scala
index fcc020f28c..fcc020f28c 100644
--- a/test/pending/run/t3705.scala
+++ b/test/files/run/t3705.scala
diff --git a/test/files/run/t3758.scala b/test/files/run/t3758-old.scala
index 18750b0a9c..f00254afee 100644
--- a/test/files/run/t3758.scala
+++ b/test/files/run/t3758-old.scala
@@ -7,4 +7,4 @@ object Test {
assert(manifest[Array[Int]].typeArguments contains manifest[Int])
assert(manifest[Array[Float]].typeArguments contains manifest[Float])
}
-}
+} \ No newline at end of file
diff --git a/test/files/run/t3798.check b/test/files/run/t3798.check
new file mode 100644
index 0000000000..27ba77ddaf
--- /dev/null
+++ b/test/files/run/t3798.check
@@ -0,0 +1 @@
+true
diff --git a/test/files/run/t3798.scala b/test/files/run/t3798.scala
new file mode 100644
index 0000000000..3ede57bee7
--- /dev/null
+++ b/test/files/run/t3798.scala
@@ -0,0 +1,10 @@
+object Test {
+ def main(args: Array[String]) {
+ val seq: MySeq[Undefined] = new MySeq[Floats](new Array[Float](10))
+ println(10 == seq.array.length)
+ }
+}
+
+sealed trait Undefined { type ArrayType <: Array[_] }
+sealed trait Floats extends Undefined { type ArrayType = Array[Float] }
+class MySeq[+T <: Undefined](val array: T#ArrayType)
diff --git a/test/files/run/t3835.scala b/test/files/run/t3835.scala
index 49e591195f..c120a61f6e 100644
--- a/test/files/run/t3835.scala
+++ b/test/files/run/t3835.scala
@@ -1,4 +1,9 @@
object Test extends App {
- println((1, 2, 3) match { case (r, \u03b8, \u03c6) => r + \u03b8 + \u03c6 })
- println(1 match { case \u00e9 => \u00e9 })
+ // work around optimizer bug SI-5672 -- generates wrong bytecode for switches in arguments
+ // virtpatmat happily emits a switch for a one-case switch, whereas -Xoldpatmat did not
+ // this is not the focus of this test, hence the temporary workaround
+ def a = (1, 2, 3) match { case (r, \u03b8, \u03c6) => r + \u03b8 + \u03c6 }
+ println(a)
+ def b = (1 match { case \u00e9 => \u00e9 })
+ println(b)
}
diff --git a/test/files/run/t4110-new.check b/test/files/run/t4110-new.check
new file mode 100644
index 0000000000..28f220e1fe
--- /dev/null
+++ b/test/files/run/t4110-new.check
@@ -0,0 +1,2 @@
+ConcreteTypeTag[Test.A with Test.B]
+ConcreteTypeTag[Test.A with Test.B]
diff --git a/test/files/run/t4110-new.scala b/test/files/run/t4110-new.scala
new file mode 100644
index 0000000000..3285b82c61
--- /dev/null
+++ b/test/files/run/t4110-new.scala
@@ -0,0 +1,11 @@
+object Test extends App {
+ def inferredType[T : TypeTag](v : T) = println(typeTag[T])
+
+ trait A
+ trait B
+
+ inferredType(new A with B)
+
+ val name = new A with B
+ inferredType(name)
+} \ No newline at end of file
diff --git a/test/files/run/t4110.check b/test/files/run/t4110-old.check
index 8b005989de..8b005989de 100644
--- a/test/files/run/t4110.check
+++ b/test/files/run/t4110-old.check
diff --git a/test/files/run/t4110.scala b/test/files/run/t4110-old.scala
index 4bd377b73e..a42646ce52 100644
--- a/test/files/run/t4110.scala
+++ b/test/files/run/t4110-old.scala
@@ -3,7 +3,7 @@ object Test extends App {
trait A
trait B
-
+
inferredType(new A with B)
val name = new A with B
diff --git a/test/files/run/t4172.check b/test/files/run/t4172.check
index da467e27ea..4598e02d1f 100644
--- a/test/files/run/t4172.check
+++ b/test/files/run/t4172.check
@@ -4,6 +4,8 @@ Type :help for more information.
scala>
scala> val c = { class C { override def toString = "C" }; ((new C, new C { def f = 2 })) }
+warning: there were 1 feature warnings; re-run with -feature for details
+warning: there were 1 feature warnings; re-run with -feature for details
c: (C, C{def f: Int}) forSome { type C <: Object } = (C,C)
scala>
diff --git a/test/files/run/t4190.check b/test/files/run/t4190.check
new file mode 100644
index 0000000000..b8aae0c7a1
--- /dev/null
+++ b/test/files/run/t4190.check
@@ -0,0 +1,3 @@
+a0
+b0
+c0
diff --git a/test/files/run/t4190.scala b/test/files/run/t4190.scala
new file mode 100644
index 0000000000..aa88b8708d
--- /dev/null
+++ b/test/files/run/t4190.scala
@@ -0,0 +1,6 @@
+import collection.mutable._
+
+object Test extends App {
+ val x: ArrayBuffer[String] = ArrayBuffer("a", "b", "c")
+ x.view map (_ + "0") foreach println
+}
diff --git a/test/files/run/t4216.check b/test/files/run/t4216.check
new file mode 100644
index 0000000000..ac19a98315
--- /dev/null
+++ b/test/files/run/t4216.check
@@ -0,0 +1,34 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala> def f[A: ArrayTag](a: A) = java.util.Arrays.asList(Array(a): _*)
+f: [A](a: A)(implicit evidence$1: ArrayTag[A])java.util.List[A]
+
+scala> f(".")
+res0: java.util.List[String] = [.]
+
+scala> f(0)
+res1: java.util.List[Int] = [0]
+
+scala> def i(a: Int) = java.util.Arrays.asList(Array(a): _*)
+i: (a: Int)java.util.List[Int]
+
+scala> i(0)
+res2: java.util.List[Int] = [0]
+
+scala> def o(a: Any) = java.util.Arrays.asList(Array(a): _*)
+o: (a: Any)java.util.List[Any]
+
+scala> o(".")
+res3: java.util.List[Any] = [.]
+
+scala> class V(val a: Int) extends AnyVal
+defined class V
+
+scala> f(new V(0))
+res4: java.util.List[V] = [V@0]
+
+scala> o(new V(0))
+res5: java.util.List[Any] = [V@0]
+
+scala>
diff --git a/test/files/run/t4216.scala b/test/files/run/t4216.scala
new file mode 100644
index 0000000000..4ada8f48aa
--- /dev/null
+++ b/test/files/run/t4216.scala
@@ -0,0 +1,18 @@
+import scala.tools.partest.ReplTest
+
+// t4216
+object Test extends ReplTest {
+ def code =
+ """
+ |def f[A: ArrayTag](a: A) = java.util.Arrays.asList(Array(a): _*)
+ |f(".")
+ |f(0)
+ |def i(a: Int) = java.util.Arrays.asList(Array(a): _*)
+ |i(0)
+ |def o(a: Any) = java.util.Arrays.asList(Array(a): _*)
+ |o(".")
+ |class V(val a: Int) extends AnyVal
+ |f(new V(0))
+ |o(new V(0))
+ |""".stripMargin.trim
+}
diff --git a/test/files/run/t4317/S_1.scala b/test/files/run/t4317/S_1.scala
index 2de408268c..2756c879eb 100644
--- a/test/files/run/t4317/S_1.scala
+++ b/test/files/run/t4317/S_1.scala
@@ -1,3 +1,5 @@
+import language.existentials
+
object S_1 {
def foo1(x: Class[_ <: AnyRef]) = 0
def foo2(x: Class[_ <: AnyRef], y: Int) = 99
diff --git a/test/pending/run/t4415.scala b/test/files/run/t4415.scala
index f96031d650..f96031d650 100644
--- a/test/pending/run/t4415.scala
+++ b/test/files/run/t4415.scala
diff --git a/test/files/run/t4536.check b/test/files/run/t4536.check
new file mode 100644
index 0000000000..0c5a72ada7
--- /dev/null
+++ b/test/files/run/t4536.check
@@ -0,0 +1,8 @@
+cls: bar
+obj: foo
+obj: bar
+cls: bar
+obj: bar
+trait: pili
+trait: mili
+trait: foo \ No newline at end of file
diff --git a/test/files/run/t4536.scala b/test/files/run/t4536.scala
new file mode 100644
index 0000000000..acd91deb7f
--- /dev/null
+++ b/test/files/run/t4536.scala
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+object dynamicObject extends Dynamic {
+ def applyDynamic(m: String)() = println("obj: " + m);
+ this.foo()
+}
+
+
+class dynamicClass extends Dynamic {
+ def applyDynamic(m: String)() = println("cls: " + m);
+ this.bar()
+ dynamicObject.bar()
+}
+
+
+abstract class dynamicAbstractClass extends Dynamic {
+ def applyDynamic(m: String)(args: Any*): Unit
+ this.pili(1, new dynamicClass, "hello");
+}
+
+
+trait dynamicTrait extends Dynamic {
+ def applyDynamic(m: String)(args: Any*) = println("trait: " + m);
+ def two = 2
+ this.mili(1,2,3)
+ two
+}
+
+
+object dynamicMixin extends dynamicAbstractClass with dynamicTrait {
+ this.foo(None)
+}
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ val cls = new dynamicClass
+ dynamicMixin
+ }
+
+}
diff --git a/test/files/run/t4658.check b/test/files/run/t4658.check
index 743b0faee3..bb6405175e 100644
--- a/test/files/run/t4658.check
+++ b/test/files/run/t4658.check
@@ -19,8 +19,8 @@ Ranges:
-30
-10
IntRanges:
-Disabled #1
-Disabled #2
+-1073741824
+-1073741824
0
0
55
@@ -39,8 +39,8 @@ Disabled #2
-30
-10
LongRanges:
-Disabled #1
-Disabled #2
+2305843008139952128
+-2305843008139952128
0
0
55
@@ -59,8 +59,8 @@ Disabled #2
-30
-10
BigIntRanges:
-Disabled #1
-Disabled #2
+2305843008139952128
+-2305843008139952128
0
0
55
diff --git a/test/files/run/t4658.scala b/test/files/run/t4658.scala
index e1799fae9b..8c07c50694 100644
--- a/test/files/run/t4658.scala
+++ b/test/files/run/t4658.scala
@@ -20,22 +20,14 @@ object Test {
def numericBigIntRanges = rangeData.map(r => if (r.inclusive) NumericRange.inclusive(BigInt(r.start), BigInt(r.end), BigInt(r.step)) else NumericRange(BigInt(r.start), BigInt(r.end), BigInt(r.step)))
def main(args: Array[String]) {
- // We drop the first two tests for all ranges which don't have a decent sum implementation,
- // because it is just too slow.
println("Ranges:")
ranges.foreach{range => println(range.sum)}
println("IntRanges:")
- println("Disabled #1")
- println("Disabled #2")
- numericIntRanges.drop(2).foreach{range => println(range.sum)}
+ numericIntRanges.foreach{range => println(range.sum)}
println("LongRanges:")
- println("Disabled #1")
- println("Disabled #2")
- numericLongRanges.drop(2).foreach{range => println(range.sum)}
+ numericLongRanges.foreach{range => println(range.sum)}
println("BigIntRanges:")
- println("Disabled #1")
- println("Disabled #2")
- numericBigIntRanges.drop(2).foreach{range => println(range.sum)}
+ numericBigIntRanges.foreach{range => println(range.sum)}
}
} \ No newline at end of file
diff --git a/test/files/run/t4710.check b/test/files/run/t4710.check
index aa2f08d452..7c2b10b098 100644
--- a/test/files/run/t4710.check
+++ b/test/files/run/t4710.check
@@ -2,6 +2,7 @@ Type in expressions to have them evaluated.
Type :help for more information.
scala> def method : String = { implicit def f(s: Symbol) = "" ; 'symbol }
+warning: there were 1 feature warnings; re-run with -feature for details
method: String
scala>
diff --git a/test/files/run/t4929.check b/test/files/run/t4929.check
new file mode 100644
index 0000000000..0f0c913d55
--- /dev/null
+++ b/test/files/run/t4929.check
@@ -0,0 +1 @@
+success \ No newline at end of file
diff --git a/test/files/run/t4929.scala b/test/files/run/t4929.scala
new file mode 100644
index 0000000000..3208cd1b09
--- /dev/null
+++ b/test/files/run/t4929.scala
@@ -0,0 +1,42 @@
+import scala.util.parsing.json._
+import java.util.concurrent._
+import collection.JavaConversions._
+
+object Test extends App {
+
+ val LIMIT = 2000
+ val THREAD_COUNT = 20
+ val count = new java.util.concurrent.atomic.AtomicInteger(0)
+
+ val begin = new CountDownLatch(THREAD_COUNT)
+ val finish = new CountDownLatch(THREAD_COUNT)
+
+ val errors = new ConcurrentLinkedQueue[Throwable]
+
+ (1 to THREAD_COUNT) foreach { i =>
+ val thread = new Thread {
+ override def run() {
+ begin.await(1, TimeUnit.SECONDS)
+ try {
+ while (count.getAndIncrement() < LIMIT && errors.isEmpty) {
+ JSON.parseFull("""{"foo": [1,2,3,4]}""")
+ }
+ } catch {
+ case t: Throwable => errors.add(t)
+ }
+
+ finish.await(10, TimeUnit.SECONDS)
+ }
+ }
+
+ thread.setDaemon(true)
+ thread.start()
+
+ }
+
+
+ errors foreach { throw(_) }
+
+ println("success")
+
+}
diff --git a/test/files/run/t5018.scala b/test/files/run/t5018.scala
new file mode 100644
index 0000000000..bb67a252e5
--- /dev/null
+++ b/test/files/run/t5018.scala
@@ -0,0 +1,37 @@
+
+
+
+import java.io._
+import collection._
+
+
+
+object Test {
+
+ def serializeDeserialize[T <: AnyRef](obj: T) = {
+ val buffer = new ByteArrayOutputStream
+ val out = new ObjectOutputStream(buffer)
+ out.writeObject(obj)
+ val in = new ObjectInputStream(new ByteArrayInputStream(buffer.toByteArray))
+ in.readObject.asInstanceOf[T]
+ }
+
+ def main(args: Array[String]) {
+ val values = mutable.Map(1 -> 1).values
+ assert(serializeDeserialize(values).toList == values.toList)
+
+ val keyset = mutable.Map(1 -> 1).keySet
+ assert(serializeDeserialize(keyset) == keyset)
+
+ val imkeyset = immutable.Map(1 -> 1).keySet
+ assert(serializeDeserialize(imkeyset) == imkeyset)
+
+ val defaultmap = immutable.Map(1 -> 1).withDefaultValue(1)
+ assert(serializeDeserialize(defaultmap) == defaultmap)
+
+ val minusmap = mutable.Map(1 -> 1).withDefault(x => -x)
+ assert(serializeDeserialize(minusmap) == minusmap)
+ }
+
+}
+
diff --git a/test/files/run/t5040.check b/test/files/run/t5040.check
new file mode 100644
index 0000000000..3f7b5908a9
--- /dev/null
+++ b/test/files/run/t5040.check
@@ -0,0 +1 @@
+applyDynamic
diff --git a/test/files/run/t5040.scala b/test/files/run/t5040.scala
new file mode 100644
index 0000000000..6cd2c22234
--- /dev/null
+++ b/test/files/run/t5040.scala
@@ -0,0 +1,11 @@
+abstract class Prova2 extends Dynamic {
+ def applyDynamic(m: String)(): Unit
+ private def privateMethod() = println("private method")
+}
+
+object Test extends App {
+ val prova= new Prova2 {
+ def applyDynamic(m: String)() = println("applyDynamic")
+ }
+ prova.privateMethod()
+}
diff --git a/test/files/run/t5224.check b/test/files/run/t5224.check
index 28bc75d4fd..c754f23551 100644
--- a/test/files/run/t5224.check
+++ b/test/files/run/t5224.check
@@ -1,9 +1,9 @@
-{
- @new Foo(bar = "qwe") class C extends scala.AnyRef {
- def <init>() = {
- super.<init>();
- ()
- }
- };
- ()
-}
+{
+ @new Foo(bar = "qwe") class C extends Object {
+ def <init>() = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+}
diff --git a/test/files/run/t5224.scala b/test/files/run/t5224.scala
index 2226a69a05..cf65f16457 100644
--- a/test/files/run/t5224.scala
+++ b/test/files/run/t5224.scala
@@ -1,9 +1,8 @@
-import scala.reflect._
-import scala.reflect.api._
+import scala.reflect.mirror._
-class Foo(bar: String) extends ClassfileAnnotation
+class Foo(bar: String) extends annotation.ClassfileAnnotation
object Test extends App {
- val tree = scala.reflect.Code.lift{@Foo(bar = "qwe") class C}.tree
+ val tree = reify{@Foo(bar = "qwe") class C}.tree
println(tree.toString)
} \ No newline at end of file
diff --git a/test/files/run/t5225_1.check b/test/files/run/t5225_1.check
index 719da572c7..40db2468b1 100644
--- a/test/files/run/t5225_1.check
+++ b/test/files/run/t5225_1.check
@@ -1,4 +1,4 @@
-{
- @new transient() @new volatile() var x: Int = 2;
- ()
-}
+{
+ @new transient() @new volatile() var x = 2;
+ ()
+}
diff --git a/test/files/run/t5225_1.scala b/test/files/run/t5225_1.scala
index a655b7dd71..5e1d3b1f17 100644
--- a/test/files/run/t5225_1.scala
+++ b/test/files/run/t5225_1.scala
@@ -1,7 +1,6 @@
-import scala.reflect._
-import scala.reflect.api._
+import scala.reflect.mirror._
object Test extends App {
- val tree = scala.reflect.Code.lift{@transient @volatile var x = 2}.tree
+ val tree = reify{@transient @volatile var x = 2}.tree
println(tree.toString)
} \ No newline at end of file
diff --git a/test/files/run/t5225_2.check b/test/files/run/t5225_2.check
index c4f6b4761e..8cd2ddc1a4 100644
--- a/test/files/run/t5225_2.check
+++ b/test/files/run/t5225_2.check
@@ -1,4 +1,4 @@
-{
- def foo(@new cloneable() x: Int): String = "";
- ()
-}
+{
+ def foo(@new cloneable() x: Int) = "";
+ ()
+}
diff --git a/test/files/run/t5225_2.scala b/test/files/run/t5225_2.scala
index 65ea9b2f73..4cab640fe8 100644
--- a/test/files/run/t5225_2.scala
+++ b/test/files/run/t5225_2.scala
@@ -1,7 +1,6 @@
-import scala.reflect._
-import scala.reflect.api._
+import scala.reflect.mirror._
object Test extends App {
- val tree = scala.reflect.Code.lift{def foo(@cloneable x: Int) = ""}.tree
+ val tree = reify{def foo(@cloneable x: Int) = ""}.tree
println(tree.toString)
} \ No newline at end of file
diff --git a/test/files/run/t5229_1.scala b/test/files/run/t5229_1.scala
index d5af569656..273079a89d 100644
--- a/test/files/run/t5229_1.scala
+++ b/test/files/run/t5229_1.scala
@@ -1,13 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
object C
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5229_2.scala b/test/files/run/t5229_2.scala
index 07f9ac6b84..85bf78ba31 100644
--- a/test/files/run/t5229_2.scala
+++ b/test/files/run/t5229_2.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
object C {
val x = 2
}
@@ -11,8 +9,7 @@ object Test extends App {
println(C.x)
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val evaluated = toolbox.runExpr(code.tree)
println("evaluated = " + evaluated)
}
diff --git a/test/files/run/t5230.scala b/test/files/run/t5230.scala
index d3106ca05c..e0632f591c 100644
--- a/test/files/run/t5230.scala
+++ b/test/files/run/t5230.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
class C {
val x = 2
}
@@ -11,8 +9,7 @@ object Test extends App {
println(new C().x)
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val evaluated = toolbox.runExpr(code.tree)
println("evaluated = " + evaluated)
}
diff --git a/test/files/run/t5258a.scala b/test/files/run/t5258a.scala
index 8cc4249e06..127829c724 100644
--- a/test/files/run/t5258a.scala
+++ b/test/files/run/t5258a.scala
@@ -1,13 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
println(classOf[Int])
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
} \ No newline at end of file
diff --git a/test/files/run/t5266_1.scala b/test/files/run/t5266_1.scala
index 4262bc7a7b..ebb432be71 100644
--- a/test/files/run/t5266_1.scala
+++ b/test/files/run/t5266_1.scala
@@ -1,15 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
def x = 2
println(x)
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val evaluated = toolbox.runExpr(code.tree)
println("evaluated = " + evaluated)
} \ No newline at end of file
diff --git a/test/files/run/t5266_2.scala b/test/files/run/t5266_2.scala
index d0f718dbd7..27c91c35a8 100644
--- a/test/files/run/t5266_2.scala
+++ b/test/files/run/t5266_2.scala
@@ -1,16 +1,13 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
def x = 2
def y = x
println(y)
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val evaluated = toolbox.runExpr(code.tree)
println("evaluated = " + evaluated)
}
diff --git a/test/files/run/t5269.scala b/test/files/run/t5269.scala
index cab99f17e6..9026090b29 100644
--- a/test/files/run/t5269.scala
+++ b/test/files/run/t5269.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
trait Z {
val z = 2
}
@@ -13,9 +11,5 @@ object Test extends App {
}
new X().println()
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5270.scala b/test/files/run/t5270.scala
index 934cc13dea..476b610148 100644
--- a/test/files/run/t5270.scala
+++ b/test/files/run/t5270.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class Y {
def y = 100
}
@@ -17,9 +15,5 @@ object Test extends App {
}
new X().println()
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5271_1.check b/test/files/run/t5271_1.check
index 9b956da17a..5245173228 100644
--- a/test/files/run/t5271_1.check
+++ b/test/files/run/t5271_1.check
@@ -1,11 +1,12 @@
-{
- case class C extends Object with Product with Serializable {
- <caseaccessor> <paramaccessor> val foo : Int = _;
- <caseaccessor> <paramaccessor> val bar : Int = _;
- def <init>(foo: Int, bar: Int) = {
- super.<init>();
- ()
- }
- };
- ()
-}
+{
+ case class C extends Product with Serializable {
+ <caseaccessor> <paramaccessor> val foo: Int = _;
+ <caseaccessor> <paramaccessor> val bar: Int = _;
+ def <init>(foo: Int, bar: Int) = {
+ super.<init>();
+ ()
+ }
+ };
+ ()
+}
+()
diff --git a/test/files/run/t5271_1.scala b/test/files/run/t5271_1.scala
index fbc57aead7..20cafa6a08 100644
--- a/test/files/run/t5271_1.scala
+++ b/test/files/run/t5271_1.scala
@@ -1,13 +1,11 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
case class C(foo: Int, bar: Int)
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
println(code.tree)
+ println(code.eval)
}
diff --git a/test/files/run/t5271_2.check b/test/files/run/t5271_2.check
index 27297febb6..0765b3a6a4 100644
--- a/test/files/run/t5271_2.check
+++ b/test/files/run/t5271_2.check
@@ -1,12 +1,14 @@
-{
- case class C extends Object with Product with Serializable {
- <caseaccessor> <paramaccessor> val foo : Int = _;
- <caseaccessor> <paramaccessor> val bar : Int = _;
- def <init>(foo: Int, bar: Int) = {
- super.<init>();
- ()
- }
- };
- val c = C.apply(2, 2);
- scala.this.Predef.println(c.foo.$times(c.bar))
-}
+{
+ case class C extends Product with Serializable {
+ <caseaccessor> <paramaccessor> val foo: Int = _;
+ <caseaccessor> <paramaccessor> val bar: Int = _;
+ def <init>(foo: Int, bar: Int) = {
+ super.<init>();
+ ()
+ }
+ };
+ val c = C.apply(2, 2);
+ scala.this.Predef.println(c.foo.$times(c.bar))
+}
+4
+()
diff --git a/test/files/run/t5271_2.scala b/test/files/run/t5271_2.scala
index 4bfc574e00..af6491407c 100644
--- a/test/files/run/t5271_2.scala
+++ b/test/files/run/t5271_2.scala
@@ -1,15 +1,13 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
case class C(foo: Int, bar: Int)
val c = C(2, 2)
println(c.foo * c.bar)
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
println(code.tree)
+ println(code.eval)
}
diff --git a/test/files/run/t5271_3.check b/test/files/run/t5271_3.check
index 9331c78959..2b920a36a8 100644
--- a/test/files/run/t5271_3.check
+++ b/test/files/run/t5271_3.check
@@ -1,19 +1,21 @@
-{
- object C extends scala.AnyRef with Serializable {
- def <init>() = {
- super.<init>();
- ()
- };
- def qwe: Int = 4
- };
- case class C extends Object with Product with Serializable {
- <caseaccessor> <paramaccessor> val foo : Int = _;
- <caseaccessor> <paramaccessor> val bar : Int = _;
- def <init>(foo: Int, bar: Int) = {
- super.<init>();
- ()
- }
- };
- val c = C.apply(2, 2);
- scala.this.Predef.println(c.foo.$times(c.bar).$eq$eq(C.qwe))
-}
+{
+ object C extends Object {
+ def <init>() = {
+ super.<init>();
+ ()
+ };
+ def qwe = 4
+ };
+ case class C extends Product with Serializable {
+ <caseaccessor> <paramaccessor> val foo: Int = _;
+ <caseaccessor> <paramaccessor> val bar: Int = _;
+ def <init>(foo: Int, bar: Int) = {
+ super.<init>();
+ ()
+ }
+ };
+ val c = C.apply(2, 2);
+ scala.this.Predef.println(c.foo.$times(c.bar).$eq$eq(C.qwe))
+}
+true
+()
diff --git a/test/files/run/t5271_3.scala b/test/files/run/t5271_3.scala
index a085bdca4c..646b10a8e5 100644
--- a/test/files/run/t5271_3.scala
+++ b/test/files/run/t5271_3.scala
@@ -1,16 +1,14 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
object C { def qwe = 4 }
case class C(foo: Int, bar: Int)
val c = C(2, 2)
println(c.foo * c.bar == C.qwe)
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
println(code.tree)
+ println(code.eval)
}
diff --git a/test/files/run/t5271_4.scala b/test/files/run/t5271_4.scala
index c253b1adca..e13a331d9c 100644
--- a/test/files/run/t5271_4.scala
+++ b/test/files/run/t5271_4.scala
@@ -1,13 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
case object C
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5272_1.flags b/test/files/run/t5272_1.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t5272_1.flags
diff --git a/test/files/run/t5272_1.scala b/test/files/run/t5272_1.scala
index 882287f033..46472babf3 100644
--- a/test/files/run/t5272_1.scala
+++ b/test/files/run/t5272_1.scala
@@ -1,16 +1,10 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
2 match {
case 2 => println("okay")
case _ => println("not okay")
}
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5272_2.flags b/test/files/run/t5272_2.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t5272_2.flags
diff --git a/test/files/run/t5272_2.scala b/test/files/run/t5272_2.scala
index 48b6a670bb..f5bab44205 100644
--- a/test/files/run/t5272_2.scala
+++ b/test/files/run/t5272_2.scala
@@ -1,15 +1,9 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
2 match {
case x => println("okay" + x)
}
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5273_1.flags b/test/files/run/t5273_1.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t5273_1.flags
diff --git a/test/files/run/t5273_1.scala b/test/files/run/t5273_1.scala
index 80460a4ae6..1b491923b2 100644
--- a/test/files/run/t5273_1.scala
+++ b/test/files/run/t5273_1.scala
@@ -1,16 +1,10 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
List(1, 2, 3) match {
case foo :: bar :: _ => println(foo * bar)
case _ => println("this is getting out of hand!")
}
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5273_2a.flags b/test/files/run/t5273_2a.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t5273_2a.flags
diff --git a/test/files/run/t5273_2a.scala b/test/files/run/t5273_2a.scala
index a7a336d8a7..062ff79d11 100644
--- a/test/files/run/t5273_2a.scala
+++ b/test/files/run/t5273_2a.scala
@@ -1,14 +1,8 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
val foo :: bar :: _ = List(1, 2, 3)
println(foo * bar)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5273_2b.flags b/test/files/run/t5273_2b.flags
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t5273_2b.flags
diff --git a/test/files/run/t5273_2b.scala b/test/files/run/t5273_2b.scala
index 85c40f0607..82f1de89f7 100644
--- a/test/files/run/t5273_2b.scala
+++ b/test/files/run/t5273_2b.scala
@@ -1,15 +1,9 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
val RegexParser = """(.*) \d+([A-Z]+) \| (.*) \|.*""".r
val RegexParser(name, shortname, value) = "American Dollar 1USD | 2,8567 | sometext"
println("name = %s, shortname = %s, value = %s".format(name, shortname, value))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5274_1.scala b/test/files/run/t5274_1.scala
index 74a5b81bcb..7ef332aa05 100644
--- a/test/files/run/t5274_1.scala
+++ b/test/files/run/t5274_1.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
def factorial(n: BigInt): BigInt =
if (n == 0) 1 else n * factorial(n-1)
@@ -11,9 +9,5 @@ object Test extends App {
println("50! = " + f50)
println("49! = " + f49)
println("50!/49! = " + (f50 / f49))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5274_2.scala b/test/files/run/t5274_2.scala
index 5984a64967..0b373b358f 100644
--- a/test/files/run/t5274_2.scala
+++ b/test/files/run/t5274_2.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
/** Nested methods can use and even update everything
* visible in their scope (including local variables or
* arguments of enclosing methods).
@@ -48,9 +46,5 @@ object Test extends App {
println(ar)
sort(ar)
println(ar)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5275.scala b/test/files/run/t5275.scala
index 285d8a18a4..534672be3c 100644
--- a/test/files/run/t5275.scala
+++ b/test/files/run/t5275.scala
@@ -1,14 +1,8 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C(val foo: Int)
println(new C(2).foo)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5276_1a.scala b/test/files/run/t5276_1a.scala
index b717675824..a6e327c0e7 100644
--- a/test/files/run/t5276_1a.scala
+++ b/test/files/run/t5276_1a.scala
@@ -1,14 +1,8 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
lazy val x = 2
println(x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5276_1b.scala b/test/files/run/t5276_1b.scala
index 1ff25504ca..1bc3e246c9 100644
--- a/test/files/run/t5276_1b.scala
+++ b/test/files/run/t5276_1b.scala
@@ -1,14 +1,8 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
implicit lazy val x = 2
println(implicitly[Int])
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5276_2a.scala b/test/files/run/t5276_2a.scala
index af5ff2a565..cdd87ddc9e 100644
--- a/test/files/run/t5276_2a.scala
+++ b/test/files/run/t5276_2a.scala
@@ -1,17 +1,11 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C {
lazy val x = 2
}
println(new C().x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5276_2b.scala b/test/files/run/t5276_2b.scala
index 63904b2898..2fac951731 100644
--- a/test/files/run/t5276_2b.scala
+++ b/test/files/run/t5276_2b.scala
@@ -1,18 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C {
implicit lazy val x = 2
def y = implicitly[Int]
}
println(new C().y)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5277_1.scala b/test/files/run/t5277_1.scala
index 0aaec7cdf2..f95e9ab6ec 100644
--- a/test/files/run/t5277_1.scala
+++ b/test/files/run/t5277_1.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
def fact(n: Int): BigInt =
if (n == 0) 1 else fact(n-1) * n
class Factorizer(n: Int) {
@@ -12,9 +10,5 @@ object Test extends App {
implicit def int2fact(n: Int) = new Factorizer(n)
println("10! = " + (10!))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5277_2.scala b/test/files/run/t5277_2.scala
index 91ed55122a..5f1737f503 100644
--- a/test/files/run/t5277_2.scala
+++ b/test/files/run/t5277_2.scala
@@ -1,17 +1,11 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
def p(implicit i: Int) = print(i)
implicit val v = 2
println(p)
println(p(1))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5279.scala b/test/files/run/t5279.scala
index cef58535d5..aab5588877 100644
--- a/test/files/run/t5279.scala
+++ b/test/files/run/t5279.scala
@@ -1,13 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
println(new Integer(10))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5334_1.scala b/test/files/run/t5334_1.scala
index 9887bebf78..49dbea6b68 100644
--- a/test/files/run/t5334_1.scala
+++ b/test/files/run/t5334_1.scala
@@ -1,14 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
class C { override def toString = "C" }
- new C
+ val ret = new C
+ ret.asInstanceOf[Object]
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
println(toolbox.runExpr(code.tree))
}
diff --git a/test/files/run/t5334_2.scala b/test/files/run/t5334_2.scala
index 775a05aaf7..c6a77158dd 100644
--- a/test/files/run/t5334_2.scala
+++ b/test/files/run/t5334_2.scala
@@ -1,14 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ val code = reify {
class C { override def toString() = "C" }
- List((new C, new C))
+ val ret = List((new C, new C))
+ ret.asInstanceOf[List[Any]]
};
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
println(toolbox.runExpr(code.tree))
}
diff --git a/test/files/run/t5335.scala b/test/files/run/t5335.scala
index 8e2ed59db6..a0fe6c5822 100644
--- a/test/files/run/t5335.scala
+++ b/test/files/run/t5335.scala
@@ -1,13 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
println(new {def x = 2}.x)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/files/run/t5415.scala b/test/files/run/t5415.scala
index 3db356da86..c6552f69b3 100644
--- a/test/files/run/t5415.scala
+++ b/test/files/run/t5415.scala
@@ -1,14 +1,10 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import scala.reflect.runtime.Mirror.ToolBox
-
object Test extends App{
case class Queryable2[T]() { def filter(predicate: T => Boolean) = ??? }
trait CoffeesTable{ def sales : Int }
val q = Queryable2[CoffeesTable]()
- val code = scala.reflect.Code.lift{q.filter(_.sales > 5)}
+ import scala.reflect.mirror._
+ val code = reify{q.filter(_.sales > 5)}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val ttree = toolbox.typeCheck(code.tree)
}
diff --git a/test/files/run/t5419.check b/test/files/run/t5419.check
index 7e6d739354..50751b168e 100644
--- a/test/files/run/t5419.check
+++ b/test/files/run/t5419.check
@@ -1 +1 @@
-(5: Int(5) @Foo)
+5: @Foo.asInstanceOf[Int]
diff --git a/test/files/run/t5419.scala b/test/files/run/t5419.scala
index 695786e5c4..5f11f5056c 100644
--- a/test/files/run/t5419.scala
+++ b/test/files/run/t5419.scala
@@ -1,9 +1,8 @@
-import scala.reflect._
-import scala.reflect.api._
+import scala.reflect.mirror._
-class Foo extends StaticAnnotation
+class Foo extends annotation.StaticAnnotation
object Test extends App {
- val tree = scala.reflect.Code.lift{5: @Foo}.tree
+ val tree = reify{(5: @Foo).asInstanceOf[Int]}.tree
println(tree.toString)
} \ No newline at end of file
diff --git a/test/files/run/t5423.scala b/test/files/run/t5423.scala
index fc507c417b..ed1faf0429 100644
--- a/test/files/run/t5423.scala
+++ b/test/files/run/t5423.scala
@@ -1,9 +1,6 @@
-import java.lang.Class
import scala.reflect.mirror._
-import scala.reflect.runtime.Mirror.ToolBox
-import scala.reflect.Code
-final class table extends StaticAnnotation
+final class table extends annotation.StaticAnnotation
@table class A
object Test extends App {
diff --git a/test/files/run/t5514.check b/test/files/run/t5514.check
new file mode 100644
index 0000000000..c68f7c9029
--- /dev/null
+++ b/test/files/run/t5514.check
@@ -0,0 +1,19 @@
+constructed reader: 10
+constructed reader: 9
+constructed reader: 8
+constructed reader: 7
+constructed reader: 6
+constructed reader: 5
+constructed reader: 4
+constructed reader: 3
+constructed reader: 2
+constructed reader: 1
+constructed reader: 0
+[0.0] parsed: List(s10, s9, s8, s7, s6, s5, s4, s3, s2, s1)
+constructed reader: 10
+constructed reader: 9
+constructed reader: 8
+constructed reader: 7
+constructed reader: 6
+constructed reader: 5
+[0.0] parsed: List(s10, s9, s8, s7, s6) \ No newline at end of file
diff --git a/test/files/run/t5514.scala b/test/files/run/t5514.scala
new file mode 100644
index 0000000000..efd5ba6cb9
--- /dev/null
+++ b/test/files/run/t5514.scala
@@ -0,0 +1,35 @@
+
+
+
+import scala.io.Source
+import scala.util.parsing.combinator.Parsers
+import scala.util.parsing.input.Reader
+import scala.util.parsing.input.Position
+
+
+
+class DemoReader(n: Int) extends Reader[String] {
+ def atEnd = n == 0
+ def first = if (n >= 0) "s" + n else throw new IllegalArgumentException("No more input.")
+ def rest = new DemoReader(n - 1)
+ def pos = new Position {
+ def line = 0
+ def column = 0
+ def lineContents = first
+ }
+ println("constructed reader: " + n)
+}
+
+
+object Test extends App with Parsers {
+ type Elem = String
+ def startsWith(prefix: String) = acceptIf(_ startsWith prefix)("Error: " + _)
+
+ val resrep = startsWith("s").*(new DemoReader(10))
+ Console println resrep
+
+ val resrep5 = repN(5, startsWith("s"))(new DemoReader(10))
+ Console println resrep5
+}
+
+
diff --git a/test/files/run/t5535.check b/test/files/run/t5535.check
new file mode 100644
index 0000000000..8da9829b78
--- /dev/null
+++ b/test/files/run/t5535.check
@@ -0,0 +1,20 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> def h()(i: Int) = 1 + i
+h: ()(i: Int)Int
+
+scala> println(h()(5))
+6
+
+scala> val f = h() _
+f: Int => Int = <function1>
+
+scala> println(f(10))
+11
+
+scala>
+
+scala>
diff --git a/test/files/run/t5535.scala b/test/files/run/t5535.scala
new file mode 100644
index 0000000000..7bc12f3470
--- /dev/null
+++ b/test/files/run/t5535.scala
@@ -0,0 +1,10 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+def h()(i: Int) = 1 + i
+println(h()(5))
+val f = h() _
+println(f(10))
+ """
+}
diff --git a/test/files/run/t5543.check b/test/files/run/t5543.check
new file mode 100644
index 0000000000..517038f4c7
--- /dev/null
+++ b/test/files/run/t5543.check
@@ -0,0 +1,3 @@
+Test, 7, 119
+m, 3, 19
+Test, 5, 85
diff --git a/test/files/run/t5543.scala b/test/files/run/t5543.scala
new file mode 100644
index 0000000000..651bc7f2b2
--- /dev/null
+++ b/test/files/run/t5543.scala
@@ -0,0 +1,26 @@
+
+object Test extends Function0[Int] {
+ // this and v resolve to Test.this, Test.v not A.this, A.v
+ class A(x: Function0[Int] = this)(val a: Int = v, val b: Int = v * x()) extends Function0[Int] {
+ val v = 3
+ override def toString = x.toString +", "+ a +", "+ b
+ // ordinary instance scope
+ def m(i: Int = v, y: Function0[Int] = this) = "m, "+ i +", "+ y()
+ def apply() = 19
+ }
+ object A {
+ val v = 5
+ // should happily coexist with default getters, in a happier world
+ def init(x: Function0[Int] = Test.this)(a: Int = v, b: Int = v * x()) = x.toString +", "+ a +", "+ b
+ override def toString = "A"
+ }
+ val v = 7
+ def apply() = 17
+ override def toString = "Test"
+ def main(args: Array[String]) {
+ val sut = new A()()
+ println(sut.toString)
+ println(sut.m())
+ println(A.init()())
+ }
+}
diff --git a/test/files/run/t5577.check b/test/files/run/t5577.check
new file mode 100644
index 0000000000..3eca387955
--- /dev/null
+++ b/test/files/run/t5577.check
@@ -0,0 +1,11 @@
+Received a size hint: 10
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9 \ No newline at end of file
diff --git a/test/files/run/t5577.scala b/test/files/run/t5577.scala
new file mode 100644
index 0000000000..b5d6d8c5b6
--- /dev/null
+++ b/test/files/run/t5577.scala
@@ -0,0 +1,27 @@
+
+
+
+import collection._
+
+
+
+object Test {
+
+ class AlarmingBuffer[T] extends mutable.ArrayBuffer[T] {
+ override def sizeHint(x: Int) {
+ println("Received a size hint: " + x)
+ super.sizeHint(x)
+ }
+ }
+
+ def main(args: Array[String]) {
+ val iteratorBuilder = (new AlarmingBuffer[Int]) mapResult {
+ res => res.iterator
+ }
+
+ iteratorBuilder.sizeHint(10)
+ iteratorBuilder ++= (0 until 10)
+ iteratorBuilder.result.foreach(println)
+ }
+
+}
diff --git a/test/files/run/t5583.check b/test/files/run/t5583.check
new file mode 100644
index 0000000000..39b969fbe7
--- /dev/null
+++ b/test/files/run/t5583.check
@@ -0,0 +1,20 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> var s = 0
+s: Int = 0
+
+scala> for (i <- 1 to 10) {s += i}
+
+scala> for (i <- 1 to 10) {s += i}
+
+scala> for (i <- 1 to 10) {s += i}
+
+scala> println(s)
+165
+
+scala>
+
+scala>
diff --git a/test/files/run/t5583.scala b/test/files/run/t5583.scala
new file mode 100644
index 0000000000..8561a5946f
--- /dev/null
+++ b/test/files/run/t5583.scala
@@ -0,0 +1,11 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+var s = 0
+for (i <- 1 to 10) {s += i}
+for (i <- 1 to 10) {s += i}
+for (i <- 1 to 10) {s += i}
+println(s)
+ """
+}
diff --git a/test/files/run/t5590.check b/test/files/run/t5590.check
new file mode 100644
index 0000000000..ad4a2eee64
--- /dev/null
+++ b/test/files/run/t5590.check
@@ -0,0 +1,4 @@
+Map(a -> a, b -> b, c -> c)
+Map(a -> a, b -> b, c -> c)
+Set(a, b, c, d, e)
+Set(a, b, c, d, e) \ No newline at end of file
diff --git a/test/files/run/t5590.scala b/test/files/run/t5590.scala
new file mode 100644
index 0000000000..9c806e0b7d
--- /dev/null
+++ b/test/files/run/t5590.scala
@@ -0,0 +1,31 @@
+
+
+
+import java.io._
+import collection._
+
+
+
+object Test {
+
+ def check(obj: AnyRef) {
+ println(obj)
+
+ val bos = new ByteArrayOutputStream()
+ val out = new ObjectOutputStream(bos)
+ out.writeObject(obj)
+ val arr = bos.toByteArray()
+ val in = new ObjectInputStream(new ByteArrayInputStream(arr))
+ val deser = in.readObject()
+
+ println(deser)
+ }
+
+ def main(args: Array[String]) {
+ val lhm = mutable.LinkedHashMap("a" -> "a", "b" -> "b", "c" -> "c")
+ val lhs = mutable.LinkedHashSet("a", "b", "c", "d", "e")
+ check(lhm)
+ check(lhs)
+ }
+
+}
diff --git a/test/files/run/t5608.check b/test/files/run/t5608.check
new file mode 100644
index 0000000000..ba70d21701
--- /dev/null
+++ b/test/files/run/t5608.check
@@ -0,0 +1 @@
+A@6
diff --git a/test/files/run/t5608.scala b/test/files/run/t5608.scala
new file mode 100644
index 0000000000..19b3681932
--- /dev/null
+++ b/test/files/run/t5608.scala
@@ -0,0 +1,12 @@
+object Test {
+ def main(args:Array[String]) {
+ val ns = Array(3L, 3L, 3L)
+ val a1: A = new A(ns(0))
+ val a2: A = new A(ns(0))
+ println(a1 + a2)
+ }
+}
+
+class A(val u: Long) extends AnyVal {
+ def +(other: A) = new A(other.u + u)
+}
diff --git a/test/files/run/t5612.check b/test/files/run/t5612.check
new file mode 100644
index 0000000000..9d19cca292
--- /dev/null
+++ b/test/files/run/t5612.check
@@ -0,0 +1,4 @@
+START for List(Two, Two, One, Three)
+TWO
+TWO
+ONE
diff --git a/test/files/run/t5612.scala b/test/files/run/t5612.scala
new file mode 100644
index 0000000000..48b3093548
--- /dev/null
+++ b/test/files/run/t5612.scala
@@ -0,0 +1,28 @@
+object L extends Enumeration {
+ val One, Two, Three = Value
+}
+
+class Foo {
+ def foo(xs: List[L.Value]) {
+ import scala.util.control.Breaks.{break, breakable}
+ println("START for " + xs)
+ breakable {
+ for (x <- xs) {
+ x match {
+ case L.One => println("ONE"); return
+ case L.Two => println("TWO")
+ case L.Three => println("THREE"); break
+ }
+ }
+ }
+ println("FINISH")
+ }
+}
+
+object Test {
+ def main(args: Array[String]) {
+ val f = new Foo()
+ val l = List(L.Two, L.Two, L.One, L.Three)
+ f.foo(l)
+ }
+}
diff --git a/test/files/run/t5614.check b/test/files/run/t5614.check
new file mode 100644
index 0000000000..f659f2da3b
--- /dev/null
+++ b/test/files/run/t5614.check
@@ -0,0 +1,3 @@
+3
+a
+b
diff --git a/test/files/run/t5614.flags b/test/files/run/t5614.flags
new file mode 100644
index 0000000000..48fd867160
--- /dev/null
+++ b/test/files/run/t5614.flags
@@ -0,0 +1 @@
+-Xexperimental
diff --git a/test/files/run/t5614.scala b/test/files/run/t5614.scala
new file mode 100644
index 0000000000..7c85c33f12
--- /dev/null
+++ b/test/files/run/t5614.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ val str = s"a\nb"
+ println(str.length)
+ println(str)
+}
diff --git a/test/files/run/t5629.check b/test/files/run/t5629.check
new file mode 100644
index 0000000000..6a2d630f4e
--- /dev/null
+++ b/test/files/run/t5629.check
@@ -0,0 +1,2 @@
+int child got: 33
+any child got: 33
diff --git a/test/files/run/t5629.scala b/test/files/run/t5629.scala
new file mode 100644
index 0000000000..69feddd3a5
--- /dev/null
+++ b/test/files/run/t5629.scala
@@ -0,0 +1,36 @@
+
+
+
+import scala.{specialized => spec}
+
+
+
+trait GrandParent[@spec(Int) -A] {
+ def foo(a: A): Unit
+ def bar[B <: A](b: B): Unit = println("grandparent got: %s" format b)
+}
+
+
+trait Parent[@spec(Int) -A] extends GrandParent[A] {
+ def foo(a: A) = bar(a)
+}
+
+
+class IntChild extends Parent[Int] {
+ override def bar[B <: Int](b: B): Unit = println("int child got: %s" format b)
+}
+
+
+class AnyChild extends Parent[Any] {
+ override def bar[B <: Any](b: B): Unit = println("any child got: %s" format b)
+}
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ new IntChild().foo(33)
+ new AnyChild().foo(33)
+ }
+
+}
diff --git a/test/files/run/t5629b.check b/test/files/run/t5629b.check
new file mode 100644
index 0000000000..1bc0248c3d
--- /dev/null
+++ b/test/files/run/t5629b.check
@@ -0,0 +1,10 @@
+=== pf(1):
+MySmartPF.apply entered...
+newPF.applyOrElse entered...
+default
+scala.MatchError: () (of class scala.runtime.BoxedUnit)
+=== pf(42):
+MySmartPF.apply entered...
+newPF.applyOrElse entered...
+ok
+=== done
diff --git a/test/files/run/t5629b.scala b/test/files/run/t5629b.scala
new file mode 100644
index 0000000000..6c908081b9
--- /dev/null
+++ b/test/files/run/t5629b.scala
@@ -0,0 +1,41 @@
+
+
+
+
+
+object Test extends App {
+
+ trait MyPF[@specialized(Int) -A] extends (A => Unit) {
+ def isDefinedAt(x: A): Boolean
+ def applyOrElse[A1 <: A](x: A1, default: A1 => Unit): Unit = {
+ println("MyPF.applyOrElse entered...")
+ if (isDefinedAt(x)) apply(x) else default(x)
+ }
+ }
+
+ trait MySmartPF[@specialized(Int) -A] extends MyPF[A] {
+ def apply(x: A): Unit = {
+ println("MySmartPF.apply entered...")
+ applyOrElse(x, { _: Any => throw new MatchError })
+ }
+ }
+
+ type T = Int
+ //type T = Any
+
+ def newPF(test: T): MyPF[T] = new MySmartPF[T] {
+ def isDefinedAt(x: T): Boolean = x != test
+ override def applyOrElse[A1 <: T](x: A1, default: A1 => Unit): Unit = {
+ println("newPF.applyOrElse entered...")
+ if (x != test) { println("ok"); () } else { println("default"); default(x) }
+ }
+ }
+
+ val pf = newPF(1)
+ println("=== pf(1):")
+ try { pf(1) } catch { case x => println(x) }
+ println("=== pf(42):")
+ pf(42)
+ println("=== done")
+
+}
diff --git a/test/files/run/t5648.check b/test/files/run/t5648.check
new file mode 100644
index 0000000000..1140ff52e2
--- /dev/null
+++ b/test/files/run/t5648.check
@@ -0,0 +1,4 @@
+true
+true
+true
+true
diff --git a/test/files/run/t5648.flags b/test/files/run/t5648.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/files/run/t5648.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/files/run/t5648.scala b/test/files/run/t5648.scala
new file mode 100644
index 0000000000..c5cea9e1cb
--- /dev/null
+++ b/test/files/run/t5648.scala
@@ -0,0 +1,10 @@
+case class C(val s: Int*)
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ println(new C(1, 3, 7) == new C(1, 3, 7))
+ println(new C(1, 3, 7) == C(1, 3, 7))
+ println(C(1, 3, 7) == new C(1, 3, 7))
+ println(C(1, 3, 7) == C(1, 3, 7))
+ }
+}
diff --git a/test/files/run/t5655.check b/test/files/run/t5655.check
new file mode 100644
index 0000000000..43ebd50e7a
--- /dev/null
+++ b/test/files/run/t5655.check
@@ -0,0 +1,30 @@
+Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> object x { def x={} }
+defined module x
+
+scala> import x._
+import x._
+
+scala> x
+<console>:12: error: reference to x is ambiguous;
+it is imported twice in the same scope by
+import x._
+and import x
+ x
+ ^
+
+scala> x
+<console>:12: error: reference to x is ambiguous;
+it is imported twice in the same scope by
+import x._
+and import x
+ x
+ ^
+
+scala>
+
+scala>
diff --git a/test/files/run/t5655.scala b/test/files/run/t5655.scala
new file mode 100644
index 0000000000..b15feb788e
--- /dev/null
+++ b/test/files/run/t5655.scala
@@ -0,0 +1,10 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ def code = """
+object x { def x={} }
+import x._
+x
+x
+ """
+}
diff --git a/test/files/run/t5656.check b/test/files/run/t5656.check
new file mode 100644
index 0000000000..9543ee799e
--- /dev/null
+++ b/test/files/run/t5656.check
@@ -0,0 +1 @@
+List(1, 2, 3)_List(a, b, c) \ No newline at end of file
diff --git a/test/files/run/t5656.scala b/test/files/run/t5656.scala
new file mode 100644
index 0000000000..f5ea147a4e
--- /dev/null
+++ b/test/files/run/t5656.scala
@@ -0,0 +1,11 @@
+
+
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ println(Seq(List('1', '2', '3'), List('a', 'b', 'c')).view.addString(new StringBuilder, "_"))
+ }
+
+}
diff --git a/test/files/run/t5680.check b/test/files/run/t5680.check
new file mode 100644
index 0000000000..9fec3b6505
--- /dev/null
+++ b/test/files/run/t5680.check
@@ -0,0 +1,3 @@
+[Lscala.runtime.BoxedUnit
+()
+()
diff --git a/test/files/run/t5680.scala b/test/files/run/t5680.scala
new file mode 100644
index 0000000000..f61cbd6e20
--- /dev/null
+++ b/test/files/run/t5680.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ val x = Array[Unit]((), ())
+ println(x.toString.substring(0, x.toString.indexOf(";")))
+ println(x(0))
+ x(1) = ()
+ println(x(1))
+} \ No newline at end of file
diff --git a/test/files/run/t5688.check b/test/files/run/t5688.check
new file mode 100644
index 0000000000..2c84f9e2ef
--- /dev/null
+++ b/test/files/run/t5688.check
@@ -0,0 +1 @@
+Vector(ta, tb, tab)
diff --git a/test/files/run/t5688.scala b/test/files/run/t5688.scala
new file mode 100644
index 0000000000..f99bfb47d3
--- /dev/null
+++ b/test/files/run/t5688.scala
@@ -0,0 +1,23 @@
+object Test extends App {
+ trait T
+
+ trait TA
+ trait TB
+
+ class A extends T with TA
+ class B extends T with TB
+ class AB extends T with TA with TB
+ // Matching on _: TA with TB
+
+ val li: Vector[T] = Vector(new A, new B, new AB)
+
+ val matched = (for (l <- li) yield {
+ l match {
+ case _: TA with TB => "tab"
+ case _: TA => "ta"
+ case _: TB => "tb"
+ }
+ })
+
+ println(matched)
+} \ No newline at end of file
diff --git a/test/files/run/t5704.check b/test/files/run/t5704.check
new file mode 100644
index 0000000000..7b56bf2bfd
--- /dev/null
+++ b/test/files/run/t5704.check
@@ -0,0 +1 @@
+String \ No newline at end of file
diff --git a/test/files/run/t5704.flags b/test/files/run/t5704.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/t5704.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/t5704.scala b/test/files/run/t5704.scala
new file mode 100644
index 0000000000..8fd721d4e7
--- /dev/null
+++ b/test/files/run/t5704.scala
@@ -0,0 +1,16 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class MyQuerycollection{
+ def findUserByName( name:String ) = {
+ val tree = reify{ "test" == name }.tree
+ val toolbox = mkToolBox()
+ toolbox.typeCheck(tree) match{
+ case Apply(Select(lhs,op),rhs::Nil) =>
+ println(rhs.tpe)
+ }
+ }
+ }
+ val qc = new MyQuerycollection
+ qc.findUserByName("some value")
+}
diff --git a/test/files/run/t5713.check b/test/files/run/t5713.check
new file mode 100644
index 0000000000..d3e9348123
--- /dev/null
+++ b/test/files/run/t5713.check
@@ -0,0 +1 @@
+err
diff --git a/test/files/run/t5713.flags b/test/files/run/t5713.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/files/run/t5713.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/files/run/t5713/Impls_Macros_1.scala b/test/files/run/t5713/Impls_Macros_1.scala
new file mode 100644
index 0000000000..b499bc7e4e
--- /dev/null
+++ b/test/files/run/t5713/Impls_Macros_1.scala
@@ -0,0 +1,27 @@
+package m
+
+import language.experimental.macros
+import scala.reflect.makro.Context
+
+object Level extends Enumeration {
+ val Error = Value(5)
+}
+
+object Logger {
+ def error(message: String): Unit = macro LoggerMacros.error
+}
+
+private object LoggerMacros {
+
+ type LoggerContext = Context { type PrefixType = Logger.type }
+
+ def error(c: LoggerContext)(message: c.Expr[String]): c.Expr[Unit] =
+ log(c)(c.reify(Level.Error), message)
+
+ private def log(c: LoggerContext)(level: c.Expr[Level.Value], message: c.Expr[String]): c.Expr[Unit] =
+ if (level.eval.id < 4) // TODO Remove hack!
+ c.reify(())
+ else {
+ c.reify(println(message.eval))
+ }
+} \ No newline at end of file
diff --git a/test/files/run/t5713/Test_2.scala b/test/files/run/t5713/Test_2.scala
new file mode 100644
index 0000000000..24f9e79b11
--- /dev/null
+++ b/test/files/run/t5713/Test_2.scala
@@ -0,0 +1,5 @@
+import m._
+
+object Test extends App {
+ Logger.error("err")
+} \ No newline at end of file
diff --git a/test/files/run/toolbox_console_reporter.check b/test/files/run/toolbox_console_reporter.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/toolbox_console_reporter.check
diff --git a/test/files/run/toolbox_console_reporter.scala b/test/files/run/toolbox_console_reporter.scala
new file mode 100644
index 0000000000..1da9a6bc16
--- /dev/null
+++ b/test/files/run/toolbox_console_reporter.scala
@@ -0,0 +1,16 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ // todo. cannot test this unfortunately, because ConsoleFrontEnd grabs Console.out too early
+ // todo. and isn't affected by Console.setOut employed by partest to intercept output
+
+ //val toolbox = mkToolBox(frontEnd = mkConsoleFrontEnd(), options = "-deprecation")
+ //toolbox.runExpr(reify{
+ // object Utils {
+ // @deprecated("test", "2.10.0")
+ // def foo { println("hello") }
+ // }
+ //
+ // Utils.foo
+ //})
+}
diff --git a/test/files/run/toolbox_default_reporter_is_silent.check b/test/files/run/toolbox_default_reporter_is_silent.check
new file mode 100644
index 0000000000..ef0493b275
--- /dev/null
+++ b/test/files/run/toolbox_default_reporter_is_silent.check
@@ -0,0 +1 @@
+hello
diff --git a/test/files/run/toolbox_default_reporter_is_silent.scala b/test/files/run/toolbox_default_reporter_is_silent.scala
new file mode 100644
index 0000000000..6908c001a3
--- /dev/null
+++ b/test/files/run/toolbox_default_reporter_is_silent.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val toolbox = mkToolBox()
+ toolbox.runExpr(reify{
+ object Utils {
+ @deprecated("test", "2.10.0")
+ def foo { println("hello") }
+ }
+
+ Utils.foo
+ }.tree)
+}
diff --git a/test/files/run/toolbox_silent_reporter.check b/test/files/run/toolbox_silent_reporter.check
new file mode 100644
index 0000000000..2d05b1e3f8
--- /dev/null
+++ b/test/files/run/toolbox_silent_reporter.check
@@ -0,0 +1,4 @@
+hello
+============compiler messages============
+Info(NoPosition,method foo in object Utils is deprecated: test,WARNING)
+=========================================
diff --git a/test/files/run/toolbox_silent_reporter.scala b/test/files/run/toolbox_silent_reporter.scala
new file mode 100644
index 0000000000..6f5687ba4f
--- /dev/null
+++ b/test/files/run/toolbox_silent_reporter.scala
@@ -0,0 +1,16 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val toolbox = mkToolBox(options = "-deprecation")
+ toolbox.runExpr(reify{
+ object Utils {
+ @deprecated("test", "2.10.0")
+ def foo { println("hello") }
+ }
+
+ Utils.foo
+ }.tree)
+ println("============compiler messages============")
+ toolbox.frontEnd.infos.foreach(println(_))
+ println("=========================================")
+} \ No newline at end of file
diff --git a/test/files/run/toolbox_typecheck_implicitsdisabled.check b/test/files/run/toolbox_typecheck_implicitsdisabled.check
new file mode 100644
index 0000000000..4bc64530ab
--- /dev/null
+++ b/test/files/run/toolbox_typecheck_implicitsdisabled.check
@@ -0,0 +1,5 @@
+{
+ import scala.Predef._;
+ scala.Predef.any2ArrowAssoc[Int](1).->[Int](2)
+}
+scala.reflect.runtime.ToolBoxes$ToolBox$ToolBoxError: reflective typecheck has failed: value -> is not a member of Int
diff --git a/test/files/run/toolbox_typecheck_implicitsdisabled.scala b/test/files/run/toolbox_typecheck_implicitsdisabled.scala
new file mode 100644
index 0000000000..9d52e91f73
--- /dev/null
+++ b/test/files/run/toolbox_typecheck_implicitsdisabled.scala
@@ -0,0 +1,24 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val toolbox = mkToolBox()
+
+ val tree1 = Block(
+ Import(Select(Ident(newTermName("scala")), newTermName("Predef")), List(ImportSelector(nme.WILDCARD, -1, null, -1))),
+ Apply(Select(Literal(Constant(1)), newTermName("$minus$greater")), List(Literal(Constant(2))))
+ )
+ val ttree1 = toolbox.typeCheck(tree1, withImplicitViewsDisabled = false)
+ println(ttree1)
+
+ try {
+ val tree2 = Block(
+ Import(Select(Ident(newTermName("scala")), newTermName("Predef")), List(ImportSelector(nme.WILDCARD, -1, null, -1))),
+ Apply(Select(Literal(Constant(1)), newTermName("$minus$greater")), List(Literal(Constant(2))))
+ )
+ val ttree2 = toolbox.typeCheck(tree2, withImplicitViewsDisabled = true)
+ println(ttree2)
+ } catch {
+ case ex: Throwable =>
+ println(ex)
+ }
+} \ No newline at end of file
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled.check b/test/files/run/toolbox_typecheck_macrosdisabled.check
new file mode 100644
index 0000000000..c4af175812
--- /dev/null
+++ b/test/files/run/toolbox_typecheck_macrosdisabled.check
@@ -0,0 +1,5 @@
+{
+ val $mr: mr.type = mr;
+ $mr.Expr.apply[Int(2)]($mr.Literal.apply($mr.Constant.apply(2)))($mr.ConcreteTypeTag.apply[Int(2)]($mr.ConstantType.apply($mr.Constant.apply(2)), classOf[scala.Int]))
+}
+mr.reify[Int](2)
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled.scala b/test/files/run/toolbox_typecheck_macrosdisabled.scala
new file mode 100644
index 0000000000..afbbce1736
--- /dev/null
+++ b/test/files/run/toolbox_typecheck_macrosdisabled.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val toolbox = mkToolBox()
+ val mrPkg = staticModule("scala.reflect.package")
+ val mrSym = selectTerm(mrPkg, "mirror")
+ val NullaryMethodType(mrTpe) = mrSym.typeSignature
+ val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror)
+
+ val tree1 = Apply(Select(Ident(mr), newTermName("reify")), List(Literal(Constant(2))))
+ val ttree1 = toolbox.typeCheck(tree1, withMacrosDisabled = false)
+ println(ttree1)
+
+ val tree2 = Apply(Select(Ident(mr), newTermName("reify")), List(Literal(Constant(2))))
+ val ttree2 = toolbox.typeCheck(tree2, withMacrosDisabled = true)
+ println(ttree2)
+}
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled2.check b/test/files/run/toolbox_typecheck_macrosdisabled2.check
new file mode 100644
index 0000000000..271139b031
--- /dev/null
+++ b/test/files/run/toolbox_typecheck_macrosdisabled2.check
@@ -0,0 +1,5 @@
+{
+ val $mr: mr.type = mr;
+ $mr.Expr.apply[Array[Int]]($mr.Apply.apply($mr.Select.apply($mr.Select.apply($mr.Ident($mr.staticModule("scala")), $mr.newTermName("Array")), $mr.newTermName("apply")), scala.collection.immutable.List.apply[$mr.Literal]($mr.Literal.apply($mr.Constant.apply(2)))))($mr.ConcreteTypeTag.apply[Array[Int]]($mr.TypeRef.apply($mr.thisModuleType("scala"), $mr.staticClass("scala.Array"), scala.collection.immutable.List.apply[$mr.Type]($mr.staticClass("scala.Int").asTypeConstructor)), ScalaRunTime.this.arrayClass(classOf[scala.Int])))
+}
+mr.reify[Array[Int]](scala.Array.apply(2))
diff --git a/test/files/run/toolbox_typecheck_macrosdisabled2.scala b/test/files/run/toolbox_typecheck_macrosdisabled2.scala
new file mode 100644
index 0000000000..b4c76d0600
--- /dev/null
+++ b/test/files/run/toolbox_typecheck_macrosdisabled2.scala
@@ -0,0 +1,17 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val toolbox = mkToolBox()
+ val mrPkg = staticModule("scala.reflect.package")
+ val mrSym = selectTerm(mrPkg, "mirror")
+ val NullaryMethodType(mrTpe) = mrSym.typeSignature
+ val mr = newFreeTerm("mr", mrTpe, scala.reflect.mirror)
+
+ val tree1 = Apply(Select(Ident(mr), newTermName("reify")), List(Apply(Select(Ident(newTermName("scala")), newTermName("Array")), List(Literal(Constant(2))))))
+ val ttree1 = toolbox.typeCheck(tree1, withMacrosDisabled = false)
+ println(ttree1)
+
+ val tree2 = Apply(Select(Ident(mr), newTermName("reify")), List(Apply(Select(Ident(newTermName("scala")), newTermName("Array")), List(Literal(Constant(2))))))
+ val ttree2 = toolbox.typeCheck(tree2, withMacrosDisabled = true)
+ println(ttree2)
+}
diff --git a/test/files/run/treePrint.scala b/test/files/run/treePrint.scala
index e0332a705f..4a80e2824d 100644
--- a/test/files/run/treePrint.scala
+++ b/test/files/run/treePrint.scala
@@ -4,7 +4,7 @@ object Test {
import scala.tools.nsc._
import interpreter._
import java.io.{ OutputStream, BufferedReader, StringReader, PrintWriter, Writer, OutputStreamWriter}
-
+
val code = """
def foo = {
var q: Boolean = false
@@ -22,11 +22,11 @@ object Test {
else 20
}
else 30
-
+
(x == 5) || !q || true
}
- """
-
+ """
+
class NullOutputStream extends OutputStream { def write(b: Int) { } }
def main(args: Array[String]) {
@@ -35,7 +35,8 @@ object Test {
settings.Ycompacttrees.value = true
val intp = new IMain(settings, new PrintWriter(new NullOutputStream))
- val power = new Power(intp, new ReplVals { })
+ val vals = new ReplVals { }
+ val power = new Power(intp, vals)
intp.interpret("""def initialize = "Have to interpret something or we get errors." """)
power trees code foreach println
}
diff --git a/test/files/run/tuple-zipped.scala b/test/files/run/tuple-zipped.scala
index a9851346bc..b197183844 100644
--- a/test/files/run/tuple-zipped.scala
+++ b/test/files/run/tuple-zipped.scala
@@ -15,14 +15,14 @@ object Test {
def main(args: Array[String]): Unit = {
for (cc1 <- xss1 ; cc2 <- xss2) {
- val sum1 = (cc1, cc2).zip map { case (x, y) => x + y } sum
+ val sum1 = (cc1, cc2).zipped map { case (x, y) => x + y } sum
val sum2 = (cc1, cc2).zipped map (_ + _) sum
assert(sum1 == sum2)
}
for (cc1 <- xss1 ; cc2 <- xss2 ; cc3 <- xss3) {
- val sum1 = (cc1, cc2, cc3).zip map { case (x, y, z) => x + y + z } sum
+ val sum1 = (cc1, cc2, cc3).zipped map { case (x, y, z) => x + y + z } sum
val sum2 = (cc1, cc2, cc3).zipped map (_ + _ + _) sum
assert(sum1 == sum2)
diff --git a/test/files/run/typetags_core.check b/test/files/run/typetags_core.check
new file mode 100644
index 0000000000..f124aa6a35
--- /dev/null
+++ b/test/files/run/typetags_core.check
@@ -0,0 +1,32 @@
+true
+ConcreteTypeTag[Byte]
+true
+ConcreteTypeTag[Short]
+true
+ConcreteTypeTag[Char]
+true
+ConcreteTypeTag[Int]
+true
+ConcreteTypeTag[Long]
+true
+ConcreteTypeTag[Float]
+true
+ConcreteTypeTag[Double]
+true
+ConcreteTypeTag[Boolean]
+true
+ConcreteTypeTag[Unit]
+true
+ConcreteTypeTag[Any]
+true
+ConcreteTypeTag[Object]
+true
+ConcreteTypeTag[AnyVal]
+true
+ConcreteTypeTag[AnyRef]
+true
+ConcreteTypeTag[Null]
+true
+ConcreteTypeTag[Nothing]
+true
+ConcreteTypeTag[String]
diff --git a/test/files/run/typetags_core.scala b/test/files/run/typetags_core.scala
new file mode 100644
index 0000000000..7d6be16379
--- /dev/null
+++ b/test/files/run/typetags_core.scala
@@ -0,0 +1,34 @@
+object Test extends App {
+ println(implicitly[TypeTag[Byte]] eq TypeTag.Byte)
+ println(implicitly[TypeTag[Byte]])
+ println(implicitly[TypeTag[Short]] eq TypeTag.Short)
+ println(implicitly[TypeTag[Short]])
+ println(implicitly[TypeTag[Char]] eq TypeTag.Char)
+ println(implicitly[TypeTag[Char]])
+ println(implicitly[TypeTag[Int]] eq TypeTag.Int)
+ println(implicitly[TypeTag[Int]])
+ println(implicitly[TypeTag[Long]] eq TypeTag.Long)
+ println(implicitly[TypeTag[Long]])
+ println(implicitly[TypeTag[Float]] eq TypeTag.Float)
+ println(implicitly[TypeTag[Float]])
+ println(implicitly[TypeTag[Double]] eq TypeTag.Double)
+ println(implicitly[TypeTag[Double]])
+ println(implicitly[TypeTag[Boolean]] eq TypeTag.Boolean)
+ println(implicitly[TypeTag[Boolean]])
+ println(implicitly[TypeTag[Unit]] eq TypeTag.Unit)
+ println(implicitly[TypeTag[Unit]])
+ println(implicitly[TypeTag[Any]] eq TypeTag.Any)
+ println(implicitly[TypeTag[Any]])
+ println(implicitly[TypeTag[Object]] eq TypeTag.Object)
+ println(implicitly[TypeTag[Object]])
+ println(implicitly[TypeTag[AnyVal]] eq TypeTag.AnyVal)
+ println(implicitly[TypeTag[AnyVal]])
+ println(implicitly[TypeTag[AnyRef]] eq TypeTag.AnyRef)
+ println(implicitly[TypeTag[AnyRef]])
+ println(implicitly[TypeTag[Null]] eq TypeTag.Null)
+ println(implicitly[TypeTag[Null]])
+ println(implicitly[TypeTag[Nothing]] eq TypeTag.Nothing)
+ println(implicitly[TypeTag[Nothing]])
+ println(implicitly[TypeTag[String]] eq TypeTag.String)
+ println(implicitly[TypeTag[String]])
+} \ No newline at end of file
diff --git a/test/files/run/typetags_multi.check b/test/files/run/typetags_multi.check
new file mode 100644
index 0000000000..613106985c
--- /dev/null
+++ b/test/files/run/typetags_multi.check
@@ -0,0 +1,5 @@
+ConcreteTypeTag[Int]
+ConcreteTypeTag[Array[Int]]
+ConcreteTypeTag[Array[Array[Int]]]
+ConcreteTypeTag[Array[Array[Array[Int]]]]
+ConcreteTypeTag[Array[Array[Array[Array[Int]]]]]
diff --git a/test/files/run/typetags_multi.scala b/test/files/run/typetags_multi.scala
new file mode 100644
index 0000000000..868edc2b2a
--- /dev/null
+++ b/test/files/run/typetags_multi.scala
@@ -0,0 +1,7 @@
+object Test extends App {
+ println(typeTag[Int])
+ println(typeTag[Array[Int]])
+ println(typeTag[Array[Array[Int]]])
+ println(typeTag[Array[Array[Array[Int]]]])
+ println(typeTag[Array[Array[Array[Array[Int]]]]])
+} \ No newline at end of file
diff --git a/test/files/run/virtpatmat_alts.flags b/test/files/run/virtpatmat_alts.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_alts.flags
+++ b/test/files/run/virtpatmat_alts.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_apply.flags b/test/files/run/virtpatmat_apply.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_apply.flags
+++ b/test/files/run/virtpatmat_apply.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_casting.flags b/test/files/run/virtpatmat_casting.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_casting.flags
+++ b/test/files/run/virtpatmat_casting.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_extends_product.flags b/test/files/run/virtpatmat_extends_product.flags
index ac6b805bd0..8b13789179 100644
--- a/test/files/run/virtpatmat_extends_product.flags
+++ b/test/files/run/virtpatmat_extends_product.flags
@@ -1 +1 @@
--Yvirtpatmat
+
diff --git a/test/files/run/virtpatmat_literal.flags b/test/files/run/virtpatmat_literal.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_literal.flags
+++ b/test/files/run/virtpatmat_literal.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_nested_lists.flags b/test/files/run/virtpatmat_nested_lists.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_nested_lists.flags
+++ b/test/files/run/virtpatmat_nested_lists.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_npe.flags b/test/files/run/virtpatmat_npe.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_npe.flags
+++ b/test/files/run/virtpatmat_npe.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_opt_sharing.flags b/test/files/run/virtpatmat_opt_sharing.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_opt_sharing.flags
+++ b/test/files/run/virtpatmat_opt_sharing.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_partial.flags b/test/files/run/virtpatmat_partial.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_partial.flags
+++ b/test/files/run/virtpatmat_partial.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_partial_backquoted.check b/test/files/run/virtpatmat_partial_backquoted.check
new file mode 100644
index 0000000000..8ab8f29677
--- /dev/null
+++ b/test/files/run/virtpatmat_partial_backquoted.check
@@ -0,0 +1 @@
+Set(You got me!)
diff --git a/test/files/run/virtpatmat_partial_backquoted.scala b/test/files/run/virtpatmat_partial_backquoted.scala
new file mode 100644
index 0000000000..6d92229d6b
--- /dev/null
+++ b/test/files/run/virtpatmat_partial_backquoted.scala
@@ -0,0 +1,12 @@
+object Test extends App {
+ class Region { override def toString = "You got me!" }
+ class SymbolType
+ case class SymbolInfo(tp: SymbolType, regions: List[Region], x: Any)
+
+ def findRegionsWithSymbolType(rawSymbolInfos: Seq[SymbolInfo], symbolType: SymbolType): Set[Region] =
+ rawSymbolInfos.collect { case SymbolInfo(`symbolType`, regions, _) => regions }.flatten.toSet
+
+ val stp = new SymbolType
+ val stp2 = new SymbolType
+ println(findRegionsWithSymbolType(List(SymbolInfo(stp2, List(), null), SymbolInfo(stp, List(new Region), null)), stp))
+} \ No newline at end of file
diff --git a/test/files/run/virtpatmat_staging.flags b/test/files/run/virtpatmat_staging.flags
index 9769db9257..48fd867160 100644
--- a/test/files/run/virtpatmat_staging.flags
+++ b/test/files/run/virtpatmat_staging.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+-Xexperimental
diff --git a/test/files/run/virtpatmat_stringinterp.check b/test/files/run/virtpatmat_stringinterp.check
new file mode 100644
index 0000000000..7927f4f2d9
--- /dev/null
+++ b/test/files/run/virtpatmat_stringinterp.check
@@ -0,0 +1 @@
+Node(1)
diff --git a/test/files/pos/annotDepMethType.flags b/test/files/run/virtpatmat_stringinterp.flags
index e1b37447c9..e1b37447c9 100644
--- a/test/files/pos/annotDepMethType.flags
+++ b/test/files/run/virtpatmat_stringinterp.flags
diff --git a/test/files/run/virtpatmat_stringinterp.scala b/test/files/run/virtpatmat_stringinterp.scala
new file mode 100644
index 0000000000..213712f17a
--- /dev/null
+++ b/test/files/run/virtpatmat_stringinterp.scala
@@ -0,0 +1,13 @@
+object Test extends App {
+ case class Node(x: Int)
+
+ implicit def sc2xml(sc: StringContext): XMLContext = new XMLContext(sc)
+ class XMLContext(sc: StringContext) {
+ object xml {
+ def unapplySeq(xml: Node): Option[Seq[Node]] = Some(List(Node(1)))
+ }
+ }
+
+ val x: Node = Node(0)
+ x match { case xml"""<foo arg=$a/>""" => println(a) }
+} \ No newline at end of file
diff --git a/test/files/run/virtpatmat_switch.flags b/test/files/run/virtpatmat_switch.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_switch.flags
+++ b/test/files/run/virtpatmat_switch.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_tailcalls_verifyerror.flags b/test/files/run/virtpatmat_tailcalls_verifyerror.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_tailcalls_verifyerror.flags
+++ b/test/files/run/virtpatmat_tailcalls_verifyerror.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_try.flags b/test/files/run/virtpatmat_try.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_try.flags
+++ b/test/files/run/virtpatmat_try.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_typed.flags b/test/files/run/virtpatmat_typed.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_typed.flags
+++ b/test/files/run/virtpatmat_typed.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_unapply.flags b/test/files/run/virtpatmat_unapply.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_unapply.flags
+++ b/test/files/run/virtpatmat_unapply.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_unapplyprod.flags b/test/files/run/virtpatmat_unapplyprod.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_unapplyprod.flags
+++ b/test/files/run/virtpatmat_unapplyprod.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_unapplyseq.flags b/test/files/run/virtpatmat_unapplyseq.flags
index 9769db9257..3f5a3100e4 100644
--- a/test/files/run/virtpatmat_unapplyseq.flags
+++ b/test/files/run/virtpatmat_unapplyseq.flags
@@ -1 +1 @@
- -Yvirtpatmat -Xexperimental
+ -Xexperimental
diff --git a/test/files/run/virtpatmat_valdef.check b/test/files/run/virtpatmat_valdef.check
new file mode 100644
index 0000000000..1a45335bd2
--- /dev/null
+++ b/test/files/run/virtpatmat_valdef.check
@@ -0,0 +1 @@
+meh(true,null)
diff --git a/test/files/run/virtpatmat_valdef.scala b/test/files/run/virtpatmat_valdef.scala
new file mode 100644
index 0000000000..f1a9b46cdd
--- /dev/null
+++ b/test/files/run/virtpatmat_valdef.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ // patterns in valdefs...
+ // TODO: irrefutability should indicate we don't actually need to test, just deconstruct
+ val (modified, result) : (Boolean, String) = (true, null)
+ println("meh"+ (modified, result))
+} \ No newline at end of file
diff --git a/test/files/scalacheck/array-new.scala b/test/files/scalacheck/array-new.scala
new file mode 100644
index 0000000000..18d577ca6d
--- /dev/null
+++ b/test/files/scalacheck/array-new.scala
@@ -0,0 +1,36 @@
+import org.scalacheck._
+import Prop._
+import Gen._
+import Arbitrary._
+import util._
+import Buildable._
+import scala.collection.mutable.ArraySeq
+
+object Test extends Properties("Array") {
+ /** At this moment the authentic scalacheck Array Builder/Arb bits are commented out.
+ */
+ implicit def arbArray[T](implicit a: Arbitrary[T], m: ArrayTag[T]): Arbitrary[Array[T]] =
+ Arbitrary(containerOf[List,T](arbitrary[T]) map (_.toArray))
+
+ val arrGen: Gen[Array[_]] = oneOf(
+ arbitrary[Array[Int]],
+ arbitrary[Array[Array[Int]]],
+ arbitrary[Array[List[String]]],
+ arbitrary[Array[String]],
+ arbitrary[Array[Boolean]],
+ arbitrary[Array[AnyVal]]
+ )
+
+ // inspired by #1857 and #2352
+ property("eq/ne") = forAll(arrGen, arrGen) { (c1, c2) =>
+ (c1 eq c2) || (c1 ne c2)
+ }
+
+ // inspired by #2299
+ def smallInt = choose(1, 10)
+ property("ofDim") = forAll(smallInt, smallInt, smallInt) { (i1, i2, i3) =>
+ val arr = Array.ofDim[String](i1, i2, i3)
+ val flattened = arr flatMap (x => x) flatMap (x => x)
+ flattened.length == i1 * i2 * i3
+ }
+}
diff --git a/test/files/scalacheck/array.scala b/test/files/scalacheck/array-old.scala
index f262bc6320..f262bc6320 100644
--- a/test/files/scalacheck/array.scala
+++ b/test/files/scalacheck/array-old.scala
diff --git a/test/files/scalap/caseClass/result.test b/test/files/scalap/caseClass/result.test
index 7dfe3a0356..6165444026 100644
--- a/test/files/scalap/caseClass/result.test
+++ b/test/files/scalap/caseClass/result.test
@@ -14,3 +14,9 @@ case class CaseClass[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String)
override def toString() : java.lang.String = { /* compiled code */ }
override def equals(x$1 : scala.Any) : scala.Boolean = { /* compiled code */ }
}
+object CaseClass extends scala.AnyRef with scala.Serializable {
+ def this() = { /* compiled code */ }
+ final override def toString() : java.lang.String = { /* compiled code */ }
+ def apply[A <: scala.Seq[scala.Int]](i : A, s : scala.Predef.String) : CaseClass[A] = { /* compiled code */ }
+ def unapply[A <: scala.Seq[scala.Int]](x$0 : CaseClass[A]) : scala.Option[scala.Tuple2[A, scala.Predef.String]] = { /* compiled code */ }
+}
diff --git a/test/files/specialized/spec-matrix.check b/test/files/specialized/spec-matrix-new.check
index 5ec3e84597..5ec3e84597 100644
--- a/test/files/specialized/spec-matrix.check
+++ b/test/files/specialized/spec-matrix-new.check
diff --git a/test/files/specialized/spec-matrix-new.scala b/test/files/specialized/spec-matrix-new.scala
new file mode 100644
index 0000000000..65b46e8d48
--- /dev/null
+++ b/test/files/specialized/spec-matrix-new.scala
@@ -0,0 +1,80 @@
+/** Test matrix multiplication with specialization.
+ */
+
+class Matrix[@specialized A: ArrayTag](val rows: Int, val cols: Int) {
+ private val arr: Array[Array[A]] = Array.ofDim[A](rows, cols)
+
+ def apply(i: Int, j: Int): A = {
+ if (i < 0 || i >= rows || j < 0 || j >= cols)
+ throw new NoSuchElementException("Indexes out of bounds: " + (i, j))
+
+ arr(i)(j)
+ }
+
+ def update(i: Int, j: Int, e: A) {
+ arr(i)(j) = e
+ }
+
+ def rowsIterator: Iterator[Array[A]] = new Iterator[Array[A]] {
+ var idx = 0;
+ def hasNext = idx < rows
+ def next = {
+ idx += 1
+ arr(idx - 1)
+ }
+ }
+}
+
+object Test {
+ def main(args: Array[String]) {
+ val m = randomMatrix(200, 100)
+ val n = randomMatrix(100, 200)
+
+ val p = mult(m, n)
+ println(p(0, 0))
+ println("Boxed doubles: " + runtime.BoxesRunTime.doubleBoxCount)
+// println("Boxed integers: " + runtime.BoxesRunTime.integerBoxCount)
+ }
+
+ def randomMatrix(n: Int, m: Int) = {
+ val r = new util.Random(10)
+ val x = new Matrix[Double](n, m)
+ for (i <- 0 until n; j <- 0 until m)
+ x(i, j) = (r.nextInt % 1000).toDouble
+ x
+ }
+
+ def printMatrix[Double](m: Matrix[Double]) {
+ for (i <- 0 until m.rows) {
+ for (j <- 0 until m.cols)
+ print("%5.3f ".format(m(i, j)))
+ println
+ }
+ }
+
+ def multTag[@specialized(Int) T](m: Matrix[T], n: Matrix[T])(implicit at: ArrayTag[T], num: Numeric[T]) {
+ val p = new Matrix[T](m.rows, n.cols)
+ import num._
+
+ for (i <- 0 until m.rows)
+ for (j <- 0 until n.cols) {
+ var sum = num.zero
+ for (k <- 0 until n.rows)
+ sum += m(i, k) * n(k, j)
+ p(i, j) = sum
+ }
+ }
+
+ def mult(m: Matrix[Double], n: Matrix[Double]) = {
+ val p = new Matrix[Double](m.rows, n.cols)
+
+ for (i <- 0 until m.rows)
+ for (j <- 0 until n.cols) {
+ var sum = 0.0
+ for (k <- 0 until n.rows)
+ sum += m(i, k) * n(k, j)
+ p(i, j) = sum
+ }
+ p
+ }
+}
diff --git a/test/files/specialized/spec-matrix-old.check b/test/files/specialized/spec-matrix-old.check
new file mode 100644
index 0000000000..5ec3e84597
--- /dev/null
+++ b/test/files/specialized/spec-matrix-old.check
@@ -0,0 +1,2 @@
+251437.0
+Boxed doubles: 1
diff --git a/test/files/specialized/spec-matrix.scala b/test/files/specialized/spec-matrix-old.scala
index 98735c8c03..98735c8c03 100644
--- a/test/files/specialized/spec-matrix.scala
+++ b/test/files/specialized/spec-matrix-old.scala
diff --git a/test/files/specialized/spec-patmatch.check b/test/files/specialized/spec-patmatch.check
index 33306ab5d9..a2746c0f48 100644
--- a/test/files/specialized/spec-patmatch.check
+++ b/test/files/specialized/spec-patmatch.check
@@ -17,4 +17,4 @@ long
double
float
default
-2 \ No newline at end of file
+10
diff --git a/test/files/speclib/instrumented.jar.desired.sha1 b/test/files/speclib/instrumented.jar.desired.sha1
index 2d4cd04a92..a7da67429e 100644
--- a/test/files/speclib/instrumented.jar.desired.sha1
+++ b/test/files/speclib/instrumented.jar.desired.sha1
@@ -1 +1 @@
-d83c6bf3765ab1378943020a8d9cda8851604ffa ?instrumented.jar
+15f200d9f0f25f9fd871bad2ebb4ba5cfc671db4 ?instrumented.jar
diff --git a/test/instrumented/boxes.patch b/test/instrumented/boxes.patch
index 11c5b37aa8..6c5ff23f9f 100644
--- a/test/instrumented/boxes.patch
+++ b/test/instrumented/boxes.patch
@@ -1,7 +1,8 @@
-9a10,11
+9c9
+<
+---
> /* INSTRUMENTED VERSION */
->
-50a53,61
+51a52,59
> public static int booleanBoxCount = 0;
> public static int characterBoxCount = 0;
> public static int byteBoxCount = 0;
@@ -10,20 +11,19 @@
> public static int longBoxCount = 0;
> public static int floatBoxCount = 0;
> public static int doubleBoxCount = 0;
->
-51a63
-> booleanBoxCount++;
-55a68
-> characterBoxCount++;
-59a73
-> byteBoxCount++;
-63a78
-> shortBoxCount++;
-67a83
-> integerBoxCount++;
-71a88
-> longBoxCount++;
-75a93
-> floatBoxCount++;
-79a98
-> doubleBoxCount++;
+53a62
+> booleanBoxCount += 1;
+57a67
+> characterBoxCount += 1;
+61a72
+> byteBoxCount += 1;
+65a77
+> shortBoxCount += 1;
+69a82
+> integerBoxCount += 1;
+73a87
+> longBoxCount += 1;
+77a92
+> floatBoxCount += 1;
+83a99
+> doubleBoxCount += 1;
diff --git a/test/instrumented/library/scala/runtime/BoxesRunTime.java b/test/instrumented/library/scala/runtime/BoxesRunTime.java
index f06f86f2f2..172ed8ee14 100644
--- a/test/instrumented/library/scala/runtime/BoxesRunTime.java
+++ b/test/instrumented/library/scala/runtime/BoxesRunTime.java
@@ -6,10 +6,8 @@
** |/ **
\* */
-
/* INSTRUMENTED VERSION */
-
package scala.runtime;
import java.io.*;
@@ -33,14 +31,16 @@ public final class BoxesRunTime
{
private static final int CHAR = 0, BYTE = 1, SHORT = 2, INT = 3, LONG = 4, FLOAT = 5, DOUBLE = 6, OTHER = 7;
+ /** We don't need to return BYTE and SHORT, as everything which might
+ * care widens to INT.
+ */
private static int typeCode(Object a) {
if (a instanceof java.lang.Integer) return INT;
- if (a instanceof java.lang.Byte) return BYTE;
- if (a instanceof java.lang.Character) return CHAR;
- if (a instanceof java.lang.Long) return LONG;
if (a instanceof java.lang.Double) return DOUBLE;
- if (a instanceof java.lang.Short) return SHORT;
+ if (a instanceof java.lang.Long) return LONG;
+ if (a instanceof java.lang.Character) return CHAR;
if (a instanceof java.lang.Float) return FLOAT;
+ if ((a instanceof java.lang.Byte) || (a instanceof java.lang.Short)) return INT;
return OTHER;
}
@@ -49,7 +49,6 @@ public final class BoxesRunTime
}
/* BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING ... BOXING */
-
public static int booleanBoxCount = 0;
public static int characterBoxCount = 0;
public static int byteBoxCount = 0;
@@ -58,46 +57,46 @@ public final class BoxesRunTime
public static int longBoxCount = 0;
public static int floatBoxCount = 0;
public static int doubleBoxCount = 0;
-
+
public static java.lang.Boolean boxToBoolean(boolean b) {
- booleanBoxCount++;
+ booleanBoxCount += 1;
return java.lang.Boolean.valueOf(b);
}
public static java.lang.Character boxToCharacter(char c) {
- characterBoxCount++;
+ characterBoxCount += 1;
return java.lang.Character.valueOf(c);
}
public static java.lang.Byte boxToByte(byte b) {
- byteBoxCount++;
+ byteBoxCount += 1;
return java.lang.Byte.valueOf(b);
}
public static java.lang.Short boxToShort(short s) {
- shortBoxCount++;
+ shortBoxCount += 1;
return java.lang.Short.valueOf(s);
}
public static java.lang.Integer boxToInteger(int i) {
- integerBoxCount++;
+ integerBoxCount += 1;
return java.lang.Integer.valueOf(i);
}
public static java.lang.Long boxToLong(long l) {
- longBoxCount++;
+ longBoxCount += 1;
return java.lang.Long.valueOf(l);
}
public static java.lang.Float boxToFloat(float f) {
- floatBoxCount++;
+ floatBoxCount += 1;
return java.lang.Float.valueOf(f);
}
public static java.lang.Double boxToDouble(double d) {
- doubleBoxCount++;
// System.out.println("box " + d);
// (new Throwable()).printStackTrace();
+ doubleBoxCount += 1;
return java.lang.Double.valueOf(d);
}
@@ -138,15 +137,6 @@ public final class BoxesRunTime
/* COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON ... COMPARISON */
- private static int eqTypeCode(Number a) {
- if ((a instanceof java.lang.Integer) || (a instanceof java.lang.Byte)) return INT;
- if (a instanceof java.lang.Long) return LONG;
- if (a instanceof java.lang.Double) return DOUBLE;
- if (a instanceof java.lang.Short) return INT;
- if (a instanceof java.lang.Float) return FLOAT;
- return OTHER;
- }
-
public static boolean equals(Object x, Object y) {
if (x == y) return true;
return equals2(x, y);
@@ -178,8 +168,8 @@ public final class BoxesRunTime
}
public static boolean equalsNumNum(java.lang.Number xn, java.lang.Number yn) {
- int xcode = eqTypeCode(xn);
- int ycode = eqTypeCode(yn);
+ int xcode = typeCode(xn);
+ int ycode = typeCode(yn);
switch (ycode > xcode ? ycode : xcode) {
case INT:
return xn.intValue() == yn.intValue();
@@ -211,8 +201,11 @@ public final class BoxesRunTime
}
private static boolean equalsNumChar(java.lang.Number xn, java.lang.Character yc) {
+ if (yc == null)
+ return xn == null;
+
char ch = yc.charValue();
- switch (eqTypeCode(xn)) {
+ switch (typeCode(xn)) {
case INT:
return xn.intValue() == ch;
case LONG:
@@ -222,9 +215,6 @@ public final class BoxesRunTime
case DOUBLE:
return xn.doubleValue() == ch;
default:
- if (xn == null)
- return yc == null;
-
return xn.equals(yc);
}
}
@@ -290,6 +280,31 @@ public final class BoxesRunTime
else return a.hashCode();
}
+ private static int unboxCharOrInt(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).intValue();
+ }
+ private static long unboxCharOrLong(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).longValue();
+ }
+ private static float unboxCharOrFloat(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).floatValue();
+ }
+ private static double unboxCharOrDouble(Object arg1, int code) {
+ if (code == CHAR)
+ return ((java.lang.Character) arg1).charValue();
+ else
+ return ((java.lang.Number) arg1).doubleValue();
+ }
+
/* OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS ... OPERATORS */
/** arg1 + arg2 */
@@ -298,24 +313,16 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 + val2);
+ return boxToInteger(unboxCharOrInt(arg1, code1) + unboxCharOrInt(arg2, code2));
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 + val2);
+ return boxToLong(unboxCharOrLong(arg1, code1) + unboxCharOrLong(arg2, code2));
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 + val2);
+ return boxToFloat(unboxCharOrFloat(arg1, code1) + unboxCharOrFloat(arg2, code2));
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 + val2);
+ return boxToDouble(unboxCharOrDouble(arg1, code1) + unboxCharOrDouble(arg2, code2));
}
throw new NoSuchMethodException();
}
@@ -326,24 +333,16 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 - val2);
+ return boxToInteger(unboxCharOrInt(arg1, code1) - unboxCharOrInt(arg2, code2));
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 - val2);
+ return boxToLong(unboxCharOrLong(arg1, code1) - unboxCharOrLong(arg2, code2));
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 - val2);
+ return boxToFloat(unboxCharOrFloat(arg1, code1) - unboxCharOrFloat(arg2, code2));
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 - val2);
+ return boxToDouble(unboxCharOrDouble(arg1, code1) - unboxCharOrDouble(arg2, code2));
}
throw new NoSuchMethodException();
}
@@ -354,24 +353,16 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 * val2);
+ return boxToInteger(unboxCharOrInt(arg1, code1) * unboxCharOrInt(arg2, code2));
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 * val2);
+ return boxToLong(unboxCharOrLong(arg1, code1) * unboxCharOrLong(arg2, code2));
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 * val2);
+ return boxToFloat(unboxCharOrFloat(arg1, code1) * unboxCharOrFloat(arg2, code2));
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 * val2);
+ return boxToDouble(unboxCharOrDouble(arg1, code1) * unboxCharOrDouble(arg2, code2));
}
throw new NoSuchMethodException();
}
@@ -381,26 +372,16 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 / val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 / val2);
- }
- if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 / val2);
- }
- if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 / val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) / unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) / unboxCharOrLong(arg2, code2));
+ if (maxcode <= FLOAT)
+ return boxToFloat(unboxCharOrFloat(arg1, code1) / unboxCharOrFloat(arg2, code2));
+ if (maxcode <= DOUBLE)
+ return boxToDouble(unboxCharOrDouble(arg1, code1) / unboxCharOrDouble(arg2, code2));
+
throw new NoSuchMethodException();
}
@@ -409,26 +390,16 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 % val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 % val2);
- }
- if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
- return boxToFloat(val1 % val2);
- }
- if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
- return boxToDouble(val1 % val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) % unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) % unboxCharOrLong(arg2, code2));
+ if (maxcode <= FLOAT)
+ return boxToFloat(unboxCharOrFloat(arg1, code1) % unboxCharOrFloat(arg2, code2));
+ if (maxcode <= DOUBLE)
+ return boxToDouble(unboxCharOrDouble(arg1, code1) % unboxCharOrDouble(arg2, code2));
+
throw new NoSuchMethodException();
}
@@ -437,24 +408,24 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
if (code1 <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToInteger(val1 >> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToInteger(val1 >> val2);
}
}
if (code1 <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToLong(val1 >> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToLong(val1 >> val2);
}
}
@@ -466,24 +437,24 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
if (code1 <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToInteger(val1 << val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToInteger(val1 << val2);
}
}
if (code1 <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToLong(val1 << val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToLong(val1 << val2);
}
}
@@ -495,24 +466,24 @@ public final class BoxesRunTime
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
if (code1 <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToInteger(val1 >>> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToInteger(val1 >>> val2);
}
}
if (code1 <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
if (code2 <= INT) {
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToLong(val1 >>> val2);
}
if (code2 <= LONG) {
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToLong(val1 >>> val2);
}
}
@@ -523,19 +494,19 @@ public final class BoxesRunTime
public static Object negate(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
if (code <= INT) {
- int val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).intValue();
+ int val = unboxCharOrInt(arg, code);
return boxToInteger(-val);
}
if (code <= LONG) {
- long val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).longValue();
+ long val = unboxCharOrLong(arg, code);
return boxToLong(-val);
}
if (code <= FLOAT) {
- float val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).floatValue();
+ float val = unboxCharOrFloat(arg, code);
return boxToFloat(-val);
}
if (code <= DOUBLE) {
- double val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).doubleValue();
+ double val = unboxCharOrDouble(arg, code);
return boxToDouble(-val);
}
throw new NoSuchMethodException();
@@ -545,20 +516,16 @@ public final class BoxesRunTime
public static Object positive(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
if (code <= INT) {
- int val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).intValue();
- return boxToInteger(+val);
+ return boxToInteger(+unboxCharOrInt(arg, code));
}
if (code <= LONG) {
- long val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).longValue();
- return boxToLong(+val);
+ return boxToLong(+unboxCharOrLong(arg, code));
}
if (code <= FLOAT) {
- float val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).floatValue();
- return boxToFloat(+val);
+ return boxToFloat(+unboxCharOrFloat(arg, code));
}
if (code <= DOUBLE) {
- double val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).doubleValue();
- return boxToDouble(+val);
+ return boxToDouble(+unboxCharOrDouble(arg, code));
}
throw new NoSuchMethodException();
}
@@ -566,72 +533,60 @@ public final class BoxesRunTime
/** arg1 & arg2 */
public static Object takeAnd(Object arg1, Object arg2) throws NoSuchMethodException {
if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
- if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue());
+ else
throw new NoSuchMethodException();
- }
- return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() & ((java.lang.Boolean) arg2).booleanValue());
}
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 & val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 & val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) & unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) & unboxCharOrLong(arg2, code2));
+
throw new NoSuchMethodException();
}
/** arg1 | arg2 */
public static Object takeOr(Object arg1, Object arg2) throws NoSuchMethodException {
if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
- if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() | ((java.lang.Boolean) arg2).booleanValue());
+ else
throw new NoSuchMethodException();
- }
- return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() | ((java.lang.Boolean) arg2).booleanValue());
}
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 | val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 | val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) | unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) | unboxCharOrLong(arg2, code2));
+
throw new NoSuchMethodException();
}
/** arg1 ^ arg2 */
public static Object takeXor(Object arg1, Object arg2) throws NoSuchMethodException {
if ((arg1 instanceof Boolean) || (arg2 instanceof Boolean)) {
- if (!((arg1 instanceof Boolean) && (arg2 instanceof Boolean))) {
+ if ((arg1 instanceof Boolean) && (arg2 instanceof Boolean))
+ return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() ^ ((java.lang.Boolean) arg2).booleanValue());
+ else
throw new NoSuchMethodException();
- }
- return boxToBoolean(((java.lang.Boolean) arg1).booleanValue() ^ ((java.lang.Boolean) arg2).booleanValue());
}
int code1 = typeCode(arg1);
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
- if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
- return boxToInteger(val1 ^ val2);
- }
- if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
- return boxToLong(val1 ^ val2);
- }
+
+ if (maxcode <= INT)
+ return boxToInteger(unboxCharOrInt(arg1, code1) ^ unboxCharOrInt(arg2, code2));
+ if (maxcode <= LONG)
+ return boxToLong(unboxCharOrLong(arg1, code1) ^ unboxCharOrLong(arg2, code2));
+
throw new NoSuchMethodException();
}
@@ -655,12 +610,10 @@ public final class BoxesRunTime
public static Object complement(Object arg) throws NoSuchMethodException {
int code = typeCode(arg);
if (code <= INT) {
- int val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).intValue();
- return boxToInteger(~val);
+ return boxToInteger(~unboxCharOrInt(arg, code));
}
if (code <= LONG) {
- long val = (code == CHAR) ? ((java.lang.Character) arg).charValue() : ((java.lang.Number) arg).longValue();
- return boxToLong(~val);
+ return boxToLong(~unboxCharOrLong(arg, code));
}
throw new NoSuchMethodException();
}
@@ -686,23 +639,23 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 < val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 < val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 < val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 < val2);
}
throw new NoSuchMethodException();
@@ -713,23 +666,23 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 <= val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 <= val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 <= val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 <= val2);
}
throw new NoSuchMethodException();
@@ -740,23 +693,23 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 >= val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 >= val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 >= val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 >= val2);
}
throw new NoSuchMethodException();
@@ -767,33 +720,30 @@ public final class BoxesRunTime
int code2 = typeCode(arg2);
int maxcode = (code1 < code2) ? code2 : code1;
if (maxcode <= INT) {
- int val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).intValue();
- int val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).intValue();
+ int val1 = unboxCharOrInt(arg1, code1);
+ int val2 = unboxCharOrInt(arg2, code2);
return boxToBoolean(val1 > val2);
}
if (maxcode <= LONG) {
- long val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).longValue();
- long val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).longValue();
+ long val1 = unboxCharOrLong(arg1, code1);
+ long val2 = unboxCharOrLong(arg2, code2);
return boxToBoolean(val1 > val2);
}
if (maxcode <= FLOAT) {
- float val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).floatValue();
- float val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).floatValue();
+ float val1 = unboxCharOrFloat(arg1, code1);
+ float val2 = unboxCharOrFloat(arg2, code2);
return boxToBoolean(val1 > val2);
}
if (maxcode <= DOUBLE) {
- double val1 = (code1 == CHAR) ? ((java.lang.Character) arg1).charValue() : ((java.lang.Number) arg1).doubleValue();
- double val2 = (code2 == CHAR) ? ((java.lang.Character) arg2).charValue() : ((java.lang.Number) arg2).doubleValue();
+ double val1 = unboxCharOrDouble(arg1, code1);
+ double val2 = unboxCharOrDouble(arg2, code2);
return boxToBoolean(val1 > val2);
}
throw new NoSuchMethodException();
}
-
+
public static boolean isBoxedNumberOrBoolean(Object arg) {
- if (arg instanceof java.lang.Boolean)
- return true;
- else
- return isBoxedNumber(arg);
+ return (arg instanceof java.lang.Boolean) || isBoxedNumber(arg);
}
public static boolean isBoxedNumber(Object arg) {
return (
diff --git a/test/instrumented/library/scala/runtime/ScalaRunTime.scala b/test/instrumented/library/scala/runtime/ScalaRunTime.scala
index 9eb93a418d..63908fcc29 100644
--- a/test/instrumented/library/scala/runtime/ScalaRunTime.scala
+++ b/test/instrumented/library/scala/runtime/ScalaRunTime.scala
@@ -6,9 +6,9 @@
** |/ **
\* */
-package scala.runtime
/* INSTRUMENTED VERSION */
+package scala.runtime
import scala.collection.{ Seq, IndexedSeq, TraversableView, AbstractIterator }
import scala.collection.mutable.WrappedArray
@@ -33,10 +33,7 @@ object ScalaRunTime {
clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1))
def isValueClass(clazz: Class[_]) = clazz.isPrimitive()
- var arrayApplyCount = 0
- var arrayUpdateCount = 0
-
- def isTuple(x: Any) = tupleNames(x.getClass.getName)
+ def isTuple(x: Any) = x != null && tupleNames(x.getClass.getName)
def isAnyVal(x: Any) = x match {
case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true
case _ => false
@@ -52,56 +49,68 @@ object ScalaRunTime {
names.toSet
}
+ /** Return the class object representing an array with element class `clazz`.
+ */
+ def arrayClass(clazz: Class[_]): Class[_] = {
+ // newInstance throws an exception if the erasure is Void.TYPE. see SI-5680
+ if (clazz == java.lang.Void.TYPE) classOf[Array[Unit]]
+ else java.lang.reflect.Array.newInstance(clazz, 0).getClass
+ }
+
+ /** Return the class object representing elements in arrays described by a given schematic.
+ */
+ def arrayElementClass(schematic: Any): Class[_] = schematic match {
+ case cls: Class[_] => cls.getComponentType
+ case tag: ClassTag[_] => tag.erasure
+ case tag: ArrayTag[_] => tag.newArray(0).getClass.getComponentType
+ case _ => throw new UnsupportedOperationException("unsupported schematic %s (%s)".format(schematic, if (schematic == null) "null" else schematic.getClass))
+ }
+
/** Return the class object representing an unboxed value type,
* e.g. classOf[int], not classOf[java.lang.Integer]. The compiler
* rewrites expressions like 5.getClass to come here.
*/
- def anyValClass[T <: AnyVal](value: T): Class[T] = (value match {
- case x: Byte => java.lang.Byte.TYPE
- case x: Short => java.lang.Short.TYPE
- case x: Char => java.lang.Character.TYPE
- case x: Int => java.lang.Integer.TYPE
- case x: Long => java.lang.Long.TYPE
- case x: Float => java.lang.Float.TYPE
- case x: Double => java.lang.Double.TYPE
- case x: Boolean => java.lang.Boolean.TYPE
- case x: Unit => java.lang.Void.TYPE
- }).asInstanceOf[Class[T]]
+ def anyValClass[T <: AnyVal : ClassTag](value: T): Class[T] =
+ classTag[T].erasure.asInstanceOf[Class[T]]
+
+ var arrayApplyCount = 0
/** Retrieve generic array element */
def array_apply(xs: AnyRef, idx: Int): Any = {
arrayApplyCount += 1
xs match {
- case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
- case x: Array[Int] => x(idx).asInstanceOf[Any]
- case x: Array[Double] => x(idx).asInstanceOf[Any]
- case x: Array[Long] => x(idx).asInstanceOf[Any]
- case x: Array[Float] => x(idx).asInstanceOf[Any]
- case x: Array[Char] => x(idx).asInstanceOf[Any]
- case x: Array[Byte] => x(idx).asInstanceOf[Any]
- case x: Array[Short] => x(idx).asInstanceOf[Any]
- case x: Array[Boolean] => x(idx).asInstanceOf[Any]
- case x: Array[Unit] => x(idx).asInstanceOf[Any]
- case null => throw new NullPointerException
- }
+ case x: Array[AnyRef] => x(idx).asInstanceOf[Any]
+ case x: Array[Int] => x(idx).asInstanceOf[Any]
+ case x: Array[Double] => x(idx).asInstanceOf[Any]
+ case x: Array[Long] => x(idx).asInstanceOf[Any]
+ case x: Array[Float] => x(idx).asInstanceOf[Any]
+ case x: Array[Char] => x(idx).asInstanceOf[Any]
+ case x: Array[Byte] => x(idx).asInstanceOf[Any]
+ case x: Array[Short] => x(idx).asInstanceOf[Any]
+ case x: Array[Boolean] => x(idx).asInstanceOf[Any]
+ case x: Array[Unit] => x(idx).asInstanceOf[Any]
+ case null => throw new NullPointerException
+ }
}
+ var arrayUpdateCount = 0
+
/** update generic array element */
def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
arrayUpdateCount += 1
xs match {
- case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
- case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
- case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
- case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
- case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
- case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
- case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
- case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
- case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
- case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
- case null => throw new NullPointerException
- }
+ case x: Array[AnyRef] => x(idx) = value.asInstanceOf[AnyRef]
+ case x: Array[Int] => x(idx) = value.asInstanceOf[Int]
+ case x: Array[Double] => x(idx) = value.asInstanceOf[Double]
+ case x: Array[Long] => x(idx) = value.asInstanceOf[Long]
+ case x: Array[Float] => x(idx) = value.asInstanceOf[Float]
+ case x: Array[Char] => x(idx) = value.asInstanceOf[Char]
+ case x: Array[Byte] => x(idx) = value.asInstanceOf[Byte]
+ case x: Array[Short] => x(idx) = value.asInstanceOf[Short]
+ case x: Array[Boolean] => x(idx) = value.asInstanceOf[Boolean]
+ case x: Array[Unit] => x(idx) = value.asInstanceOf[Unit]
+ case null => throw new NullPointerException
+ }
}
/** Get generic array length */
@@ -340,14 +349,14 @@ object ScalaRunTime {
case null => "null"
case "" => "\"\""
case x: String => if (x.head.isWhitespace || x.last.isWhitespace) "\"" + x + "\"" else x
- case x if useOwnToString(x) => x toString
+ case x if useOwnToString(x) => x.toString
case x: AnyRef if isArray(x) => arrayToString(x)
case x: collection.Map[_, _] => x.iterator take maxElements map mapInner mkString (x.stringPrefix + "(", ", ", ")")
case x: Iterable[_] => x.iterator take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
case x: Traversable[_] => x take maxElements map inner mkString (x.stringPrefix + "(", ", ", ")")
case x: Product1[_] if isTuple(x) => "(" + inner(x._1) + ",)" // that special trailing comma
case x: Product if isTuple(x) => x.productIterator map inner mkString ("(", ",", ")")
- case x => x toString
+ case x => x.toString
}
// The try/catch is defense against iterables which aren't actually designed
diff --git a/test/instrumented/srt.patch b/test/instrumented/srt.patch
index 2f472ff1c0..8d08550165 100644
--- a/test/instrumented/srt.patch
+++ b/test/instrumented/srt.patch
@@ -1,23 +1,26 @@
9a10,11
> /* INSTRUMENTED VERSION */
->
-33a36,38
+>
+43c45,48
+< def isTuple(x: Any) = x != null && tupleNames(x.getClass.getName)
+---
> var arrayApplyCount = 0
> var arrayUpdateCount = 0
->
-35c40,42
+>
+> def isTuple(x: Any) = tupleNames(x.getClass.getName)
+75c80,82
< def array_apply(xs: AnyRef, idx: Int): Any = xs match {
---
> def array_apply(xs: AnyRef, idx: Int): Any = {
> arrayApplyCount += 1
> xs match {
-47a55
+87a95
> }
-50c58,60
+90c98,100
< def array_update(xs: AnyRef, idx: Int, value: Any): Unit = xs match {
---
> def array_update(xs: AnyRef, idx: Int, value: Any): Unit = {
> arrayUpdateCount += 1
> xs match {
-62a73
+101a112
> }
diff --git a/test/pending/neg/reify_packed.check b/test/pending/neg/reify_packed.check
new file mode 100644
index 0000000000..adba330d56
--- /dev/null
+++ b/test/pending/neg/reify_packed.check
@@ -0,0 +1,4 @@
+reify_packed.scala:6: error: implementation restriction: cannot reify block of type List[_$1] that involves a type declared inside the block being reified. consider casting the return value to a suitable type.
+ reify {
+ ^
+one error found
diff --git a/test/pending/neg/reify_packed.scala b/test/pending/neg/reify_packed.scala
new file mode 100644
index 0000000000..0240f2a4b5
--- /dev/null
+++ b/test/pending/neg/reify_packed.scala
@@ -0,0 +1,10 @@
+object Test extends App {
+ reify {
+ class C { override def toString() = "C" }
+ val ret = List((new C, new C))
+ ret.asInstanceOf[List[_]]
+ };
+
+ val toolbox = mkToolBox()
+ println(toolbox.runExpr(code.tree))
+}
diff --git a/test/pending/neg/t1557.scala b/test/pending/neg/t1557.scala
new file mode 100644
index 0000000000..ba93b45fad
--- /dev/null
+++ b/test/pending/neg/t1557.scala
@@ -0,0 +1,18 @@
+object Test extends App {
+ trait A
+ trait B extends A
+
+ trait C {
+ trait D { type T >: B <: A }
+ val y: (D with this.type)#T = new B { }
+ }
+
+ class D extends C {
+ trait E
+ type T = E
+ def frob(arg : E) : E = arg
+ frob(y)
+ }
+
+ new D
+} \ No newline at end of file
diff --git a/test/pending/neg/t2066.scala b/test/pending/neg/t2066.scala
new file mode 100644
index 0000000000..46177b19f7
--- /dev/null
+++ b/test/pending/neg/t2066.scala
@@ -0,0 +1,16 @@
+object Test extends App {
+ trait A {
+ def f[T[_]](x : T[Int]) : T[Any]
+ }
+
+ class B extends A {
+ def f[T[+_]](x : T[Int]) : T[Any] = x
+ }
+
+ class P[Y](var y : Y)
+
+ val p = new P(1)
+ val palias = (new B():A).f[P](p)
+ palias.y = "hello"
+ val z: Int = p.y
+} \ No newline at end of file
diff --git a/test/pending/neg/t3189.check b/test/pending/neg/t3189.check
deleted file mode 100644
index 43dd0f29a0..0000000000
--- a/test/pending/neg/t3189.check
+++ /dev/null
@@ -1,7 +0,0 @@
-t3189.scala:2: error: illegal start of simple pattern
- val Array(a,b*) = ("": Any)
- ^
-t3189.scala:3: error: ')' expected but '}' found.
-}
-^
-two errors found
diff --git a/test/pending/neg/t5378.scala b/test/pending/neg/t5378.scala
new file mode 100644
index 0000000000..cada29b0a0
--- /dev/null
+++ b/test/pending/neg/t5378.scala
@@ -0,0 +1,19 @@
+import language.reflectiveCalls
+
+class Coll[+T] {
+ def contains = new { def apply[T1 <: T](value: T1) = ??? }
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ val xs = new Coll[List[String]]
+ val ys: Coll[Traversable[String]] = xs
+
+ println(ys contains Nil)
+ // java.lang.NoSuchMethodException: Coll$$anon$1.apply(scala.collection.Traversable)
+ // at java.lang.Class.getMethod(Class.java:1605)
+ // at Test$.reflMethod$Method1(a.scala:14)
+ // at Test$.main(a.scala:14)
+ // at Test.main(a.scala)
+ }
+}
diff --git a/test/pending/neg/t5618.check b/test/pending/neg/t5618.check
new file mode 100644
index 0000000000..118e812ae4
--- /dev/null
+++ b/test/pending/neg/t5618.check
@@ -0,0 +1,7 @@
+t5618.scala:12: error: could not find implicit value for parameter class1: Class1
+ val class2 = new Class2
+ ^
+t5618.scala:18: error: could not find implicit value for parameter class1: Class1
+ val class2 = new Class2
+ ^
+two errors found \ No newline at end of file
diff --git a/test/pending/neg/t5618.scala b/test/pending/neg/t5618.scala
new file mode 100644
index 0000000000..66e06787f1
--- /dev/null
+++ b/test/pending/neg/t5618.scala
@@ -0,0 +1,27 @@
+
+
+
+
+case class Class1
+
+
+case class Class2(implicit class1: Class1)
+
+
+object Test1 {
+ val class2 = new Class2
+ implicit val class1 = new Class1
+}
+
+
+object Test2 {
+ val class2 = new Class2
+ implicit val class1: Class1 = new Class1
+}
+
+
+object Test3 {
+ implicit val class1 = new Class1
+ val class2 = new Class2
+}
+
diff --git a/test/pending/pos/inference.scala b/test/pending/pos/inference.scala
index d28d003435..3672351fca 100644
--- a/test/pending/pos/inference.scala
+++ b/test/pending/pos/inference.scala
@@ -1,15 +1,15 @@
// inference illuminator
object Test {
- class D1[T1 : Manifest, T2 <: T1 : Manifest](x: T1) { println(manifest[(T1, T2)]) }
- class D2[T1 : Manifest, T2 >: T1 : Manifest](x: T1) { println(manifest[(T1, T2)]) }
- class D3[+T1 : Manifest, T2 <: T1 : Manifest](x: T1) { println(manifest[(T1, T2)]) }
- class D4[-T1 : Manifest, T2 >: T1 : Manifest](x: T1) { println(manifest[(T1, T2)]) }
-
- class E1[T1 : Manifest, T2 <: T1 : Manifest](x: D1[T1, T2]) { println(manifest[(T1, T2)]) }
- class E2[T1 : Manifest, T2 >: T1 : Manifest](x: D2[T1, T2]) { println(manifest[(T1, T2)]) }
- class E3[+T1 : Manifest, T2 <: T1 : Manifest](x: D3[T1, T2]) { println(manifest[(T1, T2)]) }
- class E4[-T1 : Manifest, T2 >: T1 : Manifest](x: D4[T1, T2]) { println(manifest[(T1, T2)]) }
-
+ class D1[T1 : TypeTag, T2 <: T1 : TypeTag](x: T1) { println(typeTag[(T1, T2)]) }
+ class D2[T1 : TypeTag, T2 >: T1 : TypeTag](x: T1) { println(typeTag[(T1, T2)]) }
+ class D3[+T1 : TypeTag, T2 <: T1 : TypeTag](x: T1) { println(typeTag[(T1, T2)]) }
+ class D4[-T1 : TypeTag, T2 >: T1 : TypeTag](x: T1) { println(typeTag[(T1, T2)]) }
+
+ class E1[T1 : TypeTag, T2 <: T1 : TypeTag](x: D1[T1, T2]) { println(typeTag[(T1, T2)]) }
+ class E2[T1 : TypeTag, T2 >: T1 : TypeTag](x: D2[T1, T2]) { println(typeTag[(T1, T2)]) }
+ class E3[+T1 : TypeTag, T2 <: T1 : TypeTag](x: D3[T1, T2]) { println(typeTag[(T1, T2)]) }
+ class E4[-T1 : TypeTag, T2 >: T1 : TypeTag](x: D4[T1, T2]) { println(typeTag[(T1, T2)]) }
+
def main(args: Array[String]): Unit = {
// WHY YOU NO LIKE NOTHING SO MUCH SCALAC?
val d1 = new D1(5)
diff --git a/test/pending/pos/t4683.scala b/test/pending/pos/t4683.scala
new file mode 100644
index 0000000000..7af7024159
--- /dev/null
+++ b/test/pending/pos/t4683.scala
@@ -0,0 +1,11 @@
+
+
+
+
+class DelayedInitTest {
+ def a = ()
+ class B extends DelayedInit {
+ a
+ def delayedInit(body: => Unit) = ()
+ }
+}
diff --git a/test/pending/pos/t5399.scala b/test/pending/pos/t5399.scala
index d8c1d5e51c..89caba39c1 100644
--- a/test/pending/pos/t5399.scala
+++ b/test/pending/pos/t5399.scala
@@ -1,15 +1,8 @@
class Test {
- type AnyCyclic = Execute[Task]#CyclicException[_]
+ class A[T]
+ class B[T](val a: A[T])
- trait Task[T]
+ case class CaseClass[T](x: T)
- trait Execute[A[_] <: AnyRef] {
- class CyclicException[T](val caller: A[T], val target: A[T])
- }
-
- def convertCyclic(c: AnyCyclic): String =
- (c.caller, c.target) match {
- case (caller: Task[_], target: Task[_]) => "bazinga!"
- }
+ def break(existB: B[_]) = CaseClass(existB.a) match { case CaseClass(_) => }
}
-
diff --git a/test/pending/pos/t5399a.scala b/test/pending/pos/t5399a.scala
new file mode 100644
index 0000000000..4ebd85ad03
--- /dev/null
+++ b/test/pending/pos/t5399a.scala
@@ -0,0 +1,19 @@
+class Foo {
+ trait Init[T]
+ class ScopedKey[T] extends Init[T]
+
+ trait Setting[T] {
+ val key: ScopedKey[T]
+ }
+
+ case class ScopedKey1[T](val foo: Init[T]) extends ScopedKey[T]
+
+ val scalaHome: Setting[Option[String]] = null
+ val scalaVersion: Setting[String] = null
+
+ def testPatternMatch(s: Setting[_]) {
+ s.key match {
+ case ScopedKey1(scalaHome.key | scalaVersion.key) => ()
+ }
+ }
+}
diff --git a/test/pending/pos/t5503.flags b/test/pending/pos/t5503.flags
new file mode 100644
index 0000000000..e8fb65d50c
--- /dev/null
+++ b/test/pending/pos/t5503.flags
@@ -0,0 +1 @@
+-Xfatal-warnings \ No newline at end of file
diff --git a/test/pending/pos/t5503.scala b/test/pending/pos/t5503.scala
new file mode 100644
index 0000000000..8a1925df1f
--- /dev/null
+++ b/test/pending/pos/t5503.scala
@@ -0,0 +1,18 @@
+trait A {
+ type Type
+ type MethodType <: Type
+
+ val MethodType: MethodTypeExtractor = null
+
+ abstract class MethodTypeExtractor {
+ def unapply(tpe: MethodType): Option[(Any, Any)]
+ }
+}
+
+object Test {
+ val a: A = null
+
+ def foo(tpe: a.Type) = tpe match {
+ case a.MethodType(_, _) =>
+ }
+} \ No newline at end of file
diff --git a/test/pending/pos/t5521.scala b/test/pending/pos/t5521.scala
new file mode 100644
index 0000000000..dc025d0945
--- /dev/null
+++ b/test/pending/pos/t5521.scala
@@ -0,0 +1,3 @@
+class Foo { type Bar }
+
+class Quux(val foo: Foo)(val bar: foo.Bar) \ No newline at end of file
diff --git a/test/pending/pos/t5534.scala b/test/pending/pos/t5534.scala
new file mode 100644
index 0000000000..834c4fd68d
--- /dev/null
+++ b/test/pending/pos/t5534.scala
@@ -0,0 +1,11 @@
+object Phrase extends Enumeration {
+ type Phrase = Value
+ val PHRASE1 = Value("My phrase 1")
+ val PHRASE2 = Value("My phrase 2")
+}
+
+class Entity(text:String)
+
+object Test {
+ val myMapWithPhrases = Phrase.values.map(p => (p -> new Entity(p.toString))).toMap
+} \ No newline at end of file
diff --git a/test/pending/pos/t5559.scala b/test/pending/pos/t5559.scala
new file mode 100644
index 0000000000..586e52cd4f
--- /dev/null
+++ b/test/pending/pos/t5559.scala
@@ -0,0 +1,23 @@
+
+
+
+
+object Test {
+
+ class Inv[T]
+
+ def foo[S](interface: Inv[_ >: S], implementation: Inv[S]) {}
+
+ def bar[R, T <: R](interface: Inv[R], impl: Inv[T]) {
+ //foo[T](interface, impl)
+ foo(interface, impl) // Compilation Error
+ // Inv[R] <: Inv[_ >: S]
+ // Inv[T] <: Inv[S]
+ // ----------------------
+ // R >: S
+ // T == S
+ }
+
+}
+
+
diff --git a/test/pending/pos/t5564.scala b/test/pending/pos/t5564.scala
new file mode 100644
index 0000000000..1783a903ed
--- /dev/null
+++ b/test/pending/pos/t5564.scala
@@ -0,0 +1,5 @@
+trait C
+
+class Foo[@specialized(Int) T, A] {
+ def bar[B >: A <: C]: T = ???
+}
diff --git a/test/pending/pos/t5579.scala b/test/pending/pos/t5579.scala
new file mode 100644
index 0000000000..a1ee077fe7
--- /dev/null
+++ b/test/pending/pos/t5579.scala
@@ -0,0 +1,29 @@
+import language.existentials
+
+class Result[+A]
+
+case class Success[A](x: A) extends Result[A]
+
+class Apply[A]
+
+object Apply {
+ def apply[A](f: Int => Result[A]): Apply[A] = new Apply[A]
+}
+
+object TestUnit {
+ //Error is here:
+ def goo = Apply { i =>
+ i match {
+ case 1 => Success(Some(1))
+ case _ => Success(None)
+ }
+ }
+
+ //If type is defined explicitly (which I wanted from compiler to infer), then all is ok
+ def foo = Apply[t forSome { type t >: Some[Int] with None.type <: Option[Int] }] { i =>
+ i match {
+ case 1 => Success(Some(1))
+ case _ => Success(None)
+ }
+ }
+}
diff --git a/test/pending/pos/t5585.scala b/test/pending/pos/t5585.scala
new file mode 100644
index 0000000000..5d3eb86111
--- /dev/null
+++ b/test/pending/pos/t5585.scala
@@ -0,0 +1,18 @@
+class Result[+A]
+
+case class Success[A](x: A) extends Result[A]
+
+class Apply[A]
+
+object Apply {
+ def apply[A](f: Int => Result[A]): Apply[A] = new Apply[A]
+}
+
+object TestUnit {
+ def goo : Apply[Option[Int]] = Apply { i =>
+ val p = i match {
+ case 1 => Success(Some(1))
+ case _ => Success(None)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/pending/pos/t5606.scala b/test/pending/pos/t5606.scala
new file mode 100644
index 0000000000..2545271e32
--- /dev/null
+++ b/test/pending/pos/t5606.scala
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+case class CaseTest[_](someData:String)
diff --git a/test/pending/pos/t5639/Bar.scala b/test/pending/pos/t5639/Bar.scala
new file mode 100644
index 0000000000..f577500acd
--- /dev/null
+++ b/test/pending/pos/t5639/Bar.scala
@@ -0,0 +1,7 @@
+package pack.age
+
+import pack.age.Implicits._
+
+object Quux {
+ def baz : Baz = 1
+}
diff --git a/test/pending/pos/t5639/Foo.scala b/test/pending/pos/t5639/Foo.scala
new file mode 100644
index 0000000000..6602150661
--- /dev/null
+++ b/test/pending/pos/t5639/Foo.scala
@@ -0,0 +1,7 @@
+package pack.age
+
+class Baz
+
+object Implicits {
+ implicit def Baz(n: Int): Baz = new Baz
+}
diff --git a/test/pending/pos/t5654.scala b/test/pending/pos/t5654.scala
new file mode 100644
index 0000000000..eb711a5f37
--- /dev/null
+++ b/test/pending/pos/t5654.scala
@@ -0,0 +1,4 @@
+case class Bomb(a: Array[_])
+case class Bomb2(a: Array[T] forSome { type T })
+class Okay1(a: Array[_])
+case class Okay2(s: Seq[_]) \ No newline at end of file
diff --git a/test/pending/pos/t5712.scala b/test/pending/pos/t5712.scala
new file mode 100644
index 0000000000..31f365028a
--- /dev/null
+++ b/test/pending/pos/t5712.scala
@@ -0,0 +1,14 @@
+import scala.tools.nsc._
+
+object Test {
+
+ // works
+ def mkReifier(global: Global)(typer: global.analyzer.Typer) = typer
+
+/*
+<console>:10: error: not found: value global
+ class Reifier(global: Global)(typer: global.analyzer.Typer) { }
+*/
+ class Reifier(global: Global)(typer: global.analyzer.Typer) { }
+
+}
diff --git a/test/pending/presentation/t5708.check b/test/pending/presentation/t5708.check
new file mode 100644
index 0000000000..9d944d6cfc
--- /dev/null
+++ b/test/pending/presentation/t5708.check
@@ -0,0 +1,81 @@
+reload: Completions.scala
+
+askTypeCompletion at Completions.scala(9,9)
+================================================================================
+[response] aksTypeCompletion at (9,9)
+retrieved 38 members
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(test.Compat.type, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)test.Compat.type`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)test.Compat.type`
+[accessible: true] `method ensuring(cond: test.Compat.type => Boolean)test.Compat.type`
+[accessible: true] `method ensuring(cond: test.Compat.type => Boolean, msg: => Any)test.Compat.type`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> test.Compat.type`
+[accessible: true] `method →[B](y: B)(test.Compat.type, B)`
+[accessible: true] `lazy value fooInt`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: true] `value CONST_STRINGString("constant")`
+[accessible: false] `value __leftOfArrowtest.Compat.type`
+[accessible: false] `value __resultOfEnsuringtest.Compat.type`
+[accessible: false] `value selfAny`
+================================================================================
+
+askTypeCompletion at Completions.scala(10,9)
+================================================================================
+[response] aksTypeCompletion at (10,9)
+retrieved 38 members
+[accessible: true] `method !=(x$1: Any)Boolean`
+[accessible: true] `method !=(x$1: AnyRef)Boolean`
+[accessible: true] `method ##()Int`
+[accessible: true] `method +(other: String)String`
+[accessible: true] `method ->[B](y: B)(test.Compat.type, B)`
+[accessible: true] `method ==(x$1: Any)Boolean`
+[accessible: true] `method ==(x$1: AnyRef)Boolean`
+[accessible: true] `method asInstanceOf[T0]=> T0`
+[accessible: true] `method ensuring(cond: Boolean)test.Compat.type`
+[accessible: true] `method ensuring(cond: Boolean, msg: => Any)test.Compat.type`
+[accessible: true] `method ensuring(cond: test.Compat.type => Boolean)test.Compat.type`
+[accessible: true] `method ensuring(cond: test.Compat.type => Boolean, msg: => Any)test.Compat.type`
+[accessible: true] `method eq(x$1: AnyRef)Boolean`
+[accessible: true] `method equals(x$1: Any)Boolean`
+[accessible: true] `method formatted(fmtstr: String)String`
+[accessible: true] `method hashCode()Int`
+[accessible: true] `method isInstanceOf[T0]=> Boolean`
+[accessible: true] `method ne(x$1: AnyRef)Boolean`
+[accessible: true] `method notify()Unit`
+[accessible: true] `method notifyAll()Unit`
+[accessible: true] `method synchronized[T0](x$1: T0)T0`
+[accessible: true] `method toString()String`
+[accessible: true] `method wait()Unit`
+[accessible: true] `method wait(x$1: Long)Unit`
+[accessible: true] `method wait(x$1: Long, x$2: Int)Unit`
+[accessible: true] `method x=> test.Compat.type`
+[accessible: true] `method →[B](y: B)(test.Compat.type, B)`
+[accessible: true] `lazy value fooInt`
+[accessible: false] `method clone()Object`
+[accessible: false] `method finalize()Unit`
+[accessible: true] `value CONST_STRINGString("constant")`
+[accessible: false] `value __leftOfArrowtest.Compat.type`
+[accessible: false] `value __resultOfEnsuringtest.Compat.type`
+[accessible: false] `value selfAny`
+================================================================================
diff --git a/test/pending/presentation/t5708/Test.scala b/test/pending/presentation/t5708/Test.scala
new file mode 100644
index 0000000000..96e758d974
--- /dev/null
+++ b/test/pending/presentation/t5708/Test.scala
@@ -0,0 +1,5 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+object Test extends InteractiveTest {
+
+} \ No newline at end of file
diff --git a/test/pending/presentation/t5708/src/Completions.scala b/test/pending/presentation/t5708/src/Completions.scala
new file mode 100644
index 0000000000..cc41492df7
--- /dev/null
+++ b/test/pending/presentation/t5708/src/Completions.scala
@@ -0,0 +1,11 @@
+package test
+
+object Compat {
+ final val CONST_STRING = "constant"
+ lazy val foo = 4
+}
+
+class Foo {
+ Compat./*!*/CONST_STRING // its 'accessible' flag is false
+ Compat./*!*/foo // its 'accessible' flag is false
+}
diff --git a/test/files/pos/macros.flags b/test/pending/run/macro-expand-default.flags
index 7fea2ff901..7fea2ff901 100644
--- a/test/files/pos/macros.flags
+++ b/test/pending/run/macro-expand-default.flags
diff --git a/test/pending/run/macro-expand-default/Impls_1.scala b/test/pending/run/macro-expand-default/Impls_1.scala
new file mode 100644
index 0000000000..fefe8fc4e2
--- /dev/null
+++ b/test/pending/run/macro-expand-default/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int], y: c.Expr[Int]) = {
+ import c.mirror._
+ val sum = Apply(Select(x.tree, newTermName("$minus")), List(y.tree))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(sum))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/pending/run/macro-expand-default/Macros_Test_2.scala b/test/pending/run/macro-expand-default/Macros_Test_2.scala
new file mode 100644
index 0000000000..92fe84d04a
--- /dev/null
+++ b/test/pending/run/macro-expand-default/Macros_Test_2.scala
@@ -0,0 +1,8 @@
+object Test extends App {
+ def foo(x: Int = 2, y: Int = -40) = macro Impls.foo
+ foo(y = -40, x = 2)
+ foo(x = 2, y = -40)
+ foo(x = 100)
+ foo(y = 100)
+ foo()
+} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-implicit-macro-defeats-type-inference.check b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference.check
new file mode 100644
index 0000000000..08f7cb9e3e
--- /dev/null
+++ b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference.check
@@ -0,0 +1,6 @@
+openImplicits are: List()
+enclosingImplicits are: List((List[Int],scala.this.Predef.implicitly[List[Int]]))
+typetag is: ConcreteTypeTag[Nothing]
+openImplicits are: List()
+enclosingImplicits are: List((List[String],Test.this.bar[String]))
+typetag is: ConcreteTypeTag[Nothing]
diff --git a/test/pending/run/macro-expand-implicit-macro-defeats-type-inference.flags b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala
new file mode 100644
index 0000000000..c096a83c5e
--- /dev/null
+++ b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.Context
+
+object Impls {
+ def foo[T: c.TypeTag](c: Context): c.Expr[List[T]] = c.reify {
+ println("openImplicits are: " + c.literal(c.openImplicits.toString).eval)
+ println("enclosingImplicits are: " + c.literal(c.enclosingImplicits.toString).eval)
+ println("typetag is: " + c.literal(c.tag[T].toString).eval)
+ null
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Macros_Test_2.scala b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Macros_Test_2.scala
new file mode 100644
index 0000000000..27d0662799
--- /dev/null
+++ b/test/pending/run/macro-expand-implicit-macro-defeats-type-inference/Macros_Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ implicit def foo[T]: List[T] = macro Impls.foo[T]
+ def bar[T](implicit foo: List[T]) {}
+ implicitly[List[Int]]
+ bar[String]
+} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-implicit-macro-has-context-bound.check b/test/pending/run/macro-expand-implicit-macro-has-context-bound.check
new file mode 100644
index 0000000000..ac4213d6e9
--- /dev/null
+++ b/test/pending/run/macro-expand-implicit-macro-has-context-bound.check
@@ -0,0 +1 @@
+43 \ No newline at end of file
diff --git a/test/pending/run/macro-overload.flags b/test/pending/run/macro-expand-implicit-macro-has-context-bound.flags
index 7fea2ff901..7fea2ff901 100644
--- a/test/pending/run/macro-overload.flags
+++ b/test/pending/run/macro-expand-implicit-macro-has-context-bound.flags
diff --git a/test/pending/run/macro-expand-implicit-macro-has-context-bound/Impls_1.scala b/test/pending/run/macro-expand-implicit-macro-has-context-bound/Impls_1.scala
new file mode 100644
index 0000000000..5c50576281
--- /dev/null
+++ b/test/pending/run/macro-expand-implicit-macro-has-context-bound/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[U](c: Ctx)(x: c.Expr[U])(evidence: c.Expr[Numeric[U]]) = {
+ import c.mirror._
+ val plusOne = Apply(Select(evidence.tree, newTermName("plus")), List(x.tree, Literal(Constant(1))))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(plusOne))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/pending/run/macro-expand-implicit-macro-has-context-bound/Macros_Test_2.scala b/test/pending/run/macro-expand-implicit-macro-has-context-bound/Macros_Test_2.scala
new file mode 100644
index 0000000000..7d16b773a6
--- /dev/null
+++ b/test/pending/run/macro-expand-implicit-macro-has-context-bound/Macros_Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ def foo[U: Numeric](x: U) = macro Impls.foo[U]
+ foo(42)
+} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-named.flags b/test/pending/run/macro-expand-named.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-expand-named.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-expand-named/Impls_1.scala b/test/pending/run/macro-expand-named/Impls_1.scala
new file mode 100644
index 0000000000..fefe8fc4e2
--- /dev/null
+++ b/test/pending/run/macro-expand-named/Impls_1.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo(c: Ctx)(x: c.Expr[Int], y: c.Expr[Int]) = {
+ import c.mirror._
+ val sum = Apply(Select(x.tree, newTermName("$minus")), List(y.tree))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(sum))
+ Expr[Unit](body)
+ }
+}
diff --git a/test/pending/run/macro-expand-named/Macros_Test_2.scala b/test/pending/run/macro-expand-named/Macros_Test_2.scala
new file mode 100644
index 0000000000..abebcf8448
--- /dev/null
+++ b/test/pending/run/macro-expand-named/Macros_Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ def foo(x: Int, y: Int) = macro Impls.foo
+ foo(y = -40, x = 2)
+ foo(x = 2, y = -40)
+} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-tparams-prefix-e1.check b/test/pending/run/macro-expand-tparams-prefix-e1.check
new file mode 100644
index 0000000000..4fa05a7678
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-e1.check
@@ -0,0 +1,3 @@
+TypeTag(List[Int])
+TypeTag(String)
+TypeTag(Boolean)
diff --git a/test/pending/run/macro-expand-tparams-prefix-e1.flags b/test/pending/run/macro-expand-tparams-prefix-e1.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-e1.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-expand-tparams-prefix-e1/Impls_1.scala b/test/pending/run/macro-expand-tparams-prefix-e1/Impls_1.scala
new file mode 100644
index 0000000000..bc880fdf77
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-e1/Impls_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T, U: c.TypeTag, V](c: Ctx)(implicit T: c.TypeTag[T], V: c.TypeTag[V]): c.Expr[Unit] = {
+ import c.mirror._
+ Block(List(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(T.toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(implicitly[c.TypeTag[U]].toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(V.toString))))),
+ Literal(Constant(())))
+ }
+}
diff --git a/test/pending/run/macro-expand-tparams-prefix-e1/Macros_Test_2.scala b/test/pending/run/macro-expand-tparams-prefix-e1/Macros_Test_2.scala
new file mode 100644
index 0000000000..5c863804d0
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-e1/Macros_Test_2.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class D[T: TypeTag] {
+ class C[U: TypeTag] {
+ def foo[V] = macro Impls.foo[List[T], U, V]
+ foo[Boolean]
+ }
+ }
+
+ val outer1 = new D[Int]
+ new outer1.C[String]
+} \ No newline at end of file
diff --git a/test/pending/run/macro-expand-tparams-prefix-f1.check b/test/pending/run/macro-expand-tparams-prefix-f1.check
new file mode 100644
index 0000000000..d15226143a
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-f1.check
@@ -0,0 +1,3 @@
+TypeTag(List[T])
+TypeTag(U)
+TypeTag(Boolean)
diff --git a/test/pending/run/macro-expand-tparams-prefix-f1.flags b/test/pending/run/macro-expand-tparams-prefix-f1.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-f1.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-expand-tparams-prefix-f1/Impls_1.scala b/test/pending/run/macro-expand-tparams-prefix-f1/Impls_1.scala
new file mode 100644
index 0000000000..bc880fdf77
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-f1/Impls_1.scala
@@ -0,0 +1,12 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Impls {
+ def foo[T, U: c.TypeTag, V](c: Ctx)(implicit T: c.TypeTag[T], V: c.TypeTag[V]): c.Expr[Unit] = {
+ import c.mirror._
+ Block(List(
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(T.toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(implicitly[c.TypeTag[U]].toString)))),
+ Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Literal(Constant(V.toString))))),
+ Literal(Constant(())))
+ }
+}
diff --git a/test/pending/run/macro-expand-tparams-prefix-f1/Macros_Test_2.scala b/test/pending/run/macro-expand-tparams-prefix-f1/Macros_Test_2.scala
new file mode 100644
index 0000000000..bc8e7ac75c
--- /dev/null
+++ b/test/pending/run/macro-expand-tparams-prefix-f1/Macros_Test_2.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class D[T] {
+ class C[U] {
+ def foo[V] = macro Impls.foo[List[T], U, V]
+ foo[Boolean]
+ }
+ }
+
+ val outer1 = new D[Int]
+ new outer1.C[String]
+} \ No newline at end of file
diff --git a/test/pending/run/macro-overload.check b/test/pending/run/macro-overload.check
deleted file mode 100644
index 764f914e48..0000000000
--- a/test/pending/run/macro-overload.check
+++ /dev/null
@@ -1,4 +0,0 @@
-object-Int
-object-String
-class-Int
-class-String \ No newline at end of file
diff --git a/test/pending/run/macro-overload/Macros_1.scala b/test/pending/run/macro-overload/Macros_1.scala
deleted file mode 100644
index f24c69ea7b..0000000000
--- a/test/pending/run/macro-overload/Macros_1.scala
+++ /dev/null
@@ -1,9 +0,0 @@
-object Macros {
- def macro bar(x: Int): Int = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("object-Int"))))
- def macro bar(x: String): String = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("object-String"))))
-}
-
-class Macros {
- def macro bar(x: Int): Int = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("class-Int"))))
- def macro bar(x: String): String = Apply(Select(Select(Ident("scala"), newTermName("Predef")), newTermName("println")), List(Literal(Constant("class-String"))))
-} \ No newline at end of file
diff --git a/test/pending/run/macro-overload/Test_2.scala b/test/pending/run/macro-overload/Test_2.scala
deleted file mode 100644
index 75f6572e03..0000000000
--- a/test/pending/run/macro-overload/Test_2.scala
+++ /dev/null
@@ -1,6 +0,0 @@
-object Test extends App {
- Macros.bar(2)
- Macros.bar("2")
- new Macros.bar(2)
- new Macros.bar("2")
-} \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-a.check b/test/pending/run/macro-quasiinvalidbody-a.check
new file mode 100644
index 0000000000..f70d7bba4a
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-a.check
@@ -0,0 +1 @@
+42 \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-a.flags b/test/pending/run/macro-quasiinvalidbody-a.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-a.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-a/Impls_1.scala b/test/pending/run/macro-quasiinvalidbody-a/Impls_1.scala
new file mode 100644
index 0000000000..0da37cd5c0
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-a/Impls_1.scala
@@ -0,0 +1,5 @@
+import scala.reflect.makro.{Context => Ctx}
+
+trait Impls {
+ def impl(c: Ctx)(x: c.Expr[Any]) = x
+} \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-a/Macros_Test_2.scala b/test/pending/run/macro-quasiinvalidbody-a/Macros_Test_2.scala
new file mode 100644
index 0000000000..04a43080bd
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-a/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros extends Impls {
+ def foo(x: Any) = macro impl
+}
+
+object Test extends App {
+ import Macros._
+ println(foo(42))
+} \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-b.check b/test/pending/run/macro-quasiinvalidbody-b.check
new file mode 100644
index 0000000000..f70d7bba4a
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-b.check
@@ -0,0 +1 @@
+42 \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-b.flags b/test/pending/run/macro-quasiinvalidbody-b.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-b.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-b/Impls_1.scala b/test/pending/run/macro-quasiinvalidbody-b/Impls_1.scala
new file mode 100644
index 0000000000..d84d04974f
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-b/Impls_1.scala
@@ -0,0 +1,7 @@
+import scala.reflect.makro.{Context => Ctx}
+
+trait ImplContainer {
+ object Impls {
+ def foo(c: Ctx)(x: c.Expr[Any]) = x
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/macro-quasiinvalidbody-b/Macros_Test_2.scala b/test/pending/run/macro-quasiinvalidbody-b/Macros_Test_2.scala
new file mode 100644
index 0000000000..82f88b62e4
--- /dev/null
+++ b/test/pending/run/macro-quasiinvalidbody-b/Macros_Test_2.scala
@@ -0,0 +1,10 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros extends ImplContainer {
+ def foo(x: Any) = macro Impls.foo
+}
+
+object Test extends App {
+ import Macros._
+ println(foo(42))
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-array.flags b/test/pending/run/macro-reify-array.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-reify-array.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-reify-array/Macros_1.scala b/test/pending/run/macro-reify-array/Macros_1.scala
new file mode 100644
index 0000000000..af42321484
--- /dev/null
+++ b/test/pending/run/macro-reify-array/Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo[T](s: String) = macro Impls.foo[T]
+
+ object Impls {
+ def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.reify {
+ Array(s.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-array/Test_2.scala b/test/pending/run/macro-reify-array/Test_2.scala
new file mode 100644
index 0000000000..e40d5b40e0
--- /dev/null
+++ b/test/pending/run/macro-reify-array/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ val arr = Macros.foo("hello", "world")
+ println(arr.getClass)
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-eval-vs-value.flags b/test/pending/run/macro-reify-eval-vs-value.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-reify-eval-vs-value.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-reify-eval-vs-value/Macros_1.scala b/test/pending/run/macro-reify-eval-vs-value/Macros_1.scala
new file mode 100644
index 0000000000..98dd93b0f8
--- /dev/null
+++ b/test/pending/run/macro-reify-eval-vs-value/Macros_1.scala
@@ -0,0 +1,25 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def fooEval(s: String) = macro Impls.fooEval
+ def fooValue(s: String) = macro Impls.fooValue
+
+ object Impls {
+ def fooEval(c: Ctx)(s: c.Expr[String]) = c.reify {
+ println("hello " + s.eval)
+ println("hello " + s.eval)
+ }
+
+ def fooValue(c: Ctx)(s: c.Expr[String]) = c.reify {
+ {
+ println("hello " + s.value)
+ def sayHello = println(s.value)
+ sayHello
+ }
+ println("hello " + s.eval);
+ {
+ println("hello " + s.eval)
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-eval-vs-value/Test_2.scala b/test/pending/run/macro-reify-eval-vs-value/Test_2.scala
new file mode 100644
index 0000000000..8e62e6e0e7
--- /dev/null
+++ b/test/pending/run/macro-reify-eval-vs-value/Test_2.scala
@@ -0,0 +1,5 @@
+object Test extends App {
+ Macros.fooEval({ println("in ur logz"); "world"})
+ println("======================")
+ Macros.fooValue({ println("i can has cheezburger?"); "world"})
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-groundtypetag-hktypeparams-tags.check b/test/pending/run/macro-reify-groundtypetag-hktypeparams-tags.check
new file mode 100644
index 0000000000..7e4b000c52
--- /dev/null
+++ b/test/pending/run/macro-reify-groundtypetag-hktypeparams-tags.check
@@ -0,0 +1,2 @@
+TypeTag(List[Int])
+TypeTag(List[List[Int]])
diff --git a/test/pending/run/macro-reify-groundtypetag-hktypeparams-tags/Test.scala b/test/pending/run/macro-reify-groundtypetag-hktypeparams-tags/Test.scala
new file mode 100644
index 0000000000..ef70a66f1a
--- /dev/null
+++ b/test/pending/run/macro-reify-groundtypetag-hktypeparams-tags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooTypeTagHK[C[_]: ConcreteTypeTag, T: ConcreteTypeTag] = {
+ println(implicitly[ConcreteTypeTag[C[T]]])
+ println(implicitly[ConcreteTypeTag[List[C[T]]]])
+ }
+ fooTypeTagHK[List, Int]
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-tagful-b.check b/test/pending/run/macro-reify-tagful-b.check
new file mode 100644
index 0000000000..5bd9fe2156
--- /dev/null
+++ b/test/pending/run/macro-reify-tagful-b.check
@@ -0,0 +1 @@
+List(List(hello world))
diff --git a/test/pending/run/macro-reify-tagful-b.flags b/test/pending/run/macro-reify-tagful-b.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-reify-tagful-b.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-reify-tagful-b/Macros_1.scala b/test/pending/run/macro-reify-tagful-b/Macros_1.scala
new file mode 100644
index 0000000000..38b839330b
--- /dev/null
+++ b/test/pending/run/macro-reify-tagful-b/Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo[T](s: T) = macro Impls.foo[List[T]]
+
+ object Impls {
+ def foo[T: c.TypeTag](c: Ctx)(s: c.Expr[T]) = c.reify {
+ List(s.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-tagful-b/Test_2.scala b/test/pending/run/macro-reify-tagful-b/Test_2.scala
new file mode 100644
index 0000000000..142234901f
--- /dev/null
+++ b/test/pending/run/macro-reify-tagful-b/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ val list: List[List[String]] = Macros.foo(List("hello world"))
+ println(list)
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-tagless-b.check b/test/pending/run/macro-reify-tagless-b.check
new file mode 100644
index 0000000000..49acd94ad6
--- /dev/null
+++ b/test/pending/run/macro-reify-tagless-b.check
@@ -0,0 +1,3 @@
+error: macro must not return an expr that contains free type variables (namely: T). have you forgot to use c.TypeTag annotations for type parameters external to a reifee?
+
+java.lang.Error: reflective compilation has failed
diff --git a/test/pending/run/macro-reify-tagless-b.flags b/test/pending/run/macro-reify-tagless-b.flags
new file mode 100644
index 0000000000..7fea2ff901
--- /dev/null
+++ b/test/pending/run/macro-reify-tagless-b.flags
@@ -0,0 +1 @@
+-Xmacros \ No newline at end of file
diff --git a/test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala b/test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala
new file mode 100644
index 0000000000..fac7ba5b98
--- /dev/null
+++ b/test/pending/run/macro-reify-tagless-b/Impls_Macros_1.scala
@@ -0,0 +1,11 @@
+import scala.reflect.makro.{Context => Ctx}
+
+object Macros {
+ def foo[T](s: T) = macro Impls.foo[List[T]]
+
+ object Impls {
+ def foo[T](c: Ctx)(s: c.Expr[T]) = c.reify {
+ List(s.eval)
+ }
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-tagless-b/Test_2.scala b/test/pending/run/macro-reify-tagless-b/Test_2.scala
new file mode 100644
index 0000000000..419ee42101
--- /dev/null
+++ b/test/pending/run/macro-reify-tagless-b/Test_2.scala
@@ -0,0 +1,11 @@
+object Test extends App {
+ //val list: List[String] = Macros.foo("hello world")
+ //println(list)
+
+ import scala.reflect.mirror._
+ val tpt = AppliedTypeTree(Ident(definitions.ListClass), List(Ident(definitions.StringClass)))
+ val rhs = Apply(Select(Ident("Macros"), newTermName("foo")), List(Literal(Constant("hello world"))))
+ val list = ValDef(NoMods, newTermName("list"), tpt, rhs)
+ val tree = Block(list, Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(Ident(list.name))))
+ println(tree.eval)
+}
diff --git a/test/pending/run/macro-reify-typetag-hktypeparams-notags.check b/test/pending/run/macro-reify-typetag-hktypeparams-notags.check
new file mode 100644
index 0000000000..db8a19d5f7
--- /dev/null
+++ b/test/pending/run/macro-reify-typetag-hktypeparams-notags.check
@@ -0,0 +1,2 @@
+TypeTag(C[T])
+TypeTag(List[C[T]])
diff --git a/test/pending/run/macro-reify-typetag-hktypeparams-notags/Test.scala b/test/pending/run/macro-reify-typetag-hktypeparams-notags/Test.scala
new file mode 100644
index 0000000000..9a370189a7
--- /dev/null
+++ b/test/pending/run/macro-reify-typetag-hktypeparams-notags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooNoTypeTagHK[C[_], T] = {
+ println(implicitly[TypeTag[C[T]]])
+ println(implicitly[TypeTag[List[C[T]]]])
+ }
+ fooNoTypeTagHK[List, Int]
+} \ No newline at end of file
diff --git a/test/pending/run/macro-reify-typetag-hktypeparams-tags.check b/test/pending/run/macro-reify-typetag-hktypeparams-tags.check
new file mode 100644
index 0000000000..7e4b000c52
--- /dev/null
+++ b/test/pending/run/macro-reify-typetag-hktypeparams-tags.check
@@ -0,0 +1,2 @@
+TypeTag(List[Int])
+TypeTag(List[List[Int]])
diff --git a/test/pending/run/macro-reify-typetag-hktypeparams-tags/Test.scala b/test/pending/run/macro-reify-typetag-hktypeparams-tags/Test.scala
new file mode 100644
index 0000000000..0358da9b0d
--- /dev/null
+++ b/test/pending/run/macro-reify-typetag-hktypeparams-tags/Test.scala
@@ -0,0 +1,9 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ def fooTypeTagHK[C[_]: TypeTag, T: TypeTag] = {
+ println(implicitly[TypeTag[C[T]]])
+ println(implicitly[TypeTag[List[C[T]]]])
+ }
+ fooTypeTagHK[List, Int]
+} \ No newline at end of file
diff --git a/test/pending/run/reify_addressbook.scala b/test/pending/run/reify_addressbook.scala
index 54dd5545bd..7cb6dc08fd 100644
--- a/test/pending/run/reify_addressbook.scala
+++ b/test/pending/run/reify_addressbook.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
case class Person(name: String, age: Int)
/** An AddressBook takes a variable number of arguments
@@ -62,9 +60,5 @@ object Test extends App {
</html>;
println(page)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/pending/run/reify_brainf_ck.scala b/test/pending/run/reify_brainf_ck.scala
index 0034644b81..e4bcb257bd 100644
--- a/test/pending/run/reify_brainf_ck.scala
+++ b/test/pending/run/reify_brainf_ck.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
import scala.annotation._
trait Func[T] {
@@ -76,9 +74,5 @@ object Test extends App {
<.#>+++++++++++[<+++++>-]<.>++++++++[<++
+>-]<.+++.------.--------.[-]>++++++++[<++++>
-]<+.[-]++++++++++.""")
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/pending/run/reify_callccinterpreter.scala b/test/pending/run/reify_callccinterpreter.scala
index 96ae9c5c17..0e23f75dcc 100644
--- a/test/pending/run/reify_callccinterpreter.scala
+++ b/test/pending/run/reify_callccinterpreter.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
type Answer = Value;
/**
@@ -85,9 +83,5 @@ object Test extends App {
println(test(term0))
println(test(term1))
println(test(term2))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/pending/run/reify_classfileann_b.scala b/test/pending/run/reify_classfileann_b.scala
deleted file mode 100644
index c31826377a..0000000000
--- a/test/pending/run/reify_classfileann_b.scala
+++ /dev/null
@@ -1,24 +0,0 @@
-import scala.reflect._
-import scala.reflect.api._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
-class ann(bar: String, quux: Array[String] = Array(), baz: ann = null) extends ClassfileAnnotation
-
-object Test extends App {
- // test 1: reify
- val tree = scala.reflect.Code.lift{
- class C {
- def x: Int = {
- 2: @ann(bar="1", quux=Array("2", "3"), baz = new ann(bar = "4"))
- }
- }
- }.tree
- println(tree.toString)
-
- // test 2: import and compile
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(tree)
-} \ No newline at end of file
diff --git a/test/pending/run/reify_closure2b.scala b/test/pending/run/reify_closure2b.scala
index b9c0063290..f9ed16d309 100644
--- a/test/pending/run/reify_closure2b.scala
+++ b/test/pending/run/reify_closure2b.scala
@@ -1,17 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
object Test extends App {
def foo(y: Int): Int => Int = {
class Foo(y: Int) {
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reflect.mirror.reify{(x: Int) => {
x + y
}}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(new Foo(y).fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/pending/run/reify_closure3b.scala b/test/pending/run/reify_closure3b.scala
index 8f161dbff3..8ef0a60c66 100644
--- a/test/pending/run/reify_closure3b.scala
+++ b/test/pending/run/reify_closure3b.scala
@@ -1,19 +1,14 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
object Test extends App {
def foo(y: Int): Int => Int = {
class Foo(y: Int) {
def y1 = y
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reflect.mirror.reify{(x: Int) => {
x + y1
}}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(new Foo(y).fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/pending/run/reify_closure4b.scala b/test/pending/run/reify_closure4b.scala
index 238795d4dd..9eeb01b459 100644
--- a/test/pending/run/reify_closure4b.scala
+++ b/test/pending/run/reify_closure4b.scala
@@ -1,19 +1,14 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
object Test extends App {
def foo(y: Int): Int => Int = {
class Foo(y: Int) {
val y1 = y
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reflect.mirror.reify{(x: Int) => {
x + y1
}}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(new Foo(y).fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/pending/run/reify_closure5b.scala b/test/pending/run/reify_closure5b.scala
index bdb2583e8a..51f1ec318d 100644
--- a/test/pending/run/reify_closure5b.scala
+++ b/test/pending/run/reify_closure5b.scala
@@ -1,17 +1,12 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
object Test extends App {
def foo[T](ys: List[T]): Int => Int = {
class Foo[T](ys: List[T]) {
- val fun = reflect.Code.lift{(x: Int) => {
+ val fun = reflect.mirror.reify{(x: Int) => {
x + ys.length
}}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(new Foo(ys).fun.tree)
dyn.asInstanceOf[Int => Int]
}
diff --git a/test/pending/run/reify_closure8b.check b/test/pending/run/reify_closure8b.check
deleted file mode 100644
index 9a037142aa..0000000000
--- a/test/pending/run/reify_closure8b.check
+++ /dev/null
@@ -1 +0,0 @@
-10 \ No newline at end of file
diff --git a/test/pending/run/reify_closure8b.scala b/test/pending/run/reify_closure8b.scala
deleted file mode 100644
index 38031c217b..0000000000
--- a/test/pending/run/reify_closure8b.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-import scala.reflect.Code._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
-object Test extends App {
- class Foo(y: Int) {
- def fun = lift{y}
- }
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- val dyn = toolbox.runExpr(new Foo(10).fun.tree)
- val foo = dyn.asInstanceOf[Int]
- println(foo)
-}
diff --git a/test/pending/run/reify_closure9a.scala b/test/pending/run/reify_closure9a.scala
index 185f4ffca1..1fc18cfa13 100644
--- a/test/pending/run/reify_closure9a.scala
+++ b/test/pending/run/reify_closure9a.scala
@@ -1,16 +1,11 @@
-import scala.reflect.Code._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
+import scala.reflect.mirror._
object Test extends App {
def foo(y: Int) = {
class Foo(val y: Int) {
- def fun = lift{y}
+ def fun = reify{y}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(new Foo(y).fun.tree)
dyn.asInstanceOf[Int]
}
diff --git a/test/pending/run/reify_closure9b.scala b/test/pending/run/reify_closure9b.scala
index ad279fac6d..32b05d00ee 100644
--- a/test/pending/run/reify_closure9b.scala
+++ b/test/pending/run/reify_closure9b.scala
@@ -1,16 +1,11 @@
-import scala.reflect.Code._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
+import scala.reflect.mirror._
object Test extends App {
def foo(y: Int) = {
class Foo(y: Int) {
- def fun = lift{y}
+ def fun = reify{y}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(new Foo(y).fun.tree)
dyn.asInstanceOf[Int]
}
diff --git a/test/pending/run/reify_closures11.scala b/test/pending/run/reify_closures11.scala
index 2c4177b8f2..ceb224c6d6 100644
--- a/test/pending/run/reify_closures11.scala
+++ b/test/pending/run/reify_closures11.scala
@@ -1,16 +1,11 @@
-import scala.reflect.Code._
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
+import scala.reflect.mirror._
object Test extends App {
def fun() = {
def z() = 2
- lift{z}
+ reify{z}
}
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
+ val toolbox = mkToolBox()
val dyn = toolbox.runExpr(fun().tree)
val foo = dyn.asInstanceOf[Int]
println(foo)
diff --git a/test/pending/run/reify_gadts.scala b/test/pending/run/reify_gadts.scala
index 9feb7a5726..652a7d99d8 100644
--- a/test/pending/run/reify_gadts.scala
+++ b/test/pending/run/reify_gadts.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
/* The syntax tree of a toy language */
abstract class Term[T]
@@ -36,9 +34,5 @@ object Test extends App {
}
println(
eval(If(IsZero(Lit(1)), Lit(41), Succ(Lit(41)))))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/pending/run/reify_newimpl_07.scala b/test/pending/run/reify_newimpl_07.scala
new file mode 100644
index 0000000000..13ca6bda8b
--- /dev/null
+++ b/test/pending/run/reify_newimpl_07.scala
@@ -0,0 +1,13 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ {
+ class C(val y: Int) {
+ val code = reify {
+ reify{y}.eval
+ }
+ }
+
+ println(new C(2).code.eval)
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/reify_newimpl_08.scala b/test/pending/run/reify_newimpl_08.scala
new file mode 100644
index 0000000000..e2faa3c9af
--- /dev/null
+++ b/test/pending/run/reify_newimpl_08.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ val code = reify {
+ class C(val y: Int) {
+ val code = reify {
+ reify{y}.eval
+ }
+ }
+
+ new C(2).code.eval
+ }
+
+ println(code.eval)
+} \ No newline at end of file
diff --git a/test/pending/run/reify_newimpl_35.scala b/test/pending/run/reify_newimpl_35.scala
new file mode 100644
index 0000000000..5e1d163e9e
--- /dev/null
+++ b/test/pending/run/reify_newimpl_35.scala
@@ -0,0 +1,10 @@
+import scala.tools.partest.ReplTest
+
+object Test extends ReplTest {
+ override def extraSettings = "-Xlog-free-types"
+ def code = """
+import scala.reflect.mirror._
+def foo[T: TypeTag] = reify{List[T]()}
+println(foo)
+ """
+}
diff --git a/test/pending/run/reify_newimpl_46.scala b/test/pending/run/reify_newimpl_46.scala
new file mode 100644
index 0000000000..840d695e83
--- /dev/null
+++ b/test/pending/run/reify_newimpl_46.scala
@@ -0,0 +1,12 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C[T[_] >: Null] {
+ val code = reify{val x: T[String] = null; println("ima worx"); x}
+ println(freeTypes(code))
+ val T = freeTypes(code)(0)
+ mkToolBox().runExpr(code, Map(T -> definitions.ListClass.asType))
+ }
+
+ new C[List]
+} \ No newline at end of file
diff --git a/test/pending/run/reify_newimpl_53.scala b/test/pending/run/reify_newimpl_53.scala
new file mode 100644
index 0000000000..26645dea6a
--- /dev/null
+++ b/test/pending/run/reify_newimpl_53.scala
@@ -0,0 +1,15 @@
+import scala.reflect.mirror._
+
+object Test extends App {
+ class C[T >: Null] {
+ val code = reify{
+ val tt = implicitly[TypeTag[T]]
+ println("mah typetag is: %s".format(tt))
+ }
+ println(freeTypes(code))
+ val T = freeTypes(code)(0)
+ mkToolBox().runExpr(code, Map(T -> definitions.StringClass.asType))
+ }
+
+ new C[String]
+} \ No newline at end of file
diff --git a/test/pending/run/reify_simpleinterpreter.scala b/test/pending/run/reify_simpleinterpreter.scala
index 4762afb3cc..2193edeea7 100644
--- a/test/pending/run/reify_simpleinterpreter.scala
+++ b/test/pending/run/reify_simpleinterpreter.scala
@@ -1,9 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
case class M[A](value: A) {
def bind[B](k: A => M[B]): M[B] = k(value)
def map[B](f: A => B): M[B] = bind(x => unitM(f(x)))
@@ -73,9 +71,5 @@ object Test extends App {
println(test(term0))
println(test(term1))
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
}
diff --git a/test/pending/run/t4560.scala b/test/pending/run/t4560.scala
new file mode 100644
index 0000000000..fe62136319
--- /dev/null
+++ b/test/pending/run/t4560.scala
@@ -0,0 +1,9 @@
+trait B {
+ this: Test.type =>
+
+ def y = new { def f() = () }
+ def fail() = y.f()
+}
+object Test extends B {
+ def main(args: Array[String]): Unit = fail()
+} \ No newline at end of file
diff --git a/test/pending/run/t4728.check b/test/pending/run/t4728.check
new file mode 100644
index 0000000000..7a754f414c
--- /dev/null
+++ b/test/pending/run/t4728.check
@@ -0,0 +1,2 @@
+1
+2 \ No newline at end of file
diff --git a/test/pending/run/t4728.scala b/test/pending/run/t4728.scala
new file mode 100644
index 0000000000..36f7860613
--- /dev/null
+++ b/test/pending/run/t4728.scala
@@ -0,0 +1,11 @@
+class X
+class Y extends X
+object Ambiguous {
+ def f(x: X) = 1
+ def f(ys: Y*) = 2
+}
+
+object Test extends App {
+ println(Ambiguous.f(new X))
+ println(Ambiguous.f(new Y))
+} \ No newline at end of file
diff --git a/test/pending/run/t5258b.scala b/test/pending/run/t5258b.scala
index 3a603095b3..82555cde96 100644
--- a/test/pending/run/t5258b.scala
+++ b/test/pending/run/t5258b.scala
@@ -1,14 +1,8 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
class C
println(classOf[C])
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
} \ No newline at end of file
diff --git a/test/pending/run/t5258c.scala b/test/pending/run/t5258c.scala
index b0d16ba0b1..a0a1647486 100644
--- a/test/pending/run/t5258c.scala
+++ b/test/pending/run/t5258c.scala
@@ -1,14 +1,8 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
object E extends Enumeration { val foo, bar = Value }
println(E.foo)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
} \ No newline at end of file
diff --git a/test/pending/run/t5271_1.scala b/test/pending/run/t5271_1.scala
deleted file mode 100644
index afbd8fe465..0000000000
--- a/test/pending/run/t5271_1.scala
+++ /dev/null
@@ -1,13 +0,0 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
-object Test extends App {
- val code = scala.reflect.Code.lift{
- case class C(foo: Int, bar: Int)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
-}
diff --git a/test/pending/run/t5271_2.check b/test/pending/run/t5271_2.check
deleted file mode 100644
index b8626c4cff..0000000000
--- a/test/pending/run/t5271_2.check
+++ /dev/null
@@ -1 +0,0 @@
-4
diff --git a/test/pending/run/t5271_2.scala b/test/pending/run/t5271_2.scala
deleted file mode 100644
index d85d945973..0000000000
--- a/test/pending/run/t5271_2.scala
+++ /dev/null
@@ -1,15 +0,0 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
-object Test extends App {
- val code = scala.reflect.Code.lift{
- case class C(foo: Int, bar: Int)
- val c = C(2, 2)
- println(c.foo * c.bar)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
-}
diff --git a/test/pending/run/t5271_3.check b/test/pending/run/t5271_3.check
deleted file mode 100644
index f32a5804e2..0000000000
--- a/test/pending/run/t5271_3.check
+++ /dev/null
@@ -1 +0,0 @@
-true \ No newline at end of file
diff --git a/test/pending/run/t5271_3.scala b/test/pending/run/t5271_3.scala
deleted file mode 100644
index 5a624de903..0000000000
--- a/test/pending/run/t5271_3.scala
+++ /dev/null
@@ -1,16 +0,0 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
-
-object Test extends App {
- val code = scala.reflect.Code.lift{
- object C { def qwe = 4 }
- case class C(foo: Int, bar: Int)
- val c = C(2, 2)
- println(c.foo * c.bar == C.qwe)
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
-}
diff --git a/test/pending/run/t5418.scala b/test/pending/run/t5418.scala
index fe813cf5ae..9b0a954e47 100644
--- a/test/pending/run/t5418.scala
+++ b/test/pending/run/t5418.scala
@@ -1,13 +1,7 @@
-import scala.tools.nsc.reporters._
-import scala.tools.nsc.Settings
-import reflect.runtime.Mirror.ToolBox
+import scala.reflect.mirror._
object Test extends App {
- val code = scala.reflect.Code.lift{
+ reify {
new Object().getClass
- };
-
- val reporter = new ConsoleReporter(new Settings)
- val toolbox = new ToolBox(reporter)
- toolbox.runExpr(code.tree)
+ }.eval
} \ No newline at end of file
diff --git a/test/pending/run/t5610a.check b/test/pending/run/t5610a.check
new file mode 100644
index 0000000000..2aa46b3b91
--- /dev/null
+++ b/test/pending/run/t5610a.check
@@ -0,0 +1 @@
+Stroke a kitten
diff --git a/test/pending/run/t5610a.scala b/test/pending/run/t5610a.scala
new file mode 100644
index 0000000000..f20b295762
--- /dev/null
+++ b/test/pending/run/t5610a.scala
@@ -0,0 +1,19 @@
+object Test extends App {
+ class Result(_str: => String) {
+ lazy val str = _str
+ }
+
+ def foo(str: => String)(i: Int) = new Result(str)
+
+ def bar(f: Int => Result) = f(42)
+
+ var test: String = null
+ val result = bar(foo(test))
+ test = "bar"
+
+ if (result.str == null) {
+ println("Destroy ALL THE THINGS!!!")
+ } else {
+ println("Stroke a kitten")
+ }
+} \ No newline at end of file
diff --git a/test/pending/run/t5610b.check b/test/pending/run/t5610b.check
new file mode 100644
index 0000000000..2aa46b3b91
--- /dev/null
+++ b/test/pending/run/t5610b.check
@@ -0,0 +1 @@
+Stroke a kitten
diff --git a/test/pending/run/t5610b.scala b/test/pending/run/t5610b.scala
new file mode 100644
index 0000000000..d922d6333c
--- /dev/null
+++ b/test/pending/run/t5610b.scala
@@ -0,0 +1,21 @@
+object Bug {
+ def main(args: Array[String]) {
+ var test: String = null
+ val result = bar(foo(test))
+ test = "bar"
+
+ if (result.str == null) {
+ println("Destroy ALL THE THINGS!!!")
+ } else {
+ println("Stroke a kitten")
+ }
+ }
+
+ class Result(_str: => String) {
+ lazy val str = _str
+ }
+
+ def foo(str: => String)(i: Int) = new Result(str)
+
+ def bar(f: Int => Result) = f(42)
+} \ No newline at end of file
diff --git a/test/pending/run/t5676.flags b/test/pending/run/t5676.flags
new file mode 100644
index 0000000000..e1b37447c9
--- /dev/null
+++ b/test/pending/run/t5676.flags
@@ -0,0 +1 @@
+-Xexperimental \ No newline at end of file
diff --git a/test/pending/run/t5676.scala b/test/pending/run/t5676.scala
new file mode 100644
index 0000000000..3ff498eaa2
--- /dev/null
+++ b/test/pending/run/t5676.scala
@@ -0,0 +1,25 @@
+
+
+
+
+class Bar[T]
+
+
+class Foo[T] {
+ object A extends Bar[T]
+}
+
+
+class Baz[S] extends Foo[S] {
+ override object A extends Bar[S]
+}
+
+
+object Test {
+
+ def main(a: Array[String]) {
+ val b = new Baz[Any]
+ println(b)
+ }
+
+}
diff --git a/test/pending/run/t5692.flags b/test/pending/run/t5692.flags
new file mode 100644
index 0000000000..cd66464f2f
--- /dev/null
+++ b/test/pending/run/t5692.flags
@@ -0,0 +1 @@
+-language:experimental.macros \ No newline at end of file
diff --git a/test/pending/run/t5692/Impls_Macros_1.scala b/test/pending/run/t5692/Impls_Macros_1.scala
new file mode 100644
index 0000000000..f9c1e5f12b
--- /dev/null
+++ b/test/pending/run/t5692/Impls_Macros_1.scala
@@ -0,0 +1,9 @@
+import scala.reflect.makro.Context
+
+object Impls {
+ def impl[A](c: reflect.makro.Context) = c.reify(())
+}
+
+object Macros {
+ def decl[A] = macro Impls.impl[A]
+} \ No newline at end of file
diff --git a/test/pending/run/t5692/Test_2.scala b/test/pending/run/t5692/Test_2.scala
new file mode 100644
index 0000000000..29251a5ef5
--- /dev/null
+++ b/test/pending/run/t5692/Test_2.scala
@@ -0,0 +1,4 @@
+object Test extends App {
+ val x = Macros.decl
+ def y() { Macros.decl(); }
+} \ No newline at end of file
diff --git a/test/pending/run/t5695.check b/test/pending/run/t5695.check
new file mode 100644
index 0000000000..d50069ab4f
--- /dev/null
+++ b/test/pending/run/t5695.check
@@ -0,0 +1,2 @@
+..
+..
diff --git a/test/pending/run/t5695/part_1.scala b/test/pending/run/t5695/part_1.scala
new file mode 100644
index 0000000000..b8e8f8e52f
--- /dev/null
+++ b/test/pending/run/t5695/part_1.scala
@@ -0,0 +1,12 @@
+import language.experimental.macros
+import scala.reflect.makro.Context
+
+object Defs {
+
+ def mkInt = macro mkIntImpl
+ def mkIntImpl(c: Context): c.Expr[Any] = {
+ println(c.enclosingApplication)
+ c.reify{ 23 }
+ }
+
+}
diff --git a/test/pending/run/t5695/part_2.scala b/test/pending/run/t5695/part_2.scala
new file mode 100644
index 0000000000..d34219437d
--- /dev/null
+++ b/test/pending/run/t5695/part_2.scala
@@ -0,0 +1,8 @@
+import Defs._
+
+object Test extends App {
+
+ val i1 = mkInt
+ val i2 = identity(mkInt)
+
+}
diff --git a/test/pending/run/t5698/client.scala b/test/pending/run/t5698/client.scala
new file mode 100644
index 0000000000..de672c1809
--- /dev/null
+++ b/test/pending/run/t5698/client.scala
@@ -0,0 +1,9 @@
+package client
+
+
+
+object Client extends App {
+ val peer = actors.remote.Node("localhost", 23456)
+ val a = actors.remote.RemoteActor.select(peer, 'test)
+ a ! server.TestMsg
+}
diff --git a/test/pending/run/t5698/server.scala b/test/pending/run/t5698/server.scala
new file mode 100644
index 0000000000..e8f3cea225
--- /dev/null
+++ b/test/pending/run/t5698/server.scala
@@ -0,0 +1,22 @@
+package server
+
+
+
+object Server extends App {
+
+ class ServerActor extends actors.Actor {
+ def act() {
+ actors.remote.RemoteActor.alive(23456)
+ actors.remote.RemoteActor.register('test, actors.Actor.self)
+ loop {
+ react {
+ case TestMsg => println("Yay!")
+ }
+ }
+ }
+ }
+
+ val a = new ServerActor
+ a.start()
+
+}
diff --git a/test/pending/run/t5698/testmsg.scala b/test/pending/run/t5698/testmsg.scala
new file mode 100644
index 0000000000..004ff0b8c7
--- /dev/null
+++ b/test/pending/run/t5698/testmsg.scala
@@ -0,0 +1,5 @@
+package server
+
+
+
+case object TestMsg
diff --git a/test/pending/run/t5722.scala b/test/pending/run/t5722.scala
new file mode 100644
index 0000000000..21ace060d6
--- /dev/null
+++ b/test/pending/run/t5722.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ def foo[T: ClassTag] = println(classOf[T])
+ foo[Int]
+ foo[Array[Int]]
+ foo[List[Int]]
+} \ No newline at end of file
diff --git a/test/pending/run/t5726a.scala b/test/pending/run/t5726a.scala
new file mode 100644
index 0000000000..24d828a159
--- /dev/null
+++ b/test/pending/run/t5726a.scala
@@ -0,0 +1,17 @@
+import language.dynamics
+
+class DynamicTest extends Dynamic {
+ def selectDynamic(name: String) = s"value of $name"
+ def updateDynamic(name: String)(value: Any) {
+ println(s"You have just updated property '$name' with value: $value")
+ }
+}
+
+object MyApp extends App {
+ def testing() {
+ val test = new DynamicTest
+ test.firstName = "John"
+ }
+
+ testing()
+} \ No newline at end of file
diff --git a/test/pending/run/t5726b.scala b/test/pending/run/t5726b.scala
new file mode 100644
index 0000000000..839dcf40b5
--- /dev/null
+++ b/test/pending/run/t5726b.scala
@@ -0,0 +1,16 @@
+import language.dynamics
+
+class DynamicTest extends Dynamic {
+ def updateDynamic(name: String)(value: Any) {
+ println(s"You have just updated property '$name' with value: $value")
+ }
+}
+
+object MyApp extends App {
+ def testing() {
+ val test = new DynamicTest
+ test.firstName = "John"
+ }
+
+ testing()
+} \ No newline at end of file
diff --git a/test/pending/shootout/meteor.scala b/test/pending/shootout/meteor.scala
index 2fd702753a..154695533b 100644
--- a/test/pending/shootout/meteor.scala
+++ b/test/pending/shootout/meteor.scala
@@ -19,7 +19,7 @@ object meteor {
-// Solver.scala
+// Solver.scala
// import scala.collection.mutable._
final class Solver (n: Int) {
@@ -29,8 +29,8 @@ final class Solver (n: Int) {
private val board = new Board()
- val pieces = Array(
- new Piece(0), new Piece(1), new Piece(2), new Piece(3), new Piece(4),
+ val pieces = Array(
+ new Piece(0), new Piece(1), new Piece(2), new Piece(3), new Piece(4),
new Piece(5), new Piece(6), new Piece(7), new Piece(8), new Piece(9) )
val unplaced = new BitSet(pieces.length)
@@ -71,8 +71,8 @@ final class Solver (n: Int) {
private def puzzleSolved() = {
val b = board.asString
- if (first == null){
- first = b; last = b
+ if (first == null){
+ first = b; last = b
} else {
if (b < first){ first = b } else { if (b > last){ last = b } }
}
@@ -81,7 +81,7 @@ final class Solver (n: Int) {
private def shouldPrune() = {
board.unmark
- !board.cells.forall(c => c.contiguousEmptyCells % Piece.size == 0)
+ !board.cells.forall(c => c.contiguousEmptyCells % Piece.size == 0)
}
@@ -108,8 +108,8 @@ final class Solver (n: Int) {
}
/*
- def printPieces() =
- for (i <- Iterator.range(0,Board.pieces)) pieces(i).print
+ def printPieces() =
+ for (i <- Iterator.range(0,Board.pieces)) pieces(i).print
*/
}
@@ -126,7 +126,7 @@ object Board {
val size = rows * cols
}
-final class Board {
+final class Board {
val cells = boardCells()
val cellsPieceWillFill = new Array[BoardCell](Piece.size)
@@ -134,9 +134,9 @@ final class Board {
def unmark() = for (c <- cells) c.unmark
- def asString() =
- new String( cells map(
- c => if (c.piece == null) '-'.toByte
+ def asString() =
+ new String( cells map(
+ c => if (c.piece == null) '-'.toByte
else (c.piece.number + 48).toByte ))
def firstEmptyCellIndex() = cells.findIndexOf(c => c.isEmpty)
@@ -144,13 +144,13 @@ final class Board {
def add(pieceIndex: Int, boardIndex: Int, p: Piece) = {
cellCount = 0
p.unmark
-
+
find( p.cells(pieceIndex), cells(boardIndex))
- val boardHasSpace = cellCount == Piece.size &&
- cellsPieceWillFill.forall(c => c.isEmpty)
+ val boardHasSpace = cellCount == Piece.size &&
+ cellsPieceWillFill.forall(c => c.isEmpty)
- if (boardHasSpace) cellsPieceWillFill.foreach(c => c.piece = p)
+ if (boardHasSpace) cellsPieceWillFill.foreach(c => c.piece = p)
boardHasSpace
}
@@ -180,10 +180,10 @@ final class Board {
if (row % 2 == 1) {
if (!isLast) c.next(Cell.NE) = a(i-(Board.cols-1))
- c.next(Cell.NW) = a(i-Board.cols)
+ c.next(Cell.NW) = a(i-Board.cols)
if (row != m) {
if (!isLast) c.next(Cell.SE) = a(i+(Board.cols+1))
- c.next(Cell.SW) = a(i+Board.cols)
+ c.next(Cell.SW) = a(i+Board.cols)
}
} else {
if (row != 0) {
@@ -212,9 +212,9 @@ final class Board {
Console.print(i + "\t")
for (j <- Iterator.range(0,Cell.sides)){
val c = cells(i).next(j)
- if (c == null)
- Console.print("-- ")
- else
+ if (c == null)
+ Console.print("-- ")
+ else
Console.printf("{0,number,00} ")(c.number)
}
Console.println("")
@@ -241,7 +241,7 @@ final class Piece(_number: Int) {
val number = _number
val cells = for (i <- Array.range(0,Piece.size)) yield new PieceCell()
- {
+ {
number match {
case 0 => make0
case 1 => make1
@@ -252,7 +252,7 @@ final class Piece(_number: Int) {
case 6 => make6
case 7 => make7
case 8 => make8
- case 9 => make9
+ case 9 => make9
}
}
@@ -395,12 +395,12 @@ final class Piece(_number: Int) {
Console.print(i + "\t")
for (j <- Iterator.range(0,Cell.sides)){
val c = cells(i).next(j)
- if (c == null)
- Console.print("-- ")
- else
+ if (c == null)
+ Console.print("-- ")
+ else
for (k <- Iterator.range(0,Piece.size)){
if (cells(k) == c) Console.printf(" {0,number,0} ")(k)
- }
+ }
}
Console.println("")
}
@@ -418,13 +418,13 @@ final class Piece(_number: Int) {
object Cell {
val NW = 0; val NE = 1
val W = 2; val E = 3
- val SW = 4; val SE = 5
+ val SW = 4; val SE = 5
val sides = 6
}
abstract class Cell {
- implicit def m: Manifest[T]
+ implicit def t: ClassTag[T]
type T
val next = new Array[T](Cell.sides)
var marked = false
@@ -437,7 +437,7 @@ abstract class Cell {
final class BoardCell(_number: Int) extends {
type T = BoardCell
- implicit val m = manifest[BoardCell]
+ implicit val t = classTag[BoardCell]
} with Cell {
val number = _number
var piece: Piece = _
@@ -448,10 +448,10 @@ final class BoardCell(_number: Int) extends {
def contiguousEmptyCells(): Int = {
if (!marked && isEmpty){
mark
- var count = 1
+ var count = 1
for (neighbour <- next)
- if (neighbour != null && neighbour.isEmpty)
+ if (neighbour != null && neighbour.isEmpty)
count = count + neighbour.contiguousEmptyCells
count } else { 0 }
diff --git a/test/scaladoc/resources/implicits-base-res.scala b/test/scaladoc/resources/implicits-base-res.scala
new file mode 100644
index 0000000000..65d7bdf67c
--- /dev/null
+++ b/test/scaladoc/resources/implicits-base-res.scala
@@ -0,0 +1,148 @@
+/**
+ * Test scaladoc implicits - the bread and butter of the testsuite :)
+ */
+package scala.test.scaladoc.implicits.base
+
+class Foo[T]
+class Bar[T]
+trait MyNumeric[R]
+
+/** Class A
+ * - tests the complete type inference
+ * - the following inherited methods should appear:
+ * {{{
+ * def convToGtColonDoubleA(x: Double) // pimpA3: with a constraint that T <: Double
+ * def convToIntA(x: Int) // pimpA2: with a constraint that T = Int
+ * def convToManifestA(x: T) // pimpA7: with 2 constraints: T: Manifest and T <: Double
+ * def convToMyNumericA(x: T) // pimpA6: with a constraint that there is x: MyNumeric[T] implicit in scope
+ * def convToNumericA(x: T) // pimpA1: with a constraint that there is x: Numeric[T] implicit in scope
+ * def convToPimpedA(x: Bar[Foo[T]]) // pimpA5: no constraints
+ * def convToPimpedA(x: S) // pimpA4: with 3 constraints: T = Foo[Bar[S]], S: Foo and S: Bar
+ * def convToTraversableOps(x: T) // pimpA7: with 2 constraints: T: Manifest and T <: Double
+ * // should not be abstract!
+ * }}}
+ */
+class A[T] {
+ /** This should prevent the implicitly inherited `def convToPimpedA: T` from `pimpA0` from showing up */
+ def convToPimpedA(x: T): T = sys.error("Let's check it out!")
+ /** This should check implicit member elimination in the case of subtyping */
+ def foo(a: T, b: AnyRef): T
+}
+/** Companion object with implicit transformations */
+object A {
+ import language.implicitConversions // according to SIP18
+
+ implicit def pimpA0[V](a: A[V]) = new PimpedA(a)
+ implicit def pimpA1[ZBUR: Numeric](a: A[ZBUR]) = new NumericA[ZBUR](a)
+ implicit def pimpA2(a: A[Int]) = new IntA(a)
+ implicit def pimpA3(a: A[T] forSome { type T <: Double }) = new GtColonDoubleA(a)
+ implicit def pimpA4[S](a: A[Foo[Bar[S]]])(implicit foo: Foo[S], bar: Bar[S]): PimpedA[S] = sys.error("not implemented")
+ implicit def pimpA5[Z](a: A[Z]): PimpedA[Bar[Foo[Z]]] = sys.error("not implemented")
+ implicit def pimpA6[Z: MyNumeric](a: A[Z]) = new MyNumericA[Z](a)
+ // TODO: Add H <: Double and see why it crashes for C and D -- context bounds, need to check!
+ implicit def pimpA7[H <: Double : Manifest](a: A[H]) = new ManifestA[H](a) with MyTraversableOps[H] { def convToTraversableOps(x: H): H = sys.error("no") }
+}
+
+
+/** Class B
+ * - tests the existential type solving
+ * - the following inherited methods should appear:
+ * {{{
+ * def convToGtColonDoubleA(x: Double) // pimpA3: no constraints
+ * def convToManifestA(x: Double) // pimpA7: no constraints
+ * def convToMyNumericA(x: Double) // pimpA6: (if showAll is set) with a constraint that there is x: MyNumeric[Double] implicit in scope
+ * def convToNumericA(x: Double) // pimpA1: no constraintsd
+ * def convToPimpedA(x: Bar[Foo[Double]]) // pimpA5: no constraints
+ * def convToTraversableOps(x: Double) // pimpA7: no constraints
+ * // should not be abstract!
+ * }}}
+ */
+class B extends A[Double]
+object B extends A
+
+
+/** Class C
+ * - tests asSeenFrom
+ * - the following inherited methods should appear:
+ * {{{
+ * def convToIntA(x: Int) // pimpA2: no constraints
+ * def convToMyNumericA(x: Int) // pimpA6: (if showAll is set) with a constraint that there is x: MyNumeric[Int] implicit in scope
+ * def convToNumericA(x: Int) // pimpA1: no constraints
+ * def convToPimpedA(x: Bar[Foo[Int]]) // pimpA5: no constraints
+ * }}}
+ */
+class C extends A[Int]
+object C extends A
+
+
+/** Class D
+ * - tests implicit elimination
+ * - the following inherited methods should appear:
+ * {{{
+ * def convToMyNumericA(x: String) // pimpA6: (if showAll is set) with a constraint that there is x: MyNumeric[String] implicit in scope
+ * def convToNumericA(x: String) // pimpA1: (if showAll is set) with a constraint that there is x: Numeric[String] implicit in scope
+ * def convToPimpedA(x: Bar[Foo[String]]) // pimpA5: no constraints
+ * }}}
+ */
+class D extends A[String]
+/** Companion object with implicit transformations */
+object D extends A
+
+
+/** PimpedA class <br/>
+ * - tests simple inheritance and asSeenFrom
+ * - A, B and C should be implicitly converted to this */
+class PimpedA[V](a: A[V]) {
+ /** The convToPimpedA: V documentation... */
+ def convToPimpedA(x: V): V = sys.error("Not implemented")
+}
+
+/** NumericA class <br/>
+ * - tests the implicit conversion between parametric and fixed types
+ * - A, B and C should be implicitly converted to this */
+class NumericA[U: Numeric](a: A[U]) {
+ /** The convToNumericA: U documentation... */
+ def convToNumericA(x: U): U = implicitly[Numeric[U]].zero
+}
+
+/** IntA class <br/>
+ * - tests the interaction between implicit conversion and specific types
+ * - A and C should be implicitly converted to this */
+class IntA(a: A[Int]) {
+ /** The convToIntA: Int documentation... */
+ def convToIntA(x: Int): Int = 0
+}
+
+/** GtColonDoubleA class <br/>
+ * - tests the interaction between implicit conversion and existential types
+ * - A and B should be implicitly converted to this */
+class GtColonDoubleA(a: A[T] forSome { type T <: Double }) {
+ /** The convToGtColonDoubleA: Double documentation... */
+ def convToGtColonDoubleA(x: Double): Double = 0
+}
+
+/** MyNumericA class <br/>
+ * - tests the implicit conversion between parametric and fixed types
+ * - A should be implicitly converted to this */
+class MyNumericA[U: MyNumeric](a: A[U]) {
+ /** The convToMyNumericA: U documentation... */
+ def convToMyNumericA(x: U): U = sys.error("dunno")
+}
+
+/** ManifestA class <br/>
+ * - tests the manifest recognition
+ * - A, B, C, D should be implicitly converted to this */
+class ManifestA[W: Manifest](a: A[W]) {
+ /** The convToManifestA: W documentation... */
+ def convToManifestA(x: W): W = sys.error("dunno")
+}
+
+// [Eugene to Vlad] how do I test typetags here?
+
+/** MyTraversableOps class <br/>
+ * - checks if any abstract members are added - should not happen!
+ */
+trait MyTraversableOps[S] {
+ /** The convToTraversableOps: S documentation... */
+ def convToTraversableOps(x: S): S
+}
diff --git a/test/scaladoc/resources/implicits-chaining-res.scala b/test/scaladoc/resources/implicits-chaining-res.scala
new file mode 100644
index 0000000000..c005d5fe09
--- /dev/null
+++ b/test/scaladoc/resources/implicits-chaining-res.scala
@@ -0,0 +1,50 @@
+/**
+ * Testing scaladoc implicits chaining
+ */
+package scala.test.scaladoc.implicits {
+
+ import language.implicitConversions // according to SIP18
+
+ // the classes involved
+ case class Z[U](a: U)
+ case class Intermediate[T, U](t: T, u: U)
+ class Implicit1[T](b: Implicit2[T])
+ class Implicit2[T](c: Implicit3[T])
+ class Implicit3[T](/* and so on */)
+
+ object chaining {
+
+ // the base conversion
+ implicit def convertToZ[T](a: A[T])(implicit b: Implicit1[T]): Z[A[T]] = Z(a)
+
+ // and the implicit chaining, don't you just love it? :D
+ // implicit1, with one alternative
+ implicit def implicit1[T <: Intermediate[_, _]](implicit b: Implicit2[T]) = new Implicit1[T](b)
+ // implicit2, with two alternatives
+ implicit def implicit2alt1[T <: Intermediate[_ <: String, _]](implicit c: Implicit3[T]) = new Implicit2[T](c)
+ implicit def implicit2alt2[T <: Intermediate[_ <: Double, _]](implicit c: Implicit3[T]) = new Implicit2[T](c)
+ // implicit3, with two alternatives
+ implicit def implicit3alt1[T <: Intermediate[_, _ <: Int]] = new Implicit3[T]()
+ implicit def implicit3alt2[T <: Intermediate[_ <: Double, _ <: AnyRef],X] = new Implicit3[T]()
+
+ // and our targets
+ /** conversion here, with constraints */
+ class A[T]()
+ /** conversion here, no constraints */
+ class B extends A[Intermediate[String, Int]]
+ /** no conversion */
+ class C extends A[Intermediate[String, String]]
+ /** conversion here, no constraints */
+ class D extends A[Intermediate[Double, Int]]
+ /** conversion here, no constraints */
+ class E extends A[Intermediate[Double, String]]
+ /** no conversion */
+ class F extends A[Intermediate[String, Double]]
+
+ object scalacTest {
+ (new B).a
+ (new D).a
+ (new E).a
+ }
+ }
+}
diff --git a/test/scaladoc/resources/implicits-elimination-res.scala b/test/scaladoc/resources/implicits-elimination-res.scala
new file mode 100644
index 0000000000..b23667440c
--- /dev/null
+++ b/test/scaladoc/resources/implicits-elimination-res.scala
@@ -0,0 +1,14 @@
+/**
+ * Testing scaladoc implicits elimination
+ */
+package scala.test.scaladoc.implicits.elimination {
+
+ import language.implicitConversions // according to SIP18
+
+ /** No conversion, as B doesn't bring any member */
+ class A
+ class B { class C; trait V; type T; }
+ object A {
+ implicit def toB(a: A): B = null
+ }
+}
diff --git a/test/scaladoc/resources/implicits-scopes-res.scala b/test/scaladoc/resources/implicits-scopes-res.scala
new file mode 100644
index 0000000000..aaeb43f95b
--- /dev/null
+++ b/test/scaladoc/resources/implicits-scopes-res.scala
@@ -0,0 +1,52 @@
+/**
+ * Testing scaladoc implicit scopes - looking for implicits in the right places
+ */
+package scala.test.scaladoc.implicits.scopes
+import language.implicitConversions // according to SIP18
+
+// TEST1 - In package object
+package object test1 {
+ implicit def toB(a: A): B = null
+}
+package test1 {
+ class A
+ class B { def b = "" }
+}
+
+// TEST2 - In enclosing package - doesn't seem to work even in scalac
+package object test2 {
+ import classes._
+ implicit def toB(a: A): B = null
+}
+package test2 {
+ package classes {
+ class A
+ class B { def b = "" }
+ object test { /* (new A).b won't compile */ }
+ }
+}
+
+// TEST3 - In companion object
+package test3 {
+ class A
+ object A { implicit def toB(a: A): B = null }
+ class B { def b = "" }
+}
+
+// TEST4 - Nested type's companion object
+package test4 {
+ class U[V]
+ class S
+ object S { implicit def toB(a: A): B = null }
+ class A extends U[S]
+ class B { def b = "" }
+}
+
+// TEST5 - In scope
+package test5 {
+ object scope {
+ class A
+ class B { def b = "" }
+ implicit def toB(a: A): B = null
+ }
+}
diff --git a/test/scaladoc/resources/implicits-shadowing-res.scala b/test/scaladoc/resources/implicits-shadowing-res.scala
new file mode 100644
index 0000000000..c5e9493bf3
--- /dev/null
+++ b/test/scaladoc/resources/implicits-shadowing-res.scala
@@ -0,0 +1,64 @@
+/**
+ * Test scaladoc implicits distinguishing -- supress all members by implicit conversion that are shadowed by the
+ * class' own members
+ *
+ * {{{
+ * scala> class A { def foo(t: String) = 4 }
+ * defined class A
+ *
+ * scala> class B { def foo(t: Any) = 5 }
+ * defined class B
+ *
+ * scala> implicit def AtoB(a:A) = new B
+ * AtoB: (a: A)B
+ *
+ * scala> val a = new A
+ * a: A = A@28f553e3
+ *
+ * scala> a.foo("T")
+ * res1: Int = 4
+ *
+ * scala> a.foo(4)
+ * res2: Int = 5
+ * }}}
+ */
+package scala.test.scaladoc.implicits.shadowing
+import language.implicitConversions // according to SIP18
+
+/** conv5, conv8, conv9, conv10, conv11 should be visible */
+class A[T] {
+ def conv1: AnyRef = ???
+ def conv2: T = ???
+ def conv3(l: Int): AnyRef = ???
+ def conv4(l: AnyRef): AnyRef = ???
+ def conv5(l: String): AnyRef = ???
+ def conv6(l: AnyRef): AnyRef = ???
+ def conv7(l: AnyRef): String = ???
+ def conv8(l: String)(m: String): AnyRef = ???
+ def conv9(l: AnyRef)(m: AnyRef): AnyRef = ???
+ def conv10(l: T): T = ???
+ def conv11(l: T): T = ???
+}
+/** conv5, conv8, conv9, conv11 should be visible */
+class B extends A[Int]
+/** conv5, conv8, conv9, conv10, conv11 should be visible */
+class C extends A[Double]
+/** conv5, conv8, conv9, conv10 should be visible */
+class D extends A[AnyRef]
+
+class Z[T] {
+ def conv1: AnyRef = ???
+ def conv2: T = ???
+ def conv3(p: Int): AnyRef = ???
+ def conv4(p: String): AnyRef = ???
+ def conv5(p: AnyRef): AnyRef = ???
+ def conv6(p: AnyRef): String = ???
+ def conv7(p: AnyRef): AnyRef = ???
+ def conv8(p: String, q: String): AnyRef = ???
+ def conv9(p: AnyRef, q: AnyRef): AnyRef = ???
+ def conv10(p: Int): T = ???
+ def conv11(p: String): T = ???
+}
+object A {
+ implicit def AtoZ[T](a: A[T]) = new Z[T]
+}
diff --git a/test/scaladoc/resources/package-object-res.scala b/test/scaladoc/resources/package-object-res.scala
new file mode 100644
index 0000000000..17d5c0a499
--- /dev/null
+++ b/test/scaladoc/resources/package-object-res.scala
@@ -0,0 +1,14 @@
+/** This package have A and B.
+ */
+package test {
+ trait A { def hi = "hello" }
+ trait B { def bye = "bye!" }
+}
+
+/** This package object extends A and B.
+ */
+package object test extends A with B {
+ override def hi = "good morning!"
+ override def bye = "good bye!"
+ protected def thank = "thank you!"
+}
diff --git a/test/scaladoc/run/SI-5373.check b/test/scaladoc/run/SI-5373.check
index c55eb001cf..619c56180b 100644
--- a/test/scaladoc/run/SI-5373.check
+++ b/test/scaladoc/run/SI-5373.check
@@ -1 +1 @@
-model contains 6 documentable templates
+Done.
diff --git a/test/scaladoc/run/SI-5373.scala b/test/scaladoc/run/SI-5373.scala
index af433a1844..0062abbb2a 100644
--- a/test/scaladoc/run/SI-5373.scala
+++ b/test/scaladoc/run/SI-5373.scala
@@ -1,9 +1,9 @@
import scala.tools.nsc.doc.model._
import scala.tools.partest.ScaladocModelTest
-object Test extends ScaladocModelTest {
+object Test extends ScaladocModelTest {
- def code = """
+ override def code = """
import scala.annotation.bridge
package scala.test {
@@ -23,7 +23,7 @@ object Test extends ScaladocModelTest {
// no need for special settings
def scaladocSettings = ""
-
+
def testModel(rootPackage: Package) = {
// get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
import access._
diff --git a/test/scaladoc/run/implicits-base.check b/test/scaladoc/run/implicits-base.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/implicits-base.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/implicits-base.scala b/test/scaladoc/run/implicits-base.scala
new file mode 100644
index 0000000000..06d017ed70
--- /dev/null
+++ b/test/scaladoc/run/implicits-base.scala
@@ -0,0 +1,180 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+import language._
+
+object Test extends ScaladocModelTest {
+
+ // test a file instead of a piece of code
+ override def resourceFile = "implicits-base-res.scala"
+
+ // start implicits
+ def scaladocSettings = "-implicits -implicits-show-all"
+
+ def testModel(root: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // SEE THE test/resources/implicits-base-res.scala FOR THE EXPLANATION OF WHAT'S CHECKED HERE:
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._package("base")
+ var conv: ImplicitConversion = null
+
+//// class A ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val A = base._class("A")
+
+ // the method pimped on by pimpA0 should be shadowed by the method in class A
+ assert(A._conversions(A.qualifiedName + ".pimpA0").isEmpty)
+
+ // def convToNumericA: T // pimpA1: with a constraint that there is x: Numeric[T] implicit in scope
+ conv = A._conversion(A.qualifiedName + ".pimpA1")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToNumericA").resultType.name == "T")
+
+ // def convToIntA: Int // pimpA2: with a constraint that T = Int
+ conv = A._conversion(A.qualifiedName + ".pimpA2")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToIntA").resultType.name == "Int")
+
+ // def convToGtColonDoubleA: Double // pimpA3: with a constraint that T <: Double
+ conv = A._conversion(A.qualifiedName + ".pimpA3")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToGtColonDoubleA").resultType.name == "Double")
+
+ // def convToPimpedA: S // pimpA4: with 3 constraints: T = Foo[Bar[S]], S: Foo and S: Bar
+ conv = A._conversion(A.qualifiedName + ".pimpA4")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 3)
+ assert(conv._member("convToPimpedA").resultType.name == "S")
+
+ // def convToPimpedA: Bar[Foo[T]] // pimpA5: no constraints
+ conv = A._conversion(A.qualifiedName + ".pimpA5")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToPimpedA").resultType.name == "Bar[Foo[T]]")
+
+ // def convToMyNumericA: T // pimpA6: with a constraint that there is x: MyNumeric[T] implicit in scope
+ conv = A._conversion(A.qualifiedName + ".pimpA6")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToMyNumericA").resultType.name == "T")
+
+ // def convToManifestA: T // pimpA7: with 2 constraints: T: Manifest and T <: Double
+ // def convToTraversableOps: T // pimpA7: with 2 constraints: T: Manifest and T <: Double
+ // should not be abstract!
+ conv = A._conversion(A.qualifiedName + ".pimpA7")
+ assert(conv.members.length == 2)
+ assert(conv.constraints.length == 2)
+ assert(conv._member("convToManifestA").resultType.name == "T")
+ assert(conv._member("convToTraversableOps").resultType.name == "T")
+ assert(conv._member("convToTraversableOps").flags.toString.indexOf("abstract") == -1)
+
+//// class B ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val B = base._class("B")
+
+ // these conversions should not affect B
+ assert(B._conversions(A.qualifiedName + ".pimpA0").isEmpty)
+ assert(B._conversions(A.qualifiedName + ".pimpA2").isEmpty)
+ assert(B._conversions(A.qualifiedName + ".pimpA4").isEmpty)
+
+ // def convToNumericA: Double // pimpA1: no constraintsd
+ conv = B._conversion(A.qualifiedName + ".pimpA1")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToNumericA").resultType.name == "Double")
+
+ // def convToGtColonDoubleA: Double // pimpA3: no constraints
+ conv = B._conversion(A.qualifiedName + ".pimpA3")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToGtColonDoubleA").resultType.name == "Double")
+
+ // def convToPimpedA: Bar[Foo[Double]] // pimpA5: no constraints
+ conv = B._conversion(A.qualifiedName + ".pimpA5")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToPimpedA").resultType.name == "Bar[Foo[Double]]")
+
+ // def convToMyNumericA: Double // pimpA6: (if showAll is set) with a constraint that there is x: MyNumeric[Double] implicit in scope
+ conv = B._conversion(A.qualifiedName + ".pimpA6")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToMyNumericA").resultType.name == "Double")
+
+ // def convToManifestA: Double // pimpA7: no constraints
+ // def convToTraversableOps: Double // pimpA7: no constraints
+ // // should not be abstract!
+ conv = B._conversion(A.qualifiedName + ".pimpA7")
+ assert(conv.members.length == 2)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToManifestA").resultType.name == "Double")
+ assert(conv._member("convToTraversableOps").resultType.name == "Double")
+ assert(conv._member("convToTraversableOps").flags.toString.indexOf("abstract") == -1)
+
+//// class C ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val C = base._class("C")
+
+ // these conversions should not affect C
+ assert(C._conversions(A.qualifiedName + ".pimpA0").isEmpty)
+ assert(C._conversions(A.qualifiedName + ".pimpA3").isEmpty)
+ assert(C._conversions(A.qualifiedName + ".pimpA4").isEmpty)
+ assert(C._conversions(A.qualifiedName + ".pimpA7").isEmpty)
+
+ // def convToNumericA: Int // pimpA1: no constraints
+ conv = C._conversion(A.qualifiedName + ".pimpA1")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToNumericA").resultType.name == "Int")
+
+ // def convToIntA: Int // pimpA2: no constraints
+ conv = C._conversion(A.qualifiedName + ".pimpA2")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToIntA").resultType.name == "Int")
+
+ // def convToPimpedA: Bar[Foo[Int]] // pimpA5: no constraints
+ conv = C._conversion(A.qualifiedName + ".pimpA5")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToPimpedA").resultType.name == "Bar[Foo[Int]]")
+
+ // def convToMyNumericA: Int // pimpA6: (if showAll is set) with a constraint that there is x: MyNumeric[Int] implicit in scope
+ conv = C._conversion(A.qualifiedName + ".pimpA6")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToMyNumericA").resultType.name == "Int")
+
+//// class D ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val D = base._class("D")
+
+ // these conversions should not affect D
+ assert(D._conversions(A.qualifiedName + ".pimpA0").isEmpty)
+ assert(D._conversions(A.qualifiedName + ".pimpA2").isEmpty)
+ assert(D._conversions(A.qualifiedName + ".pimpA3").isEmpty)
+ assert(D._conversions(A.qualifiedName + ".pimpA4").isEmpty)
+ assert(D._conversions(A.qualifiedName + ".pimpA7").isEmpty)
+
+ // def convToNumericA: String // pimpA1: (if showAll is set) with a constraint that there is x: Numeric[String] implicit in scope
+ conv = D._conversion(A.qualifiedName + ".pimpA1")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToNumericA").resultType.name == "String")
+
+ // def convToPimpedA: Bar[Foo[String]] // pimpA5: no constraints
+ conv = D._conversion(A.qualifiedName + ".pimpA5")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ assert(conv._member("convToPimpedA").resultType.name == "Bar[Foo[String]]")
+
+ // def convToMyNumericA: String // pimpA6: (if showAll is set) with a constraint that there is x: MyNumeric[String] implicit in scope
+ conv = D._conversion(A.qualifiedName + ".pimpA6")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+ assert(conv._member("convToMyNumericA").resultType.name == "String")
+ }
+}
diff --git a/test/scaladoc/run/implicits-chaining.check b/test/scaladoc/run/implicits-chaining.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/implicits-chaining.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/implicits-chaining.scala b/test/scaladoc/run/implicits-chaining.scala
new file mode 100644
index 0000000000..858ca9ce61
--- /dev/null
+++ b/test/scaladoc/run/implicits-chaining.scala
@@ -0,0 +1,65 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+import language._
+
+object Test extends ScaladocModelTest {
+
+ // test a file instead of a piece of code
+ override def resourceFile = "implicits-chaining-res.scala"
+
+ // start implicits
+ def scaladocSettings = "-implicits"
+
+ def testModel(root: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // SEE THE test/resources/implicits-chaining-res.scala FOR THE EXPLANATION OF WHAT'S CHECKED HERE:
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._object("chaining")
+ var conv: ImplicitConversion = null
+
+//// class A ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val A = base._class("A")
+
+ conv = A._conversion(base.qualifiedName + ".convertToZ")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 1)
+
+//// class B ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val B = base._class("B")
+
+ conv = B._conversion(base.qualifiedName + ".convertToZ")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+
+//// class C ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val C = base._class("C")
+
+ assert(C._conversions(base.qualifiedName + ".convertToZ").isEmpty)
+
+//// class D ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val D = base._class("D")
+
+ conv = D._conversion(base.qualifiedName + ".convertToZ")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+
+//// class E ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val E = base._class("E")
+
+ conv = E._conversion(base.qualifiedName + ".convertToZ")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+
+//// class F ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val F = base._class("F")
+
+ assert(F._conversions(base.qualifiedName + ".convertToZ").isEmpty)
+ }
+}
diff --git a/test/scaladoc/run/implicits-elimination.check b/test/scaladoc/run/implicits-elimination.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/implicits-elimination.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/implicits-elimination.scala b/test/scaladoc/run/implicits-elimination.scala
new file mode 100644
index 0000000000..ed37b9cd90
--- /dev/null
+++ b/test/scaladoc/run/implicits-elimination.scala
@@ -0,0 +1,23 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+import language._
+
+object Test extends ScaladocModelTest {
+
+ // test a file instead of a piece of code
+ override def resourceFile = "implicits-elimination-res.scala"
+
+ // start implicits
+ def scaladocSettings = "-implicits"
+
+ def testModel(root: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // SEE THE test/resources/implicits-elimination-res.scala FOR THE EXPLANATION OF WHAT'S CHECKED HERE:
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._package("elimination")
+ val A = base._class("A")
+
+ assert(A._conversions(A.qualifiedName + ".toB").isEmpty)
+ }
+}
diff --git a/test/scaladoc/run/implicits-scopes.check b/test/scaladoc/run/implicits-scopes.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/implicits-scopes.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/implicits-scopes.scala b/test/scaladoc/run/implicits-scopes.scala
new file mode 100644
index 0000000000..7b9e80e148
--- /dev/null
+++ b/test/scaladoc/run/implicits-scopes.scala
@@ -0,0 +1,77 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+import language._
+
+object Test extends ScaladocModelTest {
+
+ // test a file instead of a piece of code
+ override def resourceFile = "implicits-scopes-res.scala"
+
+ // start implicits
+ def scaladocSettings = "-implicits"
+
+ def testModel(root: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+ var conv: ImplicitConversion = null
+
+ // SEE THE test/resources/implicits-chaining-res.scala FOR THE EXPLANATION OF WHAT'S CHECKED HERE:
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._package("scopes")
+
+//// test1 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val doTest1 = {
+ val test1 = base._package("test1")
+ val A = test1._class("A")
+
+ conv = A._conversion(test1.qualifiedName + ".package.toB") // the .package means it's the package object
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ }
+
+//// test2 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val doTest2 = {
+ val test2 = base._package("test2")
+ val classes = test2._package("classes")
+ val A = classes._class("A")
+
+ assert(A._conversions(test2.qualifiedName + ".toB").isEmpty)
+ }
+
+//// test3 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val doTest3 = {
+ val test3 = base._package("test3")
+ val A = test3._class("A")
+
+ conv = A._conversion(A.qualifiedName + ".toB")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ }
+
+//// test4 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val doTest4 = {
+ val test4 = base._package("test4")
+ val A = test4._class("A")
+ val S = test4._object("S")
+
+ conv = A._conversion(S.qualifiedName + ".toB")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ }
+
+//// test5 /////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val doTest5 = {
+ val test5 = base._package("test5")
+ val scope = test5._object("scope")
+ val A = scope._class("A")
+
+ conv = A._conversion(scope.qualifiedName + ".toB")
+ assert(conv.members.length == 1)
+ assert(conv.constraints.length == 0)
+ }
+ }
+}
diff --git a/test/scaladoc/run/implicits-shadowing.check b/test/scaladoc/run/implicits-shadowing.check
new file mode 100644
index 0000000000..619c56180b
--- /dev/null
+++ b/test/scaladoc/run/implicits-shadowing.check
@@ -0,0 +1 @@
+Done.
diff --git a/test/scaladoc/run/implicits-shadowing.scala b/test/scaladoc/run/implicits-shadowing.scala
new file mode 100644
index 0000000000..7835223d21
--- /dev/null
+++ b/test/scaladoc/run/implicits-shadowing.scala
@@ -0,0 +1,70 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+
+object Test extends ScaladocModelTest {
+
+ // test a file instead of a piece of code
+ override def resourceFile = "implicits-shadowing-res.scala"
+
+ // start implicits
+ def scaladocSettings = "-implicits"
+
+ def testModel(root: Package) = {
+ // get the quick access implicit defs in scope (_package(s), _class(es), _trait(s), object(s) _method(s), _value(s))
+ import access._
+
+ // SEE THE test/resources/implicits-chaining-res.scala FOR THE EXPLANATION OF WHAT'S CHECKED HERE:
+ val base = root._package("scala")._package("test")._package("scaladoc")._package("implicits")._object("shadowing")
+ var conv: ImplicitConversion = null
+
+//// class A ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val A = base._class("A")
+
+ conv = A._conversion(base._object("A").qualifiedName + ".AtoZ")
+ assert(conv.members.length == 5)
+ conv._member("conv5")
+ conv._member("conv8")
+ conv._member("conv9")
+ conv._member("conv10")
+ conv._member("conv11")
+ assert(conv.constraints.length == 0)
+
+//// class B ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val B = base._class("B")
+
+ conv = B._conversion(base._object("A").qualifiedName + ".AtoZ")
+ assert(conv.members.length == 4)
+ conv._member("conv5")
+ conv._member("conv8")
+ conv._member("conv9")
+ conv._member("conv11")
+ assert(conv.constraints.length == 0)
+
+//// class C ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val C = base._class("C")
+
+ conv = C._conversion(base._object("A").qualifiedName + ".AtoZ")
+ assert(conv.members.length == 5)
+ conv._member("conv5")
+ conv._member("conv8")
+ conv._member("conv9")
+ conv._member("conv10")
+ conv._member("conv11")
+ assert(conv.constraints.length == 0)
+
+//// class D ///////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ val D = base._class("D")
+
+ conv = D._conversion(base._object("A").qualifiedName + ".AtoZ")
+ assert(conv.members.length == 4)
+ conv._member("conv5")
+ conv._member("conv8")
+ conv._member("conv9")
+ conv._member("conv10")
+ assert(conv.constraints.length == 0)
+ }
+} \ No newline at end of file
diff --git a/test/scaladoc/run/package-object.check b/test/scaladoc/run/package-object.check
new file mode 100644
index 0000000000..4297847e73
--- /dev/null
+++ b/test/scaladoc/run/package-object.check
@@ -0,0 +1,2 @@
+List((test.B,B), (test.A,A), (scala.AnyRef,AnyRef), (scala.Any,Any))
+Done.
diff --git a/test/scaladoc/run/package-object.scala b/test/scaladoc/run/package-object.scala
new file mode 100644
index 0000000000..fd36a8df7b
--- /dev/null
+++ b/test/scaladoc/run/package-object.scala
@@ -0,0 +1,15 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+import language._
+
+object Test extends ScaladocModelTest {
+ override def resourceFile = "package-object-res.scala"
+ override def scaladocSettings = ""
+ def testModel(root: Package) = {
+ import access._
+
+ val p = root._package("test")
+ println(p.linearization)
+ }
+}
+
diff --git a/test/scaladoc/run/usecase-var-expansion.check b/test/scaladoc/run/usecase-var-expansion.check
new file mode 100644
index 0000000000..3faa4735c0
--- /dev/null
+++ b/test/scaladoc/run/usecase-var-expansion.check
@@ -0,0 +1,4 @@
+newSource:8: error: Incorrect variable expansion for $Coll in use case. Does the variable expand to wiki syntax when documenting class Test2?
+ * @usecase def foo: $Coll[T]
+ ^
+Done.
diff --git a/test/scaladoc/run/usecase-var-expansion.scala b/test/scaladoc/run/usecase-var-expansion.scala
new file mode 100644
index 0000000000..e86ea4a835
--- /dev/null
+++ b/test/scaladoc/run/usecase-var-expansion.scala
@@ -0,0 +1,26 @@
+import scala.tools.nsc.doc.model._
+import scala.tools.partest.ScaladocModelTest
+import language._
+
+object Test extends ScaladocModelTest {
+
+ override def code = """
+ /**
+ * @define Coll `Test`
+ */
+ class Test[T] {
+ /**
+ * member $Coll
+ * @usecase def foo: $Coll[T]
+ * usecase $Coll
+ */
+ def foo(implicit err: String): Test[T] = sys.error(err)
+ }
+
+ /** @define Coll {{{some `really` < !! >> invalid $$$ thing}}} */
+ class Test2[T] extends Test[Int]
+ """
+
+ def scaladocSettings = ""
+ def testModel(root: Package) = ()
+}
diff --git a/test/scaladoc/scalacheck/CommentFactoryTest.scala b/test/scaladoc/scalacheck/CommentFactoryTest.scala
index 69c314a64c..68ca68efdd 100644
--- a/test/scaladoc/scalacheck/CommentFactoryTest.scala
+++ b/test/scaladoc/scalacheck/CommentFactoryTest.scala
@@ -3,11 +3,12 @@ import org.scalacheck.Prop._
import scala.tools.nsc.Global
import scala.tools.nsc.doc
+import scala.tools.nsc.doc.model._
import scala.tools.nsc.doc.model.comment._
class Factory(val g: Global, val s: doc.Settings)
extends doc.model.ModelFactory(g, s) {
- thisFactory: Factory with CommentFactory with doc.model.TreeFactory =>
+ thisFactory: Factory with ModelFactoryImplicitSupport with CommentFactory with doc.model.TreeFactory =>
def strip(c: Comment): Option[Inline] = {
c.body match {
@@ -28,7 +29,7 @@ object Test extends Properties("CommentFactory") {
val settings = new doc.Settings((str: String) => {})
val reporter = new scala.tools.nsc.reporters.ConsoleReporter(settings)
val g = new Global(settings, reporter)
- (new Factory(g, settings) with CommentFactory with doc.model.TreeFactory)
+ (new Factory(g, settings) with ModelFactoryImplicitSupport with CommentFactory with doc.model.TreeFactory)
}
def parse(src: String, dst: Inline) = {
diff --git a/tools/binary-repo-lib.sh b/tools/binary-repo-lib.sh
index 4c5497e803..a22747520c 100755
--- a/tools/binary-repo-lib.sh
+++ b/tools/binary-repo-lib.sh
@@ -88,12 +88,28 @@ pushJarFile() {
# rm $jar
}
+getJarSha() {
+ local jar=$1
+ if [[ ! -f "$jar" ]]; then
+ echo ""
+ elif which sha1sum 2>/dev/null >/dev/null; then
+ shastring=$(sha1sum "$jar")
+ echo "$shastring" | sed 's/ .*//'
+ elif which shasum 2>/dev/null >/dev/null; then
+ shastring=$(shasum "$jar")
+ echo "$shastring" | sed 's/ .*//'
+ else
+ shastring=$(openssl sha1 "$jar")
+ echo "$shastring" | sed 's/^.*= //'
+ fi
+}
+
# Tests whether or not the .desired.sha1 hash matches a given file.
# Arugment 1 - The jar file to test validity.
# Returns: Empty string on failure, "OK" on success.
isJarFileValid() {
local jar=$1
- if [[ ! -f $jar ]]; then
+ if [[ ! -f "$jar" ]]; then
echo ""
else
local jar_dir=$(dirname $jar)
@@ -131,6 +147,27 @@ pushJarFiles() {
fi
}
+
+checkJarSha() {
+ local jar=$1
+ local sha=$2
+ local testsha=$(getJarSha "$jar")
+ if test "$sha" == "$testsha"; then
+ echo "OK"
+ fi
+}
+
+makeCacheLocation() {
+ local uri=$1
+ local sha=$2
+ local cache_loc="$cache_dir/$uri"
+ local cdir=$(dirname $cache_loc)
+ if [[ ! -d "$cdir" ]]; then
+ mkdir -p "$cdir"
+ fi
+ echo "$cache_loc"
+}
+
# Pulls a single binary artifact from a remote repository.
# Argument 1 - The uri to the file that should be downloaded.
# Argument 2 - SHA of the file...
@@ -138,16 +175,19 @@ pushJarFiles() {
pullJarFileToCache() {
local uri=$1
local sha=$2
- local cache_loc=$cache_dir/$uri
- local cdir=$(dirname $cache_loc)
- if [[ ! -d $cdir ]]; then
- mkdir -p $cdir
- fi
+ local cache_loc="$(makeCacheLocation $uri)"
# TODO - Check SHA of local cache is accurate.
- if [[ ! -f $cache_loc ]]; then
+ if test -f "$cache_loc" && test "$(checkJarSha "$cache_loc" "$sha")" != "OK"; then
+ echo "Found bad cached file: $cache_loc"
+ rm -f "$cache_loc"
+ fi
+ if [[ ! -f "$cache_loc" ]]; then
curlDownload $cache_loc ${remote_urlbase}/${uri}
+ if test "$(checkJarSha "$cache_loc" "$sha")" != "OK"; then
+ echo "Trouble downloading $uri. Please try pull-binary-libs again when your internet connection is stable."
+ exit 2
+ fi
fi
- echo "$cache_loc"
}
# Pulls a single binary artifact from a remote repository.
@@ -162,7 +202,8 @@ pullJarFile() {
local version=${sha1% ?$jar_name}
local remote_uri=${version}/${jar#$basedir/}
echo "Resolving [${remote_uri}]"
- local cached_file=$(pullJarFileToCache $remote_uri $version)
+ pullJarFileToCache $remote_uri $version
+ local cached_file=$(makeCacheLocation $remote_uri)
cp $cached_file $jar
}
diff --git a/tools/cleanup-commit b/tools/cleanup-commit
new file mode 100755
index 0000000000..400d434359
--- /dev/null
+++ b/tools/cleanup-commit
@@ -0,0 +1,130 @@
+#!/bin/bash
+
+##
+## The cleanup-commit script
+## -------------------------
+## This little script will cleanup your commit before you send it. You need to add the files to the staged area and
+## run this script. It will automatically cleanup tabs and trailing spaces for the files you added and then add the
+## clean versions to the staging area.
+##
+## Use at your own risk, I spent some time making the script error-proof so it will abort if sees any inconsistency,
+## but of course playing around with your commit might break things. Btw, it saves the original file to file.bak.
+##
+## Happy hacking!
+##
+
+ABORT="Ab0rT0p3r4+|0n"
+
+#
+# Cleanup function
+#
+function cleanup {
+ echo Cleaning up $1...
+ # prepare the ground
+ rm -rf $1.bak
+ # compress <TAB> into double <BLANK> and eliminate trailing <BLANC>s
+ sed -i.bak -e 's/\t/ /g' -e 's/ *$//' $1
+}
+
+
+#
+# Get the git status for the current staged commit
+#
+FULLSTATUS=`git status --porcelain`
+
+if [ $? -ne 0 ]
+then
+ echo "Unable to run git. Check if:"
+ echo " -- git is installed (you can run git in the command line)"
+ echo " -- the current directory is a valid git repository"
+ exit 1
+fi
+
+echo
+
+#
+# Based on the status decide what files will get cleaned up
+#
+CLEANUP_FILES=`echo "$FULLSTATUS" | while read LINE
+do
+
+ STATUS=$(echo $LINE | sed 's/^\(..\).*$/\1/')
+ if [ $? -ne 0 ]
+ then
+ echo "Could not get the status for line: $LINE"
+ echo " -- you have the basic unix tools installed (grep, cut, sed)"
+ echo $ABORT # This goes to CLEANUP_FILES
+ exit 1
+ fi
+
+ FILES=$(echo $LINE | sed 's/^..//')
+ FILE1=$(echo $FILES | cut -d ' ' -f 1)
+ FILE2=$(echo $FILES | cut -d ' ' -f 3)
+
+ case "$STATUS" in
+ [AMRDC]" ")
+ case "$STATUS" in
+ "A "|"M ")
+ echo $FILE1
+ ;;
+ "R ")
+ echo $FILE2
+ ;;
+ "D ")
+ #nothing to do
+ ;;
+ "C ")
+ echo $FILE1
+ echo $FILE2
+ ;;
+ esac
+ ;;
+ "??")
+ # File is not tracked, no need to do anything about it
+ # echo Untracked: $FILE1
+ ;;
+ *)
+ echo "Unstable status of file $FILE1 (\"$STATUS\")" >&2
+ echo "Aborting cleanup!" >&2
+ echo $ABORT # This goes to CLEANUP_FILES
+ exit 1
+ esac
+done; echo $CLEANUP_FILES`
+
+
+#
+# Perform actual cleanup
+#
+case $CLEANUP_FILES in
+*"$ABORT")
+ echo
+ exit 1
+ ;;
+"")
+ echo Nothing to do!
+ ;;
+*)
+ cd $(git rev-parse --show-toplevel)
+
+ if [ $? -ne 0 ]
+ then
+ echo Unexpected error: cannot cd to the repository root
+ echo Aborting cleanup!
+ exit 1
+ fi
+
+ echo "$CLEANUP_FILES" | while read FILE
+ do
+ cleanup $FILE
+ done
+
+ cd - &>/dev/null
+
+ echo
+ echo "Cleanup done: "
+ echo " - original files saved as .bak"
+ echo " - you can do \"git diff\" to see the changes the script did"
+ echo " - you can do \"git commit -a\" to commit the cleaned up files"
+ echo
+ ;;
+esac
diff --git a/tools/codegen b/tools/codegen
index 734235aef8..35c93fba16 100755
--- a/tools/codegen
+++ b/tools/codegen
@@ -3,6 +3,6 @@
THISDIR=`dirname $0`
SCALALIB=$THISDIR/../src/library/scala
-BINDIR=$THISDIR/../build/pack/bin
+BINDIR=$THISDIR/../build/quick/bin
$BINDIR/scala scala.tools.cmd.gen.Codegen "$@"
diff --git a/tools/dump-class b/tools/dump-class
new file mode 100755
index 0000000000..0b4f2a73fa
--- /dev/null
+++ b/tools/dump-class
@@ -0,0 +1,6 @@
+#!/bin/sh
+#
+
+classpath=$($(dirname $BASH_SOURCE)/quickcp)
+
+java -cp "$classpath" scala.tools.nsc.MainGenericRunner -usejavacp scala.tools.cmd.program.DumpClass "$@" \ No newline at end of file
diff --git a/tools/get-scala-commit-date.bat b/tools/get-scala-commit-date.bat
index a07155533f..2a75073633 100644
--- a/tools/get-scala-commit-date.bat
+++ b/tools/get-scala-commit-date.bat
@@ -1,24 +1,9 @@
-@echo off
-rem
-rem Usage: get-scala-revison.bat [dir]
-rem Figures out current scala commit date of a git clone.
-rem
-rem If no dir is given, current working dir is used.
-
-@setlocal
-set _DIR=
-if "%*"=="" (
- for /f "delims=;" %%i in ('cd') do set "_DIR=%%i"
-) else (
- set "_DIR=%~1"
-)
-cd %_DIR%
-
-rem TODO - Check with a real windows user that this works!
-if exist .git\NUL (
- for /f "tokens=1delims= " in ('git log --format="%ci" -1') do set commitdate=%%a
- echo %commitdate%
-)
-
-:end
-@endlocal
+@echo off
+for %%X in (bash.exe) do (set FOUND=%%~$PATH:X)
+if defined FOUND (
+ bash "%~dp0\get-scala-commit-date"
+) else (
+ rem echo this script does not work with cmd.exe. please, install bash
+ echo unknown
+ exit 1
+) \ No newline at end of file
diff --git a/tools/get-scala-commit-sha.bat b/tools/get-scala-commit-sha.bat
index 7a5afa11b1..390e2d99d0 100644
--- a/tools/get-scala-commit-sha.bat
+++ b/tools/get-scala-commit-sha.bat
@@ -1,21 +1,9 @@
-@echo off
-rem
-rem Usage: get-scala-commit-drift.bat [dir]
-rem Figures out current scala commit drift, of a clone.
-rem
-rem If no dir is given, current working dir is used.
-
-@setlocal
-set _DIR=
-if "%*"=="" (
- for /f "delims=;" %%i in ('cd') do set "_DIR=%%i"
-) else (
- set "_DIR=%~1"
-)
-cd %_DIR%
-
-rem TODO - truncate chars.
-git log -1 --format="%H
-
-:end
-@endlocal
+@echo off
+for %%X in (bash.exe) do (set FOUND=%%~$PATH:X)
+if defined FOUND (
+ bash "%~dp0\get-scala-commit-sha"
+) else (
+ rem echo this script does not work with cmd.exe. please, install bash
+ echo unknown
+ exit 1
+) \ No newline at end of file