diff options
26 files changed, 232 insertions, 113 deletions
diff --git a/src/compiler/scala/reflect/macros/contexts/Parsers.scala b/src/compiler/scala/reflect/macros/contexts/Parsers.scala index 3dab02beba..ae6488b5a8 100644 --- a/src/compiler/scala/reflect/macros/contexts/Parsers.scala +++ b/src/compiler/scala/reflect/macros/contexts/Parsers.scala @@ -1,24 +1,20 @@ package scala.reflect.macros package contexts -import scala.language.existentials -import scala.tools.reflect.ToolBox -import scala.tools.reflect.ToolBoxError +import scala.tools.nsc.reporters.StoreReporter trait Parsers { self: Context => + import global._ - def parse(code: String): Tree = - // todo. provide decent implementation - // see `Typers.typedUseCase` for details - try { - import scala.reflect.runtime.{universe => ru} - val parsed = ru.rootMirror.mkToolBox().parse(code) - val importer = universe.mkImporter(ru) - importer.importTree(parsed) - } catch { - case ToolBoxError(msg, cause) => - // todo. provide a position - throw new ParseException(universe.NoPosition, msg) + def parse(code: String) = { + val sreporter = new StoreReporter() + val unit = new CompilationUnit(newSourceFile(code, "<macro>")) { override def reporter = sreporter } + val parser = newUnitParser(unit) + val tree = gen.mkTreeOrBlock(parser.parseStats()) + sreporter.infos.foreach { + case sreporter.Info(pos, msg, sreporter.ERROR) => throw ParseException(pos, msg) } -} + tree + } +}
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/CompilationUnits.scala b/src/compiler/scala/tools/nsc/CompilationUnits.scala index f7437e4e6c..1de5c1f626 100644 --- a/src/compiler/scala/tools/nsc/CompilationUnits.scala +++ b/src/compiler/scala/tools/nsc/CompilationUnits.scala @@ -9,8 +9,9 @@ import util.FreshNameCreator import scala.reflect.internal.util.{ SourceFile, NoSourceFile } import scala.collection.mutable import scala.collection.mutable.{ LinkedHashSet, ListBuffer } +import scala.tools.nsc.reporters.Reporter -trait CompilationUnits { self: Global => +trait CompilationUnits { global: Global => /** An object representing a missing compilation unit. */ @@ -119,6 +120,8 @@ trait CompilationUnits { self: Global => */ val icode: LinkedHashSet[icodes.IClass] = new LinkedHashSet + def reporter = global.reporter + def echo(pos: Position, msg: String) = reporter.echo(pos, msg) diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 19fb2a9289..f3a2d49697 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -110,7 +110,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter) } /** A spare instance of TreeBuilder left for backwards compatibility. */ - lazy val treeBuilder: TreeBuilder { val global: Global.this.type } = new syntaxAnalyzer.ParserTreeBuilder + lazy val treeBuilder: TreeBuilder { val global: Global.this.type } = new UnitTreeBuilder { + val global: Global.this.type = Global.this; + val unit = currentUnit + } /** Fold constants */ object constfold extends { @@ -1159,11 +1162,20 @@ class Global(var currentSettings: Settings, var reporter: Reporter) warning("there were %d %s warning(s); re-run with %s for details".format(warnings.size, what, option.name)) } - def newCompilationUnit(code: String) = new CompilationUnit(newSourceFile(code)) - def newSourceFile(code: String) = new BatchSourceFile("<console>", code) - def newUnitScanner(unit: CompilationUnit): UnitScanner = new UnitScanner(unit) - def newUnitParser(unit: CompilationUnit): UnitParser = new UnitParser(unit) - def newUnitParser(code: String): UnitParser = newUnitParser(newCompilationUnit(code)) + def newSourceFile(code: String, filename: String = "<console>") = + new BatchSourceFile(filename, code) + + def newCompilationUnit(code: String, filename: String = "<console>") = + new CompilationUnit(newSourceFile(code, filename)) + + def newUnitScanner(unit: CompilationUnit): UnitScanner = + new UnitScanner(unit) + + def newUnitParser(unit: CompilationUnit): UnitParser = + new UnitParser(unit) + + def newUnitParser(code: String, filename: String = "<console>"): UnitParser = + newUnitParser(newCompilationUnit(code, filename)) /** A Run is a single execution of the compiler on a set of units. */ diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index a974352169..07e24900e9 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -28,20 +28,14 @@ import util.FreshNameCreator */ trait ParsersCommon extends ScannersCommon { self => val global : Global - import global._ + // the use of currentUnit in the parser should be avoided as it might + // cause unexpected behaviour when you work with two units at the + // same time; use Parser.unit instead + import global.{currentUnit => _, _} def newLiteral(const: Any) = Literal(Constant(const)) def literalUnit = newLiteral(()) - class ParserTreeBuilder extends TreeBuilder { - val global: self.global.type = self.global - def freshName(prefix: String): Name = freshTermName(prefix) - def freshTermName(prefix: String): TermName = currentUnit.freshTermName(prefix) - def freshTypeName(prefix: String): TypeName = currentUnit.freshTypeName(prefix) - def o2p(offset: Int): Position = new OffsetPosition(currentUnit.source, offset) - def r2p(start: Int, mid: Int, end: Int): Position = rangePos(currentUnit.source, start, mid, end) - } - /** This is now an abstract class, only to work around the optimizer: * methods in traits are never inlined. */ @@ -172,6 +166,7 @@ self => private val globalFresh = new FreshNameCreator.Default + def unit = global.currentUnit def freshName(prefix: String): Name = freshTermName(prefix) def freshTermName(prefix: String): TermName = newTermName(globalFresh.newName(prefix)) def freshTypeName(prefix: String): TypeName = newTypeName(globalFresh.newName(prefix)) @@ -196,7 +191,7 @@ self => * that we don't have the xml library on the compilation classpath. */ private[this] lazy val xmlp = { - currentUnit.encounteredXml(o2p(in.offset)) + unit.encounteredXml(o2p(in.offset)) new MarkupParser(this, preserveWS = true) } @@ -225,7 +220,7 @@ self => override def templateBody(isPre: Boolean) = skipBraces((emptyValDef, EmptyTree.asList)) } - class UnitParser(val unit: global.CompilationUnit, patches: List[BracePatch]) extends SourceFileParser(unit.source) { + class UnitParser(override val unit: global.CompilationUnit, patches: List[BracePatch]) extends SourceFileParser(unit.source) { uself => def this(unit: global.CompilationUnit) = this(unit, Nil) override def newScanner() = new UnitScanner(unit, patches) @@ -298,9 +293,10 @@ self => import nme.raw - abstract class Parser extends ParserCommon { + abstract class Parser extends ParserCommon { parser => val in: Scanner + def unit: CompilationUnit def freshName(prefix: String): Name def freshTermName(prefix: String): TermName def freshTypeName(prefix: String): TypeName @@ -310,8 +306,12 @@ self => /** whether a non-continuable syntax error has been seen */ private var lastErrorOffset : Int = -1 + class ParserTreeBuilder extends UnitTreeBuilder { + val global: self.global.type = self.global + def unit = parser.unit + } val treeBuilder = new ParserTreeBuilder - import treeBuilder.{global => _, _} + import treeBuilder.{global => _, unit => _, _} /** The types of the context bounds of type parameters of the surrounding class */ diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 8ea0ceddbb..91ff530e05 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -8,6 +8,7 @@ package ast.parser import symtab.Flags._ import scala.collection.mutable.ListBuffer +import scala.reflect.internal.util.OffsetPosition /** Methods for building trees, used in the parser. All the trees * returned by this class must be untyped. @@ -529,3 +530,13 @@ abstract class TreeBuilder { } } } + +abstract class UnitTreeBuilder extends TreeBuilder { + import global._ + def unit: CompilationUnit + def freshName(prefix: String): Name = freshTermName(prefix) + def freshTermName(prefix: String): TermName = unit.freshTermName(prefix) + def freshTypeName(prefix: String): TypeName = unit.freshTypeName(prefix) + def o2p(offset: Int): Position = new OffsetPosition(unit.source, offset) + def r2p(start: Int, mid: Int, end: Int): Position = rangePos(unit.source, start, mid, end) +} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index edb1c55224..8d025b5451 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -1479,7 +1479,7 @@ abstract class GenASM extends SubComponent with BytecodeWriters with GenJVMASM { sym.owner.isSynthetic && sym.owner.tpe.parents.exists { t => val TypeRef(_, sym, _) = t - FunctionClass contains sym + FunctionClass.seq contains sym } } diff --git a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala index 34e2a8a96a..04c5bdf824 100644 --- a/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala +++ b/src/compiler/scala/tools/nsc/reporters/StoreReporter.scala @@ -14,7 +14,7 @@ import scala.reflect.internal.util.Position * console. */ class StoreReporter extends Reporter { - class Info(val pos: Position, val msg: String, val severity: Severity) { + case class Info(pos: Position, msg: String, severity: Severity) { override def toString() = "pos: " + pos + " " + msg + " " + severity } val infos = new mutable.LinkedHashSet[Info] diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index 57ebe1b30d..b77a536caf 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -273,15 +273,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => def parse(code: String): Tree = { reporter.reset() - val file = new BatchSourceFile("<toolbox>", code) - val unit = new CompilationUnit(file) - val parsed = newUnitParser(unit).parseStats() + val tree = gen.mkTreeOrBlock(newUnitParser(code, "<toolbox>").parseStats()) throwIfErrors() - parsed match { - case Nil => EmptyTree - case expr :: Nil => expr - case stats :+ expr => Block(stats, expr) - } + tree } def showAttributed(artifact: Any, printTypes: Boolean = true, printIds: Boolean = true, printKinds: Boolean = false): String = { @@ -355,7 +349,8 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } def inferImplicitView(tree: u.Tree, from: u.Type, to: u.Type, silent: Boolean = true, withMacrosDisabled: Boolean = false, pos: u.Position = u.NoPosition): u.Tree = { - val viewTpe = u.appliedType(u.definitions.FunctionClass(1).toTypeConstructor, List(from, to)) + val functionTypeCtor = u.definitions.FunctionClass(1).asClass.toTypeConstructor + val viewTpe = u.appliedType(functionTypeCtor, List(from, to)) inferImplicit(tree, viewTpe, isView = true, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) } diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala index 19888fa8d2..5a1a25cfa1 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Parsers.scala @@ -49,7 +49,7 @@ trait Parsers { self: Quasiquotes => def entryPoint: QuasiquoteParser => Tree - class QuasiquoteParser(source0: SourceFile) extends SourceFileParser(source0) { + class QuasiquoteParser(source0: SourceFile) extends SourceFileParser(source0) { parser => def isHole: Boolean = isIdent && isHole(in.name) def isHole(name: Name): Boolean = holeMap.contains(name) @@ -73,7 +73,7 @@ trait Parsers { self: Quasiquotes => override def makeFunctionTypeTree(argtpes: List[Tree], restpe: Tree): Tree = AppliedTypeTree(Ident(tpnme.QUASIQUOTE_FUNCTION), argtpes :+ restpe) } - import treeBuilder.{global => _, _} + import treeBuilder.{global => _, unit => _, _} // q"def foo($x)" override def allowTypelessParams = true @@ -144,11 +144,7 @@ trait Parsers { self: Quasiquotes => } object TermParser extends Parser { - def entryPoint = _.templateStats() match { - case Nil => EmptyTree - case tree :: Nil => tree - case stats :+ tree => Block(stats, tree) - } + def entryPoint = { parser => gen.mkTreeOrBlock(parser.templateStats()) } } object TypeParser extends Parser { diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala index af4e34536c..c2d8bcdcd6 100644 --- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala +++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala @@ -228,6 +228,8 @@ trait Reifiers { self: Quasiquotes => override def reifyTreeSyntactically(tree: Tree): Tree = tree match { case RefTree(qual, SymbolPlaceholder(tree)) => mirrorBuildCall(nme.RefTree, reify(qual), tree) + case This(SymbolPlaceholder(tree)) => + mirrorCall(nme.This, tree) case _ => super.reifyTreeSyntactically(tree) } diff --git a/src/reflect/scala/reflect/api/FlagSets.scala b/src/reflect/scala/reflect/api/FlagSets.scala index 8a1d2f7f1d..3d5a213f2f 100644 --- a/src/reflect/scala/reflect/api/FlagSets.scala +++ b/src/reflect/scala/reflect/api/FlagSets.scala @@ -166,6 +166,9 @@ trait FlagSets { self: Universe => /** Flag indicating that tree represents a variable or a member initialized to the default value */ val DEFAULTINIT: FlagSet + + /** Flag indicating that tree was generated by the compiler */ + val SYNTHETIC: FlagSet } /** The empty set of flags diff --git a/src/reflect/scala/reflect/api/StandardDefinitions.scala b/src/reflect/scala/reflect/api/StandardDefinitions.scala index bbfebcb434..e255d305f7 100644 --- a/src/reflect/scala/reflect/api/StandardDefinitions.scala +++ b/src/reflect/scala/reflect/api/StandardDefinitions.scala @@ -214,29 +214,35 @@ trait StandardDefinitions { /** The module symbol of module `scala.Some`. */ def SomeModule: ModuleSymbol - /** The array of class symbols for classes `scala.ProductX`. + /** Function-like object that maps arity to symbols for classes `scala.ProductX`. * - 0th element is `Unit` * - 1st element is `Product1` * - ... * - 22nd element is `Product22` + * - 23nd element is `NoSymbol` + * - ... */ - def ProductClass : Array[ClassSymbol] + def ProductClass: Int => Symbol - /** The array of class symbols for classes `scala.FunctionX`. + /** Function-like object that maps arity to symbols for classes `scala.FunctionX`. * - 0th element is `Function0` * - 1st element is `Function1` * - ... * - 22nd element is `Function22` + * - 23nd element is `NoSymbol` + * - ... */ - def FunctionClass : Array[ClassSymbol] + def FunctionClass: Int => Symbol - /** The array of class symbols for classes `scala.TupleX`. + /** Function-like object that maps arity to symbols for classes `scala.TupleX`. * - 0th element is `NoSymbol` * - 1st element is `Product1` * - ... * - 22nd element is `Product22` + * - 23nd element is `NoSymbol` + * - ... */ - def TupleClass: Array[Symbol] // cannot make it Array[ClassSymbol], because TupleClass(0) is supposed to be NoSymbol. weird + def TupleClass: Int => Symbol /** Contains Scala primitive value classes: * - Byte diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index 443f34ccae..7a627bc875 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -2210,13 +2210,13 @@ trait Trees { self: Universe => * Flattens directly nested blocks. * @group Factories */ - @deprecated("Use the canonical Block constructor, explicitly specifying its expression if necessary. Flatten directly nested blocks manually if needed", "2.10.1") + @deprecated("Use q\"{..$stats}\" instead. Flatten directly nested blocks manually if needed", "2.10.1") def Block(stats: Tree*): Block /** A factory method for `CaseDef` nodes. * @group Factories */ - @deprecated("Use the canonical CaseDef constructor passing EmptyTree for guard", "2.10.1") + @deprecated("Use cq\"$pat => $body\" instead", "2.10.1") def CaseDef(pat: Tree, body: Tree): CaseDef /** A factory method for `Bind` nodes. @@ -2228,50 +2228,50 @@ trait Trees { self: Universe => /** A factory method for `Try` nodes. * @group Factories */ - @deprecated("Use canonical CaseDef constructors to to create exception catching expressions and then wrap them in Try", "2.10.1") + @deprecated("Convert cases into casedefs and use q\"try $body catch { case ..$newcases }\" instead", "2.10.1") def Try(body: Tree, cases: (Tree, Tree)*): Try /** A factory method for `Throw` nodes. * @group Factories */ - @deprecated("Use the canonical New constructor to create an object instantiation expression and then wrap it in Throw", "2.10.1") + @deprecated("Use q\"throw new $tpe(..$args)\" instead", "2.10.1") def Throw(tpe: Type, args: Tree*): Throw /** Factory method for object creation `new tpt(args_1)...(args_n)` * A `New(t, as)` is expanded to: `(new t).<init>(as)` * @group Factories */ - @deprecated("Use Apply(...Apply(Select(New(tpt), nme.CONSTRUCTOR), args1)...argsN) instead", "2.10.1") + @deprecated("Use q\"new $tpt(...$argss)\" instead", "2.10.1") def New(tpt: Tree, argss: List[List[Tree]]): Tree /** 0-1 argument list new, based on a type. * @group Factories */ - @deprecated("Use New(TypeTree(tpe), args.toList) instead", "2.10.1") + @deprecated("Use q\"new $tpe(..$args)\" instead", "2.10.1") def New(tpe: Type, args: Tree*): Tree /** 0-1 argument list new, based on a symbol. * @group Factories */ - @deprecated("Use New(sym.toType, args) instead", "2.10.1") + @deprecated("Use q\"new ${sym.toType}(..$args)\" instead", "2.10.1") def New(sym: Symbol, args: Tree*): Tree /** A factory method for `Apply` nodes. * @group Factories */ - @deprecated("Use Apply(Ident(sym), args.toList) instead", "2.10.1") + @deprecated("Use q\"$sym(..$args)\" instead", "2.10.1") def Apply(sym: Symbol, args: Tree*): Tree /** 0-1 argument list new, based on a type tree. * @group Factories */ - @deprecated("Use Apply(Select(New(tpt), nme.CONSTRUCTOR), args) instead", "2.10.1") + @deprecated("Use q\"new $tpt(..$args)\" instead", "2.10.1") def ApplyConstructor(tpt: Tree, args: List[Tree]): Tree /** A factory method for `Super` nodes. * @group Factories */ - @deprecated("Use Super(This(sym), mix) instead", "2.10.1") + @deprecated("Use q\"$sym.super[$mix].x\".qualifier instead", "2.10.1") def Super(sym: Symbol, mix: TypeName): Tree /** A factory method for `This` nodes. @@ -2283,7 +2283,7 @@ trait Trees { self: Universe => * The string `name` argument is assumed to represent a [[scala.reflect.api.Names#TermName `TermName`]]. * @group Factories */ - @deprecated("Use Select(tree, newTermName(name)) instead", "2.10.1") + @deprecated("Use Select(tree, TermName(name)) instead", "2.10.1") def Select(qualifier: Tree, name: String): Select /** A factory method for `Select` nodes. @@ -2294,7 +2294,7 @@ trait Trees { self: Universe => /** A factory method for `Ident` nodes. * @group Factories */ - @deprecated("Use Ident(newTermName(name)) instead", "2.10.1") + @deprecated("Use Ident(TermName(name)) instead", "2.10.1") def Ident(name: String): Ident /** A factory method for `Ident` nodes. diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala index 06a6e10c30..2584dcb117 100644 --- a/src/reflect/scala/reflect/internal/BuildUtils.scala +++ b/src/reflect/scala/reflect/internal/BuildUtils.scala @@ -5,7 +5,7 @@ package internal import Flags._ trait BuildUtils { self: SymbolTable => - import definitions.{TupleClass, FunctionClass, MaxTupleArity, MaxFunctionArity, ScalaPackage, UnitClass} + import definitions.{TupleClass, FunctionClass, ScalaPackage, UnitClass} class BuildImpl extends BuildApi { @@ -271,32 +271,30 @@ trait BuildUtils { self: SymbolTable => } } private object TupleClassRef extends ScalaMemberRef { - val symbols = TupleClass.filter { _ != null }.toSeq + val symbols = TupleClass.seq } private object TupleCompanionRef extends ScalaMemberRef { - val symbols = TupleClassRef.symbols.map { _.companionModule } + val symbols = TupleClass.seq.map { _.companionModule } } private object UnitClassRef extends ScalaMemberRef { val symbols = Seq(UnitClass) } private object FunctionClassRef extends ScalaMemberRef { - val symbols = FunctionClass.toSeq + val symbols = FunctionClass.seq } object SyntacticTuple extends SyntacticTupleExtractor { def apply(args: List[Tree]): Tree = args match { case Nil => Literal(Constant(())) case _ => - require(args.length <= MaxTupleArity, s"Tuples with arity bigger than $MaxTupleArity aren't supported") + require(TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported") self.Apply(TupleClass(args.length).companionModule, args: _*) } def unapply(tree: Tree): Option[List[Tree]] = tree match { case Literal(Constant(())) => Some(Nil) - case Apply(TupleCompanionRef(sym), args) - if args.length <= MaxTupleArity - && sym == TupleClass(args.length).companionModule => + case Apply(TupleCompanionRef(sym), args) if sym == TupleClass(args.length).companionModule => Some(args) case _ => None @@ -307,15 +305,14 @@ trait BuildUtils { self: SymbolTable => def apply(args: List[Tree]): Tree = args match { case Nil => self.Select(self.Ident(nme.scala_), tpnme.Unit) case _ => - require(args.length <= MaxTupleArity, s"Tuples with arity bigger than $MaxTupleArity aren't supported") + require(TupleClass(args.length).exists, s"Tuples with ${args.length} arity aren't supported") AppliedTypeTree(Ident(TupleClass(args.length)), args) } def unapply(tree: Tree): Option[List[Tree]] = tree match { case UnitClassRef(_) => Some(Nil) - case AppliedTypeTree(TupleClassRef(sym), args) - if args.length <= MaxTupleArity && sym == TupleClass(args.length) => + case AppliedTypeTree(TupleClassRef(sym), args) if sym == TupleClass(args.length) => Some(args) case _ => None @@ -324,13 +321,12 @@ trait BuildUtils { self: SymbolTable => object SyntacticFunctionType extends SyntacticFunctionTypeExtractor { def apply(argtpes: List[Tree], restpe: Tree): Tree = { - require(argtpes.length <= MaxFunctionArity + 1, s"Function types with arity bigger than $MaxFunctionArity aren't supported") + require(FunctionClass(argtpes.length).exists, s"Function types with ${argtpes.length} arity aren't supported") gen.mkFunctionTypeTree(argtpes, restpe) } def unapply(tree: Tree): Option[(List[Tree], Tree)] = tree match { - case AppliedTypeTree(FunctionClassRef(sym), args @ (argtpes :+ restpe)) - if args.length - 1 <= MaxFunctionArity && sym == FunctionClass(args.length - 1) => + case AppliedTypeTree(FunctionClassRef(sym), args @ (argtpes :+ restpe)) if sym == FunctionClass(args.length - 1) => Some((argtpes, restpe)) case _ => None } diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index c56637874c..ed1c3f1044 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -585,30 +585,29 @@ trait Definitions extends api.StandardDefinitions { def hasJavaMainMethod(sym: Symbol): Boolean = (sym.tpe member nme.main).alternatives exists isJavaMainMethod - // Product, Tuple, Function, AbstractFunction - private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[ClassSymbol] = { - val list = countFrom to arity map (i => getRequiredClass("scala." + name + i)) - list.toArray - } - def prepend[S >: ClassSymbol : ClassTag](elem0: S, elems: Array[ClassSymbol]): Array[S] = elem0 +: elems - - private def aritySpecificType[S <: Symbol](symbolArray: Array[S], args: List[Type], others: Type*): Type = { - val arity = args.length - if (arity >= symbolArray.length) NoType - else appliedType(symbolArray(arity), args ++ others: _*) + class VarArityClass(name: String, maxArity: Int, countFrom: Int = 0, init: Option[ClassSymbol] = None) extends (Int => Symbol) { + private val offset = countFrom - init.size + private def isDefinedAt(i: Int) = i < seq.length + offset && i >= offset + val seq: IndexedSeq[ClassSymbol] = (init ++: countFrom.to(maxArity).map { i => getRequiredClass("scala." + name + i) }).toVector + def apply(i: Int) = if (isDefinedAt(i)) seq(i - offset) else NoSymbol + def specificType(args: List[Type], others: Type*): Type = { + val arity = args.length + if (!isDefinedAt(arity)) NoType + else appliedType(apply(arity), args ++ others: _*) + } } val MaxTupleArity, MaxProductArity, MaxFunctionArity = 22 - lazy val ProductClass: Array[ClassSymbol] = prepend(UnitClass, mkArityArray("Product", MaxProductArity, 1)) - lazy val TupleClass: Array[Symbol] = prepend(null, mkArityArray("Tuple", MaxTupleArity, 1)) - lazy val FunctionClass = mkArityArray("Function", MaxFunctionArity, 0) - lazy val AbstractFunctionClass = mkArityArray("runtime.AbstractFunction", MaxFunctionArity, 0) + lazy val ProductClass = new VarArityClass("Product", MaxProductArity, countFrom = 1, init = Some(UnitClass)) + lazy val TupleClass = new VarArityClass("Tuple", MaxTupleArity, countFrom = 1) + lazy val FunctionClass = new VarArityClass("Function", MaxFunctionArity) + lazy val AbstractFunctionClass = new VarArityClass("runtime.AbstractFunction", MaxFunctionArity) /** Creators for TupleN, ProductN, FunctionN. */ - def tupleType(elems: List[Type]) = aritySpecificType(TupleClass, elems) - def functionType(formals: List[Type], restpe: Type) = aritySpecificType(FunctionClass, formals, restpe) - def abstractFunctionType(formals: List[Type], restpe: Type) = aritySpecificType(AbstractFunctionClass, formals, restpe) + def tupleType(elems: List[Type]) = TupleClass.specificType(elems) + def functionType(formals: List[Type], restpe: Type) = FunctionClass.specificType(formals, restpe) + def abstractFunctionType(formals: List[Type], restpe: Type) = AbstractFunctionClass.specificType(formals, restpe) def wrapArrayMethodName(elemtp: Type): TermName = elemtp.typeSymbol match { case ByteClass => nme.wrapByteArray @@ -625,12 +624,11 @@ trait Definitions extends api.StandardDefinitions { else nme.genericWrapArray } - // NOTE: returns true for NoSymbol since it's included in the TupleClass array -- is this intensional? - def isTupleSymbol(sym: Symbol) = TupleClass contains unspecializedSymbol(sym) - def isProductNClass(sym: Symbol) = ProductClass contains sym + def isTupleSymbol(sym: Symbol) = TupleClass.seq contains unspecializedSymbol(sym) + def isProductNClass(sym: Symbol) = ProductClass.seq contains sym def tupleField(n: Int, j: Int) = getMemberValue(TupleClass(n), nme.productAccessorName(j)) - def isFunctionSymbol(sym: Symbol) = FunctionClass contains unspecializedSymbol(sym) - def isProductNSymbol(sym: Symbol) = ProductClass contains unspecializedSymbol(sym) + def isFunctionSymbol(sym: Symbol) = FunctionClass.seq contains unspecializedSymbol(sym) + def isProductNSymbol(sym: Symbol) = ProductClass.seq contains unspecializedSymbol(sym) def unspecializedSymbol(sym: Symbol): Symbol = { if (sym hasFlag SPECIALIZED) { @@ -1233,7 +1231,7 @@ trait Definitions extends api.StandardDefinitions { lazy val symbolsNotPresentInBytecode = syntheticCoreClasses ++ syntheticCoreMethods ++ hijackedCoreClasses /** Is the symbol that of a parent which is added during parsing? */ - lazy val isPossibleSyntheticParent = ProductClass.toSet[Symbol] + ProductRootClass + SerializableClass + lazy val isPossibleSyntheticParent = ProductClass.seq.toSet[Symbol] + ProductRootClass + SerializableClass private lazy val boxedValueClassesSet = boxedClass.values.toSet[Symbol] + BoxedUnitClass diff --git a/src/reflect/scala/reflect/internal/FlagSets.scala b/src/reflect/scala/reflect/internal/FlagSets.scala index 961adb2c57..84825ff2da 100644 --- a/src/reflect/scala/reflect/internal/FlagSets.scala +++ b/src/reflect/scala/reflect/internal/FlagSets.scala @@ -42,5 +42,6 @@ trait FlagSets extends api.FlagSets { self: SymbolTable => val DEFAULTPARAM : FlagSet = Flags.DEFAULTPARAM val PRESUPER : FlagSet = Flags.PRESUPER val DEFAULTINIT : FlagSet = Flags.DEFAULTINIT + val SYNTHETIC : FlagSet = Flags.SYNTHETIC } } diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index 07fa6fb317..26adf20c52 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -437,4 +437,10 @@ abstract class TreeGen extends macros.TreeBuilder { else if (!stats.last.isTerm) Block(stats, Literal(Constant(()))) else if (stats.length == 1) stats.head else Block(stats.init, stats.last) + + def mkTreeOrBlock(stats: List[Tree]) = stats match { + case Nil => EmptyTree + case head :: Nil => head + case _ => gen.mkBlock(stats) + } } diff --git a/test/files/run/macro-parse-position-malformed.check b/test/files/run/macro-parse-position-malformed.check new file mode 100644 index 0000000000..00f0bc5b62 --- /dev/null +++ b/test/files/run/macro-parse-position-malformed.check @@ -0,0 +1 @@ +failed with 'source-<macro>,line-1,offset=7' position and '')' expected but eof found.' message diff --git a/test/files/run/macro-parse-position-malformed/Impls_Macros_1.scala b/test/files/run/macro-parse-position-malformed/Impls_Macros_1.scala new file mode 100644 index 0000000000..2417eb6897 --- /dev/null +++ b/test/files/run/macro-parse-position-malformed/Impls_Macros_1.scala @@ -0,0 +1,17 @@ +import scala.language.experimental.macros +import scala.reflect.macros.{Context => Ctx, ParseException} + +object Macros { + def impl(c: Ctx)() = { + import c.universe._ + val out = try { + c.parse("foo(bar") + "didn't fail" + } catch { + case e: ParseException => + s"failed with '${e.pos}' position and '${e.msg}' message" + } + c.Expr[String](Literal(Constant(out))) + } + def foo(): String = macro impl +}
\ No newline at end of file diff --git a/test/files/run/macro-parse-position-malformed/Test_2.scala b/test/files/run/macro-parse-position-malformed/Test_2.scala new file mode 100644 index 0000000000..cff569bd81 --- /dev/null +++ b/test/files/run/macro-parse-position-malformed/Test_2.scala @@ -0,0 +1,3 @@ +object Test extends App { + println(Macros.foo) +} diff --git a/test/files/run/macro-parse-position.check b/test/files/run/macro-parse-position.check new file mode 100644 index 0000000000..3da0320696 --- /dev/null +++ b/test/files/run/macro-parse-position.check @@ -0,0 +1,5 @@ +false +source-<macro>,line-1,offset=4 +8 +foo bar + diff --git a/test/files/run/macro-parse-position/Impls_Macros_1.scala b/test/files/run/macro-parse-position/Impls_Macros_1.scala new file mode 100644 index 0000000000..b6f1ebbcd5 --- /dev/null +++ b/test/files/run/macro-parse-position/Impls_Macros_1.scala @@ -0,0 +1,12 @@ +import scala.language.experimental.macros +import scala.reflect.macros.{Context => Ctx} + +object Macros { + def impl(c: Ctx)() = { + import c.universe._ + val t = c.parse("foo bar") + val out = s"${t.pos == NoPosition}\n${t.pos}\n${t.pos.source.content.length}\n${new String(t.pos.source.content)}" + c.Expr[String](Literal(Constant(out))) + } + def foo(): String = macro impl +}
\ No newline at end of file diff --git a/test/files/run/macro-parse-position/Test_2.scala b/test/files/run/macro-parse-position/Test_2.scala new file mode 100644 index 0000000000..cff569bd81 --- /dev/null +++ b/test/files/run/macro-parse-position/Test_2.scala @@ -0,0 +1,3 @@ +object Test extends App { + println(Macros.foo) +} diff --git a/test/files/run/reify_copypaste1.scala b/test/files/run/reify_copypaste1.scala index b2eef28026..cf813182ae 100644 --- a/test/files/run/reify_copypaste1.scala +++ b/test/files/run/reify_copypaste1.scala @@ -12,7 +12,7 @@ object Test extends App { val reify = Select(Select(Select(Select(Ident(ScalaPackage), TermName("reflect")), TermName("runtime")), TermName("universe")), TermName("reify")) val reifee = Block(List(ValDef(Modifiers(LAZY), TermName("x"), TypeTree(), Apply(Ident(ListModule), List(Literal(Constant(1)), Literal(Constant(2)))))), Ident(TermName("x"))) toolBox.eval(Apply(reify, List(reifee))) - val Block(List(tpeCopypaste), exprCopypaste @ ModuleDef(_, _, Template(_, _, (_ :: stats) :+ expr))) = toolBox.parse(output.toString()) + val Block(List(tpeCopypaste, exprCopypaste @ ModuleDef(_, _, Template(_, _, (_ :: stats) :+ expr))), Literal(Constant(()))) = toolBox.parse(output.toString()) output.reset() toolBox.eval(Block(stats, expr)) stdout.println(output.toString) diff --git a/test/files/scalacheck/quasiquotes/DeprecationProps.scala b/test/files/scalacheck/quasiquotes/DeprecationProps.scala new file mode 100644 index 0000000000..8e1601cf9d --- /dev/null +++ b/test/files/scalacheck/quasiquotes/DeprecationProps.scala @@ -0,0 +1,52 @@ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._ + +object DeprecationProps extends QuasiquoteProperties("deprecation") { + val tname = TypeName("Foo") + val tpt = tq"Foo" + val tpe = typeOf[Int] + val sym = tpe.typeSymbol.asType + val argss = List(q"x") :: List(q"y") :: Nil + val args = q"x" :: q"y" :: Nil + + property("new tpt argss") = test { + assert(q"new $tpt(...$argss)" ≈ New(tpt, argss)) + } + + property("new tpe args") = test { + assert(q"new $tpe(..$args)" ≈ New(tpe, args: _*)) + } + + property("new tpe args") = test { + assert(q"new ${sym.toType}(..$args)" ≈ New(sym, args: _*)) + } + + property("apply sym args") = test { + assert(q"$sym(..$args)" ≈ Apply(sym, args: _*)) + } + + property("applyconstructor") = test { + assert(q"new $tpt(..$args)" ≈ ApplyConstructor(tpt, args)) + } + + property("super sym name") = test { + assert(q"$sym.super[$tname].x".qualifier ≈ Super(sym, tname)) + } + + property("throw tpe args") = test { + assert(q"throw new $tpe(..$args)" ≈ Throw(tpe, args: _*)) + } + + property("casedef pat body") = test { + val pat = pq"foo" + val body = q"bar" + assert(cq"$pat => $body" ≈ CaseDef(pat, body)) + } + + property("try body cases") = test { + val cases = (pq"a", q"b") :: (pq"c", q"d") :: Nil + val newcases = cases.map { case (pat, body) => cq"$pat => $body" } + val body = q"foo" + assert(q"try $body catch { case ..$newcases }" ≈ Try(body, cases: _*)) + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/Test.scala b/test/files/scalacheck/quasiquotes/Test.scala index 05097711ef..f41d961888 100644 --- a/test/files/scalacheck/quasiquotes/Test.scala +++ b/test/files/scalacheck/quasiquotes/Test.scala @@ -11,4 +11,5 @@ object Test extends Properties("quasiquotes") { include(ErrorProps) include(DefinitionConstructionProps) include(DefinitionDeconstructionProps) -}
\ No newline at end of file + include(DeprecationProps) +} |