summaryrefslogtreecommitdiff
path: root/sources/scala/tools/nsc/typechecker/Analyzer.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2005-02-09 19:00:27 +0000
committerMartin Odersky <odersky@gmail.com>2005-02-09 19:00:27 +0000
commit1addfa71cfc6b01b0a9494b1fedb263be61f3477 (patch)
tree94705e3a3b4c51963b38104032ad0e57c3dc845f /sources/scala/tools/nsc/typechecker/Analyzer.scala
parentd554c8332b3201b62f6d6571bb9b15ab83bdc09b (diff)
downloadscala-1addfa71cfc6b01b0a9494b1fedb263be61f3477.tar.gz
scala-1addfa71cfc6b01b0a9494b1fedb263be61f3477.tar.bz2
scala-1addfa71cfc6b01b0a9494b1fedb263be61f3477.zip
*** empty log message ***
Diffstat (limited to 'sources/scala/tools/nsc/typechecker/Analyzer.scala')
-rw-r--r--sources/scala/tools/nsc/typechecker/Analyzer.scala3022
1 files changed, 4 insertions, 3018 deletions
diff --git a/sources/scala/tools/nsc/typechecker/Analyzer.scala b/sources/scala/tools/nsc/typechecker/Analyzer.scala
index 537e8c980e..a0fa41d665 100644
--- a/sources/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/sources/scala/tools/nsc/typechecker/Analyzer.scala
@@ -1,3027 +1,13 @@
package scala.tools.nsc.typechecker;
import scala.tools.util.Position;
-import nsc._;
-import nsc.util._;
-import nsc.ast._;
-import nsc.symtab._;
-import nsc.symtab._;
-import Tree._;
-import java.util.HashMap;
-import scala.tools.scalac.util.NewArray;
-import java.lang.{Boolean, Byte, Short, Character, Integer, Object}
/** The main attribution phase.
*/
-abstract class Enter(c: Context): Analyzer {
+abstract class Analyzer extends Contexts with Namers with Typers with TypeCheckers {
+ val global: Global;
- import Flags._;
+ import global._;
- val contexts = new HashMap[CompilationUnit,Context];
-
- class Enter(startcontext: Context, unit: CompilationUnit) {
- var context = new Context(Tree.Empty, startContext);
- contexts(unit) = context;
- enterSyms(unit.body);
-
- def doubleDefError(pos: int, sym: Symbol): unit =
- error(pos,
- sym.name + " is already defined as " +
- (if ((sym.rawflags & CASE) != 0) "case class " + sym.name else sym.toString()));
-
- def updatePosFlags(sym: Symbol, pos: int, mods: int): Symbol = {
- val sym1 = if (sym.isExternal && !sym.isPackage) sym
- else { doubleDefError(pos, sym); sym.cloneSymbol }
- sym1.pos = pos;
- val oldflags = sym1.rawflags & (INITIALIZED | LOCKED);
- val newflags = mods & ~(INITIALIZED | LOCKED);
- sym1.rawflags = oldflags | newflags;
- if (sym1.isModule)
- updatePosFlags(sym1.moduleClass, pos, (mods & MODULE2CLASSFLAGS) | MODULE | FINAL)
- }
-
- def enterPackageSymbol(pos: int, name: Name): Symbol = {
- val p: Symbol = context.scope.lookup(name);
- if (p.isPackage) {
- p.pos = pos; p.moduleClass.pos = pos; p
- } else {
- val newp = context.owner.newPackage(pos, name);
- if (p == NoSymbol) context.scope.enter(newp)
- else doubleDefError(pos, p);
- newp
- }
- }
-
- def enterClassSymbol(pos: int, mods: int, name: Name): Symbol = {
- val c: Symbol = context.scope.lookup(name);
- if (c.isType) {
- updatePosFlags(c, pos, mods)
- } else {
- val newc = context.owner.newClass(pos, name).setFlags(mods);
- context.scope.enter(newc);
- newc
- }
- }
-
- def enterModuleSymbol(pos: int, mods: int, name: Name): Symbol = {
- val m: Symbol = context.scope.lookup(name);
- if (m.isModule) {
- updatePosFlags(m, pos, mods)
- } else {
- val newm = context.owner.newModule(pos, name);
- newm.setFlags(mods);
- newm.moduleClass.setFlags(mods);
- context.scope.enter(newm);
- newm
- }
- }
-
- def enterCaseFactorySymbol(pos: int, mods: int, name: Name): Symbol = {
- val m: Symbol = context.scope.lookup(name);
- if (m.isModule) {
- updatePosFlags(m, pos, mods)
- } else {
- val newm = context.owner.newMethod(pos, name).setFlags(mods);
- context.scope.enter(newm);
- newm
- }
- }
-
- def enterSym(tree: Tree): Symbol = {
- def finish = tree.symbol.setInfo(new LazyTreeType(tree));
- def enterAndFinish = { context.scope enter tree.symbol; finish }
- def enterUniqueAndFinish = {
- val prev = context.scope.lookup(tree.symbol.name);
- if (prev != NoSymbol) doubleDefError(tree.pos, prev);
- enterAndFinish
- }
- tree match {
- case PackageDef(name, stats) =>
- tree.symbol = enterPackageSymbol(tree.pos, name);
- val prevContext = pushContext(tree, p.moduleClass, p.info.members);
- enterSyms(stats);
- context = prevContext;
- tree.symbol
- case ClassDef(mods, name, tparams, vparams, tp, impl) =>
- tree.symbol = enterClassSymbol(tree.pos, mods, name);
- if ((mods & (CASE | ABSTRACT)) == CASE) // enter case factory method.
- enterCaseFactorySymbol(tree.pos, mods & ACCESSFLAGS | CASE, name.toTermName())
- .setInfo(new LazyCaseFactory(tree));]
- val constr = tree.symbol.newConstructor(tree.pos)
- .setFlag(tree.symbol.rawflags & CONSTRFLAGS)
- .setInfo(new LazyTreeType(tree));
- finish
- case ModuleDef(mods, name, tp, impl) =>
- tree.symbol = enterModuleSymbol(tree.pos, mods, name);
- tree.symbol.moduleClass.setInfo(new LazyTreeType(tree));
- finish
- case ValDef(mods, name, tp, rhs) =>
- tree.symbol = context.owner.newValue(tree.pos, name).setFlag(mods);
- enterAndFinish
- case DefDef(mods, nme.CONSTRNAME, tparams, vparams, tp, rhs) =>
- val owner = context.owner;
- if (owner.isClass &&
- constext.scope == owner.members &&
- !owner.isModuleClass &&
- !owner.isAnonymousClass &&
- !owner.isRefinementClass)
- error(tree.pos, "constructor definition not allowed here");
- tree.symbol = owner.newConstructor(tree.pos)
- .setFlag(mods | owner.rawflags & CONSTRFLAGS);
- enterAndFinish
- case DefDef(mods, name, tparams, vparams, tp, rhs) =>
- tree.symbol = context.owner.newMethod(tree.pos, name).setFlag(mods);
- enterAndFinish
- case AbsTypeDef(mods, name, lo, hi, vu) =>
- tree.symbol = context.owner.newAbstractType(pos, name);
- enterUniqueAndFinish
- case AliasTypeDef(mods, name, tparams, rhs) =>
- tree.symbol = context.owner.newAlias(pos, name);
- enterUniqueAndFinish
- case Attributed(_, defn) =>
- sym = enterSym(defn)
- case DocDef(_, defn) =>
- sym = enterSym(defn)
-
-
-
-
- val clazz =
- if (mods == SYNTHETIC && name == Names.ANON_CLASS_NAME.toTypeName())
- context.owner.newAnonymousClass(templ.pos, name)
- else
-
- if (!clazz.primaryConstructor().isInitialized())
- clazz.primaryConstructor().setInfo(new LazyTreeType(tree));
- if ((mods & CASE) != 0) {
- if ((mods & ABSTRACT) == 0) {
- // enter case constructor method.
- val cf: Symbol = termSymbol(
- tree.pos, name.toTermName(), owner,
- mods & ACCESSFLAGS | CASE, context.scope);
- enterInScope(cf);
- if (!cf.isInitialized() || cf.info().symbol().isModuleClass()) {
- cf.setInfo(new LazyConstrMethodType(tree));
- }
- }
- }
- enterSym(tree, clazz)
- }
-
- }
-
-
-
- def transformPackageId(tree: Tree): Tree = {
- if (tree.getType() != null) return tree;
- tree match {
- case Tree.Ident(name) =>
- tree
- .setSymbol(packageSymbol(tree.pos, context.owner, name))
- .setType(tree.symbol().getType())
-
- case Tree.Select(qual, name) =>
- val qual1: Tree = transformPackageId(qual);
- val sym: Symbol = packageSymbol(tree.pos, qual1.symbol().moduleClass(), name);
- copy.Select(tree, sym, qual1).setType(sym.getType())
-
- case _ =>
- transform(tree);
- }
- }
-
- def packageSymbol(pos: int, base: Symbol, name: Name): Symbol = {
- var p: Symbol = base.members().lookup(name);
- if (p.isNone()) {
- p = base.newPackage(pos, name);
- base.members().enterNoHide(p);
- } else if (p.isPackage()) {
- // as the package is used, we change its position to make sure
- // its symbol is not reused for a module definition with the
- // same name
- p.pos = Position.FIRSTPOS;
- p.moduleClass().pos = Position.FIRSTPOS;
- } else {
- val dst = if ((p.flags & CASE) != 0) "case class " + name;
- else "" + p;
- error(pos, "package " + name + " has the same name as existing " + dst);
- p = base.newPackage(pos, name);
- }
- p
- }
-
- def moduleSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
- val symbol = termSymbolOrNone(scope, pos, name, flags | MODUL | FINAL);
- if (symbol.isNone()) owner.newModule(pos, flags, name) else symbol;
- }
-
- def termSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
- val symbol = termSymbolOrNone(scope, pos, name, flags);
- if (symbol.isNone()) owner.newTerm(pos, flags, name) else symbol
- }
-
- def classSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
- val symbol = typeSymbolOrNone(scope, pos, CLASS, name, flags);
- if (symbol.isNone()) owner.newClass(pos, flags, name) else symbol
- }
-
- def typeAliasSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
- val symbol = typeSymbolOrNone(scope, pos, ALIAS, name, flags);
- if (symbol.isNone()) owner.newTypeAlias(pos, flags, name) else symbol
- }
-
- def absTypeSymbol(pos: int, name: Name, owner: Symbol, flags: int, scope: Scope): Symbol = {
- val symbol = typeSymbolOrNone(scope, pos, TYPE, name, flags);
- if (symbol.isNone()) owner.newAbstractType(pos, flags, name) else symbol
- }
-
- def termSymbolOrNone(scope: Scope, pos: int, name: Name, flags: int): Symbol = {
- var symbol = getDefinedSymbol(scope, VAL, name);
- if (!symbol.isNone()) {
- if (symbol.isInitialized()) {
- symbol.getType() match {
- case Type$OverloadedType(alts, _) =>
- var i = 0;
- while (i < alts.length && !alts(i).isExternal()) i = i + 1;
- if (i == alts.length)
- throw Debug.abort("missing alternative", Debug.show(symbol));
- if (i == alts.length - 1) symbol.pos = pos;
- symbol = alts(i);
- case _ =>
- }
- }
- updateFlagsAndPos(symbol, pos, flags);
- }
- symbol
- }
-
- def typeSymbolOrNone(scope: Scope, pos: int, kind: int, name: Name, flags: int): Symbol = {
- val symbol = getDefinedSymbol(scope, kind, name);
- if (!symbol.isNone()) {
- updateFlagsAndPos(symbol, pos, flags);
- symbol.allConstructors().pos = pos;
- }
- symbol
- }
-
- def getDefinedSymbol(scope: Scope, kind: int, name: Name): Symbol = {
- val entry = scope.lookupEntry(name);
- val symbol = entry.sym;
- if (entry.owner == scope && symbol.isExternal() && symbol.kind == kind) {
- symbol
- } else {
- Symbol.NONE;
- }
- }
-
- def updateFlagsAndPos(symbol: Symbol, pos: int, flags: int): unit = {
- symbol.pos = pos;
- val oldflags = symbol.flags & (INITIALIZED | LOCKED);
- val newflags = flags & ~(INITIALIZED | LOCKED);
- symbol.flags = oldflags | newflags;
- if (symbol.isModule()) {
- // here we repeat what is done in the constructor of ModuleClassSymbol
- val clasz = symbol.moduleClass();
- val classFlags = (flags & MODULE2CLASSFLAGS) | MODUL | FINAL;
- updateFlagsAndPos(clasz, pos, classFlags);
- clasz.primaryConstructor().flags =
- clasz.primaryConstructor().flags | PRIVATE;
- }
- if (symbol.isType()) {
- // here we repeat what is done in the constructor of TypeSymbol
- val constr = symbol.primaryConstructor();
- val constrFlags = flags & CONSTRFLAGS;
- updateFlagsAndPos(constr, pos, constrFlags);
- }
- }
-
- /** Enter symbol `sym' in current scope. Check for double definitions.
- * Handle overloading.
- */
- def enterInScope(sym: Symbol): unit = {
-
- def covers(presym: Symbol, newsym: Symbol) = {
- if (presym == newsym) true
- else if (!presym.isInitialized()) false
- else presym.getType() match {
- case Type$OverloadedType(alts, _) =>
- var i = 0;
- while (i < alts.length && alts(i) != newsym) i = i + 1;
- i < alts.length
- case _ =>
- false
- }
- }
-
- // handle double and overloaded definitions
- val e: Scope$Entry = context.scope.lookupEntry(sym.name);
- val other: Symbol = e.sym;
- if (covers(other, sym)) {
- if (global.debug) global.log("redefined: " + sym + ":" + sym.rawInfo());
- } else if (e.owner == context.scope) {
- assert(!other.isExternal(), other);
- if (sym.owner().isPackageClass()) {
- if (other.isPackage()) {
- val src = if ((sym.flags & CASE) != 0) "case class " + sym.name;
- else "" + sym;
- error(sym.pos, "" + src + " has the same name as existing " + other);
- } else {
- if (global.compiledNow.get(other) != null) {
- error(sym.pos, "" + sym + " is compiled twice");
- }
- context.scope.unlink(e);
- context.scope.enter(sym);
- }
- } else if (context.owner.kind == CLASS &&
- sym.kind == VAL && other.kind == VAL &&
- ((sym.flags & ACCESSOR) == 0 || (other.flags & ACCESSOR) == 0)
- ||
- (sym.name == Names.view &&
- (sym.flags & (PARAM | SYNTHETIC)) == (PARAM | SYNTHETIC))) {
- e.setSymbol(other.overloadWith(sym));
- } else if (context.owner.kind == CLASS)
- error(sym.pos,
- sym.nameString() + " is already defined as " +
- other + other.locationString());
- else
- error(sym.pos,
- sym.nameString() +
- " is already defined in local scope");
- } else {
- context.scope.enter(sym);
- }
- if (sym.owner().isPackageClass())
- global.compiledNow.put(sym, unit.source);
- }
-
- def outerEnterSym(tree: Tree): Symbol = enterSym(tree);
-
- /** If `tree' is a definition, create a symbol for it with a lazily
- * constructed type, and enter into current scope.
- */
- def enterSym(tree: Tree): Symbol = {
-
- /** Enter `sym' in current scope and make it the symbol of `tree'.
- */
- def enterSym(tree: Tree, sym: Symbol): Symbol = {
- //if (global.debug) System.out.println("entering " + sym);//DEBUG
- if (!sym.isInitialized()) {
- sym.setInfo(new LazyTreeType(tree));
- }
- if (!sym.isConstructor()) {
- val owner: Symbol = sym.owner();
- if (sym.kind == VAL && (sym.flags & (PRIVATE | SEALED)) == 0 &&
- owner != null && owner.kind == CLASS &&
- (owner.flags & FINAL) != 0)
- sym.flags = sym.flags | FINAL;
- enterInScope(sym);
- }
- tree.setSymbol(sym);
- sym
- }
-
- /** Make `sym' the symbol of import `tree' and push an
- * import context.
- */
- def enterImport(tree: Tree, sym: Symbol): Symbol = {
- sym.setInfo(new LazyTreeType(tree));
- tree.setSymbol(sym);
- pushContext(tree, context.owner, context.scope);
- sym
- }
-
- val owner: Symbol = context.owner;
- tree match {
- case Tree.PackageDef(_packaged, templ) =>
- var packaged = _packaged;
- templ match {
- case Tree.Template(_, body) =>
- val prevContext = pushContext(tree, context.owner, context.scope);
- packaged = transformPackageId(packaged);
- tree.asInstanceOf[Tree.PackageDef].packaged = packaged;
- context = prevContext;
- val pkg: Symbol = checkStable(packaged).symbol();
- if (pkg != null && !pkg.isError()) {
- if (pkg.isPackage()) {
- val prevContext = pushContext(templ, pkg.moduleClass(), pkg.members());
- enterSyms(body);
- context = prevContext;
- } else {
- error(tree.pos, "only Java packages allowed for now");
- }
- }
- templ.setSymbol(Symbol.NONE);
- null
- case _ =>
- throw new ApplicationError();
- }
-
- case Tree.Attributed(attr, definition) =>
- outerEnterSym(definition);
-
- case Tree.DocDef(comment, definition) =>
- val sym = outerEnterSym(definition);
- global.mapSymbolComment.put(sym, new Pair(comment, unit));
- sym
-
- case Tree.ClassDef(mods, name, tparams, vparams, _, templ) =>
- val clazz =
- if (mods == SYNTHETIC && name == Names.ANON_CLASS_NAME.toTypeName())
- context.owner.newAnonymousClass(templ.pos, name)
- else
- classSymbol(tree.pos, name, owner, mods, context.scope);
- if (!clazz.primaryConstructor().isInitialized())
- clazz.primaryConstructor().setInfo(new LazyTreeType(tree));
- if ((mods & CASE) != 0) {
- if ((mods & ABSTRACT) == 0) {
- // enter case constructor method.
- val cf: Symbol = termSymbol(
- tree.pos, name.toTermName(), owner,
- mods & ACCESSFLAGS | CASE, context.scope);
- enterInScope(cf);
- if (!cf.isInitialized() || cf.info().symbol().isModuleClass()) {
- cf.setInfo(new LazyConstrMethodType(tree));
- }
- }
- }
- enterSym(tree, clazz)
-
- case Tree.ModuleDef(mods, name, _, _) =>
- var modul = moduleSymbol(tree.pos, name, owner, mods, context.scope);
- val clazz: Symbol = modul.moduleClass();
- if (!clazz.isInitialized()) {
- val info = new LazyTreeType(tree);
- clazz.setInfo(info);
- modul.setInfo(info);
- }
- enterSym(tree, modul)
-
- case Tree.ValDef(mods, name, _, _) =>
- enterSym(tree, termSymbol(tree.pos, name, owner, mods, context.scope))
-
- case Tree.DefDef(mods, name, _, _, _, _) =>
- var sym: Symbol = null;
- if (name == Names.CONSTRUCTOR) {
- var c = context;
- while (c.isImportContext) c = c.outer;
- val clazz: Symbol = c.enclClass.owner;
- if (!(c.tree.isInstanceOf[Tree.Template]) ||
- clazz.isModuleClass() ||
- clazz.isAnonymousClass() ||
- clazz.isCompoundSym() ||
- clazz.isPackageClass())
- error(tree.pos, "constructor definition not allowed here");
- sym = clazz.newConstructor(tree.pos, clazz.flags & CONSTRFLAGS);
- clazz.addConstructor(sym);
- sym.flags = sym.flags | mods;
- } else {
- sym = termSymbol(tree.pos, name, owner, mods, context.scope);
- }
- enterSym(tree, sym);
-
- case Tree.AliasTypeDef(mods, name, _, _) =>
- val tsym: Symbol = typeAliasSymbol(tree.pos, name, owner, mods, context.scope);
- if (!tsym.primaryConstructor().isInitialized())
- tsym.primaryConstructor().setInfo(new LazyTreeType(tree));
- enterSym(tree, tsym)
-
- case Tree.AbsTypeDef(mods, name, _, _) =>
- enterSym(
- tree,
- absTypeSymbol(tree.pos, name, owner, mods, context.scope))
-
- case Tree.Import(expr, selectors) =>
- enterImport(tree,
- Symbol.NONE.newTerm(
- tree.pos, SYNTHETIC, Name.fromString("import " + expr)))
-
- case _ =>
- null
- }
- }
-
- /** Enter all symbols in statement list
- */
- def enterSyms(stats: Array[Tree]): unit = {
- var i = 0; while (i < stats.length) {
- stats(i) = desugarize.Definition(stats(i));
- enterSym(stats(i));
- i = i + 1
- }
- }
-
- def enterParams[t <: Tree](params: Array[t]): Array[Symbol] = {
- var i = 0; while (i < params.length) {
- enterSym(params(i));
- (params(i) : Tree) match {
- case Tree.ValDef(mods, _, _, _) =>
- if ((mods & REPEATED) != 0 && i != params.length - 1)
- error(params(i).pos,
- "`*' parameter must be the last parameter of a `('...`)' section");
- case _ =>
- }
- i = i + 1
- }
- Tree.symbolOf(params.asInstanceOf[Array[Tree]])
- }
-
- def enterParams(vparams: Array[Array[Tree.ValDef]]): Array[Array[Symbol]] = {
- val vparamSyms = new Array[Array[Symbol]](vparams.length);
- var i = 0; while (i < vparams.length) {
- vparamSyms(i) = enterParams(vparams(i));
- i = i + 1
- }
- vparamSyms
- }
-
- /** Re-enter type parameters in current scope.
- */
- def reenterParams(tparams: Array[Tree.AbsTypeDef], tsyms: Array[Symbol]): unit = {
- var i = 0; while (i < tparams.length) {
- tsyms(i).pos = tparams(i).pos;
- tsyms(i).name = tparams(i).name;
- //necessary since tsyms might have been unpickled
- tparams(i).setSymbol(tsyms(i));
- context.scope.enter(tsyms(i));
- i = i + 1
- }
- }
-
- /** Re-enter type and value parameters in current scope.
- */
- def reenterParams(tparams: Array[Tree.AbsTypeDef], vparamss: Array[Array[Tree.ValDef]], mt: Type): unit = {
- var rest: Type = mt;
- rest match {
- case Type$PolyType(tsyms, restp) =>
- reenterParams(tparams, tsyms);
- rest = restp;
- case _ =>
- }
- var j = 0; while (j < vparamss.length) {
- val vparams = vparamss(j);
- rest match {
- case Type$MethodType(vsyms, restp) =>
- var i = 0; while (i < vparams.length) {
- vsyms(i).pos = vparams(i).pos;
- vsyms(i).name = vparams(i).name;
- //necessary since vsyms might have been unpickled
- vparams(i).setSymbol(vsyms(i));
- //potential overload in case this is a view parameter
- context.scope.enterOrOverload(vsyms(i));
- i = i + 1
- }
- rest = restp;
- case _ =>
- }
- j = j + 1
- }
- }
-
- def addInheritedOverloaded(sym: Symbol, tp: Type): unit =
- if (sym.owner().kind == CLASS &&
- !sym.isConstructor() &&
- sym.owner().lookup(sym.name) == sym)
- // it's a class member which is not an overloaded alternative
- sym.addInheritedOverloaded(tp);
-
-
-// Diagnostics ----------------------------------------------------------------
-
- private def errorName(tree: Tree): Name =
- Name.fromString("<error: " + tree + ">");
-
- private def errorTree(tree: Tree): Tree =
- try {
- if (tree.isType()) errorTypeTree(tree) else errorTermTree(tree);
- } catch {
- case ex: Type$Error =>
- Tree.Empty;
- }
-
- private def errorTypeTree(tree: Tree): Tree = {
- val symbol = context.owner.newErrorClass(errorName(tree).toTypeName());
- tree match {
- case Tree.Ident(_) =>
- make.Ident(tree.pos, symbol).setType(symbol.getType());
- case Tree.Select(qualifier, _) =>
- make.Select(tree.pos, symbol, qualifier).setType(symbol.getType());
- case _ =>
- gen.mkType(tree.pos, symbol.getType());
- }
- }
-
- private def errorTermTree(tree: Tree): Tree =
- gen.mkLocalRef(tree.pos, Symbol.NONE.newErrorValue(errorName(tree)));
-
- private def setError(tree: Tree): Tree = {
- if (tree.hasSymbol() && tree.symbol() == null)
- tree.setSymbol(
- if (tree.isType()) Symbol.NONE.newErrorClass(errorName(tree).toTypeName())
- else Symbol.NONE.newErrorValue(errorName(tree)));
- tree.setType(Type.ErrorType);
- }
-
- def error(pos: int, msg: String): unit =
- unit.error(pos, msg);
-
- def typeError(pos: int, found: Type, req: Type): unit = {
- if (found.isError() || req.isError()) return;
- var msg: String = infer.typeErrorMsg("type mismatch", found, req);
- val foundResult: Type = found.resultType();
- if (foundResult != found && infer.isCompatible(foundResult, req))
- msg = msg + "\n possible cause: missing arguments for method or constructor";
- error(pos, msg);
- }
-
- def reportTypeError(pos: int, ex: Type$Error): unit = {
- if (global.debug) ex.printStackTrace();
- if (ex.isInstanceOf[CyclicReference]) {
- val cyc: CyclicReference = ex.asInstanceOf[CyclicReference];
- if (cyc.info.isInstanceOf[LazyTreeType]) {
- (cyc.info.asInstanceOf[LazyTreeType]).tree match {
- case Tree.ValDef(_, _, Tree.Empty, _) =>
- return error(pos, "recursive " + cyc.sym + " needs type");
- case Tree.DefDef(_, _, _, _, Tree.Empty, _) =>
- return error(pos, "recursive function " + cyc.sym.name + " needs result type");
- case _ =>
- }
- }
- }
- error(pos, ex.msg);
- }
-
- def decode(name: Name): String =
- if (name.isTypeName()) "type " + NameTransformer.decode(name);
- else "value " + NameTransformer.decode(name);
-
-// Checking methods ----------------------------------------------------------
-
- /** Check that symbol's definition is well-formed. This means:
- * - no conflicting modifiers
- * - `abstract' modifier only for classes
- * - `override' modifier never for classes
- * - `def' modifier never for parameters of case classes
- * - declarations only in traits or abstract classes
- * - symbols with `override' modifier override some other symbol.
- */
- def validate(sym: Symbol): unit = {
- if ((sym.flags & (ABSTRACT | OVERRIDE)) == ABSTRACT && sym.kind != CLASS) {
- error(sym.pos, "`abstract' modifier can be used only for classes; " +
- "\nit should be omitted for abstract members");
- }
- if ((sym.flags & OVERRIDE) != 0 && sym.kind == CLASS) {
- error(sym.pos, "`override' modifier not allowed for classes");
- }
- if ((sym.flags & DEF) != 0 && sym.owner().isPrimaryConstructor() &&
- (sym.owner().constructorClass().flags & CASE) != 0) {
- error(sym.pos, "pass-by-name arguments not allowed for case class parameters");
- }
- /*!!!
- if ((sym.flags & REPEATED) != 0 && sym.owner().isPrimaryConstructor()) {
- error(sym.pos, "`*' modifier not allowed for class parameters");
- }
- */
- if ((sym.flags & DEFERRED) != 0) {
- if (sym.owner().kind != CLASS || (sym.owner().flags & MODUL) != 0 || sym.owner().isAnonymousClass()) {
- error(sym.pos,
- "only classes can have declared but undefined members" +
- (if ((sym.flags & MUTABLE) == 0) ""
- else "\n(Note that variables need to be initialized to be defined)"));
- sym.flags = sym.flags & ~DEFERRED;
- }
- }
- checkNoConflict(sym, DEFERRED, PRIVATE);
- checkNoConflict(sym, FINAL, SEALED);
- if ((sym.flags & MODUL) == 0) checkNoConflict(sym, FINAL, PRIVATE);
- checkNoConflict(sym, PRIVATE, PROTECTED);
- checkNoConflict(sym, PRIVATE, OVERRIDE);
- checkNoConflict(sym, DEFERRED, FINAL);
- }
-
- /** Check that
- * - all parents are class types
- * - supertype conforms to supertypes of all mixin types.
- * - final classes are only inherited by classes which are
- * nested within definition of base class, or that occur within same
- * statement sequence.
- * - self-type of current class is a subtype of self-type of each parent class.
- * - parent constructors do not refer to value parameters of class.
- * - no two parents define same symbol.
- */
- def validateParentClasses(constrs: Array[Tree], parents: Array[Type], selfType: Type): unit = {
- var i = 0;
- while (i < parents.length) {
- if (!checkClassType(constrs(i).pos, parents(i))) return;
- val bsym: Symbol = parents(i).symbol();
- if (i > 0) {
- if ((bsym.flags & (JAVA | INTERFACE)) == JAVA)
- error(constrs(i).pos, "Java class may not be used as mixin");
- val grandparents = parents(i).parents();
- if (grandparents.length > 0 && !parents(0).isSubType(grandparents(0)))
- error(constrs(i).pos, "illegal inheritance;\n " + parents(0) +
- " does not conform to " + parents(i) + "'s supertype " + grandparents(0));
- }
- if ((bsym.flags & FINAL) != 0) {
- error(constrs(i).pos, "illegal inheritance from final class");
- } else if (bsym.isSealed() ||
- bsym.isSubClass(definitions.ANYVAL_CLASS) ||
- bsym.isSubClass(definitions.ARRAY_CLASS)) {
- // are we in same scope as base type definition?
- val e: Scope$Entry = context.scope.lookupEntry(bsym.name);
- if (e.sym != bsym) {
- // we are not within same statement sequence
- var c: Context = context;
- while (c != Context.NONE && c.owner != bsym)
- c = c.outer.enclClass;
- if (c == Context.NONE) {
- error(constrs(i).pos, "illegal inheritance from sealed class");
- }
- }
- }
- if (!selfType.isSubType(parents(i).instanceType())) {
- error(constrs(i).pos, "illegal inheritance;\n self-type " +
- selfType + " does not conform to " + parents(i) +
- "'s selftype " + parents(i).instanceType());
- }
- var j = 0; while (j < i) {
- if (parents(i).symbol() == parents(j).symbol())
- error(constrs(i).pos, "" + parents(i).symbol() + " is inherited twice");
- j = j + 1
- }
- i = i + 1;
- }
- }
-
- /** Check that type is a class type.
- */
- private def checkClassType(pos: int, tp: Type): boolean = {
- tp.unalias() match {
- case Type$TypeRef(_, sym, _) =>
- if (sym.kind == CLASS) return true;
- case _ =>
- }
- if (!tp.isError()) error(pos, "class type expected");
- false
- }
-
- /** Check that type is an object type
- */
- private def checkObjectType(pos: int, tp: Type): Type =
- if (tp.isObjectType()) tp
- else {
- if (!tp.isError()) error(pos, "object type expected");
- Type.ErrorType
- }
-
- /** Check that type is eta-expandable (i.e. no `def' or `*' parameters)
- */
- def checkEtaExpandable(pos: int, tp: Type): unit = tp match {
- case Type$MethodType(params, restype) =>
- var i = 0; while (i < params.length) {
- if ((params(i).flags & DEF) != 0)
- error(pos, "method with pass-by-name parameters needs to be fully applied");
- if ((params(i).flags & REPEATED) != 0)
- error(pos, "method with `*' parameters needs to be fully applied");
- i = i + 1
- }
- checkEtaExpandable(pos, restype);
- case _ =>
- }
-
- /** Check that `sym' does not contain both `flag1' and `flag2'
- */
- def checkNoConflict(sym: Symbol, flag1: int, flag2: int): unit = {
- if ((sym.flags & (flag1 | flag2)) == (flag1 | flag2)) {
- if (flag1 == DEFERRED)
- error(sym.pos, "abstract member may not have " +
- Modifiers$Helper.toString(flag2) + " modifier");
- else
- error(sym.pos, "illegal combination of modifiers: " +
- Modifiers$Helper.toString(flag1) + " and " +
- Modifiers$Helper.toString(flag2));
- }
- }
-
- /** Check that type `tp' is not a subtype of itself.
- */
- def checkNonCyclic(pos: int, tp: Type): unit = tp match {
- case Type$TypeRef(pre, sym, args) =>
- sym.initialize();
- if ((sym.flags & LOCKED) != 0) {
- error(pos, "cyclic aliasing or subtyping involving " + sym);
- } else if (sym.kind == ALIAS || sym.kind == TYPE) {
- sym.flags = sym.flags | LOCKED;
- //System.out.println("checking " + sym);//DEBUG
- checkNonCyclic(
- pos, pre.memberInfo(sym).subst(sym.typeParams(), args));
- if (sym.kind == TYPE) {
- checkNonCyclic(
- pos, pre.memberLoBound(sym).subst(sym.typeParams(), args));
- checkNonCyclic(
- pos, pre.memberVuBound(sym).subst(sym.typeParams(), args));
- }
- sym.flags = sym.flags & ~LOCKED;
- }
-
- case Type$CompoundType(parents, members) =>
- var i = 0; while (i < parents.length) {
- checkNonCyclic(pos, parents(i));
- i = i + 1
- }
-
- case Type$SingleType(pre, sym) =>
- sym.initialize();
- if ((sym.flags & LOCKED) != 0) {
- error(pos, "cyclic aliasing or subtyping involving " + sym);
- }
-
- case _ =>
- }
-
- /** Check that type does not refer to components defined in current scope.
- */
- def checkNoEscape(pos: int, tp: Type): Type = {
-
- val checkNoEscapeMap = new Type$Map() {
- override def apply(t: Type): Type = {
- t.unalias() match {
- case Type$TypeRef(Type.NoPrefix, sym, args) =>
- checkNoEscape(t, sym);
- case Type$SingleType(Type.NoPrefix, sym) =>
- checkNoEscape(t, sym);
- case _ =>
- }
- return map(t);
- }
- private def checkNoEscape(t: Type, sym: Symbol): unit = {
- val e: Scope$Entry = context.scope.lookupEntry(sym.name);
- if (e.sym == sym && e.owner == context.scope &&
- !(e.sym.kind == TYPE && (e.sym.flags & PARAM) != 0)) {
- throw new Type$Error(
- "type " + t + " escapes its defining scope");
- }
- }
- };
-
- try {
- checkNoEscapeMap.apply(tp)
- } catch {
- case ex: Type$Error =>
- if ((mode & EXPRmode) != 0 && infer.isFullyDefined(pt)) pt
- else {
- error(pos, ex.msg + " as part of " + tp.unalias());
- Type.ErrorType
- }
- }
- }
-
- /** Check that there are no dependent parameter types among parameters
- */
- def checkNoEscapeParams(vparams: Array[Array[Tree.ValDef]]): unit = {
- var i = 0; while (i < vparams.length) {
- var j = 0; while (j < vparams(i).length) {
- checkNoEscape(vparams(i)(j).pos, vparams(i)(j).tpe.getType());
- j = j + 1
- }
- i = i + 1
- }
- }
-
- /** Check that tree represents a legal trait definition.
- */
- def checkTraitDef(pos: int, clazz: Symbol, templ: Tree.Template) = {
-
- /** Check that type does not have value parameters
- */
- def checkNoParams(tpe: Type): unit = tpe match {
- case Type$MethodType(vparams, _) =>
- if (vparams.length > 0)
- error(pos, "trait may not have value parameters")
- case Type$PolyType(tparams, restpe) =>
- checkNoParams(infer.skipViewParams(tparams, restpe))
- case _ =>
- }
-
- /** Check that tree represents a pure constructor.
- */
- def checkPureConstr(tree: Tree): unit = {
- if (!TreeInfo.isPureConstr(tree) && !tree.getType().isError())
- error(tree.pos, "" + clazz + " may invoke only pure superclass constructors");
- }
-
- /** Check that tree refers to a trait
- */
- def checkTraitRef(tree: Tree): unit = {
- if (!tree.getType().symbol().isTrait() && !tree.getType().isError())
- error(tree.pos, " " + clazz + " may inherit only traits as mixins");
- }
-
- /** Check that tree represents a pure definition.
- */
- def checkPureDef(tree: Tree): unit = {
- if (!TreeInfo.isPureDef(tree) && !tree.getType().isError())
- error(tree.pos, "" + clazz + " may contain only pure definitions");
- }
-
- checkNoParams(clazz.primaryConstructor().getType());
- var i = 0; while (i < templ.parents.length) {
- checkPureConstr(templ.parents(i));
- if (i >= 1) checkTraitRef(templ.parents(i));
- i = i + 1
- }
- var j = 0; while (j < templ.body.length) {
- checkPureDef(templ.body(j));
- j = j + 1
- }
- }
-
- /** Check that tree is a stable expression .p
- */
- def checkStable(tree: Tree): Tree =
- if (TreeInfo.isPureExpr(tree) || tree.getType().isError()) tree;
- else {
- error(tree.pos, "stable identifier required, but " + tree + " found.");
- errorTermTree(tree);
- }
-
- /** Check that class can be instantiated.
- */
- def checkInstantiatable(pos: int, tp: Type): unit = {
- val clazz: Symbol = tp.symbol();
- if (clazz.kind == CLASS) {
- if (clazz.isAbstractClass())
- error(pos, "" + clazz + " is abstract, so it cannot be instantiated");
- else if (!tp.isSubType(tp.instanceType()))
- error(pos, "" + tp + " does not conform to its self-type " +
- tp.instanceType() + ", so it cannot be instantiated");
- }
- }
-
- /** Check that all subtrees have their types defined.
- * Used for asserting an internal invariant
- */
- private class CheckDefined extends Traverser {
- var all: Tree = null;
- override def traverse(tree: Tree): unit = {
- if (tree.getType() == null) assert(false, "" + tree + " in " + all);
- if (!tree.getType().isError())
- super.traverse(tree);
- }
- }
-
- private val checkDefined: CheckDefined = new CheckDefined();
-
- // Helper definitions for calculating types -----------------------------------------
-
- /** The qualifier type of a potential application of the `match' method.
- * or NoType, if this is something else.
- */
- private def matchQualType(fn: Tree): Type = {
- fn match {
- case Tree.Select(qual, _) =>
- if (fn.symbol() == definitions.ANY_MATCH)
- return qual.getType().widen();
-
- case Tree.TypeApply(fn1, _) =>
- return matchQualType(fn1);
-
- case Tree.Ident(_) =>
- if (fn.symbol() == definitions.ANY_MATCH)
- return context.enclClass.owner.typeOfThis();
-
- case _ =>
- }
- if (fn.getType().isError()) Type.ErrorType else Type.NoType
- }
-
- private def isSetterMethod(sym: Symbol): boolean =
- sym != null &&
- !sym.isLocal() &&
- !sym.isStable() &&
- sym.getType().isInstanceOf[Type$PolyType] &&
- sym.typeParams().length == 0;
-
-// Views -----------------------------------------------------------------------
-
- private def applyView(v: View, tree: Tree, mode: int, pt: Type): Tree = {
- val vexpr = infer.viewExpr(tree.pos, v);
- val vapp = transform(
- make.Apply(tree.pos, vexpr, NewArray.Tree(tree)), mode, pt);
- if (v.symtype.isObjectType()) {
- val tree1 = gen.mkAsInstanceOf(tree.duplicate(), vapp.getType());
- gen.If(
- gen.Apply(
- gen.Select(
- vexpr.duplicate(),
- definitions.ANY_EQEQ),
- NewArray.Tree(gen.mkNullLit(tree.pos))),
- tree1,
- vapp)
- } else vapp
- }
-
-// Contexts -------------------------------------------------------------------
-
- /** Push new context associated with given tree, owner, and scope on stack.
- */
- def pushContext(tree: Tree, owner: Symbol, scope: Scope): Context = {
- val prevContext = context;
- context = new Context(tree, owner, scope, context);
- prevContext
- }
-
-// Lazy Types ------------------------------------------------------------------
-
- /** A lazy type which, when forced returns the type of a symbol defined
- * in `tree'.
- */
- class LazyTreeType(_tree: Tree) extends Type$LazyType {
- val tree: Tree = _tree;
- val u: CompilationUnit = unit;
- val c: Context = context;
-
- override def complete(sym: Symbol): unit = {
- defineSym(tree, u, c);
- }
- }
-
- /** A lazy type for case constructor methods (whose name is a term name)
- * which sets the method's type to the class constructor type.
- */
- class LazyConstrMethodType(_tree: Tree) extends LazyTreeType(_tree) {
- override def complete(sym: Symbol): unit = {
- val constr: Symbol = tree.symbol().primaryConstructor();
- if (!sym.isInitialized())
- sym.setInfo(constr.getType().instanceType().cloneType(constr, sym));
- }
- }
-
- /** A lazy type for self types
- */
- class LazySelfType(clazz: Symbol, tree: Tree) extends LazyTreeType(tree) {
- override def complete(sym: Symbol): unit = {
- defineSelfType(sym, clazz, tree, u, c);
- }
- }
-
-// Definining Symbols -------------------------------------------------------
-
- /** Define symbol associated with `tree' using given `unit' and `context'.
- */
- def defineSym(tree: Tree, unit: CompilationUnit, curcontext: Context): unit = {
- val savedUnit: CompilationUnit = this.unit;
- this.unit = unit;
- val savedContext: Context = this.context;
- this.context = curcontext;
- val savedMode: int = this.mode;
- this.mode = EXPRmode;
- val savedPt: Type = this.pt;
- this.pt = Type.AnyType;
-
- try {
- val sym: Symbol = tree.symbol();
- if (global.debug) global.log("defining " + sym);
- var owntype: Type = null;
- tree match {
- case Tree.ClassDef(mods, name, tparams, vparams, tpe, templ) =>
- val prevContext = pushContext(
- tree, sym.primaryConstructor(), new Scope(context.scope));
- val tparamSyms = enterParams(tparams);
- var vparamSyms = enterParams(vparams);
- if (vparamSyms.length == 0) {
- vparamSyms = NewArray.SymbolArray{Symbol.EMPTY_ARRAY};
- } else if (infer.isViewBounded(tparamSyms) && vparamSyms.length == 1) {
- val vparamSyms1 = new Array[Array[Symbol]](2);
- vparamSyms1(0) = vparamSyms(0);
- vparamSyms1(1) = Symbol.EMPTY_ARRAY;
- vparamSyms = vparamSyms1
- }
- if (vparams.length > 0)
- templ.body = desugarize.addParamAccessors(
- templ.body, vparams(vparams.length - 1));
-
- val constrtype: Type = makeMethodType(
- tparamSyms,
- vparamSyms,
- Type.typeRef(sym.owner().thisType(), sym, Symbol.getType(tparamSyms)));
- //System.out.println("set info " + sym.constructor() + " to " + constrtype + " was " + sym.constructor().rawInfo());//DEBUG
- sym.primaryConstructor().setInfo(constrtype);
- // necessary so that we can access tparams
- sym.primaryConstructor().flags =
- sym.primaryConstructor().flags | INITIALIZED;
-
- if (tpe != Tree.Empty)
- sym.setTypeOfThis(new LazySelfType(sym, tpe));
-
- defineTemplate(templ, sym, new Scope());
- owntype = templ.getType();
- context = prevContext;
-
- case Tree.ModuleDef(mods, name, _tpe, templ) =>
- var tpe = _tpe;
- val clazz: Symbol = sym.moduleClass();
- val prevContext = pushContext(
- tree, clazz.primaryConstructor(), context.scope);
- defineTemplate(templ, clazz, new Scope());
- context = prevContext;
- clazz.setInfo(templ.getType());
- tpe = transform(tpe, TYPEmode);
- (tree.asInstanceOf[Tree.ModuleDef]).tpe = tpe;
- if (tpe != Tree.Empty)
- clazz.setTypeOfThis(new LazySelfType(sym, tpe));
- owntype = if (tpe == Tree.Empty) clazz.getType() else tpe.getType();
-
- case Tree.DefDef(mods, name, tparams, vparams, _tpe, _rhs) =>
- var tpe = _tpe;
- var rhs = _rhs;
- var restype: Type = null;
- val prevContext = pushContext(tree, sym, new Scope(context.scope));
- val tparamSyms = enterParams(tparams);
- val vparamSyms = enterParams(vparams);
- if (tpe != Tree.Empty) {
- tpe = transform(tpe, TYPEmode);
- (tree.asInstanceOf[Tree.DefDef]).tpe = tpe;
- restype = tpe.getType();
- } else if (name == Names.CONSTRUCTOR) {
- if (context.enclClass.owner.typeParams().length != 0)
- error(tree.pos, "secondary constructors for parameterized classes not yet implemented");
- restype = context.enclClass.owner.getType();/*.subst(
- context.enclClass.owner.typeParams(), tparamSyms)*/;
- } else {
- if ((sym.flags & PARAMACCESSOR) != 0) {
- rhs.setType(rhs.symbol().getType());
- } else {
- rhs = transform(rhs, EXPRmode);
- (tree.asInstanceOf[Tree.DefDef]).rhs = rhs;
- }
- restype = rhs.getType();
- if (!sym.isFinal()) restype = restype.deconst();
- }
- restype = checkNoEscape(tpe.pos, restype);
- if (name == Names.view &&
- infer.containsSymbol(tparamSyms, restype.symbol())) {
- error(tree.pos, "result type of view may not be a type variable");
- restype = definitions.ANY_TYPE();
- }
- context = prevContext;
-
- owntype = makeMethodType(tparamSyms, vparamSyms, restype);
- //System.out.println("methtype " + name + ":" + owntype);//DEBUG
- addInheritedOverloaded(sym, owntype);
-
- case Tree.ValDef(mods, name, _tpe, _rhs) =>
- var tpe = _tpe;
- var rhs = _rhs;
- if (tpe != Tree.Empty) {
- tpe = transform(tpe, TYPEmode);
- (tree.asInstanceOf[Tree.ValDef]).tpe = tpe;
- owntype = tpe.getType();
- } else {
- val prevContext = pushContext(tree, sym, context.scope);
- if (rhs == Tree.Empty) {
- if ((sym.owner().flags & ACCESSOR) != 0) {
- // this is the parameter of a variable setter method.
- assert((sym.flags & PARAM) != 0);
- owntype = sym.owner().accessed().getType();
- } else {
- error(tree.pos, "missing parameter type");
- owntype = Type.ErrorType;
- }
- } else {
- rhs = transform(rhs, EXPRmode);
- (tree.asInstanceOf[Tree.ValDef]).rhs = rhs;
- owntype = rhs.getType();
- if (sym.isVariable() || !sym.isFinal())
- owntype = owntype.deconst();
- }
- context = prevContext;
- addInheritedOverloaded(sym, owntype);
- }
-
- case Tree.AliasTypeDef(mods, name, tparams, _rhs) =>
- var rhs = _rhs;
- val prevContext = pushContext(tree, sym.primaryConstructor(), new Scope(context.scope));
- val tparamSyms = enterParams(tparams);
- rhs = transform(rhs, TYPEmode);
- (tree.asInstanceOf[Tree.AliasTypeDef]).rhs = rhs;
- owntype = rhs.getType();
- sym.primaryConstructor().setInfo(
- new Type$PolyType(tparamSyms, owntype));
- context = prevContext;
-
- case Tree.AbsTypeDef(mods, name, _rhs, _lobound) =>
- var rhs = _rhs;
- var lobound = _lobound;
- //can't have `sym' as owner since checkNonCyclic would fail.
- rhs = transform(rhs, TYPEmode);
- tree.asInstanceOf[Tree.AbsTypeDef].rhs = rhs;
- lobound = transform(lobound, TYPEmode);
- (tree.asInstanceOf[Tree.AbsTypeDef]).lobound = lobound;
- if (sym.isViewBounded()) {
- sym.setVuBound(rhs.getType());
- owntype = definitions.ANY_TYPE();
- } else {
- owntype = rhs.getType();
- }
- sym.setLoBound(lobound.getType());
- owntype.symbol().initialize();//to detect cycles todo: needed?
-
- case Tree.Import(_expr, selectors) =>
- val expr = transform(_expr, EXPRmode | QUALmode);
- tree.asInstanceOf[Tree.Import].expr = expr;
- checkStable(expr);
- owntype = expr.getType();
- val tp: Type = owntype.widen();
- { var i = 0; while (i < selectors.length) {
- if (selectors(i) != Names.IMPORT_WILDCARD &&
- tp.lookup(selectors(i)) == Symbol.NONE &&
- tp.lookup(selectors(i).toTypeName()) == Symbol.NONE)
- error(tree.pos, "" + NameTransformer.decode(selectors(i)) + " is not a member of " + expr);
- i = i + 2
- }}
- case _ =>
- throw new ApplicationError();
- }
- sym.setInfo(owntype);
- validate(sym);
- if (global.debug) global.log("defined " + sym);
- } catch {
- case ex: Type$Error =>
- reportTypeError(tree.pos, ex);
- setError(tree);
- if (tree.hasSymbol()) {
- tree.symbol().setInfo(Type.ErrorType);
- }
- }
-
- this.unit = savedUnit;
- this.context = savedContext;
- this.mode = savedMode;
- this.pt = savedPt;
- }
-
- /** Definition phase for a template. This enters all symbols in template
- * into symbol table.
- */
- def defineTemplate(templ: Tree.Template, clazz: Symbol, members: Scope): unit = {
- // attribute parent constructors
- templ.parents = transformConstrInvocations(templ.pos, templ.parents);
- if (templ.parents.length > 0 &&
- (templ.parents(0).getType().symbol().flags & (JAVA | INTERFACE)) == (JAVA | INTERFACE)) {
- val constrs1 = new Array[Tree](templ.parents.length + 1);
- constrs1(0) = gen.mkApply__(
- gen.mkPrimaryConstructorGlobalRef(
- templ.parents(0).pos, definitions.OBJECT_CLASS));
- System.arraycopy(templ.parents, 0, constrs1, 1, templ.parents.length);
- templ.parents = constrs1;
- }
- val parents = Tree.typeOf(templ.parents);
-
- // enter all members
- val prevContext = pushContext(templ, clazz, members);
- templ.body = desugarize.Statements(unit, templ.body, false);
- enterSyms(templ.body);
- context = prevContext;
- templ.setType(Type.compoundType(parents, members, clazz));
- }
-
- def makeMethodType(tparams: Array[Symbol], vparams: Array[Array[Symbol]], restpe: Type): Type =
- if (tparams.length == 0 && vparams.length == 0) {
- new Type$PolyType(tparams, restpe);
- } else {
- var result: Type = restpe;
- var i = vparams.length - 1;
- while (i >= 0) {
- result = new Type$MethodType(vparams(i), result);
- i = i - 1;
- }
- if (tparams.length != 0)
- result = new Type$PolyType(tparams, result);
- result
- }
-
- /** Define self type of class or module `sym'
- * associated with `tree' using given `unit' and `context'.
- */
- def defineSelfType(sym: Symbol, clazz: Symbol, tree: Tree, unit: CompilationUnit, curcontext: Context): unit = {
- val savedUnit: CompilationUnit = this.unit;
- this.unit = unit;
- val savedContext: Context = this.context;
- this.context = curcontext;
-
- val selftype: Type = transform(tree, TYPEmode).getType();
- //todo: can we really make a compound type with class
- val selftype1: Type =
- if (clazz.getType().isSubType(selftype))
- clazz.getType()
- else if (selftype.isSubType(clazz.getType()))
- selftype
- else if (selftype.isSingletonType() && selftype.singleDeref().symbol().isSubClass(clazz))
- selftype
- else
- selftype match {
- case Type$CompoundType(parts, members) =>
- val parts1 = new Array[Type](parts.length + 1);
- System.arraycopy(parts, 0, parts1, 0, parts.length);
- parts1(parts.length) = clazz.getType();
- Type.compoundTypeWithOwner(clazz.owner().enclClass(), parts1, members);
-
- case _ =>
- Type.compoundTypeWithOwner(
- clazz.owner().enclClass(), NewArray.Type(selftype, clazz.getType()), Scope.EMPTY);
- }
- if (global.debug) global.log("assigning self type " + selftype1);
- sym.setInfo(selftype1);
-
- this.unit = savedUnit;
- this.context= savedContext;
- }
-
-// Attribution and Transform -------------------------------------------------
-
- /** Turn tree type into stable type if possible and required by
- * context.
- */
- def mkStable(tree: Tree, pre: Type, mode: int, pt: Type): Tree = {
- tree.getType() match {
- case Type$ConstantType(_, value) =>
- return make.Literal(tree.pos, value).setType(tree.getType())
- case Type$PolyType(tparams, restp) =>
- if (tparams.length == 0) {
- restp match {
- case Type$ConstantType(_, value) =>
- return make.Literal(tree.pos, value).setType(tree.getType());
- case _ =>
- }
- }
- case _ =>
- }
- if ((pt != null && pt.isStable() ||
- (mode & QUALmode) != 0 ||
- tree.getType().symbol().isModuleClass()) &&
- (pre != null) && pre.isStable()) {
- var sym: Symbol = tree.symbol();
- tree.getType() match {
- case Type$OverloadedType(alts, alttypes) =>
- if ((mode & FUNmode) == 0) {
- try {
- infer.exprAlternative(tree, alts, alttypes, pt);
- sym = tree.symbol();
- } catch {
- case ex: Type$Error =>
- reportTypeError(tree.pos, ex);
- }
- }
- case _ =>
- }
- if (sym.isStable()) {
- tree.setType(Type.singleType(pre, sym));
- }
- }
- tree
- }
-
- /** The qualifying class of a this or super
- */
- def qualifyingClass(tree: Tree, name: Name): Symbol = {
- if (name == TypeNames.EMPTY) {
- val clazz: Symbol = context.enclClass.owner;
- if (clazz != null)
- clazz
- else {
- error(tree.pos, "" + tree +
- " can be used only in a class, object, or template");
- Symbol.NONE
- }
- } else {
- var i: Context = context;
- while (i != Context.NONE &&
- !(i.owner.kind == CLASS && i.owner.name == name))
- i = i.outer.enclClass;
- if (i != Context.NONE)
- i.owner
- else {
- error(tree.pos, "" + name + " is not an enclosing class");
- Symbol.NONE
- }
- }
- }
-
- /** Adapt tree to given mode and given prototype
- */
- def adapt(tree: Tree, mode: int, pt: Type): Tree = {
- //System.out.println(tree + ":" + tree.getType() + " adapt " + pt + " " + mode);//DEBUG
- tree.getType() match {
- case Type$OverloadedType(alts, alttypes) =>
- // resolve overloading
- if ((mode & FUNmode) == 0) {
- try {
- infer.exprAlternative(tree, alts, alttypes, pt);
- } catch {
- case ex: Type$Error =>
- reportTypeError(tree.pos, ex);
- }
- tree.getType() match {
- case Type$OverloadedType(_, _) =>
- // overload resolution failed bcs no alternative matched prototype.
- typeError(tree.pos, tree.getType(), pt);
- return errorTermTree(tree);
- case _ =>
- }
- return adapt(tree, mode, pt);
- }
-
- case Type$PolyType(tparams, restp) =>
- // apply parameterless functions
- // instantiate polymorphic expressions
- if (tparams.length == 0) {
- return adapt(constfold.tryToFold(tree.setType(restp)), mode, pt);
- } else if ((mode & (FUNmode | POLYmode)) == 0) {
- var tree1: Tree = null;
- try {
- tree1 = infer.exprInstance(tree, tparams, restp, pt);
- } catch {
- case ex: Type$Error =>
- error(tree.pos, ex.msg);
- tree1 = errorTermTree(tree);
- }
- return adapt(tree1, mode, pt);
- }
-
- case Type$MethodType(_, _) =>
- // convert unapplied methods to functions.
- if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
- (infer.isCompatible(tree.getType(), pt) ||
- pt.symbol() == definitions.UNIT_CLASS)) {
- checkEtaExpandable(tree.pos, tree.getType());
- if (TreeInfo.methPart(tree).symbol() == definitions.ANY_MATCH) {
- error(tree.pos, "`match' needs to be applied fully");
- return errorTree(tree)
- } else {
- return transform(desugarize.etaExpand(tree, tree.getType()), mode, pt);
- }
- } else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
- error(tree.pos, "missing arguments for class constructor");
- return errorTermTree(tree);
- }
-
- case _ =>
- }
- if ((mode & PATTERNmode) != 0) {
- if (tree.isType()) {
- val clazz: Symbol = tree.getType().withDefaultArgs().unalias().symbol();
-
- if (clazz.isCaseClass()) {
- // set type to instantiated case class constructor
- tree.setType(tree.getType().prefix().memberType(clazz.primaryConstructor()));
- // MZ: this is a hack, but I didn't know how to do it better
- if ((clazz.flags & (JAVA | CASE)) == (JAVA | CASE)) {
- val altconstr = clazz.allConstructors().alternativeSymbols();
- tree.setType(tree.getType().prefix().memberType(
- altconstr(altconstr.length - 1)));
- }
- tree.getType() match {
- case Type$PolyType(tparams, restp) =>
- try {
- infer.constructorInstance(tree, tparams, restp, pt);
- //System.out.println("constr inst " + ArrayApply.toString(tparams) + restp + " against " + pt + " = " + tree.getType());//DEBUG
- } catch {
- case ex: Type$Error =>
- if (!pt.isError()) error(tree.pos, ex.msg);
- setError(tree);
- }
- case _ =>
- }
- } else if (clazz.isSubClass(definitions.SEQ_CLASS)) {
- // set type to instantiated sequence class constructor
- // todo: should we admit even supertypes of the target type?
- val seqtp: Type = pt.baseType(clazz);
- if (seqtp != Type.NoType) {
- def seqConstructorType(paramtp: Type, resulttp: Type) = {
- val constr: Symbol = resulttp.symbol().primaryConstructor();
- val param: Symbol = constr.newVParam(
- tree.pos, REPEATED, Names.PATTERN_WILDCARD,
- paramtp.baseType(definitions.SEQ_CLASS));
- new Type$MethodType(NewArray.Symbol(param), resulttp);
- }
- tree.setType(seqConstructorType(seqtp, pt));
- } else {
- error(tree.pos, "expected pattern type " + pt +
- " does not conform to sequence " + clazz);
- return errorTermTree(tree);
- }
- } else if (!tree.getType().isError()) {
- error(tree.pos, "" + tree.getType().symbol() +
- " is neither a case class constructor nor a sequence class constructor");
- return errorTermTree(tree);
- }
- }
- if ((mode & FUNmode) != 0) {
- return tree;
- } else {
- val sym: Symbol = tree.symbol();
- // check that idents or selects are stable.
- tree match {
- case Tree.Ident(_) | Tree.Select(_, _) =>
- checkStable(tree);
- case _ =>
- }
- }
- } else if ((mode & EXPRmode) != 0) {
- if ((mode & FUNmode) != 0) {
- if (tree.getType().isObjectType()) {
- // insert apply method
- val applyMeth: Symbol = tree.getType().lookup(Names.apply);
- if (applyMeth != Symbol.NONE) {
- val applyType: Type = infer.checkAccessible(
- tree.pos, applyMeth, tree.getType().memberType(applyMeth),
- tree, tree.getType());
- val tree1 = make.Select(tree.pos, tree, Names.apply)
- .setSymbol(applyMeth)
- .setType(applyType);
- return adapt(tree1, mode, pt);
- }
- }
- } else if ((mode & QUALmode) == 0) {
- // check that packages and static modules are not used as values
- tree match {
- case Tree.Ident(_) | Tree.Select(_, _) =>
- val sym: Symbol = tree.symbol();
- if (sym != null && !sym.isError() && !sym.isValue()) {
- error(tree.pos, "" + tree.symbol() + " is not a value");
- return errorTermTree(tree);
- }
- case _ =>
- }
- }
- }
-
- var owntype: Type = tree.getType();
- if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode) && pt != Type.AnyType) {
- owntype = owntype.instanceType();
- // this works as for superclass constructor calls the expected
- // type `pt' is always AnyType (see transformConstrInvocations).
- }
- if (!(owntype.isInstanceOf[Type$PolyType] || owntype.isSubType(pt))) {
- tree match {
- case Tree.Literal(constant) =>
- var n: int = constant match {
- case AConstant$INT(value) => value
- case AConstant$CHAR(value) => value
- case _ => Integer.MAX_VALUE
- }
- val value1: AConstant =
- if (pt.symbol() == definitions.BYTE_CLASS && -128 <= n && n <= 127)
- AConstant.BYTE(n.asInstanceOf[byte])
- else if (pt.symbol() == definitions.SHORT_CLASS && -32768 <= n && n <= 32767)
- AConstant.SHORT(n.asInstanceOf[short])
- else if (pt.symbol() == definitions.CHAR_CLASS && 0 <= n && n <= 65535)
- AConstant.CHAR(n.asInstanceOf[char])
- else null;
- if (value1 != null)
- return gen.Literal(tree.pos, value1);
- case _ =>
- }
- if ((mode & EXPRmode) != 0) {
- if (pt.symbol() == definitions.UNIT_CLASS) {
- return gen.mkUnitBlock(tree);
- } else if (infer.isCompatible(tree.getType(), pt)) {
- tree match {
- case Tree.Literal(value) =>
- val value1 = constfold.cast(value, pt);
- if (value1 != null)
- return adapt(gen.Literal(tree.pos, value1), mode, pt);
- case _ =>
- }
- val v = infer.bestView(tree.getType(), pt, Names.EMPTY);
- if (v != null) return applyView(v, tree, mode, pt);
- // todo: remove
- val coerceMeth: Symbol = tree.getType().lookup(Names.coerce);
- if (coerceMeth != Symbol.NONE) {
- val coerceType = infer.checkAccessible(
- tree.pos, coerceMeth, tree.getType().memberType(coerceMeth),
- tree, tree.getType());
- val tree1 = make.Select(tree.pos, tree, Names.coerce)
- .setSymbol(coerceMeth)
- .setType(coerceType);
- return adapt(tree1, mode, pt);
- }
- }
- }
- if ((mode & CONSTRmode) == 0) {
- typeError(tree.pos, owntype, pt);
- Type.explainTypes(owntype, pt);
- setError(tree);
- } // for constructors, delay until after the `new'.
- }
- tree
- }
-
- /** Attribute an identifier consisting of a simple name or an outer reference.
- * @param tree The tree representing the identifier.
- * @param name The name of the identifier.
- */
- def transformIdent(_tree: Tree, name: Name): Tree = {
- var tree = _tree;
- //System.out.println("transforming " + name);//DEBUG
- // find applicable definition and assign to `sym'
- var sym: Symbol = Symbol.NONE;
- var pre: Type = null;
- var qual: Tree = Tree.Empty;
- var stopPos: int = Integer.MIN_VALUE;
- var nextcontext: Context = context;
- while (sym.kind == NONE && nextcontext != Context.NONE) {
- sym = nextcontext.scope.lookup(name);
- if (sym.kind != NONE) {
- stopPos = sym.pos;
- } else {
- nextcontext = nextcontext.enclClass;
- if (nextcontext != Context.NONE) {
- sym = nextcontext.owner.typeOfThis().lookup(name);
- if (sym.kind != NONE) {
- stopPos = nextcontext.owner.pos;
- } else {
- nextcontext = nextcontext.outer;
- }
- }
- }
- }
-
- if (stopPos > tree.pos) {
- // set stopPos to beginning of block enclosed in the scope which defines the
- // referenced symbol.
- var lastc = Context.NONE;
- var c = nextcontext;
- while (c.outer.scope != null && c.outer.scope.lookup(name) == sym) {
- c.tree match {
- case Tree.Block(_, _) | Tree.CaseDef(_, _, _) | Tree.ClassDef(_, _, _, _, _, _) | Tree.ModuleDef(_, _, _, _) =>
- lastc = c;
- case _ =>
- }
- c = c.outer
- }
- if (lastc != Context.NONE) {
- //System.out.println("revising stop to [" + lastc.tree + "]; symbol = " + sym + ", context = " + nextcontext);//DEBUG
- stopPos = lastc.tree.pos;
- }
- }
-
- var impcontext: Context = context.prevImport;
- var lastimpcontext: Context = null;
- var sym1: Symbol = Symbol.NONE;
- while (sym1.kind == NONE && impcontext != Context.NONE && impcontext.tree.pos > stopPos) {
- sym1 = impcontext.importedSymbol(name);
- lastimpcontext = impcontext;
- impcontext = impcontext.outer.prevImport;
- }
-
- // evaluate what was found
- if (sym1.kind == NONE) {
- if (sym.kind == NONE) {
- //System.out.println(name);//DEBUG
- error(tree.pos, "not found: " + decode(name));
- return errorTree(tree);
- } else {
- if (sym.owner().kind == CLASS) {
- pre = nextcontext.enclClass.owner.thisType();
- if (!sym.owner().isPackageClass()) {
- val qual1: Tree = gen.This(tree.pos, nextcontext.enclClass.owner);
- tree = make.Select(tree.pos, qual1, name);
- //System.out.println(name + " :::> " + tree + " " + qual1.symbol());//DEBUG
- }
- } else {
- pre = Type.NoPrefix;
- }
- }
- } else if (sym.kind != NONE && !sym.isExternal()) {
- error(tree.pos,
- "reference to " + name + " is ambiguous;\n" +
- "it is both defined in " + sym.owner() +
- " and imported subsequently by \n" + lastimpcontext.tree);
- return errorTree(tree);
- } else {
- // check that there are no other applicable imports in same scope.
- while (impcontext != Context.NONE && impcontext.scope == lastimpcontext.scope) {
- if (!impcontext.sameImport(lastimpcontext) && impcontext.importedSymbol(name).kind != NONE) {
- error(tree.pos,
- "reference to " + name + " is ambiguous;\n" +
- "it is imported twice in the same scope by\n " +
- lastimpcontext.tree + "\nand " + impcontext.tree);
- return errorTree(tree);
- }
- impcontext = impcontext.outer.prevImport;
- }
- sym = sym1;
- qual = lastimpcontext.importPrefix().duplicate();
- pre = qual.getType();
- //System.out.println(name + " => " + lastimpcontext.tree + "." + name);//DEBUG
- tree = make.Select(tree.pos, qual, name);
- }
-
- var symtype: Type =
- (if (sym.isType()) sym.typeConstructor() else sym.getType())
- .asSeenFrom(pre, sym.owner());
- symtype = infer.checkAccessible(
- tree.pos, sym, symtype, qual,
- if (qual == Tree.Empty && sym.owner().isPackageClass()) sym.owner().getType()
- else qual.getType());
- if (symtype == Type.NoType) {
- error(tree.pos, "not found: " + decode(name));
- return errorTree(tree);
- }
- //System.out.println(name + ":" + symtype);//DEBUG
- mkStable(tree.setSymbol(sym).setType(symtype), pre, mode, pt)
- }
-
- /** Attribute a selection where `tree' is `qual.name'.
- * `qual' is already attributed.
- */
- def transformSelect(tree: Tree, _qual: Tree, name: Name): Tree = {
- var qual = _qual;
- var uninst: Array[Symbol] = Symbol.EMPTY_ARRAY;
- qual.getType() match {
- case Type$PolyType(tparams, restype) =>
- qual = infer.mkTypeApply(qual, tparams, restype, Symbol.getType(tparams));
- uninst = tparams;
- case _ =>
- }
- var sym: Symbol = qual.getType().lookup(name);
- if (sym.kind == NONE) {
- if (name != Names.view) {
- val qtype = qual.getType().singleDeref();
- val v = infer.bestView(qtype, Type.AnyType, name);
- if (v != null) {
- qual = applyView(v, qual.setType(qtype), EXPRmode, Type.AnyType);
- sym = qual.getType().lookup(name);
- assert(sym.kind != NONE);
- } else {
- //System.out.println(qual.getType() + " has members " + qual.getType().members());//DEBUG
- error(tree.pos,
- decode(name) + " is not a member of " + qual.getType().widen());
- return errorTree(tree);
- }
- }
- }
- val qualtype =
- if (qual.isInstanceOf[Tree.Super]) context.enclClass.owner.thisType()
- else qual.getType();
- var symtype: Type =
- (if (sym.isType()) sym.typeConstructor() else sym.getType())
- .asSeenFrom(qualtype, sym.owner());
- if (symtype == Type.NoType) {
- error(tree.pos, "not found: " + decode(name));
- return errorTree(tree);
- } else
- symtype = infer.checkAccessible(tree.pos, sym, symtype, qual, qualtype);
- //System.out.println(sym.name + ":" + symtype);//DEBUG
- if (uninst.length != 0) {
- def polymorphize(tp: Type): Type = tp match {
- case Type$PolyType(tparams, restype) =>
- new Type$PolyType(tparams, polymorphize(restype))
- case Type$OverloadedType(alts, alttypes) =>
- val alttypes1 = new Array[Type](alttypes.length);
- var i = 0; while (i < alttypes.length) {
- alttypes1(i) = polymorphize(alttypes(i));
- i = i + 1
- }
- new Type$OverloadedType(alts, alttypes1)
- case _ =>
- new Type$PolyType(uninst, tp);
- }
- symtype = polymorphize(symtype);
- }
- //System.out.println(qual.getType() + ".member: " + sym + ":" + symtype);//DEBUG
- val tree1: Tree = tree match {
- case Tree.Select(_, _) =>
- copy.Select(tree, sym, qual);
- case Tree.SelectFromType(_, _) =>
- copy.SelectFromType(tree, sym, qual)
- }
- mkStable(tree1.setType(symtype), qualtype, mode, pt)
- }
-
- /** Attribute a pattern matching expression where `pattpe' is the
- * expected type of the patterns and `pt' is the expected type of the
- * results.
- */
- def transformVisitor(tree: Tree, pattpe: Type, pt: Type): Tree =
- //System.out.println("trans visitor with " + pattpe + "," + pt);//DEBUG
- tree match {
- case Tree.Visitor(cases) =>
- val cases1 = cases;
- var i = 0; while (i < cases.length) {
- cases1(i) = transformCase(cases(i), pattpe, pt);
- i = i + 1
- }
- return copy.Visitor(tree, cases1)
- .setType(Type.lub(Tree.typeOf(cases1.asInstanceOf[Array[Tree]])));
- case _ =>
- throw new ApplicationError();
- }
-
- /** Attribute a case where `pattpe' is the expected type of the pattern
- * and `pt' is the expected type of the result.
- */
- def transformCase(tree: Tree.CaseDef, pattpe: Type, pt: Type): Tree.CaseDef =
- tree match {
- case Tree.CaseDef(pat, guard, body) =>
- val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
- this.inAlternative = false; // no vars allowed below Alternative
- val pat1: Tree = transform(pat, PATTERNmode, pattpe);
- val guard1: Tree =
- if (guard == Tree.Empty) Tree.Empty
- else transform(guard, EXPRmode, definitions.boolean_TYPE());
- val body1: Tree = transform(body, EXPRmode, pt);
- context = prevContext;
- return copy.CaseDef(tree, pat1, guard1, body1)
- .setType(body1.getType()).asInstanceOf[Tree.CaseDef];
- }
-
- def transformStatSeq(stats: Array[Tree], exprOwner: Symbol): Array[Tree] = {
- var stats1 = stats;
- var i = 0; while (i < stats.length) {
- val stat: Tree = stats(i);
- if (context.owner.isCompoundSym() && !TreeInfo.isDeclaration(stat)) {
- error(stat.pos, "only declarations allowed here");
- }
- val mode: int = if (TreeInfo.isDefinition(stat)) NOmode else EXPRmode;
- var stat1: Tree = null;
- if (exprOwner.kind != NONE && !TreeInfo.isDefinition(stat)) {
- val prevContext = pushContext(stat, exprOwner, context.scope);
- stat1 = transform(stat, mode);
- context = prevContext;
- } else {
- stat1 = transform(stat, mode);
- }
- // todo: if we comment next 4 lines out, test/pos/scoping2 fails.
- // find out why
- if (stat1 != stat && stats1 == stats) {
- stats1 = new Array[Tree](stats.length);
- System.arraycopy(stats, 0, stats1, 0, i);
- }
- stats1(i) = stat1;
- i = i + 1
- }
- stats1
- }
-
- /** Attribute a sequence of constructor invocations.
- */
- def transformConstrInvocations(pos: int, constrs: Array[Tree]): Array[Tree] = {
- var i = 0; while (i < constrs.length) {
- constrs(i) = transform(constrs(i), CONSTRmode | SUPERmode, Type.AnyType);
- val f: Symbol = TreeInfo.methSymbol(constrs(i));
- if (f != null) {
- val c: Symbol = f.constructorClass();
- if (c.kind == CLASS) {
- c.initialize();//to detect cycles
- if (i > 0 && (c.flags & JAVA) == 0) loadMixinCode(pos, c);
- }
- }
- i = i + 1
- }
- constrs
- }
-
- def transformConstrInvocationArgs(constrs: Array[Tree]): unit = {
- var i = 0; while (i < constrs.length) {
- constrs(i) match {
- case Tree.Apply(fn, args) =>
- if (fn.getType().isInstanceOf[Type$MethodType])
- transformArgs(
- constrs(i).pos, TreeInfo.methSymbol(fn), Symbol.EMPTY_ARRAY,
- fn.getType(), EXPRmode, args, Type.AnyType);
- case _ =>
- }
- i = i + 1
- }
- }
-
- /** Attribute a template
- */
- def transformTemplate(templ: Tree.Template, owner: Symbol): Tree.Template = {
- //if (global.debug) global.log("transforming template of " + owner);//DEBUG
- if (templ.getType() == null)
- defineTemplate(templ, owner, owner.members());//may happen for mixins
- //System.out.println(owner.info());//DEBUG
- val parents = templ.parents;
- transformConstrInvocationArgs(parents);
- if (!owner.isError()) {
- validateParentClasses(
- parents, owner.info().parents(), owner.thisType());
- }
- val prevContext = pushContext(templ, owner, owner.members());
- /*
- val params: Scope = new Scope();
- def computeParams(t: Type): unit = t match {
- case Type$PolyType(tparams, t1) =>
- var i = 0; while (i < tparams.length) {
- params.enter(tparams(i));
- i = i + 1;
- }
- computeParams(t1);
- case Type$MethodType(vparams, _) =>
- var i = 0; while (i < vparams.length) {
- params.enter(vparams(i));
- i = i + 1;
- }
- case _ =>
- }
- computeParams(owner.primaryConstructor().getType());
- val prevContext = pushContext(templ, owner.primaryConstructor(), params);
- */
- templ.setSymbol(owner.newLocalDummy());
- val body1 = transformStatSeq(templ.body, templ.symbol());
- /*
- context = prevContext;
- */
- context = prevContext;
- val templ1: Tree.Template = copy.Template(templ, parents, body1);
- templ1.setType(owner.getType());
- // initialize all members; necessary to initialize overloaded symbols
- val members: Array[Symbol] = owner.members().elements();
- var i = 0; while (i < members.length) {
- val sym = members(i);
- sym.initialize();
- //System.out.println(owner.toString() + " defines " + sym + ":" + sym.getType());//DEBUG
- i = i + 1
- }
- templ1
- }
-
- /** Attribute an argument list.
- * @param pos Position for error reporting
- * @param meth The symbol of the called method, or `null' if none exists.
- * @param tparams The type parameters that need to be instantiated
- * @param methtype The method's type w/o type parameters
- * @param argMode The argument mode (either EXPRmode or PATTERNmode)
- * @param args The actual arguments
- * @param pt The proto-resulttype.
- * @return The vector of instantiated argument types, or null if error.
- */
- def transformArgs(pos: int, meth: Symbol, tparams: Array[Symbol], methtype: Type, argMode: int, args: Array[Tree], pt: Type): Array[Type] = {
- //System.out.println("trans args " + meth + ArrayApply.toString(tparams.asInstanceOf[Array[Object]]) + ":" + methtype + "," + pt);//DEBUG
- val argtypes = new Array[Type](args.length);
- methtype match {
- case Type$MethodType(params, restp) =>
- val formals = infer.formalTypes(params, args.length);
- if (formals.length != args.length) {
- error(pos, "wrong number of arguments for " +
- (if (meth == null) "<function>" else meth) +
- ArrayApply.toString(formals.asInstanceOf[Array[Object]], "(", ",", ")"));
- return null;
- }
- if (tparams.length == 0) {
- var i = 0; while (i < args.length) {
- args(i) = transform(args(i), argMode, formals(i));
- argtypes(i) = args(i).getType().deconst();
- i = i + 1
- }
- } else {
- // targs: the type arguments inferred from the prototype
- val targs: Array[Type] = infer.protoTypeArgs(tparams, restp, pt, params);
-
- // argpts: prototypes for arguments
- val argpts = new Array[Type](formals.length);
- var i = 0; while (i < formals.length) {
- argpts(i) = formals(i).subst(tparams, targs);
- i = i + 1
- }
-
- // transform arguments with (targs/tparams)formals as prototypes
- { var i = 0; while (i < args.length) {
- args(i) = transform(
- args(i), argMode | POLYmode, formals(i).subst(tparams, targs));
- i = i + 1
- }}
-
- // targs1: same as targs except that every AnyType is mapped to
- // formal parameter type.
- val targs1 = new Array[Type](targs.length);
- { var i = 0; while (i < targs.length) {
- targs1(i) = if (targs(i) != Type.AnyType) targs(i)
- else tparams(i).getType();
- i = i + 1
- }}
-
- { var i = 0; while (i < args.length) {
- argtypes(i) = args(i).getType().deconst();
- argtypes(i) match {
- case Type$PolyType(tparams1, restype1) =>
- argtypes(i) = infer.argumentTypeInstance(
- tparams1, restype1,
- formals(i).subst(tparams, targs1),
- argpts(i));
- case _ =>
- }
- i = i + 1
- }}
- }
- // desugarizing ident patterns
- if (params.length > 0 && (params(params.length-1).flags & REPEATED) != 0) {
- if ((mode & PATTERNmode) != 0) {
- def desug_allIdentPatterns(trees: Array[Tree], currentOwner: Symbol): unit = {
- var i = 0; while (i < trees.length) {
- trees(i) match {
- case Tree.Ident(name) =>
- if (name != Names.PATTERN_WILDCARD) {
- val vble: Symbol = context.scope.lookup(name);
- trees(i) = desugarize.IdentPattern(trees(i)).setSymbol(vble)
- .setType(vble.getType());
- } else {
- trees(i) = gen.Ident(trees(i).pos, definitions.PATTERN_WILDCARD);
- }
- case _ =>
- }
- i = i + 1
- }
- }
- desug_allIdentPatterns(args, context.owner);
- } else {
- assert(args.length != params.length ||
- !(args(params.length-1).isInstanceOf[Tree.Sequence]));
- }
- }
- argtypes;
-
- case Type$PolyType(tparams1, restp) =>
- var tparams2: Array[Symbol] = tparams1;
- if (tparams.length != 0) {
- tparams2 = new Array[Symbol](tparams.length + tparams1.length);
- System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
- System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
- }
- transformArgs(pos, meth, tparams2,
- infer.skipViewParams(tparams2, restp), argMode, args, pt)
-
- case Type.ErrorType =>
- var i = 0; while (i < args.length) {
- args(i) = transform(args(i), argMode, Type.ErrorType);
- argtypes(i) = args(i).getType().deconst();
- i = i + 1
- }
- argtypes
-
- case Type.OverloadedType(alts, alttypes) if (alts.length == 1) =>
- transformArgs(pos, alts(0), tparams, alttypes(0), argMode, args, pt)
-
- case _ =>
- var i = 0; while (i < args.length) {
- args(i) = transform(args(i), argMode, Type.AnyType);
- argtypes(i) = args(i).getType().deconst();
- i = i + 1
- }
- argtypes
- }
- }
-
- /** Atribute an expression or pattern with prototype `pt'.
- * Check that expression's type conforms to `pt'.
- * Resolve overloading and apply parameterless functions.
- * Insert `apply' function if needed.
- */
- def transform(tree: Tree, mode: int, pt: Type): Tree = {
- val savedMode: int = this.mode;
- val savedPt: Type = this.pt;
- this.mode = mode;
- this.pt = pt;
- val tree1: Tree = adapt(transform(tree), mode, pt);
-
- //System.out.println(tree1 + ": " + tree1.getType());//DEBUG
-
- this.mode = savedMode;
- this.pt = savedPt;
- tree1
- }
-
- /** Transform expression or type with a given mode.
- */
- def transform(tree: Tree, mode: int): Tree = {
- if ((mode & (EXPRmode | PATTERNmode | CONSTRmode)) != 0)
- return transform(tree, mode, Type.AnyType);
-
- val savedMode: int = this.mode;
- this.mode = mode;
- val tree1: Tree = transform(tree);
- this.mode = savedMode;
-
- if ((mode & TYPEmode) != 0) {
- val sym: Symbol = tree1.symbol();
- def typeParamCount = sym.primaryConstructor().rawInfo() match {
- case t: LazyTreeType =>
- t.tree match {
- case Tree.ClassDef(_, _, tparams, _, _, _) => tparams.length
- case Tree.AliasTypeDef(_, _, tparams, _) => tparams.length
- case _ => 0
- }
- case _ => sym.typeParams().length
- }
- if ((mode & FUNmode) == 0 && sym != null && typeParamCount != 0) {
- error(tree.pos, "" + sym + " takes type parameters.");
- return errorTree(tree);
- }
-// else if (tree1.isType())
-// return gen.mkType(tree1.pos, tree1.getType());
- }
- tree1
- }
-
- def transform(trees: Array[Tree], mode: int): Array[Tree] = {
- var i = 0; while (i < trees.length) {
- trees(i) = transform(trees(i), mode);
- i = i + 1
- }
- trees
- }
-
- override def transform(trees: Array[Tree]): Array[Tree] =
- super.transform(trees);
-
- override def transform(trees: Array[Tree.CaseDef]): Array[Tree.CaseDef] =
- super.transform(trees);
-
- override def transform(trees: Array[Tree.AbsTypeDef]): Array[Tree.AbsTypeDef] =
- super.transform(trees);
-
- override def transform(trees: Array[Tree.ValDef]): Array[Tree.ValDef] =
- super.transform(trees);
-
- override def transform(trees: Array[Array[Tree.ValDef]]): Array[Array[Tree.ValDef]] =
- super.transform(trees);
-
- /** The main attribution function
- */
- override def transform(tree: Tree): Tree = {
- //System.out.println("transforming " + tree + ":" + pt);//DEBUG
- if (tree.getType() != null) {
- checkDefined.all = tree; checkDefined.traverse(tree);//debug
- return tree;
- }
- val sym: Symbol = tree.symbol();
- if (sym != null && !sym.isInitialized()) sym.initialize();
- if (global.debug && TreeInfo.isDefinition(tree)) global.log("transforming definition of " + sym);
- try {
- tree match {
- case Tree.Empty =>
- tree.setType(Type.NoType)
-
- case Tree.Attributed(attr, definition) =>
-
- def attrInfo(attr: Tree): AttrInfo = attr match {
- case Tree.Ident(_) | Tree.Select(_, _) =>
- new Pair(attr.symbol(), new Array[AConstant](0))
- case Tree.Apply(fn, args) =>
- new Pair(attrInfo(fn).fst, attrArgInfos(args))
- case _ =>
- unit.error(attr.pos, "malformed attribute");
- new Pair(Symbol.NONE.newErrorClass(errorName(attr).toTypeName()),
- new Array[AConstant](0))
- }
-
- def attrArgInfos(args: Array[Tree]): Array[AConstant] = {
- val infos = new Array[AConstant](args.length);
- var i = 0; while (i < args.length) {
- args(i) match {
- case Tree.Literal(value) => infos(i) = value;
- case _ => unit.error(args(i).pos,
- "attribute argument needs to be a constant; found: " + args(i) + " " + args(i).getClass());
- }
- i = i + 1
- }
- infos
- }
-
- val attr1 = transform(attr, CONSTRmode, definitions.ATTRIBUTE_TYPE());
- val res = transform(definition);
- val defsym = res.symbol();
- var attrs = global.mapSymbolAttr.get(defsym).asInstanceOf[List[AttrInfo]];
- if (attrs == null) attrs = List();
- global.mapSymbolAttr.put(defsym, attrInfo(attr1) :: attrs);
- res
-
- case Tree.DocDef(comment, definition) =>
- transform(definition)
-
- case Tree.PackageDef(pkg, templ @ Tree.Template(parents, body)) =>
- val pkgSym: Symbol = pkg.symbol();
- if (pkgSym != null && pkgSym.isPackage()) {
- val prevContext = pushContext(templ, pkgSym.moduleClass(), pkgSym.members());
- val body1: Array[Tree] = transform(body);
- context = prevContext;
- val templ1: Tree.Template = copy.Template(templ, parents, body1);
- templ1.setType(Type.NoType).setSymbol(Symbol.NONE);
- copy.PackageDef(tree, pkg, templ1)
- .setType(Type.NoType);
- } else {
- setError(tree);
- }
-
- case Tree.PackageDef(_, _) =>
- setError(tree)
-
- case Tree.ClassDef(_, _, tparams, vparams, tpe, templ) =>
- val prevContext = pushContext(
- tree, sym.primaryConstructor(), new Scope(context.scope));
- reenterParams(tparams, vparams, sym.primaryConstructor().getType());
- val tparams1 = transform(tparams);
- val vparams1 = transform(vparams);
- checkNoEscapeParams(vparams1);
- val tpe1: Tree = transform(tpe, TYPEmode);
- if (vparams.length > 0 && templ.getType() == null)
- templ.body = desugarize.addParamAccessors(
- templ.body, vparams(vparams.length - 1));
-
- val templ1: Tree.Template = transformTemplate(templ, sym);
- if (sym.isTrait()) checkTraitDef(tree.pos, sym, templ1);
- checkNoEscape(tree.pos, sym.info());
- context = prevContext;
- copy.ClassDef(tree, sym, tparams1, vparams1, tpe1, templ1)
- .setType(Type.NoType);
-
- case Tree.ModuleDef(_, _, tpe, templ) =>
- val clazz = sym.moduleClass();
- clazz.initialize();
- val prevContext = pushContext(
- tree, clazz.primaryConstructor(), context.scope);
- val tpe1: Tree = transform(tpe, TYPEmode);
- context = prevContext;
- val templ1: Tree.Template = transformTemplate(templ, sym.moduleClass());
- if (tpe1 != Tree.Empty && !templ1.getType().isSubType(tpe1.getType()))
- error(tree.pos, "" + sym + " does not implement " + tpe1.getType());
-
- val lclass = sym.linkedClass();
- // Taken from SymbolLoader.initializeRoot()
- if (lclass != null) {
- if (lclass.rawInfo().isInstanceOf[SymbolLoader]) {
- lclass.setInfo(Type.ErrorType);
- val allConstr = lclass.allConstructors();
- allConstr.setInfo(Type.ErrorType);
- allConstr.flags = allConstr.flags | Modifiers.PRIVATE;
- }
- }
-
- copy.ModuleDef(tree, sym, tpe, templ1)
- .setType(Type.NoType);
-
- case Tree.DefDef(_, name, tparams, vparams, tpe, rhs) =>
- val prevContext = pushContext(tree, sym, new Scope(context.scope));
- reenterParams(tparams, vparams, sym.getType());
- if (name == Names.CONSTRUCTOR) {
- val enclClass = context.enclClass.owner;
- enclClass.flags =
- enclClass.flags | INCONSTRUCTOR;
- enclClass.primaryConstructor().flags =
- enclClass.primaryConstructor().flags | INCONSTRUCTOR;
- }
- val tparams1 = transform(tparams);
- val vparams1 = transform(vparams);
- checkNoEscapeParams(vparams1);
- val tpe1: Tree =
- if (tpe == Tree.Empty) gen.mkType(tree.pos, sym.getType().resultType())
- else transform(tpe, TYPEmode);
- var rhs1: Tree =
- if (rhs == Tree.Empty) rhs
- else transform(
- rhs,
- if (name == Names.CONSTRUCTOR) CONSTRmode else EXPRmode,
- if (name == Names.CONSTRUCTOR) definitions.void_TYPE() else tpe1.getType());
- context = prevContext;
- if (name == Names.CONSTRUCTOR) {
- val enclClass = context.enclClass.owner;
- enclClass.flags =
- enclClass.flags & ~ INCONSTRUCTOR;
- enclClass.primaryConstructor().flags =
- enclClass.primaryConstructor().flags & ~ INCONSTRUCTOR;
- }
- sym.flags = sym.flags | LOCKED;
- checkNonCyclic(tree.pos, tpe1.getType());
- sym.flags = sym.flags & ~LOCKED;
- copy.DefDef(tree, sym, tparams1, vparams1, tpe1, rhs1)
- .setType(Type.NoType);
-
- case Tree.ValDef(_, _, tpe, rhs) =>
- assert(sym != null, tree);
- val tpe1: Tree =
- if (tpe == Tree.Empty) gen.mkType(tree.pos, sym.getType())
- else transform(tpe, TYPEmode);
- var rhs1: Tree = rhs;
- if (rhs != Tree.Empty) {
- val prevContext = pushContext(tree, sym, context.scope);
- rhs1 = transform(rhs, EXPRmode, tpe1.getType());
- context = prevContext;
- } else if ((sym.flags & (MUTABLE | DEFERRED)) == MUTABLE) {
- rhs1 = gen.mkDefaultValue(tree.pos, sym.getType());
- }
- sym.flags = sym.flags | LOCKED;
- checkNonCyclic(tree.pos, tpe1.getType());
- sym.flags = sym.flags & ~LOCKED;
- copy.ValDef(tree, sym, tpe1, rhs1)
- .setType(Type.NoType);
-
- case Tree.AbsTypeDef(_, _, rhs, lobound) =>
- val rhs1: Tree = transform(rhs, TYPEmode);
- val lobound1: Tree = transform(lobound, TYPEmode);
- checkNonCyclic(tree.pos, sym.getType());
- copy.AbsTypeDef(tree, sym, rhs1, lobound1)
- .setType(Type.NoType);
-
- case Tree.AliasTypeDef(_, _, tparams, rhs) =>
- val prevContext = pushContext(tree, sym.primaryConstructor(), new Scope(context.scope));
- reenterParams(tparams, sym.typeParams());
- val tparams1 = transform(tparams);
- val rhs1: Tree = transform(rhs, TYPEmode);
- context = prevContext;
- checkNonCyclic(tree.pos, sym.getType());
- copy.AliasTypeDef(tree, sym, tparams1, rhs1)
- .setType(Type.NoType);
-
- case Tree.Import(expr, selectors) =>
- pushContext(tree, context.owner, context.scope);
- Tree.Empty
-/*
-
- case _ =>
- transform1(tree, sym)
- }
- }
-
- // extracted from transform0 to avoid overflows in GenJVM
- private def transform1(tree: Tree, sym: Symbol): Tree = {
-
- tree match {
-*/
- case Tree.Block(stats, value) =>
- val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
- val newContext = context;
- val stats1 = desugarize.Statements(unit, stats, true);
- enterSyms(stats1);
- context = newContext;
- val curmode: int = mode;
- var start: Int = 0;
- var valuemode: Int = curmode;
- if ((curmode & CONSTRmode) != 0) {
- stats1(0) = transform(stats1(0), curmode, pt);
- context.enclClass.owner.flags = context.enclClass.owner.flags & ~INCONSTRUCTOR;
- start = 1;
- valuemode = (curmode & ~CONSTRmode) | EXPRmode;
- }
- var i = start; while (i < stats1.length) {
- stats1(i) = transform(stats1(i), EXPRmode);
- i = i + 1
- }
- val value1: Tree = transform(value, valuemode & ~(FUNmode | QUALmode), pt);
- val owntype: Type =
- checkNoEscape(tree.pos, value1.getType().deconst());
- context = prevContext;
- copy.Block(tree, stats1, value1)
- .setType(owntype);
-
- case Tree.Sequence(trees) =>
- var i = 0; while (i < trees.length) {
- trees(i) = transform(trees(i),
- this.mode | SEQUENCEmode,
- pt);
- i = i + 1
- }
- copy.Sequence(tree, trees).setType(pt);
-
- case Tree.Alternative(choices) =>
- val save: boolean = this.inAlternative;
- this.inAlternative = true;
-
- val newts = new Array[Tree](choices.length);
- var i = 0; while (i < choices.length) {
- newts(i) = transform(choices(i), this.mode, pt);
- i = i + 1
- }
-
- //val tpe: Type = Type.lub(Tree.typeOf(newts));
-
- this.inAlternative = save;
- copy.Alternative(tree, newts).setType(pt);
-
- case Tree.Bind(name, body) =>
- var vble: Symbol = null;
- if(name != Names.PATTERN_WILDCARD) {
- vble = context.owner.newPatternVariable(tree.pos, name).setType(pt);
- enterInScope(vble);
- //System.out.println("Bind("+name+",...) enters in scope:"+Debug.show(vble));
-
- patternVars.put(vble, new Boolean(this.inAlternative));
- //System.out.println("case Bind.. put symbol vble="+vble+" in scope and patternVars.");
- }
- val body1: Tree = transform(body);
- if(name == Names.PATTERN_WILDCARD) body1
- else {
- //assert body1.getType() != null;
- if(TreeInfo.isSequenceValued(body1)) {
- vble.setType(definitions.LIST_TYPE(pt));
- } else {
- vble.setType(body1.getType());
- }
- copy.Bind(tree, name, body1)
- .setSymbol(vble).setType(body1.getType());
- }
-
- case Tree.Visitor(cases) =>
- if (pt.symbol().isSubClass(definitions.PARTIALFUNCTION_CLASS)) {
- val pft: Type = pt.baseType(definitions.PARTIALFUNCTION_CLASS);
- val pftargs = pft.typeArgs();
- if (pftargs.length == 2 && infer.isFullyDefined(pftargs(0))) {
- val pattype: Type = pftargs(0);
- var restype: Type = pftargs(1);
- val isDefinedAtVisitor: Tree = transformVisitor(
- desugarize.isDefinedAtVisitor(tree),
- pattype, definitions.boolean_TYPE());
- val applyVisitor: Tree = transformVisitor(tree, pattype, restype);
- if (!infer.isFullyDefined(restype))
- restype = applyVisitor.getType().deconst();
- loadMixinCode(tree.pos, definitions.PARTIALFUNCTION_CLASS);
- gen.mkPartialFunction(
- tree.pos, applyVisitor, isDefinedAtVisitor,
- pattype, restype, context.owner);
- } else {
- error(tree.pos, "expected pattern type of cases could not be determined");
- errorTermTree(tree)
- }
- } else {
- transform(desugarize.Visitor(unit, tree))
- }
-
- case Tree.Assign(Tree.Apply(_, _), _) =>
- transform(desugarize.Update(tree))
-
- case Tree.Assign(lhs, rhs) =>
- val lhs1: Tree = transform(lhs, EXPRmode);
- val varsym: Symbol = lhs1.symbol();
- if (isSetterMethod(varsym)) {
- // todo: change this to require setters in same template
- transform(desugarize.Assign(tree.pos, lhs, rhs));
- } else if (varsym != null && (varsym.flags & MUTABLE) != 0) {
- val rhs1: Tree = transform(rhs, EXPRmode, lhs1.getType());
- copy.Assign(tree, lhs1, rhs1)
- .setType(definitions.void_TYPE());
- } else {
- if (!lhs1.getType().isError())
- error(tree.pos, "assignment to non-variable ");
- gen.mkUnitLit(tree.pos)
- }
-
- case Tree.If(cond, thenp, elsep) =>
- val cond1: Tree = transform(cond, EXPRmode, definitions.boolean_TYPE());
- var thenp1: Tree = _;
- var elsep1: Tree = _;
- if (elsep == Tree.Empty) {
- thenp1 = transform(thenp, EXPRmode, definitions.void_TYPE());
- elsep1 = gen.mkUnitLit(tree.pos);
- } else {
- thenp1 = transform(thenp, EXPRmode, pt);
- elsep1 = transform(elsep, EXPRmode, pt);
- }
- copy.If(tree, cond1, thenp1, elsep1)
- .setType(Type.lub(NewArray.Type(thenp1.getType(), elsep1.getType())));
-
- case Tree.Throw(expr) =>
- val expr1: Tree = transform(
- expr, EXPRmode, definitions.THROWABLE_TYPE());
- gen.Select(tree.pos, expr1, definitions.THROWABLE_THROW);
-
- case Tree.Return(expr) =>
- if (!context.owner.isInitialized()) {
- error(tree.pos, "method with return needs result type");
- errorTermTree(tree)
- } else {
- val enclFun: Symbol = context.owner.enclMethod();
- if (enclFun.kind == VAL && !enclFun.isConstructor()) {
- val expr1: Tree = transform(
- expr, EXPRmode, enclFun.getType().resultType());
- copy.Return(tree, expr1)
- .setSymbol(enclFun).setType(definitions.ALL_TYPE());
- } else {
- error(tree.pos, "return outside method definition");
- errorTermTree(tree)
- }
- }
-
- case Tree.New(init) =>
- val init1: Tree = transform(init, CONSTRmode, pt);
- checkInstantiatable(tree.pos, init1.getType());
- val tree1 = gen.New(tree.pos, init1);
- val clazz = tree1.getType().symbol();
- if (clazz.isAnonymousClass()) {
- val parentTypes = clazz.info().parents();
- val refinement: Scope = new Scope();
- val base: Type = Type.compoundTypeWithOwner(context.enclClass.owner, parentTypes, Scope.EMPTY);
- val it: Scope$SymbolIterator = clazz.members().iterator();
- while (it.hasNext()) {
- val sym1: Symbol = it.next();
- val basesym1: Symbol = base.lookupNonPrivate(sym1.name);
- if (!basesym1.isNone() &&
- sym1.kind != VAL && // todo: remove once refinements work!
- !base.symbol().thisType().memberType(basesym1)
- .isSameAs(sym1.getType()))
- refinement.enter(sym1);
- }
- val owntype =
- if (refinement.isEmpty() && parentTypes.length == 1)
- parentTypes(0)
- else
- checkNoEscape(
- tree.pos,
- Type.compoundTypeWithOwner(
- context.enclClass.owner, parentTypes, refinement));
- gen.Typed(tree1, owntype)
- } else
- tree1
-
- case Tree.Typed(expr, tpe) =>
- expr match {
- case Tree.Ident(n)
- if (n != Names.PATTERN_WILDCARD && (mode & PATTERNmode) != 0) =>
- transform(desugarize.TypedPattern(tree.asInstanceOf[Tree.Typed]),
- mode,
- pt);
- case _ =>
- var expr1: Tree = _;
- var tpe1: Tree = _;
- tpe match {
- case Tree.Ident(TypeNames.WILDCARD_STAR) =>
- expr1 = transform(
- expr, mode & baseModes, definitions.SEQ_TYPE(pt));
- val elemtps =
- expr1.getType().baseType(definitions.SEQ_CLASS).typeArgs();
- val elemtp: Type = if (elemtps.length == 1) elemtps(0)
- else Type.ErrorType;
-
- tpe1 = tpe.setType(elemtp);
- case _ =>
- tpe1 = transform(tpe, TYPEmode);
- expr1 = transform(expr, mode & baseModes, tpe1.getType());
- }
- copy.Typed(tree, expr1, tpe1).setType(tpe1.getType())
- }
-
- case Tree.Function(vparams, body) =>
- val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
- var restype: Type = desugarize.preFunction(vparams, pt);
- enterParams(vparams);
- val vparams1 = transform(vparams);
- val body1: Tree = transform(body, EXPRmode, restype);
- if (!infer.isFullyDefined(restype))
- restype = body1.getType().deconst();
- restype = checkNoEscape(tree.pos, restype);
- context = prevContext;
- gen.mkFunction(tree.pos, vparams1, body1, restype, context.owner, false);
-
- case Tree.TypeApply(fn, args) =>
-
- val fn1: Tree = transform(
- fn, (mode & (EXPRmode | CONSTRmode)) | FUNmode, Type.AnyType);
- val args1 = transform(args, TYPEmode);
- val argtypes = Tree.typeOf(args1);
-
- // propagate errors in arguments
- var i = 0;
- while (i < argtypes.length && !argtypes(i).isError())
- i = i + 1;
- if (i < argtypes.length)
- setError(tree);
- else {
-
- // resolve overloading
- fn1.getType() match {
- case Type$OverloadedType(alts, alttypes) =>
- try {
- infer.polyAlternative(fn1, alts, alttypes, args.length);
- } catch {
- case ex: Type$Error => reportTypeError(tree.pos, ex);
- }
- case _ =>
- }
-
- // match against arguments
- fn1.getType() match {
- case Type$PolyType(tparams, restp) if (tparams.length == argtypes.length) =>
- constfold.tryToFold(
- infer.completeTypeApply(
- copy.TypeApply(tree, fn1, args1)
- .setType(restp.subst(tparams, argtypes))));
-
- case Type.ErrorType =>
- setError(tree)
-
- case fn1tp =>
- if (!fn1tp.isError()) error(tree.pos,
- infer.toString(fn1.symbol(), fn1.getType()) +
- " cannot be applied to " +
- ArrayApply.toString(
- argtypes.asInstanceOf[Array[Object]], "(", ",", ")"));
- errorTermTree(tree)
- }
- }
-
- case Tree.Apply(fn, args) =>
- mode = mode & ~SEQUENCEmode;
- var fn1: Tree = _;
- var argMode: int = _;
- var selfcc: boolean = false;
- //todo: Should we pass in both cases a methodtype with
- // AnyType's for args as a prototype?
- if ((mode & EXPRmode) != 0) {
- fn1 = transform(fn, mode | FUNmode, Type.AnyType);
- argMode = EXPRmode;
- } else if ((mode & PATTERNmode) != 0) {
- fn1 = transform(fn, mode | FUNmode, pt);
- argMode = PATTERNmode;
- } else {
- assert((mode & CONSTRmode) != 0);
- fn1 = transform(fn, mode | FUNmode, Type.AnyType);
- argMode = EXPRmode;
-
- // convert type to constructor
- val tsym: Symbol = TreeInfo.methSymbol(fn1);
- if (!tsym.isError()) {
- assert(tsym.isType(), tsym);
- fn1.getType().withDefaultArgs().unalias() match {
- case Type$TypeRef(pre, c, argtypes) =>
- if (c.kind != CLASS) {
- error(tree.pos,
- "" + tsym + " is not a class; cannot be instantiated");
- } else if (!pre.isStable()) {
- error(tree.pos, "" + pre + " is not a legal prefix for a constructor");
- } else {
- c.initialize();
- val constr: Symbol = c.allConstructors();
- val fn0: Tree = fn1;
- fn1 = gen.mkRef(fn1.pos, pre, constr);
- var enclClassOrConstructorContext = Context.NONE;
- if (constr.owner().isPackageClass()) {
- var c = context;
- while (c != Context.NONE &&
- !c.tree.isInstanceOf[Tree.ClassDef] &&
- !c.tree.isInstanceOf[Tree.ModuleDef] &&
- !c.tree.isInstanceOf[Tree.Template])
- c = c.outer;
- enclClassOrConstructorContext = c
- }
- if (enclClassOrConstructorContext == Context.NONE) {
- fn1 match {
- case Tree.Select(fn1qual, _) =>
- fn1.setType(infer.checkAccessible(
- fn1.pos, constr, fn1.getType(), fn1qual, fn1qual.getType()));
- case _ =>
- if (constr.owner().isPackageClass())
- fn1.setType(infer.checkAccessible(
- fn1.pos, constr, fn1.getType(), Tree.Empty, constr.owner().getType()));
- }
- } else {
- val cowner = enclClassOrConstructorContext.owner;
- if (cowner.isConstructor())
- // we are in a superclass constructor call
- fn1.setType(
- infer.checkAccessible(
- fn1.pos, constr, fn1.getType(),
- make.Super(tree.pos,
- Names.EMPTY.toTypeName(),
- Names.EMPTY.toTypeName()),
- cowner.constructorClass().typeConstructor()));
- else
- fn1.setType(infer.checkAccessible(
- fn1.pos, constr, fn1.getType(),
- enclClassOrConstructorContext.tree,
- cowner.typeConstructor()));
- }
- if (tsym == c) {
- fn0 match {
- case Tree.AppliedType(_, targs) =>
- fn1 = infer.completeTypeApply(gen.TypeApply(fn1, targs));
- case _ =>
- }
- } else {
- // it was an alias type
- // todo: handle overloaded constructors
- if (argtypes.length != 0)
- fn1 = gen.TypeApply(
- fn1, gen.mkTypes(fn1.pos, argtypes));
- if (tsym.typeParams().length != 0 &&
- !(fn0.isInstanceOf[Tree.AppliedType]))
- fn1.setType(new Type$PolyType(
- tsym.typeParams(), fn1.getType()));
- }
- //System.out.println(TreeInfo.methSymbol(fn1) + ":" + tp + " --> " + fn1.getType() + " of " + fn1);//DEBUG
- selfcc = TreeInfo.isSelfConstrCall(fn0);
- }
-
- case _ =>
- error(tree.pos,
- "" + tsym + " is not a class; cannot be instantiated");
- }
- }
- }
-
- // if function is overloaded with one alternative
- // whose arity matches argument length and whose result type matches prototype,
- // preselect this alternative.
- fn1.getType() match {
- case Type$OverloadedType(alts, alttypes) =>
- val argtypes = new Array[Type](args.length);
- { var i = 0; while (i < argtypes.length) {
- argtypes(i) = definitions.ALL_TYPE(); i = i + 1
- }}
- var matching1: int = -1;
- var matching2: int = -1;
- { var i = 0; while (i < alttypes.length) {
- if (infer.isApplicable(alttypes(i), argtypes, pt)) {
- //System.out.println("matches: " + alttypes(i) + " with " + pt);//debug
- matching2 = matching1;
- matching1 = i;
- }
- i = i + 1;
- }}
- if (matching1 >= 0 && matching2 < 0) {
- fn1.setSymbol(alts(matching1)).setType(alttypes(matching1));
- }
- case _ =>
- }
-
- def handleApply: Tree = {
- // handle the case of application of match to a visitor specially
- if (args.length == 1 && args(0).isInstanceOf[Tree.Visitor]) {
- val pattp: Type = matchQualType(fn1);
- if (pattp.isError()) {
- return setError(tree)
- } else if (pattp != Type.NoType) {
- if (infer.isFullyDefined(pattp) &&
- !(fn1.getType().isInstanceOf[Type$PolyType] &&
- pattp.containsSome(fn1.getType().typeParams()))) {
- val fn2: Tree = desugarize.postMatch(fn1, context.enclClass.owner);
- val arg1: Tree = transformVisitor(args(0), pattp, pt);
- return copy.Apply(tree, fn2, NewArray.Tree(arg1))
- .setType(arg1.getType());
- } else {
- error(tree.pos, "expected pattern type of cases could not be determined");
- return errorTermTree(tree)
- }
- }
- }
-
- // return prematurely if function is a superclass constructor
- // and no type arguments need to be inferred.
- if ((mode & SUPERmode) != 0 && fn1.getType().isInstanceOf[Type$MethodType]) {
- return copy.Apply(tree, fn1, args).setType(fn1.getType().resultType()) : Tree;
- }
-
- // type arguments with formals as prototypes if they exist.
- fn1.setType(infer.freshInstance(fn1.getType()));
- val argtypes = transformArgs(
- tree.pos, fn1.symbol(), Symbol.EMPTY_ARRAY, fn1.getType(), argMode, args, pt);
-
- if (argtypes == null)
- return setError(tree)
- else {
- var i: int = 0;
- while (i < argtypes.length && !argtypes(i).isError())
- i = i + 1;
- if (i < argtypes.length) return setError(tree);
- }
-
- // resolve overloading1g
- fn1.getType() match {
- case Type$OverloadedType(alts, alttypes) =>
- try {
- infer.methodAlternative(fn1, alts, alttypes, argtypes, pt);
- } catch {
- case ex: Type$Error => reportTypeError(tree.pos, ex);
- }
- case _ =>
- }
-
- // check that self constructors go backwards.
- if (selfcc) {
- val constr: Symbol = TreeInfo.methSymbol(fn1);
- if (constr != null && constr.kind == VAL &&
- !(constr.getType().isInstanceOf[Type$OverloadedType]) &&
- constr.pos > tree.pos)
- error(tree.pos,
- "illegal forward reference to self constructor");
- }
-
- fn1.getType() match {
- case Type$PolyType(tparams, restp) =>
- // if method is polymorphic,
- // infer instance, and adapt arguments to instantiated formals
- try {
- fn1 = infer.methodInstance(fn1, tparams, restp, argtypes, pt);
- //System.out.println(fn1 + ":" + fn1.getType());//DEBUG
- } catch {
- case ex: Type$Error =>
- //ex.printStackTrace();//DEBUG
- reportTypeError(tree.pos, ex);
- }
- case _ =>
- }
-
- fn1.getType() match {
- case Type$MethodType(params, restp) =>
- if ((mode & PATTERNmode) != 0) {
- return copy.Apply(tree, fn1, args).setType(restp);
- } else {
- val formals = infer.formalTypes(params, args.length);
- if (formals.length == args.length) {
- var i = 0; while (i < args.length) {
- args(i) = adapt(args(i), argMode, formals(i));
- args(i) match {
- case Tree.Typed( arg, Tree.Ident( TypeNames.WILDCARD_STAR ) ) =>
- if( i != args.length - 1 ) {
- error( arg.pos, "escape only allowed in last position");
- } else if ( args.length > params.length ) {
- error( arg.pos, "escaping cannot be mixed with values");
- }
- case _ => /* nop */
- }
- i = i + 1
- }
- }
- return constfold.tryToFold(
- copy.Apply(tree, fn1, args)
- .setType(restp));
- }
-
- case _ =>
- }
-
- if (!fn1.getType().isError())
- error(
- tree.pos,
- infer.applyErrorMsg(
- "", fn1, " cannot be applied to ", argtypes, pt));
- errorTermTree(tree)
- }
-
- handleApply
-
- case Tree.Super(qualifier, mixin) =>
- val clazz: Symbol = qualifyingClass(tree, qualifier);
- if (clazz.isNone()) {
- setError(tree);
- } else {
- tree.setSymbol(clazz);
- val parents = clazz.parents();
- if (mixin == TypeNames.EMPTY) {
- tree.setType(parents(0).instanceType());
- } else {
- var i = 0;
- while (i < parents.length && parents(i).symbol().name != mixin)
- i = i + 1;
- if (i < parents.length)
- tree.setType(parents(i).instanceType());
- else {
- error(tree.pos,
- "" + mixin + " does not name a mixin base class of " + clazz);
- errorTermTree(tree)
- }
- }
- }
-
- case Tree.This(name) =>
- val clazz: Symbol = qualifyingClass(tree, name);
- if (clazz.isNone())
- setError(tree)
- else {
- tree.setSymbol(clazz);
- tree.setType(
- if (pt != null && pt.isStable() || (mode & QUALmode) != 0) clazz.thisType()
- else clazz.typeOfThis());
- }
-
- case Tree.Select(qual, name) =>
- val qualmode: int = if (name == Names._match) EXPRmode
- else EXPRmode | POLYmode | QUALmode;
- var qual1: Tree = transform(qual, qualmode);
- if (name.isTypeName())
- qual1 = checkStable(qual1);
- transformSelect(
- tree, adapt(qual1, qualmode, Type.AnyType), name);
-
- case Tree.Ident(name) =>
- if (name == Names.CONSTRUCTOR) {
- assert((mode & CONSTRmode) != 0, tree);
- copy.Ident(tree, context.enclClass.owner)
- .setType(context.enclClass.owner.getType());
- } else if (((mode & (PATTERNmode | FUNmode)) == PATTERNmode) && name.isVariable()) {
- var vble: Symbol = null;
- var vble2: Symbol = null;
-
- // if vble is bound with @, there is already a symbol
- if (name != Names.PATTERN_WILDCARD) {
- vble2 = context.scope.lookup(name);
- }
- var tree1 = tree;
- if (patternVars.containsKey(vble2))
- vble = vble2;
- else {
- vble =
- if (name == Names.PATTERN_WILDCARD)
- definitions.PATTERN_WILDCARD
- else context.owner.newPatternVariable(tree.pos, name).setType(pt);
- //if(((mode & SEQUENCEmode) != 0)&&(name != Names.PATTERN_WILDCARD)) {
- if(name != Names.PATTERN_WILDCARD) {
- // x => x @ _ in sequence patterns
- tree1 = desugarize.IdentPattern(tree);
- }
- }
- if (name != Names.PATTERN_WILDCARD) enterInScope(vble);
- tree1.setSymbol(vble).setType(pt);
- } else {
- transformIdent(tree, name)
- }
-
- case Tree.Literal(value) =>
- tree.setType(Type.constantType(value))
-
- case Tree.LabelDef(name, params, body) =>
- assert(params.length == 0);
- val prevContext = pushContext(tree, context.owner, new Scope(context.scope));
- val lsym: Symbol = context.owner.newLabel(tree.pos, name);
- lsym.setInfo(
- new Type$MethodType(Symbol.EMPTY_ARRAY, definitions.void_TYPE()));
- context.scope.enter(lsym);
- val body1: Tree = transform(body, mode, pt);
- context = prevContext;
- copy.LabelDef(tree, lsym, params, body1)
- .setSymbol(lsym).setType(definitions.void_TYPE());
-
- case Tree.TypeTerm() =>
- tree
-
- case Tree.SingletonType(ref) =>
- val ref1: Tree = checkStable(
- transform(ref, EXPRmode | QUALmode, definitions.ANYREF_TYPE()));
- copy.SingletonType(tree, ref1)
- .setType(ref1.getType().resultType());
-
- case Tree.SelectFromType(qual, name) =>
- val qual1: Tree = transform(qual, TYPEmode);
- transformSelect(tree, qual1, name);
-
- case Tree.CompoundType(parents, refinements) =>
- val parents1 = transform(parents, TYPEmode);
- val ptypes = new Array[Type](parents1.length);
- { var i = 0; while (i < parents1.length) {
- val tp = parents(i).getType();
- if (i > 0 || tp.unalias().symbol().kind != TYPE)
- checkClassType(parents(i).pos, tp);
- ptypes(i) = tp;
- i = i + 1
- }}
- val members: Scope = new Scope();
- val cowner =
- if (context.owner.isPrimaryConstructor() && context.owner.owner().isPackageClass())
- context.owner.constructorClass()
- else context.enclClass.owner;
- val self: Type = Type.compoundTypeWithOwner(cowner, ptypes, members);
- val clazz: Symbol = self.symbol();
- val prevContext = pushContext(tree, clazz, members);
- { var i = 0; while (i < refinements.length) {
- val m = enterSym(refinements(i));
- m.flags = m.flags | OVERRIDE;
- i = i + 1
- }}
- val refinements1 = transformStatSeq(refinements, Symbol.NONE);
- context = prevContext;
- copy.CompoundType(tree, parents1, refinements1)
- .setType(self)
-
- case Tree.AppliedType(tpe, args) =>
- val tpe1: Tree = transform(tpe, mode | FUNmode);
- val args1 = transform(args, TYPEmode);
- val argtypes = Tree.typeOf(args);
- val tparams = tpe1.getType().symbol().typeParams();
- var owntype: Type = Type.ErrorType;
- if (!tpe1.getType().isError()) {
- if (tparams.length == args.length)
- owntype = Type.appliedType(tpe1.getType(), argtypes);
- else if (tparams.length == 0)
- error(tree.pos, "" + tpe1.getType() + " does not take type parameters");
- else
- error(tree.pos, "wrong number of type arguments for " +
- tpe1.getType());
- }
- copy.AppliedType(tree, tpe1, args1).setType(owntype);
-
- case Tree.FunType(_, _) =>
- transform(desugarize.FunType(tree))
-
- case _ =>
- throw new ApplicationError("illegal tree: " + tree)
- }
- } catch {
- case ex: Type$Error =>
- reportTypeError(tree.pos, ex);
- errorTree(tree)
- }
- }
-}
+ case class ImportType(expr: Tree, selectors: List[Pair[Name, Name]]) extends Type;
}
-
-// LocalWords: SOcos