summaryrefslogtreecommitdiff
path: root/sources/scalac
diff options
context:
space:
mode:
Diffstat (limited to 'sources/scalac')
-rw-r--r--sources/scalac/CompilerPhases.java6
-rw-r--r--sources/scalac/Global.java12
-rw-r--r--sources/scalac/ast/Tree.java.tmpl18
-rw-r--r--sources/scalac/ast/TreeGen.java59
-rw-r--r--sources/scalac/ast/parser/Parser.java2124
-rw-r--r--sources/scalac/ast/parser/ParserPhase.java39
-rw-r--r--sources/scalac/ast/parser/Scanner.java867
-rw-r--r--sources/scalac/ast/parser/TokenData.java44
-rw-r--r--sources/scalac/ast/parser/Tokens.java92
-rw-r--r--sources/scalac/ast/printer/HTMLTreePrinter.java176
-rw-r--r--sources/scalac/ast/printer/TextTreePrinter.java813
-rw-r--r--sources/scalac/typechecker/Analyzer.java2698
-rw-r--r--sources/scalac/typechecker/AnalyzerPhase.java69
-rw-r--r--sources/scalac/typechecker/Context.java65
-rw-r--r--sources/scalac/typechecker/DeSugarize.java663
-rw-r--r--sources/scalac/typechecker/ImportList.java74
-rw-r--r--sources/scalac/typechecker/Infer.java1059
-rw-r--r--sources/scalac/typechecker/RefCheck.java2
18 files changed, 50 insertions, 8830 deletions
diff --git a/sources/scalac/CompilerPhases.java b/sources/scalac/CompilerPhases.java
index adac32a95e..7b6c089ff6 100644
--- a/sources/scalac/CompilerPhases.java
+++ b/sources/scalac/CompilerPhases.java
@@ -15,7 +15,7 @@ import java.util.List;
* This class defines all compiler phases and maintains a list of
* active phases.
*/
-public class CompilerPhases {
+public abstract class CompilerPhases {
//########################################################################
// Public Fields
@@ -51,8 +51,8 @@ public class CompilerPhases {
/** Phase names, can be overridden to install .
*/
- protected Class PARSER_PHASE() { return scalac.ast.parser.ParserPhase.class; }
- protected Class ANALYZER_PHASE() { return scalac.typechecker.AnalyzerPhase.class; }
+ protected abstract Class PARSER_PHASE();
+ protected abstract Class ANALYZER_PHASE();
protected Class REFCHECK_PHASE() { return scalac.typechecker.RefCheckPhase.class; }
protected Class UNCURRY_PHASE() { return scalac.transformer.UnCurryPhase.class; }
protected Class TRANSMATCH_PHASE() { return scalac.transformer.TransMatchPhase.class; }
diff --git a/sources/scalac/Global.java b/sources/scalac/Global.java
index 39a5f8d08d..3b98951b6c 100644
--- a/sources/scalac/Global.java
+++ b/sources/scalac/Global.java
@@ -29,6 +29,7 @@ import scalac.backend.Primitives;
import scalac.symtab.*;
// !!! >>> Interpreter stuff
import scalac.symtab.Definitions;
+import scalac.typechecker.Infer;
import scalac.util.*;
/** The global environment of a compiler run
@@ -36,7 +37,7 @@ import scalac.util.*;
* @author Matthias Zenger
* @version 1.0
*/
-public class Global {
+public abstract class Global {
public static Global instance;
@@ -166,12 +167,9 @@ public class Global {
/** hooks for installing printers
*/
- protected TreePrinter newTextTreePrinter(PrintWriter writer) {
- return new TextTreePrinter(writer);
- }
- protected TreePrinter newHTMLTreePrinter(PrintWriter writer) {
- return new HTMLTreePrinter(writer);
- }
+ public abstract Infer newInfer();
+ public abstract TreePrinter newTextTreePrinter(PrintWriter writer);
+ public abstract TreePrinter newHTMLTreePrinter(PrintWriter writer);
/**
* Creates an instance variable.
diff --git a/sources/scalac/ast/Tree.java.tmpl b/sources/scalac/ast/Tree.java.tmpl
index 5f5277b8af..e1dbed177f 100644
--- a/sources/scalac/ast/Tree.java.tmpl
+++ b/sources/scalac/ast/Tree.java.tmpl
@@ -8,6 +8,9 @@
package scalac.ast;
+import java.io.StringWriter;
+import java.io.PrintWriter;
+
import ch.epfl.lamp.util.Position;
import scalac.Global;
@@ -15,8 +18,6 @@ import scalac.checkers.CheckTreeNodes;
import scalac.symtab.Symbol;
import scalac.symtab.Type;
import scalac.util.Debug;
-import java.io.StringWriter;
-import scalac.ast.printer.TextTreePrinter;
{#Imports#}
public class Tree {
@@ -117,15 +118,12 @@ public class Tree {
//########################################################################
// Public Methods - tree to string
- /**
- * Get string corresponding to this tree only implemented for
- * prefix trees, maybe we should generalize this; the PatternMatch
- * phase needs support for Apply, so this case got added
- */
+ /** Returns the string representation of this tree. */
public String toString() {
- StringWriter out = new StringWriter();
- new TextTreePrinter(out).print(this).flush();
- return out.toString();
+ StringWriter buffer = new StringWriter();
+ Global global = Global.instance;
+ global.newTextTreePrinter(new PrintWriter(buffer)).print(this).flush();
+ return buffer.toString();
}
//########################################################################
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java
index 27b168abd8..524e0ed253 100644
--- a/sources/scalac/ast/TreeGen.java
+++ b/sources/scalac/ast/TreeGen.java
@@ -12,9 +12,7 @@ import scalac.Global;
import scalac.ast.Tree.*;
import scalac.atree.AConstant;
import scalac.symtab.*;
-import scalac.typechecker.Infer;
import scalac.util.*;
-import scalac.ApplicationError;
/**
* This class provides method to build attributed trees.
@@ -36,9 +34,6 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
/** The tree factory */
private final TreeFactory make;
- /** The type inferencer */
- private final Infer infer;
-
/** Initializes this instance. */
public TreeGen(Global global) {
this(global, global.make);
@@ -49,7 +44,6 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
this.global = global;
this.definitions = global.definitions;
this.make = make;
- this.infer = new Infer(global, this, make);
}
//########################################################################
@@ -412,23 +406,18 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
return TypeApply(fn.pos, fn, targs);
}
public TypeApply TypeApply(int pos, Tree fn, Tree[] targs) {
- try {
- switch (fn.type) {
- case Type.OverloadedType(Symbol[] alts, Type[] alttypes):
- global.nextPhase();
- infer.polyAlternative(fn, alts, alttypes, targs.length);
- global.prevPhase();
- }
- switch (fn.type) {
- case Type.PolyType(Symbol[] tparams, Type restpe):
- global.nextPhase();
- restpe = restpe.subst(tparams, Tree.typeOf(targs));
- global.prevPhase();
- return (TypeApply)make.TypeApply(pos, fn, targs).setType(restpe);
- }
- } catch (Type.Error ex) {
- }
- throw new ApplicationError("poly type required", fn.type);
+ switch (fn.type()) {
+ case Type.OverloadedType(_, _):
+ // TreeGen only builds trees, names must already be resolved
+ throw Debug.abort("unresolved name", fn + " - " + fn.type);
+ case Type.PolyType(Symbol[] tparams, Type restpe):
+ global.nextPhase();
+ restpe = restpe.subst(tparams, Tree.typeOf(targs));
+ global.prevPhase();
+ return (TypeApply)make.TypeApply(pos, fn, targs).setType(restpe);
+ default:
+ throw Debug.abort("illegal case", fn + " - " + fn.type());
+ }
}
public TypeApply TypeApply(Tree fn, Tree[] targs) {
return TypeApply(fn.pos, fn, targs);
@@ -436,21 +425,15 @@ public class TreeGen implements Kinds, Modifiers, TypeTags {
/** Builds an Apply node with given function and arguments. */
public Apply Apply(int pos, Tree fn, Tree[] vargs) {
- try {
- switch (fn.type) {
- case Type.OverloadedType(Symbol[] alts, Type[] alttypes):
- global.nextPhase();
- infer.methodAlternative(fn, alts, alttypes,
- Tree.typeOf(vargs), Type.AnyType);
- global.prevPhase();
- }
- switch (fn.type) {
- case Type.MethodType(Symbol[] vparams, Type restpe):
- return (Apply)make.Apply(pos, fn, vargs).setType(restpe);
- }
- } catch (Type.Error ex) {
- }
- throw new ApplicationError("method type required", fn.type);
+ switch (fn.type()) {
+ case Type.OverloadedType(_, _):
+ // TreeGen only builds trees, names must already be resolved
+ throw Debug.abort("unresolved name", fn + " - " + fn.type());
+ case Type.MethodType(Symbol[] vparams, Type restpe):
+ return (Apply)make.Apply(pos, fn, vargs).setType(restpe);
+ default:
+ throw Debug.abort("illegal case", fn + " - " + fn.type());
+ }
}
public Apply Apply(Tree fn, Tree[] vargs) {
return Apply(fn.pos, fn, vargs);
diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java
deleted file mode 100644
index 6cbf3e342a..0000000000
--- a/sources/scalac/ast/parser/Parser.java
+++ /dev/null
@@ -1,2124 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
-\* */
-
-package scalac.ast.parser;
-
-import ch.epfl.lamp.util.Position;
-
-import java.util.*;
-import scalac.*;
-import scalac.util.*;
-import scalac.symtab.Modifiers;
-import scalac.ast.*;
-import scalac.atree.AConstant;
-import Tree.*;
-
-/** A recursive descent parser for the programming language Scala.
- *
- * @author Martin Odersky, Matthias Zenger, Burak Emir
- * @version 1.2
- */
-public class Parser implements Tokens {
-
- /** the lexical analyzer
- */
- Scanner s;
-
- /** the tree factory
- */
- TreeFactory make;
-
- /** the tree generator
- */
- TreeGen gen;
-
- /** pattern checker and normalizer
- */
- PatternNormalizer pN;
-
- /** The current nesting depths of while and do loops.
- */
- int loopNestingDepth;
-
- public Parser(Unit unit) {
- s = new Scanner(unit);
- make = unit.global.make;
- gen = unit.global.treeGen;
- pN = new PatternNormalizer( unit );
- mapTreeComment = unit.global.mapTreeComment;
- loopNestingDepth = 0;
- }
-
- /** this is the general parse method
- */
- public Tree[] parse() {
- Tree[] ts = s.unit.console ? templateStatSeq() : compilationUnit();
- accept(EOF);
- return ts;
- }
-
-/////// ERROR HANDLING //////////////////////////////////////////////////////
-
- private void skip() {
- //System.out.println("<skipping> " + s.token2string(s.token));//DEBUG
- int nparens = 0;
- int nbraces = 0;
- while (true) {
- switch (s.token) {
- case EOF:
- return;
- case SEMI:
- if (nparens == 0 && nbraces == 0)
- return;
- break;
- case RPAREN:
- nparens--;
- break;
- case RBRACE:
- if (nbraces == 0)
- return;
- nbraces--;
- break;
- case LPAREN:
- nparens++;
- break;
- case LBRACE:
- nbraces++;
- break;
- }
- //System.out.println("skipped: " + s.token2string(s.token));//DEBUG
- s.nextToken();
- }
- }
-
- Tree syntaxError(String msg, boolean skip) {
- return syntaxError(s.pos, msg, skip);
- }
-
- Tree syntaxError(int pos, String msg, boolean skip) {
- if (pos != s.errpos) {
- s.unit.error(pos, msg);
- s.errpos = pos;
- }
- if (skip) skip();
- return make.Bad(pos);
- }
-
- int accept(int token) {
- int pos = s.pos;
- if (s.token != token) {
- int errpos = ((s.pos >>> Position.COLUMN_BITS) >
- (s.lastpos >>> Position.COLUMN_BITS)) ?
- s.lastpos : s.pos;
- syntaxError(errpos, s.token2string(token) + " expected but " +
- s.token2string(s.token) + " found.", true);
- }
- if (s.token == token) s.nextToken();
- return pos;
- }
-
-/////// TOKEN CLASSES //////////////////////////////////////////////////////
-
- boolean isModifier() {
- return (s.token == ABSTRACT)
- || (s.token == FINAL)
- || (s.token == SEALED)
- || (s.token == PRIVATE)
- || (s.token == PROTECTED)
- || (s.token == OVERRIDE);
- }
-
- boolean isLocalModifier() {
- return (s.token == ABSTRACT)
- || (s.token == FINAL)
- || (s.token == SEALED);
- }
-
- boolean isDefIntro() {
- switch (s.token) {
- case VAL: case VAR: case DEF: case TYPE:
- case OBJECT: case CASEOBJECT: case CLASS: case CASECLASS: case TRAIT:
- return true;
- default:
- return false;
- }
- }
-
- boolean isDclIntro() {
- switch (s.token) {
- case VAL: case VAR: case DEF: case TYPE:
- return true;
- default:
- return false;
- }
- }
-
- boolean isExprIntro() {
- switch (s.token) {
- case CHARLIT: case INTLIT: case LONGLIT:
- case FLOATLIT: case DOUBLELIT: case STRINGLIT:
- case SYMBOLLIT: case TRUE: case FALSE: case NULL: case IDENTIFIER:
- case THIS: case SUPER: case IF:
- case FOR: case NEW: case USCORE:
- case TRY: case WHILE: case DO: case RETURN: case THROW:
- case LPAREN: case LBRACE:
- return true;
- default:
- return false;
- }
- }
-
-/////// COMMENT COLLECTION ///////////////////////////////////////////////////
-
- /** keep the comments associated with a given tree
- */
- protected Map mapTreeComment;
-
- /** stack of comments
- */
- protected final Stack commentStack = new Stack();
-
- /** positive if we are inside a block
- */
- protected int local = 0;
-
- /** push last encountered comment and reset the buffer
- */
- protected void pushComment() {
- if (local == 0) {
- commentStack.push(s.docBuffer == null ? null : s.docBuffer.toString());
- s.docBuffer = null;
- }
- }
-
- /** pop a comment from the stack and associate it with the given tree
- */
- protected Tree popComment(Tree tree) {
- if (local == 0)
- if (!commentStack.empty())
- mapTreeComment.put(tree, (String) commentStack.pop());
- return tree;
- }
-
-/////// TREE CONSTRUCTION ////////////////////////////////////////////////////
-
- /** Name supply
- */
- int fresh = 0;
-
- Name fresh() {
- return Name.fromString("x$" + (fresh++));
- }
-
- /** Create a tree representing a packaging
- */
- Tree makePackaging(int pos, Tree pkg, Tree[] stats) {
- while (true) {
- Template templ = make.Template(pos, Tree.EMPTY_ARRAY, stats);
- switch (pkg) {
- case Select(Tree qual, Name name):
- stats = new Tree[]{
- make.PackageDef(pos, make.Ident(pkg.pos, name), templ)};
- pkg = qual;
- break;
- default:
- return make.PackageDef(pos, pkg, templ);
- }
- }
- }
-
- /** Create tree representing binary operation expression or pattern.
- */
- Tree makeBinop(boolean isExpr, int pos, Tree left, Name op, Tree right) {
- if (isExpr) {
- if (op.isLeftAssoc()) {
- return make.Apply(pos,
- make.Select(pos, left, NameTransformer.encode(op)),
- new Tree[]{right});
- } else {
- Name x = fresh();
- return make.Block(pos,
- new Tree[]{
- make.ValDef(pos, 0, x, Tree.Empty, left)},
- make.Apply(pos,
- make.Select(pos, right, NameTransformer.encode(op)),
- new Tree[]{make.Ident(left.pos, x)}));
- }
- } else {
- return make.Apply(pos,
- make.Ident(pos, NameTransformer.encode(op).toTypeName()),
- new Tree[]{left, right});
- }
- }
-
-
- Tree scalaDot(int pos, Name name) {
- return make.Select(pos, make.Ident(pos, Names.scala), name);
- }
-
- Tree scalaRuntimeDot(int pos, Name name) {
- return make.Select(pos, scalaDot(pos, Names.runtime), name);
- }
-
- Tree ScalaRunTimeDot(int pos, Name name) {
- return make.Select(pos, scalaRuntimeDot(pos, Names.ScalaRunTime), name);
- }
-
- Tree scalaBooleanDot(int pos, Name name) {
- return make.Select(pos, scalaDot(pos, Names.Boolean), name);
- }
-
- Tree scalaXmlDot(int pos, Name name) {
- return make.Select(pos, scalaDot(pos, Names.xml), name);
- }
-
- Tree scalaXmlNoBindingDot(int pos, Name name) {
- return make.Select(pos, scalaXmlDot(pos, Names.nobinding), name);
- }
-
- Tree scalaAnyRefConstr(int pos) {
- return make.Apply(
- pos, scalaDot(pos, Names.AnyRef.toTypeName()), Tree.EMPTY_ARRAY);
- }
-
- Tree scalaObjectConstr(int pos) {
- return make.Apply(
- pos, scalaDot(pos, Names.ScalaObject.toTypeName()), Tree.EMPTY_ARRAY);
- }
-
- /** Create tree for for-comprehension <for (enums) do body> or
- * <for (enums) yield body> where mapName and flatmapName are chosen
- * corresponding to whether this is a for-do or a for-yield.
- */
- Tree makeFor(int pos, Tree[] enums, Name mapName, Name flatmapName, Tree body) {
- switch (enums[0]) {
- case PatDef(int mods, Tree pat, Tree rhs):
- if (enums.length == 1)
- return makeFor1(pos, mapName, pat, rhs, body);
- Tree[] newenums = new Tree[enums.length - 1];
- switch (enums[1]) {
- case PatDef(int mods2, Tree pat2, Tree rhs2):
- System.arraycopy(enums, 1, newenums, 0, newenums.length);
- return makeFor1(pos, flatmapName, pat, rhs,
- makeFor(enums[1].pos, newenums, mapName, flatmapName, body));
- default:
- System.arraycopy(enums, 2, newenums, 1, newenums.length - 1);
- newenums[0] = make.PatDef(
- enums[0].pos, mods, pat,
- makeFor1(enums[1].pos, Names.filter, pat.duplicate(), rhs, enums[1]));
- return makeFor(pos, newenums, mapName, flatmapName, body);
- }
- default:
- throw new ApplicationError();
- }
- }
-
- //where
- Tree makeFor1(int pos, Name name, Tree pat, Tree rhs, Tree body) {
- return make.Apply(
- pos, make.Select(pos, rhs, name),
- new Tree[]{makeForCont(pos, pat, body)});
- }
- Tree makeForCont(int pos, Tree pat, Tree body) {
- switch (pat) {
- case Ident(Name name1):
- if (name1.isVariable())
- return make.Function(
- pos,
- new Tree.ValDef[]{
- (ValDef) make.ValDef(
- pat.pos, Modifiers.PARAM,
- name1, Tree.Empty, Tree.Empty)},
- body);
- }
- return make.Visitor(pos, new Tree.CaseDef[]{
- (CaseDef)make.CaseDef(pos, pat, Tree.Empty, body)});
- }
-
- Tree makeTry(int pos, Tree body, Tree catcher, Tree finalizer) {
- Tree t = body;
- if (catcher != Tree.Empty)
- t =
- make.Apply(
- pos,
- make.Select(
- pos,
- make.Apply(
- pos, ScalaRunTimeDot(pos, Names.Try), new Tree[]{t}),
- Names.Catch),
- new Tree[]{catcher});
- if (finalizer != Tree.Empty)
- t =
- make.Apply(
- pos,
- make.Select(
- pos,
- make.Apply(
- pos, ScalaRunTimeDot(pos, Names.Try), new Tree[]{t}),
- Names.Finally),
- new Tree[]{finalizer});
- return t;
- }
-
- Tree makeWhile(int pos, Name lname, Tree cond, Tree body) {
- Tree continu = make.Apply(
- pos, make.Ident(pos, lname), Tree.EMPTY_ARRAY);
- Tree rhs = make.If(
- pos,
- cond,
- make.Block(body.pos, new Tree[]{body}, continu),
- gen.mkUnitLit(pos));
- return make.LabelDef(pos, lname, new Ident[0], rhs);
- }
-
- Tree makeDoWhile(int pos, Name lname, Tree body, Tree cond) {
- Tree continu = make.Apply(
- pos, make.Ident(pos, lname), Tree.EMPTY_ARRAY);
- Tree rhs = make.Block(
- body.pos,
- new Tree[]{
- body},
- make.If(
- cond.pos,
- cond,
- continu,
- gen.mkUnitLit(pos)));
- return make.LabelDef(pos, lname, new Ident[0], rhs);
- }
-
- /** Convert tree to formal parameter list
- */
- ValDef[] convertToParams(Tree t) {
- switch (t) {
- case Function(ValDef[] params, Tree.Empty):
- return params;
- case Ident(_):
- case Typed(Ident(_), _):
- return new ValDef[]{convertToParam(t)};
- case Literal(AConstant.UNIT):
- return Tree.ValDef_EMPTY_ARRAY; // !!!
- }
- syntaxError(t.pos, "malformed formal parameter list", false);
- return Tree.ValDef_EMPTY_ARRAY;
- }
-
- /** Convert list of trees to formal parameter list
- */
- ValDef[] convertToParams(Tree[] ts) {
- ValDef[] res = new ValDef[ts.length];
- for (int i = 0; i < res.length; i++)
- res[i] = convertToParam(ts[i]);
- return res;
- }
-
- /** Convert tree to formal parameter
- */
- ValDef convertToParam(Tree tree) {
- switch (tree) {
- case Ident(Name name):
- return (ValDef)make.ValDef(
- tree.pos, Modifiers.PARAM, name, Tree.Empty, Tree.Empty);
- case Typed(Ident(Name name), Tree tpe):
- return (ValDef)make.ValDef(
- tree.pos, Modifiers.PARAM, name, tpe, Tree.Empty);
- default:
- Tree tpe = syntaxError(tree.pos, "not a legal formal parameter", false);
- return (ValDef)make.ValDef(
- tree.pos, Modifiers.PARAM, Names.ERROR, tpe, Tree.Empty);
- }
- }
-
- /** Convert (qual)ident to type identifier
- */
- Tree convertToTypeId(Tree t) {
- switch (t) {
- case Ident(Name name):
- return make.Ident(t.pos, name.toTypeName());
- case Select(Tree qual, Name name):
- return make.Select(t.pos, qual, name.toTypeName());
- default:
- return t;
- }
- }
-
- /** Convert (qual)ident to constructor identifier
- */
- Tree convertToConstr(Tree t) {
- switch (t) {
- case Ident(Name name):
- return make.Ident(t.pos, name.toTypeName());
- case Select(Tree qual, Name name):
- return make.Select(t.pos, qual, name.toTypeName());
- default:
- return syntaxError(t.pos, "class constructor expected", false);
- }
- }
-
- /** Complete unapplied constructor with `()' arguments
- */
- Tree applyConstr(Tree t) {
- switch (t) {
- case Apply(_, _):
- return t;
- default:
- return make.Apply(t.pos, t, Tree.EMPTY_ARRAY);
- }
- }
-
-/////// OPERAND/OPERATOR STACK /////////////////////////////////////////////////
-
- Tree[] operands = new Tree[8];
- int[] positions = new int[8];
- Name[] operators = new Name[8];
- int sp = 0;
-
- void push(Tree od, int pos, Name op) {
- if (sp == operands.length) {
- Tree[] operands1 = new Tree[sp * 2];
- System.arraycopy(operands, 0, operands1, 0, sp);
- operands = operands1;
- int[] positions1 = new int[sp * 2];
- System.arraycopy(positions, 0, positions1, 0, sp);
- positions = positions1;
- Name[] operators1 = new Name[sp * 2];
- System.arraycopy(operators, 0, operators1, 0, sp);
- operators = operators1;
- }
- operands[sp] = od;
- positions[sp] = pos;
- operators[sp] = op;
- sp++;
- }
-
- Tree reduceStack(boolean isExpr, int base, Tree top,
- int prec, boolean leftAssoc) {
- if (sp != base &&
- operators[sp-1].precedence() == prec &&
- operators[sp-1].isLeftAssoc() != leftAssoc) {
- syntaxError(
- positions[sp-1],
- "left- and right-associative operators with same precedence may not be mixed",
- false);
- }
- while (sp != base &&
- (prec < operators[sp-1].precedence() ||
- (leftAssoc && prec == operators[sp-1].precedence()))) {
- sp--;
- top = makeBinop(isExpr, positions[sp], operands[sp], operators[sp], top);
- }
- return top;
- }
-
-/////// IDENTIFIERS AND LITERALS ////////////////////////////////////////////////////////////
-
- static final Name MINUS = Name.fromString("-");
- static final Name PLUS = Name.fromString("+");
- static final Name BANG = Name.fromString("!");
- static final Name TILDE = Name.fromString("~");
- static final Name STAR = Name.fromString("*");
- static final Name BAR = Name.fromString("|");
- static final Name OPT = Name.fromString("?");
-
- Name ident() {
- if (s.token == IDENTIFIER) {
- Name name = NameTransformer.encode(s.name);
- s.nextToken();
- return name;
- } else {
- accept(IDENTIFIER);
- return Names.ERROR;
- }
- }
-
- /** StableRef ::= StableId
- * | [Ident `.'] this
- * SimpleType ::= StableRef [`.' type]
- */
- Tree stableRef(boolean thisOK, boolean typeOK) {
- Tree t;
- if (s.token == THIS) {
- t = make.This(s.skipToken(), TypeNames.EMPTY);
- if (!thisOK || s.token == DOT)
- t = selectors(accept(DOT), t, typeOK);
- } else if (s.token == SUPER) {
- t = make.Super(
- s.skipToken(), TypeNames.EMPTY, mixinQualifierOpt());
- t = make.Select(accept(DOT), t, ident());
- if (s.token == DOT)
- t = selectors(s.skipToken(), t, typeOK);
- } else {
- Ident i = make.Ident(s.pos, ident());
- t = i;
- if (s.token == DOT) {
- int pos = s.skipToken();
- if (s.token == THIS) {
- s.nextToken();
- t = make.This(i.pos, i.name.toTypeName());
- if (!thisOK || s.token == DOT)
- t = selectors(accept(DOT), t, typeOK);
- } else if (s.token == SUPER) {
- s.nextToken();
- t = make.Super(
- i.pos, i.name.toTypeName(), mixinQualifierOpt());
- t = make.Select(accept(DOT), t, ident());
- if (s.token == DOT)
- t = selectors(s.skipToken(), t, typeOK);
- } else {
- t = selectors(pos, t, typeOK);
- }
- }
- }
- return t;
- }
-
- Tree selectors(int pos, Tree t, boolean typeOK) {
- if (typeOK && s.token == TYPE) {
- s.nextToken();
- return make.SingletonType(pos, t);
- } else {
- t = make.Select(pos, t, ident());
- if (s.token == DOT) {
- t = selectors(s.skipToken(), t, typeOK);
- }
- return t;
- }
- }
-
- /** MixinQualifier ::= `[' Id `]'
- */
- Name mixinQualifierOpt() {
- if (s.token == LBRACKET) {
- s.nextToken();
- Name name = ident().toTypeName();
- accept(RBRACKET);
- return name;
- } else {
- return TypeNames.EMPTY;
- }
- }
-
- /** StableId ::= Id
- * | StableRef `.' Id
- * | [Id '.'] super [MixinQualifier] ` `.' Id
- */
- Tree stableId() {
- return stableRef(false, false);
- }
-
- /** QualId ::= Id {`.' Id}
- */
- Tree qualId() {
- Tree id = make.Ident(s.pos, ident());
- if (s.token == DOT) return selectors(s.skipToken(), id, false);
- else return id;
- }
-
- /** SimpleExpr ::= literal
- * | symbol [ArgumentExprs]
- * | null
- */
- Tree literal(boolean isPattern) {
- Tree t;
- switch (s.token) {
- case CHARLIT:
- t = gen.mkCharLit(s.pos, (char)s.intVal);
- break;
- case INTLIT:
- t = gen.mkIntLit(s.pos, (int)s.intVal);
- break;
- case LONGLIT:
- t = gen.mkLongLit(s.pos, s.intVal);
- break;
- case FLOATLIT:
- t = gen.mkFloatLit(s.pos, (float)s.floatVal);
- break;
- case DOUBLELIT:
- t = gen.mkDoubleLit(s.pos, s.floatVal);
- break;
- case STRINGLIT:
- t = gen.mkStringLit(s.pos, s.name.toString());
- break;
- case TRUE:
- t = gen.mkBooleanLit(s.pos, true);
- break;
- case FALSE:
- t = gen.mkBooleanLit(s.pos, false);
- break;
- case NULL:
- t = gen.mkNullLit(s.pos);
- break;
- case SYMBOLLIT:
- int pos = s.pos;
- Tree symt = scalaDot(s.pos, Names.Symbol);
- if (isPattern) symt = convertToTypeId(symt);
- TreeList ts = new TreeList();
- ts.append(gen.mkStringLit(s.pos, s.name.toString()));
- s.nextToken();
- if (s.token == LPAREN || s.token == LBRACE)
- ts.append(argumentExprs());
- return make.Apply(pos, symt, ts.toArray());
- default:
- return syntaxError("illegal literal", true);
- }
- s.nextToken();
- return t;
- }
-
-//////// TYPES ///////////////////////////////////////////////////////////////
-
- /** TypedOpt ::= [`:' Type]
- */
- Tree typedOpt() {
- if (s.token == COLON) {
- s.nextToken();
- return type();
- } else {
- return Tree.Empty;
- }
- }
-
- /** SimpleTypedOpt ::= [`:' SimpleType]
- */
- Tree simpleTypedOpt() {
- if (s.token == COLON) {
- s.nextToken();
- return simpleType();
- } else {
- return Tree.Empty;
- }
- }
-
- /** Types ::= Type {`,' Type}
- */
- Tree[] types() {
- TreeList ts = new TreeList();
- ts.append(type());
- while (s.token == COMMA) {
- s.nextToken();
- ts.append(type());
- }
- return ts.toArray();
- }
-
- /** Type ::= Type1 `=>' Type
- * | `(' [Types] `)' `=>' Type
- * | Type1
- */
- Tree type() {
- Tree t;
- if (s.token == LPAREN) {
- s.nextToken();
- if (s.token == RPAREN) {
- s.nextToken();
- int pos = accept(ARROW);
- return make.FunType(pos, Tree.EMPTY_ARRAY, type());
- } else {
- t = type();
- if (s.token == COMMA) {
- s.nextToken();
- TreeList ts = new TreeList();
- ts.append(t);
- ts.append(types());
- accept(RPAREN);
- int pos = accept(ARROW);
- return make.FunType(pos, ts.toArray(), type());
- } else {
- accept(RPAREN);
- }
- }
- } else {
- t = type1();
- }
- if (s.token == ARROW)
- return make.FunType(s.skipToken(), new Tree[]{t}, type());
- else
- return t;
- }
-
- /** Type1 ::= SimpleType {with SimpleType} [Refinement]
- */
- Tree type1() {
- int pos = s.pos;
- Tree t = simpleType();
- if (s.token == WITH || s.token == LBRACE) {
- TreeList ts = new TreeList();
- ts.append(t);
- while (s.token == WITH) {
- s.nextToken();
- ts.append(simpleType());
- }
- Tree[] rs = (s.token == LBRACE) ? refinement() : Tree.EMPTY_ARRAY;
- return make.CompoundType(pos, ts.toArray(), rs);
- } else {
- return t;
- }
- }
-
- /** SimpleType ::= SimpleType TypeArgs
- * | SimpleType `#' Id
- * | StableId
- * | StableRef `.' type
- * | `(' Type `)'
- */
- Tree simpleType() {
- int pos = s.pos;
- Tree t;
- if (s.token == LPAREN) {
- s.nextToken();
- t = type();
- accept(RPAREN);
- } else {
- t = convertToTypeId(stableRef(false, true));
- }
- while (true) {
- if (s.token == HASH)
- t = make.SelectFromType(s.skipToken(), t, ident().toTypeName());
- else if (s.token == LBRACKET)
- t = make.AppliedType(pos, t, typeArgs());
- else break;
- }
- return t;
- }
-
- /** TypeArgs ::= `[' Types `]'
- */
- Tree[] typeArgs() {
- accept(LBRACKET);
- Tree[] ts = types();
- accept(RBRACKET);
- return ts;
- }
-
-//////// EXPRESSIONS ////////////////////////////////////////////////////////
-
- /** EqualsExpr ::= `=' Expr
- */
- Tree equalsExpr() {
- accept(EQUALS);
- return expr();
- }
-
- /** Exprs ::= Expr {`,' Expr}
- * | Expr `:' `_' `*'
- Tree[] exprs() {
- TreeList ts = new TreeList();
- ts.append(expr(true));
- while (s.token == COMMA) {
- s.nextToken();
- ts.append(expr());
- }
- return ts.toArray();
- }
- */
-
- /** Exprs ::= Expr {`,' Expr}
- */
- Tree[] exprs() {
- TreeList ts = new TreeList();
- ts.append(expr(true));
- while (s.token == COMMA) {
- s.nextToken();
- ts.append(expr(true));
- }
- return ts.toArray();
- }
-
- /** Expr ::= Bindings `=>' Expr
- * | if `(' Expr `)' Expr [[`;'] else Expr]
- * | try `{' block `}' [catch Expr] [finally Expr]
- * | while `(' Expr `)' Expr
- * | do Expr [`;'] while `(' Expr `)'
- * | for `(' Enumerators `)' (do | yield) Expr
- * | throw Expr
- * | return [Expr]
- * | [SimpleExpr `.'] Id `=' Expr
- * | SimpleExpr ArgumentExprs `=' Expr
- * | PostfixExpr [`:' Type1]
- * Bindings ::= Id [`:' Type1]
- * | `(' [Binding {`,' Binding}] `)'
- * Binding ::= Id [`:' Type]
- */
- Tree expr() {
- return expr(false);
- }
-
- Tree expr(boolean isArgument) {
- if (s.token == IF) {
- int pos = s.skipToken();
- accept(LPAREN);
- Tree cond = expr();
- accept(RPAREN);
- Tree thenp = expr();
- Tree elsep = Tree.Empty;
- if (s.token == ELSE) {
- s.nextToken();
- elsep = expr();
- } else {
- elsep = Tree.Empty;
- }
- return make.If(pos, cond, thenp, elsep);
- } else if (s.token == TRY) {
- int pos = s.skipToken();
- accept(LBRACE);
- Tree body = block(pos);
- accept(RBRACE);
- Tree catcher = Tree.Empty;
- if (s.token == CATCH) {
- s.nextToken();
- catcher = expr();
- }
- Tree finalizer = Tree.Empty;
- if (s.token == FINALLY) {
- s.nextToken();
- finalizer = expr();
- }
- return makeTry(pos, body, catcher, finalizer);
- } else if (s.token == WHILE) {
- Name lname = Name.fromString("label$" + loopNestingDepth);
- loopNestingDepth++;
- int pos = s.skipToken();
- accept(LPAREN);
- Tree cond = expr();
- accept(RPAREN);
- Tree body = expr();
- loopNestingDepth--;
- return makeWhile(pos, lname, cond, body);
- } else if (s.token == DO) {
- Name lname = Name.fromString("label$" + loopNestingDepth);
- loopNestingDepth++;
- int pos = s.skipToken();
- Tree body = expr();
- if (s.token == SEMI) s.nextToken();
- accept(WHILE);
- accept(LPAREN);
- Tree cond = expr();
- accept(RPAREN);
- loopNestingDepth--;
- return makeDoWhile(pos, lname, body, cond);
- } else if (s.token == FOR) {
- s.nextToken();
- Tree[] enums;
- accept(LPAREN);
- enums = enumerators();
- accept(RPAREN);
- if (s.token == YIELD)
- return makeFor(s.skipToken(), enums, Names.map, Names.flatmap, expr());
- else
- return makeFor(s.pos, enums, Names.foreach, Names.foreach, expr());
- } else if (s.token == RETURN) {
- int pos = s.skipToken();
- Tree e = (isExprIntro()) ? expr()
- : gen.mkUnitLit(pos);
- return make.Return(pos, e);
- } else if (s.token == THROW) {
- int pos = s.skipToken();
- return make.Throw(pos, expr());
-// } else if (s.token == ARROW) {
-// return make.Function(s.skipToken(), new ValDef[]{}, expr());
- } else {
- Tree t = postfixExpr();
- if (s.token == EQUALS) {
- switch (t) {
- case Ident(_):
- case Select(_, _):
- case Apply(_, _):
- t = make.Assign(s.skipToken(), t, expr());
- }
- } else if (s.token == COLON) {
- int pos = s.skipToken();
- if (isArgument && s.token == USCORE) {
- int pos1 = s.skipToken();
- if (s.token == IDENTIFIER && s.name == Names.STAR) {
- s.nextToken();
- /* this hack new */
- if( s.token != RPAREN ) {
- syntaxError(s.pos, " escaping sequences only allowed for last argument", true);
- }
- /* end hack */
- t = make.Typed(
- pos, t, make.Ident(pos1, TypeNames.WILDCARD_STAR));
- } else {
- syntaxError(s.pos, "`*' expected", true);
- }
- } else {
- Tree tp = type1();
- t = make.Typed(pos, t, tp);
- }
- }
- if (s.token == ARROW) {
- t = make.Function(s.skipToken(), convertToParams(t), expr());
- }
- return t;
- }
- }
-
- /** PostfixExpr ::= InfixExpr [Id]
- * InfixExpr ::= PrefixExpr
- * | InfixExpr Id InfixExpr
- */
- Tree postfixExpr() {
- int base = sp;
- Tree top = prefixExpr();
- while (s.token == IDENTIFIER) {
- top = reduceStack(
- true, base, top, s.name.precedence(), s.name.isLeftAssoc());
- push(top, s.pos, s.name);
- ident();
- if (isExprIntro()) {
- top = prefixExpr();
- } else {
- sp--;
- int pos = positions[sp];
- Name postOp = operators[sp];
- top = reduceStack(true, base, operands[sp], 0, true);
- return make.Select(pos, top, NameTransformer.encode(postOp));
- }
- }
- return reduceStack(true, base, top, 0, true);
- }
-
- /** PrefixExpr ::= [`-' | `+' | `~' | `!'] SimpleExpr
- */
- Tree prefixExpr() {
- Tree t;
- if (s.token == IDENTIFIER &&
- (s.name == MINUS ||
- s.name == PLUS ||
- s.name == TILDE ||
- s.name == BANG)) {
- Name name = ident();
- t = make.Select(s.pos, simpleExpr(), name);
- } else {
- t = simpleExpr();
- }
- return t;
- }
-
- /* SimpleExpr ::= literal
- * | StableRef
- * | `(' [Expr] `)'
- * | BlockExpr
- * | new Template
- * | SimpleExpr `.' Id
- * | SimpleExpr TypeArgs
- * | SimpleExpr ArgumentExprs
- */
- Tree simpleExpr() {
- Tree t;
- switch (s.token) {
- case CHARLIT:
- case INTLIT:
- case LONGLIT:
- case FLOATLIT:
- case DOUBLELIT:
- case STRINGLIT:
- case SYMBOLLIT:
- case TRUE:
- case FALSE:
- case NULL:
- t = literal(false);
- break;
- case IDENTIFIER:
- case THIS:
- case SUPER:
- t = stableRef(true, false);
- break;
- case LPAREN:
- int pos = s.skipToken();
- if (s.token == RPAREN) {
- s.nextToken();
- t = gen.mkUnitLit(pos);
- } else {
- t = expr();
- if (s.token == COMMA) {
- int commapos = s.skipToken();
- TreeList ts = new TreeList();
- ts.append(t);
- ts.append(exprs());
- accept(RPAREN);
- if (s.token == ARROW) {
- t = make.Function(
- pos, convertToParams(ts.toArray()), Tree.Empty);
- } else {
- t = syntaxError(commapos, "`)' expected", false);
- }
- } else {
- accept(RPAREN);
- }
- }
- break;
- case LBRACE:
- t = blockExpr();
- break;
- case NEW:
- t = make.New(s.skipToken(), template());
- break;
- default:
- return syntaxError("illegal start of expression", true);
- }
- while (true) {
- switch (s.token) {
- case DOT:
- t = make.Select(s.skipToken(), t, ident());
- break;
- case LBRACKET:
- switch (t) {
- case Ident(_):
- case Select(_, _):
- t = make.TypeApply(s.pos, t, typeArgs());
- break;
- default:
- return t;
- }
- break;
- case LPAREN:
- case LBRACE:
- t = make.Apply(s.pos, t, argumentExprs());
- break;
- default:
- return t;
- }
- }
- }
-
- /** ArgumentExprs ::= `(' [Exprs] `)'
- * | BlockExpr
- */
- Tree[] argumentExprs() {
- Tree[] ts = Tree.EMPTY_ARRAY;
- if (s.token == LBRACE) {
- ts = new Tree[]{blockExpr()};
- } else {
- accept(LPAREN);
- if (s.token != RPAREN)
- ts = exprs();
- accept(RPAREN);
- }
- return ts;
- }
-
- /** BlockExpr ::= `{' CaseClause {CaseClause} `}'
- * | `{' Block `}'
- */
- Tree blockExpr() {
- local++;
- Tree res;
- int pos = accept(LBRACE);
- if (s.token == CASE) {
- TreeList stats = new TreeList();
- do {
- stats.append(caseClause());
- } while (s.token == CASE);
- res = make.Visitor(
- pos, (CaseDef[]) stats.copyTo(new CaseDef[stats.length()]));
- } else {
- res = block(pos);
- }
- accept(RBRACE);
- local--;
- return res;
- }
-
- /** Block ::= BlockStatSeq
- */
- Tree block(int pos) {
- return block(pos, blockStatSeq(new TreeList()));
- }
- private Tree block(int pos, Tree[] stats) {
- if (stats.length == 0)
- return gen.mkUnitLit(pos);
- else if (!stats[stats.length - 1].isTerm())
- return make.Block(pos, stats, gen.mkUnitLit(pos));
- else if (stats.length == 1)
- return stats[0];
- else {
- Tree[] trees = new Tree[stats.length - 1];
- System.arraycopy(stats, 0, trees, 0, trees.length);
- return make.Block(pos, trees, stats[stats.length - 1]);
- }
- }
-
- /** CaseClause ::= case Pattern [if PostfixExpr] `=>' Block
- */
- Tree caseClause() {
- int pos = accept(CASE);
- Tree pat = validPattern();
- Tree guard = Tree.Empty;
- if (s.token == IF) {
- s.nextToken();
- guard = postfixExpr();
- }
- return make.CaseDef(pos, pat, guard, block(accept(ARROW)));
- }
-
- /** Enumerators ::= Generator {`;' Enumerator}
- * Enumerator ::= Generator
- * | Expr
- */
- Tree[] enumerators() {
- TreeList enums = new TreeList();
- enums.append(generator());
- while (s.token == SEMI) {
- s.nextToken();
- if (s.token == VAL) enums.append(generator());
- else enums.append(expr());
- }
- return enums.toArray();
- }
-
- /** Generator ::= val Pattern1 `<-' Expr
- */
- Tree generator() {
- int pos = accept(VAL);
- Tree pat = validPattern1();
- accept(LARROW);
- Tree rhs = expr();
- if (!TreeInfo.isVarPattern(pat))
- rhs = make.Apply(
- rhs.pos,
- make.Select(rhs.pos, rhs, Names.filter),
- new Tree[]{
- make.Visitor(
- rhs.pos,
- new Tree.CaseDef[]{
- (CaseDef)make.CaseDef(
- rhs.pos, pat.duplicate(), Tree.Empty,
- gen.mkBooleanLit(s.pos, true)),
- (CaseDef)make.CaseDef(
- rhs.pos, make.Ident(rhs.pos, Names.PATTERN_WILDCARD), Tree.Empty,
- gen.mkBooleanLit(s.pos, false))})});
- return make.PatDef(pos, 0, pat, rhs);
- }
-
-//////// PATTERNS ////////////////////////////////////////////////////////////
-
- /** Pattern ( see pattern() ) which is checked for validity
- */
- Tree validPattern() {
- int pos = s.pos;
-
- Tree pat = pattern();
- if( this.pN.check( pat ) ) { // reports syntax errors as side effect
- // normalize
- Tree res = pN.wrapAlternative( pN.elimSequence( pN.flattenSequence ( pat )));
- return res;
- }
- //syntaxError( pos, "invalid pattern", false ); done in pN.check...
- return make.Bad(pos);
- }
-
- /** Pattern1 ( see pattern1() ) which is checked for validity
- */
- Tree validPattern1() {
- int pos = s.pos;
-
- Tree pat = pattern1();
-
- if( this.pN.check( pat ) ) { // reports syntax errors as side effect
- // normalize
- Tree res = pN.wrapAlternative( pN.elimSequence( pN.flattenSequence ( pat )));
- return res;
- }
- //syntaxError( pos, "invalid pattern", false );
- return make.Bad(pos);
- }
-
- /** Patterns ::= Pattern {`,' Pattern}
- */
- Tree[] patterns() {
- TreeList ts = new TreeList();
- ts.append(pattern());
- while (s.token == COMMA) {
- s.nextToken();
- ts.append(pattern());
- }
- return ts.toArray();
- }
-
- /** Pattern ::= Pattern1 { `|' Pattern1 }
- */
- Tree pattern() {
- int pos = s.pos;
- Tree first = pattern1();
- if(( s.token == IDENTIFIER )&&( s.name == BAR )) {
- TreeList choices = new TreeList();
- choices.append( first );
- while(( s.token == IDENTIFIER )&&( s.name == BAR )) {
- s.nextToken();
- choices.append( pattern1() );
- }
- Tree[] tarr = choices.toArray();
- TreeList ts = pN.flattenAlternativeChildren( tarr );
- return pN.flattenAlternative( make.Alternative( pos, ts.toArray() ) );
- }
- return first;
- }
-
- /** Pattern1 ::= varid `:' Type1
- * | `_' `:' Type1
- * | Pattern2
- */
- Tree pattern1() {
- Tree p = pattern2();
- if (s.token == COLON && TreeInfo.isVarPattern(p)) {
- return make.Typed(s.skipToken(), p, type1());
- }
- return p;
- }
-
- /* Pattern2 ::= varid [ @ Pattern3 ]
- * | Pattern3
- */
- Tree pattern2() {
- Tree p = pattern3();
- if (s.token == AT && TreeInfo.isVarPattern(p)) {
- switch (p) {
- case Ident(Name name):
- if (name == Names.PATTERN_WILDCARD) return pattern3();
- }
- return make.Bind(s.skipToken(), ((Ident)p).name, pattern3());
- }
- return p;
- }
-
- /* Pattern3 ::= SimplePattern [ '*' | '?' | '+' ]
- * | SimplePattern {Id SimplePattern} // op2 must not be empty
- */
- Tree pattern3() {
- int base = sp;
- Tree top = simplePattern();
- if (s.token == IDENTIFIER) {
- if (s.name == STAR) { /* p* becomes z@( |(p,z)) */
- s.nextToken();
- Name zname = fresh();
- Tree zvar = make.Ident(s.pos, zname);
-
- return make.Bind(s.pos, zname,
- pN.flattenAlternative(
- make.Alternative(s.pos, new Tree[] {
- make.Sequence(s.pos, Tree.EMPTY_ARRAY),
- pN.flattenSequence(make.Sequence(s.pos, new Tree[] {
- top,
- zvar
- }))
- })));
- }
- else if (s.name == PLUS) { /* p+ becomes z@(p,(z| )) */
- s.nextToken();
- Name zname = fresh();
- Tree zvar = make.Ident(s.pos, zname);
-
- return make.Bind(s.pos, zname,
- pN.flattenSequence(make.Sequence(s.pos, new Tree[] {
- top,
- pN.flattenAlternative(make.Alternative(s.pos, new Tree[] {
- zvar,
- make.Sequence(s.pos, Tree.EMPTY_ARRAY)
- }))
- })));
- }
- else if (s.name == OPT) { /* p? becomes (p| ) */
- s.nextToken();
- return pN.flattenAlternative(make.Alternative(s.pos, new Tree[] {
- top,
- make.Sequence(s.pos, Tree.EMPTY_ARRAY)}));
- }
- }
- while ((s.token == IDENTIFIER) && (s.name != BAR)) {
- Name tokn = s.name; // for error message
- top = reduceStack(
- false, base, top, s.name.precedence(), s.name.isLeftAssoc());
- push(top, s.pos, s.name);
- ident();
- top = simplePattern();
- if( TreeInfo.isEmptySequence( top ) ) {
- syntaxError( top.pos, "2nd argument to binary op "+s.name+" may not be empty sequence pattern", false);
- }
- }
- return reduceStack(false, base, top, 0, true);
- }
-
- /** SimplePattern ::= varid
- * | `_'
- * | literal
- * | StableId [ `(' [Patterns] `)' ]
- * | `(' [Patterns] `)'
- * | (empty word - nothing)
- */
- Tree simplePattern() {
- switch (s.token) {
- case RPAREN:
- case COMMA:
- return make.Sequence(s.pos, Tree.EMPTY_ARRAY); // ((nothing))
- case IDENTIFIER:
- if (s.name == BAR) {
- return make.Sequence(s.pos, Tree.EMPTY_ARRAY); // ((nothing))
- }
- // else fall through to case THIS
- case THIS:
- Tree t = stableId();
- while (s.token == LPAREN) {
- Tree[] ts = Tree.EMPTY_ARRAY;
- accept(LPAREN);
- if (s.token != RPAREN)
- ts = patterns();
- accept(RPAREN);
- t = make.Apply(s.pos, convertToTypeId(t), ts);
- }
- return t;
- case USCORE:
- return make.Ident(s.skipToken(), Names.PATTERN_WILDCARD);
- case CHARLIT:
- case INTLIT:
- case LONGLIT:
- case FLOATLIT:
- case DOUBLELIT:
- case STRINGLIT:
- case SYMBOLLIT:
- case TRUE:
- case FALSE:
- case NULL:
- return literal(true);
- case LPAREN:
- int p = s.pos;
- s.nextToken();
- Tree[] ts = Tree.EMPTY_ARRAY;
- if( s.token!= RPAREN )
- ts = patterns();
- Tree t = null;
- if ((ts.length == 1)&&!( ts[0] instanceof Tree.Alternative )) {
- t = ts[0];
- } else {
- t = pN.flattenSequence(make.Sequence(s.pos, ts));
- t = pN.elimSequence(t);
- }
- accept(RPAREN);
- return t;
- default:
- return syntaxError("illegal start of pattern", true);
- }
- }
-
-////////// MODIFIERS ////////////////////////////////////////////////////////////
-
- /** Modifiers ::= {Modifier}
- * Modifier ::= final
- * | private
- * | protected
- * | override
- * | abstract
- */
- int modifiers() {
- pushComment();
- int mods = 0;
- while (true) {
- int mod;
- switch (s.token) {
- case ABSTRACT:
- mod = Modifiers.ABSTRACT;
- break;
- case FINAL:
- mod = Modifiers.FINAL;
- break;
- case SEALED:
- mod = Modifiers.SEALED;
- break;
- case PRIVATE:
- mod = Modifiers.PRIVATE;
- break;
- case PROTECTED:
- mod = Modifiers.PROTECTED;
- break;
- case OVERRIDE:
- mod = Modifiers.OVERRIDE;
- break;
- default:
- return mods;
- }
- if ((mods & mod) != 0)
- syntaxError(s.pos, "repeated modifier", false);
- mods |= mod;
- s.nextToken();
- }
- }
-
- /** LocalModifiers ::= {LocalModifier}
- * LocalModifier ::= final
- * | private
- */
- int localClassModifiers() {
- int mods = 0;
- while (true) {
- int mod;
- switch (s.token) {
- case ABSTRACT:
- mod = Modifiers.ABSTRACT;
- break;
- case FINAL:
- mod = Modifiers.FINAL;
- break;
- case SEALED:
- mod = Modifiers.SEALED;
- break;
- default:
- return mods;
- }
- if ((mods & mod) != 0)
- syntaxError(s.pos, "repeated modifier", false);
- mods |= mod;
- s.nextToken();
- }
- }
-
-//////// PARAMETERS //////////////////////////////////////////////////////////
-
- /** ParamClauses ::= {ParamClause}
- */
- ValDef[][] paramClauses() {
- ArrayList ts = new ArrayList();
- while (s.token == LPAREN)
- ts.add(paramClause());
- return (ValDef[][])ts.toArray(new ValDef[ts.size()][]);
- }
-
- /** ParamClauseOpt ::= [ParamClause]
- */
- ValDef[][] paramClauseOpt() {
- return (s.token == LPAREN) ? new ValDef[][]{paramClause()}
- : Tree.ValDef_EMPTY_ARRAY_ARRAY;
- }
-
- /** ParamClause ::= `(' [Param {`,' Param}] `)'
- */
- ValDef[] paramClause() {
- int pos = accept(LPAREN);
- TreeList params = new TreeList();
- if (s.token != RPAREN) {
- params.append(param());
- while (s.token == COMMA) {
- s.nextToken();
- params.append(param());
- }
- }
- accept(RPAREN);
- return (ValDef[])params.copyTo(new ValDef[params.length()]);
- }
-
- /** Param ::= [def] Id `:' Type [`*']
- */
- ValDef param() {
- int pos = s.pos;
- int mods = Modifiers.PARAM;
- if (s.token == DEF) {
- mods |= Modifiers.DEF;
- s.nextToken();
- }
- Name name = ident();
- accept(COLON);
- Tree tp = type();
- if (s.token == IDENTIFIER && s.name == STAR) {
- s.nextToken();
- mods |= Modifiers.REPEATED;
- tp = make.AppliedType(tp.pos,
- scalaDot(tp.pos, Names.Seq.toTypeName()),
- new Tree[]{tp});
- }
- return (ValDef)make.ValDef(pos, mods, name, tp, Tree.Empty);
- }
-
- /** TypeParamClauseOpt ::= [`[' TypeParam {`,' TypeParam} `]']
- * FunTypeParamClauseOpt ::= [`[' FunTypeParam {`,' FunTypeParam} `]']
- */
- AbsTypeDef[] typeParamClauseOpt(boolean variant) {
- TreeList params = new TreeList();
- if (s.token == LBRACKET) {
- s.nextToken();
- params.append(typeParam(variant));
- while (s.token == COMMA) {
- s.nextToken();
- params.append(typeParam(variant));
- }
- accept(RBRACKET);
- }
- return (AbsTypeDef[])params.copyTo(new AbsTypeDef[params.length()]);
- }
-
- /** TypeParam ::= [`+' | `-'] FunTypeParam
- * FunTypeParam ::= Id TypeBounds
- */
- Tree typeParam(boolean variant) {
- int mods = Modifiers.PARAM;
- if (variant && s.token == IDENTIFIER) {
- if (s.name == PLUS) {
- s.nextToken();
- mods |= Modifiers.COVARIANT;
- } else if (s.name == MINUS) {
-// syntaxError(
-// "contravariant type parameters not yet supported", false);
- s.nextToken();
- mods |= Modifiers.CONTRAVARIANT;
- }
- }
- return typeBounds(s.pos, mods, ident());
- }
-
- /** TypeBounds ::= [`>:' Type] [`<:' Type]
- */
- Tree typeBounds(int pos, int mods, Name name) {
- Tree lobound;
- Tree hibound;
- if (s.token == SUPERTYPE) {
- s.nextToken();
- lobound = type();
- } else {
- lobound = scalaDot(pos, Names.All.toTypeName());
- }
- if (s.token == SUBTYPE) {
- s.nextToken();
- hibound = type();
- } else {
- hibound = scalaDot(pos, Names.Any.toTypeName());
- }
- return make.AbsTypeDef(pos, mods, name.toTypeName(), hibound, lobound);
- }
-
-//////// DEFS ////////////////////////////////////////////////////////////////
-
- /** Import ::= import ImportExpr {`,' ImportExpr}
- */
- Tree[] importClause() {
- accept(IMPORT);
- TreeList ts = new TreeList();
- ts.append(importExpr());
- while (s.token == COMMA) {
- s.nextToken();
- ts.append(importExpr());
- }
- return ts.toArray();
- }
-
- /** ImportRef ::= StableId `.' (Id | `_' | ImportSelectors)
- */
- Tree importExpr() {
- Tree t;
- int startpos = s.pos;
- int pos;
- if (s.token == THIS) {
- t = make.This(s.skipToken(), TypeNames.EMPTY);
- t = make.Select(accept(DOT), t, ident());
- pos = accept(DOT);
- } else {
- Ident i = make.Ident(s.pos, ident());
- pos = accept(DOT);
- if (s.token == THIS) {
- s.nextToken();
- t = make.This(i.pos, i.name.toTypeName());
- t = make.Select(accept(DOT), t, ident());
- pos = accept(DOT);
- } else {
- t = i;
- }
- }
- while (true) {
- if (s.token == USCORE) {
- s.nextToken();
- return make.Import(startpos, t, new Name[]{Names.IMPORT_WILDCARD});
- } else if (s.token == LBRACE) {
- return make.Import(startpos, t, importSelectors());
- } else {
- Name name = ident();
- if (s.token == DOT) {
- t = make.Select(pos, t, name);
- pos = accept(DOT);
- } else {
- /*
- if (name == Names.ASTERISK)
- s.unit.warning(
- pos, "this imports only the identifier `*';\nuse `import xyz._' to import all members of `xyz'.");
- */
- return make.Import(startpos, t, new Name[]{name, name});
- }
- }
- }
- }
-
- /** ImportSelectors ::= `{' {ImportSelector `,'} (ImportSelector | `_') `}'
- */
- Name[] importSelectors() {
- LinkedList/*<Name>*/ names = new LinkedList();
- accept(LBRACE);
- boolean isLast = importSelector(names);
- while (!isLast && s.token == COMMA) {
- s.nextToken();
- isLast = importSelector(names);
- }
- accept(RBRACE);
- return (Name[])names.toArray(new Name[]{});
- }
-
- /** ImportSelector ::= Id [`=>' Id | `=>' `_']
- */
- boolean importSelector(LinkedList/*<Name>*/ names) {
- if (s.token == USCORE) {
- s.nextToken();
- names.add(Names.IMPORT_WILDCARD);
- return true;
- } else {
- Name name = ident();
- names.add(name);
- if (s.token == ARROW) {
- s.nextToken();
- if (s.token == USCORE) {
- s.nextToken();
- names.add(Names.IMPORT_WILDCARD);
- } else {
- names.add(ident());
- }
- } else {
- names.add(name);
- }
- return false;
- }
- }
-
- /** Def ::= val PatDef {`,' PatDef}
- * | var VarDef {`,' VarDef}
- * | def FunDef {`,' FunDef}
- * | type TypeDef {`,' TypeDef}
- * | ClsDef
- * Dcl ::= val ValDcl {`,' ValDcl}
- * | var ValDcl {`,' ValDcl}
- * | def FunDcl {`,' FunDcl}
- * | type TypeDcl {`,' TypeDcl}
- */
- Tree[] defOrDcl(int mods) {
- TreeList ts = new TreeList();
- switch (s.token) {
- case VAL:
- do {
- s.nextToken();
- ts.append(popComment(patDefOrDcl(mods)));
- } while (s.token == COMMA);
- return ts.toArray();
- case VAR:
- do {
- s.nextToken();
- ts.append(popComment(varDefOrDcl(mods)));
- } while (s.token == COMMA);
- return ts.toArray();
- case DEF:
- do {
- s.nextToken();
- ts.append(popComment(funDefOrDcl(mods)));
- } while (s.token == COMMA);
- return ts.toArray();
- case TYPE:
- do {
- s.nextToken();
- ts.append(popComment(typeDefOrDcl(mods)));
- } while (s.token == COMMA);
- return ts.toArray();
- default:
- return clsDef(mods);
- }
- }
-
- /** ClsDef ::= ([case] class | trait) ClassDef {`,' ClassDef}
- * | [case] object ObjectDef {`,' ObjectDef}
- */
- Tree[] clsDef(int mods) {
- TreeList ts = new TreeList();
- switch (s.token) {
- case CLASS:
- case CASECLASS:
- case TRAIT:
- if (s.token == CASECLASS) mods |= Modifiers.CASE;
- else if (s.token == TRAIT) mods |= Modifiers.TRAIT | Modifiers.ABSTRACT;
- do {
- s.nextToken();
- ts.append(classDef(mods));
- } while (s.token == COMMA);
- return ts.toArray();
- case OBJECT:
- case CASEOBJECT:
- if (s.token == CASEOBJECT) mods |= Modifiers.CASE;
- do {
- s.nextToken();
- ts.append(objectDef(mods));
- } while (s.token == COMMA);
- return ts.toArray();
- default:
- return new Tree[]{syntaxError("illegal start of definition", true)};
- }
- }
-
- /** PatDef ::= Pattern2 [`:' Type] `=' Expr
- * ValDcl ::= Id `:' Type
- */
- Tree patDefOrDcl(int mods) {
- int pos = s.pos;
- Tree pat = pattern2();
- Tree tp = (s.token == COLON) ? typedOpt() : Tree.Empty;
- switch (pat) {
- case Ident(Name name):
- if (tp == Tree.Empty || s.token == EQUALS)
- return make.ValDef(pos, mods, name, tp, equalsExpr());
- else
- return make.ValDef(pos, mods | Modifiers.DEFERRED, name, tp, Tree.Empty);
- default:
- return make.PatDef(pos, mods, pat, equalsExpr());
- }
- }
-
- /** VarDef ::= Id [`:' Type] `=' Expr
- * | Id `:' Type `=' `_'
- * VarDcl ::= Id `:' Type
- */
- Tree varDefOrDcl(int mods) {
- int pos = s.pos;
- Name name = ident();
- Tree type = typedOpt();
- if (type == Tree.Empty || s.token == EQUALS) {
- accept(EQUALS);
- Tree rhs;
- if (type != Tree.Empty && s.token == USCORE) {
- rhs = Tree.Empty;
- s.nextToken();
- } else {
- rhs = expr();
- }
- return make.ValDef(pos, mods | Modifiers.MUTABLE, name, type, rhs);
- } else {
- return make.ValDef(pos, mods | Modifiers.MUTABLE | Modifiers.DEFERRED,
- name, type, Tree.Empty);
- }
- }
-
- /** FunDef ::= Id [FunTypeParamClause] {ParamClauses} [`:' Type] `=' Expr
- * | this ParamClause `=' ConstrExpr
- * FunDcl ::= Id [FunTypeParamClause] {ParamClauses} `:' Type
- */
- Tree funDefOrDcl(int mods) {
- int pos = s.pos;
- if (s.token == THIS) {
- s.nextToken();
- ValDef[][] vparams = new ValDef[][]{paramClause()};
- accept(EQUALS);
- return make.DefDef(
- pos, mods, Names.CONSTRUCTOR,
- Tree.AbsTypeDef_EMPTY_ARRAY, vparams, Tree.Empty,
- constrExpr());
- } else {
- Name name = ident();
- AbsTypeDef[] tparams = typeParamClauseOpt(false);
- ValDef[][] vparams = paramClauses();
- Tree restype = typedOpt();
- if (s.token == EQUALS || restype == Tree.Empty)
- return make.DefDef(pos, mods, name, tparams, vparams,
- restype, equalsExpr());
- else
- return make.DefDef(pos, mods | Modifiers.DEFERRED, name,
- tparams, vparams, restype, Tree.Empty);
- }
- }
-
- /** ConstrExpr ::= SelfInvocation
- * | `{' SelfInvocation {`;' BlockStat} `}'
- * SelfInvocation ::= this ArgumentExpr
- */
- Tree constrExpr() {
- if (s.token == LBRACE) {
- int pos = s.skipToken();
- TreeList statlist = new TreeList();
- statlist.append(selfInvocation());
- Tree[] stats;
- if (s.token == SEMI) {
- s.nextToken();
- stats = blockStatSeq(statlist);
- } else {
- stats = statlist.toArray();
- }
- accept(RBRACE);
- return block(pos, stats);
- } else {
- return selfInvocation();
- }
- }
-
- /** SelfInvocation ::= this ArgumentExprs
- */
- Tree selfInvocation() {
- int pos = s.pos;
- accept(THIS);
- return make.Apply(
- s.pos, make.Ident(pos, Names.CONSTRUCTOR), argumentExprs());
- }
-
- /** TypeDef ::= Id `=' Type
- * TypeDcl ::= Id TypeBounds
- */
- Tree typeDefOrDcl(int mods) {
- int pos = s.pos;
- Name name = ident().toTypeName();
- switch (s.token) {
- case LBRACKET:
- AbsTypeDef[] tparams = typeParamClauseOpt(true);
- accept(EQUALS);
- return make.AliasTypeDef(pos, mods, name, tparams, type());
- case EQUALS:
- s.nextToken();
- return make.AliasTypeDef(pos, mods, name, Tree.AbsTypeDef_EMPTY_ARRAY, type());
- case SUPERTYPE:
- case SUBTYPE:
- case SEMI:
- case COMMA:
- case RBRACE:
- return typeBounds(pos, mods | Modifiers.DEFERRED, name);
- default:
- return syntaxError("`=', `>:', or `<:' expected", true);
- }
- }
-
- /** ClassDef ::= Id [TypeParamClause] [ParamClause] [`:' SimpleType] ClassTemplate
- */
- Tree classDef(int mods) {
- int pos = s.pos;
- Name clazzname = ident().toTypeName();
- AbsTypeDef[] tparams = typeParamClauseOpt(true);
- ValDef[][] params = paramClauseOpt();
- TreeList result = new TreeList();
- return popComment(make.ClassDef(pos, mods, clazzname, tparams, params,
- simpleTypedOpt(), classTemplate()));
- }
-
- /** ObjectDef ::= Id [`:' SimpleType] ClassTemplate
- */
- Tree objectDef(int mods) {
- return popComment(make.ModuleDef(
- s.pos, mods, ident(), simpleTypedOpt(), classTemplate()));
- }
-
- /** ClassTemplate ::= [`extends' Constr] {`with' Constr} [TemplateBody]
- */
- Template classTemplate() {
- int pos = s.pos;
- TreeList parents = new TreeList();
- if (s.token == EXTENDS) {
- s.nextToken();
- parents.append(constr());
- } else {
- parents.append(scalaAnyRefConstr(pos));
- }
- parents.append(scalaObjectConstr(pos));
- if (s.token == WITH) {
- s.nextToken();
- return template(parents);
- } else if (s.token == LBRACE) {
- return (Template)make.Template(
- pos, parents.toArray(), templateBody());
- } else {
- if (!(s.token == SEMI || s.token == COMMA || s.token == RBRACE))
- syntaxError("`extends' or `{' expected", true);
- return (Template)make.Template(
- pos, parents.toArray(), Tree.EMPTY_ARRAY);
- }
- }
-
-////////// TEMPLATES ////////////////////////////////////////////////////////////
-
-
- /** Template ::= Constr {`with' Constr} [TemplateBody]
- */
- Template template() {
- return template(new TreeList());
- }
-
- Template template(TreeList parents) {
- int pos = s.pos;
- parents.append(constr());
- while (s.token == WITH) {
- s.nextToken();
- parents.append(constr());
- }
- Tree[] stats = (s.token == LBRACE) ? templateBody() : Tree.EMPTY_ARRAY;
- return (Template)make.Template(pos, parents.toArray(), stats);
- }
-
- /** Constr ::= StableId [TypeArgs] [`(' [Exprs] `)']
- */
- Tree constr() {
- Tree t = convertToConstr(stableId());
- if (s.token == LBRACKET)
- t = make.AppliedType(s.pos, t, typeArgs());
- if (s.token == LPAREN)
- t = make.Apply(s.pos, t, argumentExprs());
- return applyConstr(t);
- }
-
- /** TemplateBody ::= `{' [TemplateStat {`;' TemplateStat}] `}'
- */
- Tree[] templateBody() {
- accept(LBRACE);
- Tree[] body = templateStatSeq();
- if (body.length == 0)
- body = new Tree[]{Tree.Empty};
- accept(RBRACE);
- return body;
- }
-
- /** Refinement ::= `{' [RefineStat {`;' RefineStat}] `}'
- */
- Tree[] refinement() {
- accept(LBRACE);
- Tree[] body = refineStatSeq();
- accept(RBRACE);
- return body;
- }
-
-/////// STATSEQS //////////////////////////////////////////////////////////////
-
- /** Packaging ::= package QualId `{' TopStatSeq `}'
- */
- Tree packaging() {
- int pos = accept(PACKAGE);
- Tree pkg = qualId();
- accept(LBRACE);
- Tree[] stats = topStatSeq();
- accept(RBRACE);
- return makePackaging(pos, pkg, stats);
- }
-
- /** TopStatSeq ::= [TopStat {`;' TopStat}]
- * TopStat ::= Modifiers ClsDef
- * | Packaging
- * | Import
- * |
- */
- Tree[] topStatSeq() {
- TreeList stats = new TreeList();
- while (s.token != RBRACE && s.token != EOF) {
- if (s.token == PACKAGE) {
- stats.append(packaging());
- } else if (s.token == IMPORT) {
- stats.append(importClause());
- } else if (s.token == CLASS ||
- s.token == CASECLASS ||
- s.token == TRAIT ||
- s.token == OBJECT ||
- s.token == CASEOBJECT ||
- isModifier()) {
- stats.append(clsDef(modifiers()));
- } else if (s.token != SEMI) {
- syntaxError("illegal start of class or object definition", true);
- }
- if (s.token != RBRACE && s.token != EOF) accept(SEMI);
- }
- return stats.toArray();
- }
-
- /** TemplateStatSeq ::= TemplateStat {`;' TemplateStat}
- * TemplateStat ::= Import
- * | Modifiers Def
- * | Modifiers Dcl
- * | Expr
- * |
- */
- Tree[] templateStatSeq() {
- TreeList stats = new TreeList();
- while (s.token != RBRACE && s.token != EOF) {
- if (s.token == IMPORT) {
- stats.append(importClause());
- } else if (isExprIntro()) {
- stats.append(expr());
- } else if (isDefIntro() || isModifier()) {
- stats.append(defOrDcl(modifiers()));
- } else if (s.token != SEMI) {
- syntaxError("illegal start of definition", true);
- }
- if (s.token != RBRACE) accept(SEMI);
- }
- return stats.toArray();
- }
-
- /** RefineStatSeq ::= RefineStat {`;' RefineStat}
- * RefineStat ::= Dcl
- * | type TypeDef {`,' TypeDef}
- * |
- */
- Tree[] refineStatSeq() {
- TreeList stats = new TreeList();
- while (s.token != RBRACE && s.token != EOF) {
- if (isDclIntro()) {
- stats.append(defOrDcl(0));
- } else if (s.token != SEMI) {
- syntaxError("illegal start of declaration", true);
- }
- if (s.token != RBRACE) accept(SEMI);
- }
- return stats.toArray();
- }
-
- /** BlockStatSeq ::= { BlockStat `;' } [Expr]
- * BlockStat ::= Import
- * | Def
- * | LocalModifiers ClsDef
- * | Expr
- * |
- */
- Tree[] blockStatSeq(TreeList stats) {
- while ((s.token != RBRACE) && (s.token != EOF) && (s.token != CASE)) {
- if (s.token == IMPORT) {
- stats.append(importClause());
- accept(SEMI);
- } else if (isExprIntro()) {
- stats.append(expr());
- if (s.token != RBRACE && s.token != CASE) accept(SEMI);
- } else if (isDefIntro()) {
- stats.append(defOrDcl(0));
- accept(SEMI);
- if (s.token == RBRACE || s.token == CASE) {
- stats.append(gen.mkUnitLit(s.pos));
- }
- } else if (isLocalModifier()) {
- stats.append(clsDef(localClassModifiers()));
- accept(SEMI);
- if (s.token == RBRACE || s.token == CASE) {
- stats.append(gen.mkUnitLit(s.pos));
- }
- } else if (s.token == SEMI) {
- s.nextToken();
- } else {
- syntaxError("illegal start of statement", true);
- }
- }
- return stats.toArray();
- }
-
-
- /** CompilationUnit ::= [ package QualId ( `;' | `{' TopStatSeq `}' ) ] TopStatSeq .
- */
- Tree[] compilationUnit() {
- if (s.token == PACKAGE) {
- int pos = s.skipToken();
- Tree pkg = qualId();
- if (s.token == SEMI) {
- s.nextToken();
- return new Tree[]{makePackaging(pos, pkg, topStatSeq())};
- } else {
- TreeList stats = new TreeList();
- accept(LBRACE);
- stats.append(makePackaging(pos, pkg, topStatSeq()));
- accept(RBRACE);
- stats.append(topStatSeq());
- return stats.toArray();
- }
- } else {
- return topStatSeq();
- }
- }
-}
diff --git a/sources/scalac/ast/parser/ParserPhase.java b/sources/scalac/ast/parser/ParserPhase.java
deleted file mode 100644
index 1355b3926d..0000000000
--- a/sources/scalac/ast/parser/ParserPhase.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-\* */
-
-// $Id$
-
-package scalac.ast.parser;
-
-import scalac.Global;
-import scalac.Phase;
-import scalac.PhaseDescriptor;
-import scalac.Unit;
-
-public class ParserPhase extends Phase {
-
- //########################################################################
- // Public Constructors
-
- /** Initializes this instance. */
- public ParserPhase(Global global, PhaseDescriptor descriptor) {
- super(global, descriptor);
- }
-
- //########################################################################
- // Public Methods
-
- /** Applies this phase to the given compilation units. */
- public void apply(Unit[] units) {
- for (int i = 0; i < units.length; i++) {
- global.start();
- units[i].body = new Parser(units[i]).parse();
- global.stop("parsed " + units[i].source);
- }
- }
-
- //########################################################################
-}
diff --git a/sources/scalac/ast/parser/Scanner.java b/sources/scalac/ast/parser/Scanner.java
deleted file mode 100644
index 81e15058a1..0000000000
--- a/sources/scalac/ast/parser/Scanner.java
+++ /dev/null
@@ -1,867 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
-\* */
-
-package scalac.ast.parser;
-
-import ch.epfl.lamp.util.Position;
-import ch.epfl.lamp.util.SourceFile;
-
-import scalac.*;
-import scalac.util.Name;
-
-
-/** A scanner for the programming language Scala.
- *
- * @author Matthias Zenger, Martin Odersky
- * @version 1.0
- */
-public class Scanner extends TokenData {
-
- /** buffer for the documentation comment
- */
- public StringBuffer docBuffer = null;
-
- /** add the given character to the documentation buffer
- */
- protected void addCharToDoc(byte ch) {
- if (docBuffer != null) docBuffer.append((char) ch);
- }
-
- /** layout & character constants
- */
- public int tabinc = 8;
- protected final static byte LF = SourceFile.LF;
- protected final static byte FF = SourceFile.FF;
- protected final static byte CR = SourceFile.CR;
- protected final static byte SU = SourceFile.SU;
-
- /** the names of all tokens
- */
- public Name[] tokenName = new Name[128];
- public int numToken = 0;
-
- /** keyword array; maps from name indices to tokens
- */
- protected byte[] key;
- protected int maxKey = 0;
-
- /** we need one token lookahead
- */
- protected TokenData next = new TokenData();
- protected TokenData prev = new TokenData();
-
- /** the first character position after the previous token
- */
- public int lastpos = 0;
-
- /** the last error position
- */
- public int errpos = -1;
-
- /** the input buffer:
- */
- protected byte[] buf;
- protected int bp;
-
- /** the current character
- */
- protected byte ch;
-
- /** the line and column position of the current character
- */
- public int cline;
- public int ccol;
-
- /** a buffer for character and string literals
- */
- protected byte[] lit = new byte[64];
- protected int litlen;
-
- /** the compilation unit
- */
- public Unit unit;
-
-
- /** Construct a scanner from a file input stream.
- */
- public Scanner(Unit unit) {
- this.unit = unit;
- buf = unit.source.bytes();
- cline = 1;
- bp = -1;
- ccol = 0;
- nextch();
- token = EMPTY;
- init();
- nextToken();
- }
-
- /** only used to determine keywords. used in dtd2scala tool */
- public Scanner() {
- initKeywords();
- }
-
- private void nextch() {
- ch = buf[++bp]; ccol++;
- }
-
- /** read next token and return last position
- */
- public int skipToken() {
- int p = pos;
- nextToken();
- return p;
- }
-
- public void nextToken() {
- if (token == RBRACE) {
- int prevpos = pos;
- fetchToken();
- switch (token) {
- case ELSE: case EXTENDS: case WITH:
- case YIELD: case CATCH: case FINALLY:
- case COMMA: case SEMI: case DOT:
- case COLON: case EQUALS: case ARROW:
- case LARROW: case SUBTYPE: case SUPERTYPE:
- case HASH: case AT:
- case RPAREN: case RBRACKET: case RBRACE:
- break;
- default:
- if (token == EOF ||
- ((pos >>> Position.COLUMN_BITS) >
- (prevpos >>> Position.COLUMN_BITS))) {
- next.copyFrom(this);
- this.token = SEMI;
- this.pos = prevpos;
- }
- }
- } else {
- if (next.token == EMPTY) {
- fetchToken();
- } else {
- copyFrom(next);
- next.token = EMPTY;
- }
- if (token == CASE) {
- prev.copyFrom(this);
- fetchToken();
- if (token == CLASS) {
- token = CASECLASS;
- } else if (token == OBJECT) {
- token = CASEOBJECT;
- } else {
- next.copyFrom(this);
- this.copyFrom(prev);
- }
- } else if (token == SEMI) {
- prev.copyFrom(this);
- fetchToken();
- if (token != ELSE) {
- next.copyFrom(this);
- this.copyFrom(prev);
- }
- }
- }
- //System.out.println("<" + token2string(token) + ">");//DEBUG
- }
-
- /** read next token
- */
- public void fetchToken() {
- if (token == EOF) return;
- lastpos = Position.encode(cline, ccol);
- int index = bp;
- while(true) {
- switch (ch) {
- case ' ':
- nextch();
- break;
- case '\t':
- ccol = ((ccol - 1) / tabinc * tabinc) + tabinc;
- nextch();
- break;
- case CR:
- cline++;
- ccol = 0;
- nextch();
- if (ch == LF) {
- ccol = 0;
- nextch();
- }
- break;
- case LF:
- case FF:
- cline++;
- ccol = 0;
- nextch();
- break;
- default:
- pos = Position.encode(cline, ccol);
- index = bp;
- switch (ch) {
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'L': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z': case '$':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- nextch();
- getIdentRest(index);
- return;
- case '~': case '!': case '@': case '#': case '%':
- case '^': case '*': case '+': case '-': case '<':
- case '>': case '?': case ':': case '\\':
- case '=': case '&': case '|':
- nextch();
- getOperatorRest(index);
- return;
- case '/':
- nextch();
- if (!skipComment()) {
- getOperatorRest(index);
- return;
- }
- break;
- case '_':
- nextch();
- getIdentRest(index);
- return;
- case '0':
- nextch();
- if (ch == 'x' || ch == 'X') {
- nextch();
- getNumber(index + 2, 16);
- } else
- getNumber(index, 8);
- return;
- case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- getNumber(index, 10);
- return;
- case '`':
- getStringLit('`');
- token = IDENTIFIER;
- return;
- case '\"':
- getStringLit('\"');
- return;
- case '\'':
- nextch();
- litlen = 0;
- switch (ch) {
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'L': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z': case '$': case '_':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- index = bp;
- putch(ch);
- nextch();
- if (ch != '\'') {
- getIdentRest(index);
- token = SYMBOLLIT;
- return;
- }
- break;
- default:
- getlitch();
- }
- if (ch == '\'') {
- nextch();
- token = CHARLIT;
- byte[] ascii = new byte[litlen * 2];
- int alen = SourceRepresentation.source2ascii(lit, 0, litlen, ascii);
- if (alen > 0)
- intVal = SourceRepresentation.ascii2string(ascii, 0, alen).charAt(0);
- else
- intVal = 0;
- } else
- syntaxError("unclosed character literal");
- return;
- case '.':
- nextch();
- if (('0' <= ch) && (ch <= '9')) getFraction(index);
- else token = DOT;
- return;
- case ';':
- nextch(); token = SEMI;
- return;
- case ',':
- nextch(); token = COMMA;
- return;
- case '(':
- nextch(); token = LPAREN;
- return;
- case '{':
- nextch(); token = LBRACE;
- return;
- case ')':
- nextch(); token = RPAREN;
- return;
- case '}':
- nextch(); token = RBRACE;
- return;
- case '[':
- nextch(); token = LBRACKET;
- return;
- case ']':
- nextch(); token = RBRACKET;
- return;
- case SU:
- token = EOF;
- return;
- default:
- nextch();
- syntaxError("illegal character");
- return;
- }
- }
- }
- }
-
- private boolean skipComment() {
- if (ch == '/') {
- do {
- nextch();
- } while ((ch != CR) && (ch != LF) && (ch != SU));
- return true;
- } else if (ch == '*') {
- docBuffer = null;
- int openComments = 1;
- nextch();
- if (ch == '*') {
- docBuffer = new StringBuffer("/**");
- }
- while (openComments > 0) {
- do {
- do {
- if (ch == CR) {
- cline++;
- ccol = 0;
- nextch(); addCharToDoc(ch);
- if (ch == LF) {
- ccol = 0;
- nextch(); addCharToDoc(ch);
- }
- } else if (ch == LF) {
- cline++;
- ccol = 0;
- nextch(); addCharToDoc(ch);
- }
- else if (ch == '\t') {
- ccol = ((ccol - 1) / tabinc * tabinc) + tabinc;
- nextch(); addCharToDoc(ch);
- } else if (ch == '/') {
- nextch(); addCharToDoc(ch);
- if (ch == '*') {
- nextch(); addCharToDoc(ch);
- openComments++;
- }
- } else {
- nextch(); addCharToDoc(ch);
- }
- } while ((ch != '*') && (ch != SU));
- while (ch == '*') {
- nextch(); addCharToDoc(ch);
- }
- } while (ch != '/' && ch != SU);
- if (ch == '/') {
- nextch();
- openComments--;
- } else {
- syntaxError("unclosed comment");
- return true;
- }
- }
- return true;
- } else {
- return false;
- }
- }
-
- private void getIdentRest(int index) {
- while (true) {
- switch (ch) {
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'L': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z': case '$':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- nextch();
- break;
- case '_':
- nextch();
- getIdentOrOperatorRest(index);
- return;
- default:
- treatIdent(index, bp);
- return;
- }
- }
- }
-
- private void getOperatorRest(int index) {
- while (true) {
- switch (ch) {
- case '~': case '!': case '@': case '#': case '%':
- case '^': case '*': case '+': case '-': case '<':
- case '>': case '?': case ':': case '\\':
- case '=': case '&': case '|':
- nextch();
- break;
- case '/':
- int lastbp = bp;
- nextch();
- if (skipComment()) {
- treatIdent(index, lastbp);
- return;
- } else {
- break;
- }
- /* case '_':
- nextch();
- getIdentOrOperatorRest(index);
- return; */
- default:
- treatIdent(index, bp);
- return;
- }
- }
- }
-
- private void getIdentOrOperatorRest(int index) {
- switch (ch) {
- case 'A': case 'B': case 'C': case 'D': case 'E':
- case 'F': case 'G': case 'H': case 'I': case 'J':
- case 'K': case 'L': case 'M': case 'N': case 'O':
- case 'P': case 'Q': case 'R': case 'S': case 'T':
- case 'U': case 'V': case 'W': case 'X': case 'Y':
- case 'Z': case '$':
- case 'a': case 'b': case 'c': case 'd': case 'e':
- case 'f': case 'g': case 'h': case 'i': case 'j':
- case 'k': case 'l': case 'm': case 'n': case 'o':
- case 'p': case 'q': case 'r': case 's': case 't':
- case 'u': case 'v': case 'w': case 'x': case 'y':
- case 'z':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- getIdentRest(index);
- return;
- case '~': case '!': case '@': case '#': case '%':
- case '^': case '*': case '+': case '-': case '<':
- case '>': case '?': case ':': case '\\':
- case '=': case '&': case '|':
- case '/':
- getOperatorRest(index);
- return;
- case '_':
- nextch();
- getIdentOrOperatorRest(index);
- return;
- default:
- treatIdent(index, bp);
- return;
- }
- }
-
- private void getStringLit(char delimiter) {
- nextch();
- litlen = 0;
- while (ch != delimiter && ch != CR && ch != LF && ch != SU)
- getlitch();
- if (ch == delimiter) {
- token = STRINGLIT;
- name = Name.fromSource(lit, 0, litlen);
- nextch();
- }
- else
- syntaxError("unclosed character literal");
- }
-
- /** returns true if argument corresponds to a keyword.
- * Used in dtd2scala tool.
- */
- public boolean isKeyword(String str) {
- Name name = Name.fromString(str);
- return (name.index <= maxKey);
- }
-
- void treatIdent(int start, int end) {
- name = Name.fromAscii(buf, start, end - start);
- if (name.index <= maxKey) {
- token = key[name.index];
- }
- else
- token = IDENTIFIER;
- }
-
- /** generate an error at the given position
- */
- void syntaxError(int pos, String msg) {
- unit.error(pos, msg);
- token = ERROR;
- errpos = pos;
- }
-
- /** generate an error at the current token position
- */
- void syntaxError(String msg) {
- syntaxError(pos, msg);
- }
-
- /** append characteter to "lit" buffer
- */
- protected void putch(byte c) {
- if (litlen == lit.length) {
- byte[] newlit = new byte[lit.length * 2];
- System.arraycopy(lit, 0, newlit, 0, lit.length);
- lit = newlit;
- }
- lit[litlen++] = c;
- }
-
- /** return true iff next 6 characters are a valid unicode sequence:
- */
- protected boolean isUnicode() {
- return
- (bp + 6) < buf.length &&
- (buf[bp] == '\\') &&
- (buf[bp+1] == 'u') &&
- (SourceRepresentation.digit2int(buf[bp+2], 16) >= 0) &&
- (SourceRepresentation.digit2int(buf[bp+3], 16) >= 0) &&
- (SourceRepresentation.digit2int(buf[bp+4], 16) >= 0) &&
- (SourceRepresentation.digit2int(buf[bp+5], 16) >= 0);
- }
-
- /** read next character in character or string literal:
- */
- protected void getlitch() {
- if (ch == '\\') {
- if (isUnicode()) {
- putch(ch); nextch();
- putch(ch); nextch();
- putch(ch); nextch();
- putch(ch); nextch();
- putch(ch); nextch();
- putch(ch); nextch();
- } else {
- nextch();
- if ('0' <= ch && ch <= '7') {
- byte leadch = ch;
- int oct = SourceRepresentation.digit2int(ch, 8);
- nextch();
- if ('0' <= ch && ch <= '7') {
- oct = oct * 8 + SourceRepresentation.digit2int(ch, 8);
- nextch();
- if (leadch <= '3' && '0' <= ch && ch <= '7') {
- oct = oct * 8 + SourceRepresentation.digit2int(ch, 8);
- nextch();
- }
- }
- putch((byte)oct);
- } else if (ch != SU) {
- switch (ch) {
- case 'b': case 't': case 'n':
- case 'f': case 'r': case '\"':
- case '\'': case '\\':
- putch((byte)'\\');
- putch(ch);
- break;
- default:
- syntaxError(Position.encode(cline, ccol) - 1, "invalid escape character");
- putch(ch);
- }
- nextch();
- }
- }
- } else if (ch != SU) {
- putch(ch);
- nextch();
- }
- }
-
- /** read fractional part of floating point number;
- * Then floatVal := buf[index..], converted to a floating point number.
- */
- protected void getFraction(int index) {
- while (SourceRepresentation.digit2int(ch, 10) >= 0) {
- nextch();
- }
- token = DOUBLELIT;
- if ((ch == 'e') || (ch == 'E')) {
- nextch();
- if ((ch == '+') || (ch == '-')) {
- byte sign = ch;
- nextch();
- if (('0' > ch) || (ch > '9')) {
- ch = sign;
- bp--;
- ccol--;
- }
- }
- while (SourceRepresentation.digit2int(ch, 10) >= 0) {
- nextch();
- }
- }
- double limit = Double.MAX_VALUE;
- if ((ch == 'd') || (ch == 'D')) {
- nextch();
- } else if ((ch == 'f') || (ch == 'F')) {
- token = FLOATLIT;
- limit = Float.MAX_VALUE;
- nextch();
- }
- try {
- floatVal = Double.valueOf(new String(buf, index, bp - index)).doubleValue();
- if (floatVal > limit)
- syntaxError("floating point number too large");
- } catch (NumberFormatException e) {
- syntaxError("malformed floating point number");
- }
- }
-
- /** intVal := buf[index..index+len-1], converted to an integer number.
- * base = the base of the number; one of 8, 10, 16.
- * max = the maximal number before an overflow.
- */
- protected void makeInt (int index, int len, int base, long max) {
- intVal = 0;
- int divider = (base == 10 ? 1 : 2);
- for (int i = 0; i < len; i++) {
- int d = SourceRepresentation.digit2int(buf[index + i], base);
- if (d < 0) {
- syntaxError("malformed integer number");
- return;
- }
- if (intVal < 0 ||
- max / (base / divider) < intVal ||
- max - (d / divider) < (intVal * (base / divider) - 0)) {
- syntaxError("integer number too large");
- return;
- }
- intVal = intVal * base + d;
- }
- }
-
- /** read a number,
- * and convert buf[index..], setting either intVal or floatVal.
- * base = the base of the number; one of 8, 10, 16.
- */
- protected void getNumber(int index, int base) {
- while (SourceRepresentation.digit2int(ch, base == 8 ? 10 : base) >= 0) {
- nextch();
- }
- if (base <= 10 && ch == '.') {
- nextch();
- if ((ch >= '0') && (ch <= '9'))
- getFraction(index);
- else {
- ch = buf[--bp]; ccol--;
- makeInt(index, bp - index, base, Integer.MAX_VALUE);
- intVal = (int)intVal;
- token = INTLIT;
- }
- } else if (base <= 10 &&
- (ch == 'e' || ch == 'E' ||
- ch == 'f' || ch == 'F' ||
- ch == 'd' || ch == 'D'))
- getFraction(index);
- else {
- if (ch == 'l' || ch == 'L') {
- makeInt(index, bp - index, base, Long.MAX_VALUE);
- nextch();
- token = LONGLIT;
- } else {
- makeInt(index, bp - index, base, Integer.MAX_VALUE);
- intVal = (int)intVal;
- token = INTLIT;
- }
- }
- }
-
- public int name2token(Name name) {
- if (name.index <= maxKey)
- return key[name.index];
- else
- return IDENTIFIER;
- }
-
- public String token2string(int token) {
- switch (token) {
- case IDENTIFIER:
- return "identifier";
- case CHARLIT:
- return "character literal";
- case INTLIT:
- return "integer literal";
- case LONGLIT:
- return "long literal";
- case FLOATLIT:
- return "float literal";
- case DOUBLELIT:
- return "double literal";
- case STRINGLIT:
- return "string literal";
- case SYMBOLLIT:
- return "symbol literal";
- case LPAREN:
- return "'('";
- case RPAREN:
- return "')'";
- case LBRACE:
- return "'{'";
- case RBRACE:
- return "'}'";
- case LBRACKET:
- return "'['";
- case RBRACKET:
- return "']'";
- case EOF:
- return "eof";
- case ERROR:
- return "something";
- case SEMI:
- return "';'";
- case COMMA:
- return "','";
- case CASECLASS:
- return "case class";
- case CASEOBJECT:
- return "case object";
- default:
- try {
- return "'" + tokenName[token].toString() + "'";
- } catch (ArrayIndexOutOfBoundsException e) {
- return "'<" + token + ">'";
- } catch (NullPointerException e) {
- return "'<(" + token + ")>'";
- }
- }
- }
-
- public String toString() {
- switch (token) {
- case IDENTIFIER:
- return "id(" + name + ")";
- case CHARLIT:
- return "char(" + intVal + ")";
- case INTLIT:
- return "int(" + intVal + ")";
- case LONGLIT:
- return "long(" + intVal + ")";
- case FLOATLIT:
- return "float(" + floatVal + ")";
- case DOUBLELIT:
- return "double(" + floatVal + ")";
- case STRINGLIT:
- return "string(" + name + ")";
- case SEMI:
- return ";";
- case COMMA:
- return ",";
- default:
- return token2string(token);
- }
- }
-
- protected void enterKeyword(String s, int tokenId) {
- while (tokenId > tokenName.length) {
- Name[] newTokName = new Name[tokenName.length * 2];
- System.arraycopy(tokenName, 0, newTokName, 0, newTokName.length);
- tokenName = newTokName;
- }
- Name n = Name.fromString(s);
- tokenName[tokenId] = n;
- if (n.index > maxKey)
- maxKey = n.index;
- if (tokenId >= numToken)
- numToken = tokenId + 1;
- }
-
- protected void init() {
- initKeywords();
- key = new byte[maxKey+1];
- for (int i = 0; i <= maxKey; i++)
- key[i] = IDENTIFIER;
- for (byte j = 0; j < numToken; j++)
- if (tokenName[j] != null)
- key[tokenName[j].index] = j;
- }
-
- protected void initKeywords() {
- enterKeyword("abstract", ABSTRACT);
- enterKeyword("case", CASE);
- enterKeyword("class", CLASS);
- enterKeyword("catch", CATCH);
- enterKeyword("def", DEF);
- enterKeyword("do", DO);
- enterKeyword("else", ELSE);
- enterKeyword("extends", EXTENDS);
- enterKeyword("false", FALSE);
- enterKeyword("final", FINAL);
- enterKeyword("finally", FINALLY);
- enterKeyword("for", FOR);
- enterKeyword("if", IF);
- enterKeyword("import", IMPORT);
- enterKeyword("new", NEW);
- enterKeyword("null", NULL);
- enterKeyword("object", OBJECT);
- enterKeyword("override", OVERRIDE);
- enterKeyword("package", PACKAGE);
- enterKeyword("private", PRIVATE);
- enterKeyword("protected", PROTECTED);
- enterKeyword("return", RETURN);
- enterKeyword("sealed", SEALED);
- enterKeyword("super", SUPER);
- enterKeyword("this", THIS);
- enterKeyword("throw", THROW);
- enterKeyword("trait", TRAIT);
- enterKeyword("true", TRUE);
- enterKeyword("try", TRY);
- enterKeyword("type", TYPE);
- enterKeyword("val", VAL);
- enterKeyword("var", VAR);
- enterKeyword("with", WITH);
- enterKeyword("while", WHILE);
- enterKeyword("yield", YIELD);
- enterKeyword(".", DOT);
- enterKeyword("_", USCORE);
- enterKeyword(":", COLON);
- enterKeyword("=", EQUALS);
- enterKeyword("=>", ARROW);
- enterKeyword("<-", LARROW);
- enterKeyword("<:", SUBTYPE);
- enterKeyword(">:", SUPERTYPE);
- enterKeyword("#", HASH);
- enterKeyword("@", AT);
- }
-}
-
-
diff --git a/sources/scalac/ast/parser/TokenData.java b/sources/scalac/ast/parser/TokenData.java
deleted file mode 100644
index d6bcac6c1c..0000000000
--- a/sources/scalac/ast/parser/TokenData.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
-\* */
-
-package scalac.ast.parser;
-
-import scalac.util.Name;
-
-/** A class for representing a token's data.
- *
- * @author Matthias Zenger
- * @version 1.0
- */
-public class TokenData implements Tokens {
-
- /** the next token
- */
- public int token = EMPTY;
-
- /** the token's position. pos = line << Position.LINESHIFT + col
- */
- public int pos = 0;
-
- /** the name of an identifier or token
- */
- public Name name;
-
- /** the value of a number
- */
- public long intVal;
- public double floatVal;
-
- public void copyFrom(TokenData td) {
- this.token = td.token;
- this.pos = td.pos;
- this.name = td.name;
- this.intVal = td.intVal;
- this.floatVal = td.floatVal;
- }
-}
diff --git a/sources/scalac/ast/parser/Tokens.java b/sources/scalac/ast/parser/Tokens.java
deleted file mode 100644
index 485ce6a465..0000000000
--- a/sources/scalac/ast/parser/Tokens.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
-\* */
-
-package scalac.ast.parser;
-
-public interface Tokens {
- byte EMPTY = -3,
- UNDEF = -2,
- ERROR = -1,
- EOF = 0,
-
- /* literals */
- CHARLIT = 1,
- INTLIT = 2,
- LONGLIT = 3,
- FLOATLIT = 4,
- DOUBLELIT = 5,
- STRINGLIT = 6,
- SYMBOLLIT = 7,
-
- /* identifier */
- IDENTIFIER = 10,
-
- /* keywords */
- IF = 20,
- FOR = 21,
- ELSE = 22,
- THIS = 23,
- NULL = 24,
- NEW = 25,
- WITH = 26,
- SUPER = 27,
- CASE = 28,
- CASECLASS = 29,
- CASEOBJECT = 30,
- VAL = 31,
- ABSTRACT = 32,
- FINAL = 33,
- PRIVATE = 34,
- PROTECTED = 35,
- OVERRIDE = 36,
- VAR = 37,
- DEF = 38,
- TYPE = 39,
- EXTENDS = 40,
- TRUE = 41,
- FALSE = 42,
- OBJECT = 43,
- CLASS = 44,
-
- IMPORT = 46,
- PACKAGE = 47,
- YIELD = 48,
- DO = 49,
- TRAIT = 50,
- SEALED = 51,
- THROW = 52,
- TRY = 53,
- CATCH = 54,
- FINALLY = 55,
- WHILE = 56,
- RETURN = 57,
-
- /* special symbols */
- COMMA = 61,
- SEMI = 62,
- DOT = 63,
- USCORE = 64,
- COLON = 65,
- EQUALS = 66,
- LARROW = 67,
- ARROW = 68,
- SUBTYPE = 69,
- SUPERTYPE = 70,
- HASH = 71,
- AT = 72,
-
- /* parenthesis */
- LPAREN = 90,
- RPAREN = 91,
- LBRACKET = 92,
- RBRACKET = 93,
- LBRACE = 94,
- RBRACE = 95;
-}
-
-
diff --git a/sources/scalac/ast/printer/HTMLTreePrinter.java b/sources/scalac/ast/printer/HTMLTreePrinter.java
deleted file mode 100644
index a4e6bb4f18..0000000000
--- a/sources/scalac/ast/printer/HTMLTreePrinter.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-** **
-\* */
-
-// $Id$
-
-package scalac.ast.printer;
-
-import scalac.Unit;
-import scalac.symtab.Symbol;
-import scalac.util.Name;
-
-import java.io.PrintWriter;
-import java.lang.Math;
-import java.util.HashMap;
-
-/**
- * HTML pretty printer for Scala abstract syntax trees.
- *
- * @author Michel Schinz
- * @version 1.0
- */
-
-public class HTMLTreePrinter extends TextTreePrinter {
- protected int outSectionLevel = 1;
- protected boolean started = false;
-
- public HTMLTreePrinter(PrintWriter writer) {
- super(writer);
- }
-
- public void begin() {
- assert !started;
-
- super.begin();
- out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">");
- out.println("<html>");
- out.println("<head>");
- out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=ISO-8859-1\">");
- out.println("<link rel=\"stylesheet\" href=\"scala.css\" type=\"text/css\">");
- out.println("<title>Scala tree</title>");
- out.println("</head>");
- out.println("<body>");
-
- started = true;
- }
-
- public void end() {
- assert started;
-
- out.println("</body>");
- out.println("</html>");
- super.end();
-
- started = false;
- }
-
- public void beginSection(int level, String title) {
- outSectionLevel = Math.min(level, 4);
- beginSection1(outSectionLevel, title);
- }
-
- protected void beginSection1(int level, String title) {
- if (level == 1)
- out.println("<hr/>");
- String tag = "h" + level;
- startTag(tag);
- print(Text.Simple(title));
- endTag(tag);
- }
-
- protected void startTag(String tag) {
- out.print('<'); out.print(tag); out.print('>');
- }
-
- protected void startTag(String tag, String attr1, String val1) {
- out.print('<');
- out.print(tag);
- out.print(' ');
- out.print(attr1);
- out.print("=\"");
- out.print(val1);
- out.print("\">");
- }
-
- protected void endTag(String tag) {
- out.print("</"); out.print(tag); out.print(">");
- }
-
- protected void startSpan(String cls) {
- startTag("span", "class", cls);
- }
-
- protected void endSpan() {
- endTag("span");
- }
-
- protected void printString(String str) {
- StringBuffer buf = null;
- int strLen = str.length();
-
- for (int i = 0; i < strLen; ++i) {
- String entity;
- char c = str.charAt(i);
- switch (c) {
- case '<': entity = "lt"; break;
- case '>': entity = "gt"; break;
- case '&': entity = "amp"; break;
- default: entity = null; break;
- }
- if (entity != null) {
- out.print('&');
- out.print(entity);
- out.print(';');
- } else
- out.print(c);
- }
- }
-
- protected static HashMap/*<Symbol,Integer>*/ symAnchors = new HashMap();
- protected String symbolAnchor(Symbol sym, SymbolUsage usage) {
- Integer anchorId = (Integer)symAnchors.get(sym);
- if (anchorId == null) {
- anchorId = new Integer(symAnchors.size());
- symAnchors.put(sym, anchorId);
- }
- if (usage == SymbolUsage.Definition)
- return anchorId.toString();
- else
- return "#" + anchorId.toString();
- }
-
- protected void print(Text text) {
- switch (text) {
- case Keyword(String name):
- startSpan("kw");
- printString(name);
- endSpan();
- break;
- case Literal(String str):
- startSpan("lit");
- printString(str);
- endSpan();
- break;
- case Identifier(Symbol symbol, Name name, SymbolUsage usage):
- boolean defined = (usage == SymbolUsage.Definition);
- if (defined) startSpan("idDef");
- if (symbol != null) {
- String attr = (defined ? "name" : "href");
- startTag("a", attr, symbolAnchor(symbol, usage));
- if (usage == SymbolUsage.Use)
- printString(symbol.simpleName().toString());
- else
- printString(symbol.name.toString());
- endTag("a");
- } else
- printString(name.toString());
- if (defined) endSpan();
- break;
- default:
- super.print(text);
- }
- }
-
- protected void printUnitHeader(Unit unit) {
- beginSection1(outSectionLevel + 1, unit.source.toString());
- startTag("pre");
- }
-
- protected void printUnitFooter(Unit unit) {
- endTag("pre");
- }
-}
diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java
deleted file mode 100644
index 6a8be8f696..0000000000
--- a/sources/scalac/ast/printer/TextTreePrinter.java
+++ /dev/null
@@ -1,813 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-** **
-\* */
-
-// $Id$
-
-package scalac.ast.printer;
-
-import scalac.ast.*;
-import scalac.atree.AConstant;
-import scalac.symtab.*;
-import scalac.util.Debug;
-import scalac.Global;
-import scalac.Phase;
-import scalac.Unit;
-import scalac.util.Name;
-import scalac.util.TypeNames;
-
-import java.io.*;
-import java.util.*;
-
-/**
- * Text pretty printer for Scala abstract syntax trees.
- *
- * @author Michel Schinz, Matthias Zenger
- * @version 1.0
- */
-public class TextTreePrinter implements TreePrinter {
- protected final PrintWriter out;
-
- protected int indent = 0;
- protected final int INDENT_STEP = 2;
- protected String INDENT_STRING =
- " ";
- protected final int MAX_INDENT = INDENT_STRING.length();
-
- public TextTreePrinter(PrintWriter writer) {
- this.out = writer;
- }
-
- public TextTreePrinter(Writer writer) {
- this(new PrintWriter(writer));
- }
-
- public TextTreePrinter(OutputStream stream) {
- this(new PrintWriter(stream));
- }
-
- public TextTreePrinter() {
- this(System.out);
- }
-
- public void begin() { }
-
- public void end() {
- flush();
- }
-
- public void flush() {
- out.flush();
- }
-
- public TreePrinter print(String str) {
- out.print(str);
- return this;
- }
-
- public TreePrinter println() {
- out.println();
- return this;
- }
-
- public void beginSection(int level, String title) {
- out.println("[[" + title + "]]");
- flush();
- }
-
- protected void indent() {
- indent += Math.min(MAX_INDENT, INDENT_STEP);
- }
-
- protected void undent() {
- indent -= Math.max(0, INDENT_STEP);
- }
-
- protected void printString(String str) {
- out.print(str);
- }
-
- protected void printNewLine() {
- out.println();
- while (indent > INDENT_STRING.length()) {
- INDENT_STRING = INDENT_STRING + INDENT_STRING;
- }
- if (indent > 0)
- out.write(INDENT_STRING, 0, indent);
- }
-
- public static class SymbolUsage {
- public case Definition;
- public case Use;
- }
-
- public static class Text {
- public case None;
- public case Space;
- public case Newline;
- public case Simple(String str);
- public case Literal(String str);
- public case Keyword(String name);
- public case Identifier(Symbol symbol, Name name, SymbolUsage usage);
- public case Sequence(Text[] elements);
- }
-
- protected void print(Text text) {
- switch (text) {
- case None : break;
- case Space : printString(" "); break;
- case Newline : printNewLine(); break;
- case Simple(String str) : printString(str); break;
- case Literal(String str) : printString(str); break;
- case Keyword(String name) : printString(name); break;
- case Identifier(Symbol sym, Name name, SymbolUsage usage) :
- if (sym != null) {
- if (usage == SymbolUsage.Use)
- printString(sym.simpleName().toString());
- else
- printString(sym.name.toString());
- if (Global.instance.uniqid)
- printString("#" + Global.instance.uniqueID.id(sym));
- } else {
- printString(name.toString());
- }
- break;
- case Sequence(Text[] elements) : print(elements); break;
- }
- }
-
- protected void print(Text[] texts) {
- for (int i = 0; i < texts.length; ++i)
- print(texts[i]);
- }
-
- protected static final Text KW_ABSTRACT = Text.Keyword("abstract");
- protected static final Text KW_CASE = Text.Keyword("case");
- protected static final Text KW_CLASS = Text.Keyword("class");
- protected static final Text KW_DEF = Text.Keyword("def");
- protected static final Text KW_DO = Text.Keyword("do");
- protected static final Text KW_ELSE = Text.Keyword("else");
- protected static final Text KW_EXTENDS = Text.Keyword("extends");
- protected static final Text KW_FINAL = Text.Keyword("final");
- protected static final Text KW_SEALED = Text.Keyword("sealed");
- protected static final Text KW_FOR = Text.Keyword("for");
- protected static final Text KW_IF = Text.Keyword("if");
- protected static final Text KW_IMPORT = Text.Keyword("import");
- protected static final Text KW_INTERFACE = Text.Keyword("interface");
- protected static final Text KW_OBJECT = Text.Keyword("object");
- protected static final Text KW_NEW = Text.Keyword("new");
- protected static final Text KW_NULL = Text.Keyword("null");
- protected static final Text KW_OUTER = Text.Keyword("outer");
- protected static final Text KW_OVERRIDE = Text.Keyword("override");
- protected static final Text KW_PACKAGE = Text.Keyword("package");
- protected static final Text KW_PRIVATE = Text.Keyword("private");
- protected static final Text KW_PROTECTED = Text.Keyword("protected");
- protected static final Text KW_RETURN = Text.Keyword("return");
- protected static final Text KW_STATIC = Text.Keyword("static");
- protected static final Text KW_SUPER = Text.Keyword("super");
- protected static final Text KW_THIS = Text.Keyword("this");
- protected static final Text KW_TYPE = Text.Keyword("type");
- protected static final Text KW_VAL = Text.Keyword("val");
- protected static final Text KW_VAR = Text.Keyword("var");
- protected static final Text KW_WITH = Text.Keyword("with");
- protected static final Text KW_YIELD = Text.Keyword("yield");
-
- protected static final Text TXT_ERROR = Text.Simple("<error>");
- protected static final Text TXT_UNKNOWN = Text.Simple("<unknown>");
- protected static final Text TXT_NULL = Text.Simple("<null>");
- protected static final Text TXT_OBJECT_COMMENT
- = Text.Simple("/*object*/ ");
- protected static final Text TXT_EMPTY = Text.Simple("<empty>");
-
- protected static final Text TXT_QUOTE = Text.Simple("\"");
- protected static final Text TXT_PLUS = Text.Simple("+");
- protected static final Text TXT_COLON = Text.Simple(":");
- protected static final Text TXT_SEMICOLON = Text.Simple(";");
- protected static final Text TXT_DOT = Text.Simple(".");
- protected static final Text TXT_COMMA = Text.Simple(",");
- protected static final Text TXT_EQUAL = Text.Simple("=");
- protected static final Text TXT_SUPERTYPE = Text.Simple(">:");
- protected static final Text TXT_SUBTYPE = Text.Simple("<:");
- protected static final Text TXT_HASH = Text.Simple("#");
- protected static final Text TXT_RIGHT_ARROW = Text.Simple("=>");
- protected static final Text TXT_LEFT_PAREN = Text.Simple("(");
- protected static final Text TXT_RIGHT_PAREN = Text.Simple(")");
- protected static final Text TXT_LEFT_BRACE = Text.Simple("{");
- protected static final Text TXT_RIGHT_BRACE = Text.Simple("}");
- protected static final Text TXT_LEFT_BRACKET = Text.Simple("[");
- protected static final Text TXT_RIGHT_BRACKET = Text.Simple("]");
- protected static final Text TXT_BAR = Text.Simple("|");
- protected static final Text TXT_AT = Text.Simple("@");
-
- protected static final Text TXT_WITH_SP =
- Text.Sequence(new Text[]{ Text.Space, KW_WITH, Text.Space });
- protected static final Text TXT_BLOCK_BEGIN =
- Text.Sequence(new Text[]{ TXT_LEFT_BRACE, Text.Newline });
- protected static final Text TXT_BLOCK_END =
- Text.Sequence(new Text[]{ Text.Newline, TXT_RIGHT_BRACE });
- protected static final Text TXT_BLOCK_SEP =
- Text.Sequence(new Text[]{ TXT_SEMICOLON, Text.Newline });
- protected static final Text TXT_COMMA_SP =
- Text.Sequence(new Text[]{ TXT_COMMA, Text.Space });
- protected static final Text TXT_ELSE_NL =
- Text.Sequence(new Text[]{ KW_ELSE, Text.Newline });
- protected static final Text TXT_BAR_SP =
- Text.Sequence(new Text[]{ Text.Space, TXT_BAR, Text.Space });
-
- public void print(Global global) {
- Phase phase = global.currentPhase;
- beginSection(1, "syntax trees at "+phase+" (after "+phase.prev+")");
- for (int i = 0; i < global.units.length; i++) print(global.units[i]);
- }
-
- public void print(Unit unit) {
- printUnitHeader(unit);
- if (unit.body != null) {
- for (int i = 0; i < unit.body.length; ++i) {
- print(unit.body[i]);
- print(TXT_BLOCK_SEP);
- }
- } else
- print(TXT_NULL);
- printUnitFooter(unit);
-
- flush();
- }
-
- protected void printUnitHeader(Unit unit) {
- print(Text.Simple("// Scala source: " + unit.source + "\n"));
- }
-
- protected void printUnitFooter(Unit unit) {
- print(Text.Newline);
- }
-
- public TreePrinter print(Tree tree) {
- switch (tree) {
- case Bad():
- print(TXT_ERROR);
- break;
-
- case Empty:
- print(TXT_EMPTY);
- break;
-
- case ClassDef(int mods, // :
- Name name,
- Tree.AbsTypeDef[] tparams,
- Tree.ValDef[][] vparams,
- Tree tpe,
- Tree.Template impl):
- printModifiers(mods);
- print((mods & Modifiers.INTERFACE) != 0
- ? KW_INTERFACE
- : KW_CLASS);
- print(Text.Space);
- printSymbolDefinition(tree.symbol(), name);
- printParams(tparams);
- printParams(vparams);
- printOpt(TXT_COLON, tpe, false);
- printTemplate(tree.symbol(), KW_EXTENDS, impl, true);
- break;
-
- case PackageDef(Tree packaged, Tree.Template impl):
- print(KW_PACKAGE);
- print(Text.Space);
- print(packaged);
- printTemplate(null, KW_WITH, impl, true);
- break;
-
- case ModuleDef(int mods, // :
- Name name,
- Tree tpe,
- Tree.Template impl):
- printModifiers(mods);
- print(KW_OBJECT);
- print(Text.Space);
- printSymbolDefinition(tree.symbol(), name);
- printOpt(TXT_COLON, tpe, false);
- printTemplate(null, KW_EXTENDS, impl, true);
- break;
-
- case ValDef(int mods, Name name, Tree tpe, Tree rhs):
- printModifiers(mods);
- if ((mods & Modifiers.MUTABLE) != 0) print(KW_VAR);
- else {
- if ((mods & Modifiers.MODUL) != 0) print(TXT_OBJECT_COMMENT);
- print(KW_VAL);
- }
- print(Text.Space);
- printSymbolDefinition(tree.symbol(), name);
- printOpt(TXT_COLON, tpe, false);
- if ((mods & Modifiers.DEFERRED) == 0) {
- print(Text.Space); print(TXT_EQUAL); print(Text.Space);
- if (rhs == Tree.Empty) print("_");
- else print(rhs);
- }
- break;
-
- case PatDef(int mods, Tree pat, Tree rhs):
- printModifiers(mods);
- print(KW_VAL);
- print(Text.Space);
- print(pat);
- printOpt(TXT_EQUAL, rhs, true);
- break;
-
- case DefDef(int mods,
- Name name,
- Tree.AbsTypeDef[] tparams,
- Tree.ValDef[][] vparams,
- Tree tpe,
- Tree rhs):
- printModifiers(mods);
- print(KW_DEF);
- print(Text.Space);
- if (name.isTypeName()) print(KW_THIS);
- else printSymbolDefinition(tree.symbol(), name);
- printParams(tparams);
- printParams(vparams);
- printOpt(TXT_COLON, tpe, false);
- printOpt(TXT_EQUAL, rhs, true);
- break;
-
- case AbsTypeDef(int mods,
- Name name,
- Tree rhs,
- Tree lobound):
- printModifiers(mods);
- print(KW_TYPE);
- print(Text.Space);
- printSymbolDefinition(tree.symbol(), name);
- printBounds(lobound, rhs);
- break;
-
- case AliasTypeDef(int mods,
- Name name,
- Tree.AbsTypeDef[] tparams,
- Tree rhs):
- printModifiers(mods);
- print(KW_TYPE);
- print(Text.Space);
- printSymbolDefinition(tree.symbol(), name);
- printParams(tparams);
- printOpt(TXT_EQUAL, rhs, true);
- break;
-
- case Import(Tree expr, Name[] selectors):
- print(KW_IMPORT);
- print(Text.Space);
- print(expr);
- print(TXT_DOT);
- print(TXT_LEFT_BRACE);
- for (int i = 0; i < selectors.length; i = i + 2) {
- if (i > 0) print(TXT_COMMA_SP);
- print(selectors[i].toString());
- if (i + 1 < selectors.length && selectors[i] != selectors[i+1]) {
- print(TXT_RIGHT_ARROW);
- print(selectors[i+1].toString());
- }
- }
- print(TXT_RIGHT_BRACE);
- break;
-
- case CaseDef(Tree pat, Tree guard, Tree body):
- print(KW_CASE);
- print(Text.Space);
- print(pat);
- printOpt(KW_IF, guard, true);
- print(Text.Space);
- print(TXT_RIGHT_ARROW);
- print(Text.Space);
- print(body);
- break;
-
- case LabelDef(Name name, Tree.Ident[] params, Tree rhs):
- printSymbolDefinition(tree.symbol(), name);
- printArray(params, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
- print(rhs);
- break;
-
- case Block(Tree[] stats, Tree value):
- printArray(stats, TXT_BLOCK_BEGIN, TXT_SEMICOLON, TXT_BLOCK_SEP);
- indent();
- printNewLine();
- print(value);
- undent();
- print(TXT_BLOCK_END);
- printType(tree);
- break;
-
- case Sequence(Tree[] trees): // sure ? was Tuple before...
- printArray(trees, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);
- break;
-
- /*
- case Subsequence(Tree[] trees):
- if( trees.length > 0 )
- printArray(trees, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
- else
- {
- print( TXT_LEFT_PAREN );
- print( TXT_COMMA );
- print( TXT_RIGHT_PAREN );
- }
- break;
- */
- case Alternative(Tree[] trees):
- printArray(trees, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_BAR_SP);
- break;
-
- case Bind(Name name, Tree t):
- printSymbolDefinition(tree.symbol(), name);
- print(Text.Space);
- print(TXT_AT);
- print(Text.Space);
- print(TXT_LEFT_PAREN);
- print( t );
- print(TXT_RIGHT_PAREN);
- printType(tree);
- break;
-
- case Visitor(Tree.CaseDef[] cases):
- printArray(cases, TXT_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline);
- break;
-
- case Function(Tree.ValDef[] vparams, Tree body):
- print(TXT_LEFT_PAREN);
- printParams(vparams);
- print(Text.Space);
- print(TXT_RIGHT_ARROW);
- print(Text.Space);
- print(body);
- print(TXT_RIGHT_PAREN);
- break;
-
- case Assign(Tree lhs, Tree rhs):
- print(lhs);
- print(Text.Space);
- print(TXT_EQUAL);
- print(Text.Space);
- print(rhs);
- break;
-
- case If(Tree cond, Tree thenp, Tree elsep):
- print(KW_IF);
- print(Text.Space);
- print(TXT_LEFT_PAREN);
- print(cond);
- print(TXT_RIGHT_PAREN);
- indent(); print(Text.Newline);
- print(thenp);
- undent(); print(Text.Newline);
- indent(); printOpt(TXT_ELSE_NL, elsep, false); undent();
- printType(tree);
- break;
-
- case Switch(Tree expr, int[] tags, Tree[] bodies, Tree defaultBody):
- print("<switch>");
- print(Text.Space);
- print(TXT_LEFT_PAREN);
- print(expr);
- print(TXT_RIGHT_PAREN);
- print(Text.Space);
- indent();
- print(TXT_BLOCK_BEGIN);
- for (int i = 0; i < tags.length; i++) {
- print(KW_CASE);
- print(Text.Space);
- print("" + tags[i]);
- print(Text.Space);
- print(TXT_RIGHT_ARROW);
- print(Text.Space);
- print(bodies[i]);
- print(Text.Newline);
- }
- print("<default> => ");
- print(defaultBody);
- undent();
- print(TXT_BLOCK_END);
- break;
-
- case Return(Tree expr):
- print(KW_RETURN);
- print(Text.Space);
- print(expr);
- break;
-
- case New(Tree.Template templ):
- printTemplate(null, KW_NEW, templ, false);
- printType(tree);
- break;
-
- case Typed(Tree expr, Tree tpe):
- print(TXT_LEFT_PAREN);
- print(expr);
- print(TXT_RIGHT_PAREN);
- print(Text.Space);
- print(TXT_COLON);
- print(Text.Space);
- print(tpe);
- printType(tree);
- break;
-
- case TypeApply(Tree fun, Tree[] targs):
- print(fun);
- printArray(targs, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP);
- printType(tree);
- break;
-
- case Apply(Tree fun, Tree[] vargs):
- if (fun instanceof Tree.TypeTerm)
- print(fun.type.resultType().symbol().fullName().toString());
- else
- print(fun);
- printArray(vargs, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
- printType(tree);
- break;
-
- case Super(Name qualifier, Name mixin):
- if (qualifier != TypeNames.EMPTY) {
- printSymbolUse(tree.symbol(), qualifier);
- print(TXT_DOT);
- }
- print(KW_SUPER);
- if (mixin != TypeNames.EMPTY) {
- print(TXT_LEFT_PAREN);
- print(mixin.toString());
- print(TXT_RIGHT_PAREN);
- }
- printType(tree);
- break;
-
- case This(Name name):
- if (name != TypeNames.EMPTY) {
- printSymbolUse(tree.symbol(), name);
- print(TXT_DOT);
- }
- print(KW_THIS);
- printType(tree);
- break;
-
- case Select(Tree qualifier, Name name):
- if (Global.instance.debug || qualifier.symbol() == null || !qualifier.symbol().isRoot()) {
- print(qualifier);
- print(TXT_DOT);
- }
- printSymbolUse(tree.symbol(), name);
- printType(tree);
- break;
-
- case Ident(Name name):
- printSymbolUse(tree.symbol(), name);
- printType(tree);
- break;
-
- case Literal(AConstant value):
- print(Text.Literal(value.toString()));
- printType(tree);
- break;
-
- case TypeTerm():
- print(tree.type.toString());
- break;
-
- case SingletonType(Tree ref):
- print(ref);
- print(TXT_DOT); print(KW_TYPE);
- break;
-
- case SelectFromType(Tree qualifier, Name selector):
- print(qualifier);
- print(Text.Space); print(TXT_HASH); print(Text.Space);
- printSymbolUse(tree.symbol(), selector);
- break;
-
- case FunType(Tree[] argtpes, Tree restpe):
- printArray(argtpes, TXT_LEFT_PAREN, TXT_RIGHT_PAREN, TXT_COMMA_SP);
- print(TXT_RIGHT_ARROW);
- print(restpe);
- break;
-
- case CompoundType(Tree[] baseTypes, Tree[] refinements):
- printArray(baseTypes, Text.None, Text.None, TXT_WITH_SP);
- printArray(refinements, TXT_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline);
- break;
-
- case AppliedType(Tree tpe, Tree[] args):
- print(tpe);
- indent();
- print(TXT_LEFT_BRACKET);
- for (int i = 0; i < args.length; ++i) {
- if (i > 0) print(TXT_COMMA_SP);
- print(args[i]);
- }
- undent();
- print(TXT_RIGHT_BRACKET);
- break;
-
- case Template(Tree[] parents, Tree[] body):
- Debug.abort("unexpected case: template");
- break;
-
- default:
- print(TXT_UNKNOWN);
- break;
- }
- //print("{" + tree.type + "}");//DEBUG
- return this;
- }
-
- // Printing helpers
-
- protected void printArray(Tree[] trees, Text open, Text close, Text sep) {
- indent();
- print(open);
- for (int i = 0; i < trees.length; ++i) {
- if (i > 0) print(sep);
- print(trees[i]);
- }
- undent();
- print(close);
- }
-
- protected void printOpt(Text prefix, Tree tree, boolean spaceBefore) {
- if (tree != Tree.Empty) {
- if (spaceBefore)
- print(Text.Space);
- print(prefix);
- print(Text.Space);
- print(tree);
- }
- }
-
- // Printing of symbols
-
- protected void printSymbolDefinition(Symbol symbol, Name name) {
- print(Text.Identifier(symbol, name, SymbolUsage.Definition));
- }
-
- protected void printSymbolUse(Symbol symbol, Name name) {
- print(Text.Identifier(symbol, name, SymbolUsage.Use));
- }
-
- // Printing of trees
-
- protected void printType(Tree tree) {
- if (Global.instance.printtypes) {
- print(TXT_LEFT_BRACE);
- if (tree.type != null)
- print(Text.Simple(tree.type.toString()));
- else
- print(TXT_NULL);
- print(TXT_RIGHT_BRACE);
- }
- }
-
- protected void printModifiers(int flags) {
- if ((flags & Modifiers.ABSTRACT) != 0) {
- print(KW_ABSTRACT);
- print(Text.Space);
- }
- if ((flags & Modifiers.FINAL) != 0) {
- print(KW_FINAL);
- print(Text.Space);
- }
- if ((flags & Modifiers.SEALED) != 0) {
- print(KW_SEALED);
- print(Text.Space);
- }
- if ((flags & Modifiers.PRIVATE) != 0) {
- print(KW_PRIVATE);
- print(Text.Space);
- }
- if ((flags & Modifiers.PROTECTED) != 0) {
- print(KW_PROTECTED);
- print(Text.Space);
- }
- if ((flags & Modifiers.OVERRIDE) != 0) {
- print(KW_OVERRIDE);
- print(Text.Space);
- }
- if ((flags & Modifiers.CASE) != 0) {
- print(KW_CASE);
- print(Text.Space);
- }
- if ((flags & Modifiers.DEF) != 0) {
- print(KW_DEF);
- print(Text.Space);
- }
- }
-
- protected void printTemplate(Symbol symbol,
- Text prefix,
- Tree.Template templ,
- boolean spaceBefore) {
- if (! (templ.parents.length == 0
- || (templ.parents.length == 1
- && templ.parents[0] == Tree.Empty))) {
- if (spaceBefore)
- print(Text.Space);
- print(prefix);
- print(Text.Space);
- printArray(templ.parents, Text.None, Text.None, TXT_WITH_SP);
- }
-
- List types = new ArrayList();
- if (symbol != null) {
- Global global = Global.instance;
- if (global.currentPhase.id > global.PHASE.EXPLICITOUTER.id()) {
- Scope.SymbolIterator i = symbol.members().iterator(true);
- while (i.hasNext()) {
- Symbol member = i.next();
- if (member.isTypeAlias() || member.isAbstractType())
- types.add(member);
- }
- }
- }
- if (templ.body.length > 0 || types.size() > 0) {
- print(Text.Space);
- indent();
- print(TXT_BLOCK_BEGIN);
- if (types.size() > 0) {
- SymbolTablePrinter printer = new SymbolTablePrinter(
- INDENT_STRING.substring(0, indent));
- printer.indent();
- for (int i = 0; i < types.size(); ++i) {
- if (i > 0) printer.line();
- Symbol type = (Symbol)types.get(i);
- printer.printSignature(type).print(';');
- }
- printer.undent();
- print(printer.toString().substring(indent));
- print(Text.Newline);
- }
- for (int i = 0; i < templ.body.length; ++i) {
- if (i > 0) print(TXT_BLOCK_SEP);
- print(templ.body[i]);
- }
- undent();
- print(TXT_BLOCK_END);
- }
- }
-
- protected void printParams(Tree.AbsTypeDef[] tparams) {
- if (tparams.length > 0) {
- print(TXT_LEFT_BRACKET);
- for (int i = 0; i < tparams.length; i++) {
- if (i > 0) print(TXT_COMMA_SP);
- printParam(tparams[i]);
- }
- print(TXT_RIGHT_BRACKET);
- }
- }
-
- protected void printParams(Tree.ValDef[][] vparamss) {
- for (int i = 0; i < vparamss.length; ++i)
- printParams(vparamss[i]);
- }
-
- protected void printParams(Tree.ValDef[] vparams) {
- print(TXT_LEFT_PAREN);
- for (int i = 0; i < vparams.length; ++i) {
- if (i > 0) print(TXT_COMMA_SP);
- printParam(vparams[i]);
- }
- print(TXT_RIGHT_PAREN);
- }
-
- protected void printParam(Tree tree) {
- switch (tree) {
- case AbsTypeDef(int mods, Name name, Tree bound, Tree lobound):
- printModifiers(mods);
- printSymbolDefinition(tree.symbol(), name);
- printBounds(lobound, bound);
- break;
-
- case ValDef(int mods, Name name, Tree tpe, Tree.Empty):
- printModifiers(mods);
- printSymbolDefinition(tree.symbol(), name);
- printOpt(TXT_COLON, tpe, false);
- break;
-
- default:
- Debug.abort("bad parameter: " + tree);
- }
- }
-
- protected void printBounds(Tree lobound, Tree hibound) {
- Definitions definitions = Global.instance.definitions;
- boolean printLoBound = lobound.type != null
- ? lobound.type().symbol() != definitions.ALL_CLASS
- : !"scala.All".equals(lobound.toString());
- if (printLoBound) printOpt(TXT_SUPERTYPE, lobound, true);
- boolean printHiBound = hibound.type != null
- ? hibound.type().symbol() != definitions.ANY_CLASS
- : !"scala.Any".equals(hibound.toString());
- if (printHiBound) printOpt(TXT_SUBTYPE, hibound, true);
- }
-
-}
diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java
deleted file mode 100644
index 7d889f4aef..0000000000
--- a/sources/scalac/typechecker/Analyzer.java
+++ /dev/null
@@ -1,2698 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-\* */
-
-// $Id$
-
-// todo: eliminate Typed nodes.
-// todo: use SELECTOR flag to avoid access methods for privates
-// todo: use mangled name or drop.
-// todo: emit warnings for unchecked.
-// todo: synchronize on module instantiation.
-// todo: empty package
-
-package scalac.typechecker;
-
-import ch.epfl.lamp.util.Position;
-import ch.epfl.lamp.util.Pair;
-import scalac.*;
-import scalac.util.*;
-import scalac.ast.*;
-import scalac.atree.AConstant;
-import scalac.ast.printer.*;
-import scalac.symtab.*;
-import scalac.symtab.classfile.*;
-import Tree.*;
-import java.util.*;
-
-/** The main attribution phase.
- */
-public class Analyzer extends Transformer implements Modifiers, Kinds {
-
- final Definitions definitions;
- private final DeSugarize desugarize;
- private final AnalyzerPhase descr;
- final Infer infer;
- final ConstantFolder constfold;
-
- public Analyzer(Global global, AnalyzerPhase descr) {
- super(global);
- this.definitions = global.definitions;
- this.descr = descr;
- this.infer = new Infer(this);
- this.constfold = new ConstantFolder(global);
- this.desugarize = new DeSugarize(this, global);
- }
-
- Unit unit;
- private Context context;
- private Type pt;
- private int mode;
-
- private boolean inAlternative; // for pattern matching;
- private HashMap patternVars; // for pattern matching; maps x to {true,false}
-
- public void apply(Unit[] units) {
-// for (int i = 0; i < units.length; i++) {
-// enterUnit(global.units[i]);
-// }
-// super.apply(units); // this calls apply(u) for every unit `u'.
- for (int i = 0; i < units.length; i++) enterUnit(units[i]);
- super.apply(units); // this calls apply(u) for every unit `u'.
- int n = descr.newSources.size();
- while (n > 0) {
- int l = global.units.length;
- Unit[] newUnits = new Unit[l + n];
- System.arraycopy(global.units, 0, newUnits, 0, l);
- for (int i = 0; i < n; i++)
- newUnits[i + l] = (Unit)descr.newSources.get(i);
- global.units = newUnits;
- descr.newSources.clear();
- for (int i = l; i < newUnits.length; i++) {
- apply(newUnits[i]);
- }
- n = descr.newSources.size();
- }
- }
-
- public void enterUnit(Unit unit) {
- enter(new Context(Tree.Empty, unit.console ? descr.consoleContext : descr.startContext), unit);
- }
-
- public void enter(Context context, Unit unit) {
- assert this.unit == null : "start unit non null for " + unit;
- this.unit = unit;
- this.context = context;
- this.patternVars = new HashMap();
- ImportList prevImports = context.imports;
- descr.contexts.put(unit, context);
- enterSyms(unit.body);
- context.imports = prevImports;
- this.unit = null;
- this.context = null;
- }
-
- public void lateEnter(Unit unit, Symbol sym) {
- enterUnit(unit);
- if (sym.rawFirstInfo() instanceof SourceCompleter) {
- sym.setInfo(Type.ErrorType);
- String kind = (sym.name.isTermName()) ? "object " : "class ";
- throw new Type.Error("file " + unit.source + " does not define public " +
- kind + sym.fullName());
- } else {
- descr.newSources.add(unit);
- }
- }
-
- public void apply(Unit unit) {
- global.log("checking " + unit);
- assert this.unit == null : "start unit non null for " + unit;
- this.unit = unit;
- this.context = (Context)descr.contexts.remove(unit);
- assert this.context != null : "could not find context for " + unit;
- unit.body = transformStatSeq(unit.body, Symbol.NONE);
- if (global.target != global.TARGET_INT && global.reporter.errors() == 0) {
- genSymData(unit.body);
- }
- this.unit = null;
- this.context = null;
- global.operation("checked " + unit);
- }
-
- public void genSymData(Tree[] stats) {
- for (int i = 0; i < stats.length; i++) {
- switch (stats[i]) {
- case ClassDef(_, _, _, _, _, _):
- case ModuleDef(_, _, _, _):
- Symbol sym = stats[i].symbol();
- Name fullname = sym.fullName();
- if (global.symdata.get(fullname) == null) {
- Pickle pickle = new Pickle();
- pickle.add(sym.owner().info().lookup(sym.name.toTermName()));
- pickle.add(sym.owner().info().lookup(sym.name.toTypeName()));
- pickle.pickle();
- global.symdata.put(fullname, pickle);
- }
- break;
- case PackageDef(Tree packaged, Tree.Template templ):
- genSymData(templ.body);
- }
- }
- }
-
- /** Mode constants
- */
- static final int NOmode = 0x000;
- static final int EXPRmode = 0x001; // these 4 modes are mutually exclusive.
- static final int PATTERNmode = 0x002;
- static final int CONSTRmode = 0x004;
- static final int TYPEmode = 0x008;
-
- static final int FUNmode = 0x10; // orthogonal to above. When set
- // we are looking for a method or constructor
-
- static final int POLYmode = 0x020; // orthogonal to above. When set
- // expression types can be polymorphic.
-
- static final int QUALmode = 0x040; // orthogonal to above. When set
- // expressions may be packages and
- // Java statics modules.
-
- static final int SUPERmode = 0x080; // Goes with CONSTRmode. When set
- // we are checking a superclass
- // constructor invocation.
-
- static final int baseModes = EXPRmode | PATTERNmode | CONSTRmode;
-
- static final int SEQUENCEmode = 0x1000; // orthogonal to above. When set
- // we turn "x" into "x@_"
- // and allow args to be of type Seq[ a ] instead of a
-
-// Diagnostics ----------------------------------------------------------------
-
- Tree errorTree(int pos) {
- return make.Bad(pos).setSymbol(Symbol.ERROR).setType(Type.ErrorType);
- }
-
- Tree error(int pos, String msg) {
- unit.error(pos, msg);
- return errorTree(pos);
- }
-
- void typeError(int pos, Type found, Type req) {
- String msg = infer.typeErrorMsg("type mismatch", found, req);
- Type foundResult = found.resultType();
- if (foundResult != found && infer.isCompatible(foundResult, req))
- msg = msg +
- "\n possible cause: missing arguments for method or constructor";
- error(pos, msg);
- }
-
- Tree reportTypeError(int pos, Type.Error ex) {
- if (global.debug) ex.printStackTrace();
- if (ex instanceof CyclicReference) {
- CyclicReference cyc = (CyclicReference) ex;
- if (cyc.info instanceof LazyTreeType) {
- switch (((LazyTreeType) cyc.info).tree) {
- case ValDef(_, _, Tree.Empty, _):
- return error(pos, "recursive " + cyc.sym + " needs type");
- case DefDef(_, _, _, _, Tree.Empty, _):
- return error(pos, "recursive function " + cyc.sym.name + " needs result type");
- }
- }
- }
- //throw ex;//DEBUG
- return error(pos, ex.msg);
- }
-
-// Name resolution -----------------------------------------------------------
-
- String decode(Name name) {
- if (name.isTypeName()) return "type " + NameTransformer.decode(name);
- else return "value " + NameTransformer.decode(name);
- }
-
- /** Check that `sym' is accessible as a member of tree `site' in current context.
- */
- Type checkAccessible(int pos, Symbol sym, Type symtype, Tree site) {
- if ((sym.owner().flags & INCONSTRUCTOR) != 0 &&
- !(sym.kind == TYPE && sym.isParameter())) {
- switch (site) {
- case This(_):
- error(pos, sym + " cannot be accessed from constructor");
- return Type.ErrorType;
- }
- }
- switch (symtype) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- int nacc = 0;
- for (int i = 0; i < alts.length; i++) {
- if (isAccessible(alts[i], site)) {
- nacc++;
- }
- }
- if (nacc == 0) {
- error(pos, sym + " cannot be accessed in " + site.type.widen());
- return Type.ErrorType;
- } else {
- Symbol[] alts1 = new Symbol[nacc];
- Type[] alttypes1 = new Type[nacc];
- nacc = 0;
- for (int i = 0; i < alts.length; i++) {
- if (isAccessible(alts[i], site)) {
- alts1[nacc] = alts[i];
- alttypes1[nacc] = alttypes[i];
- nacc++;
- }
- }
- return Type.OverloadedType(alts1, alttypes1);
- }
- default:
- if (isAccessible(sym, site)) {
- return symtype;
- } else {
- error(pos, sym + " cannot be accessed in " + site.type.widen());
- return Type.ErrorType;
- }
- }
- }
-
- /** Is `sym' accessible as a member of tree `site' in current context?
- */
- private boolean isAccessible(Symbol sym, Tree site) {
- return
- (sym.flags & (PRIVATE | PROTECTED)) == 0
- ||
- accessWithin(sym.owner())
- ||
- ((sym.flags & PRIVATE) == 0) &&
- site.type.symbol().isSubClass(
- sym.isConstructor() ? sym.constructorClass()
- : sym.owner()) &&
- (site instanceof Tree.Super ||
- isSubClassOfEnclosing(site.type.symbol()));
- } //where
-
- /** Are we inside definition of `owner'?
- */
- boolean accessWithin(Symbol owner) {
- Context c = context;
- while (c != Context.NONE && c.owner != owner) {
- c = c.outer.enclClass;
- }
- return c != Context.NONE;
- }
-
- /** Is `clazz' a subclass of an enclosing class?
- */
- boolean isSubClassOfEnclosing(Symbol clazz) {
- Context c = context;
- while (c != Context.NONE && !clazz.isSubClass(c.owner)) {
- c = c.outer.enclClass;
- }
- return c != Context.NONE;
- }
-
-// 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.
- */
- void validate(Symbol sym) {
- 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, "`def' modifier 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" +
- (((sym.flags & MUTABLE) == 0) ? ""
- : "\n(Note that variables need to be initialized to be defined)"));
- sym.flags &= ~DEFERRED;
- }
- }
- checkNoConflict(sym, DEFERRED, PRIVATE);
- checkNoConflict(sym, FINAL, SEALED);
- 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.
- */
- void validateParentClasses(Tree[] constrs, Type[] parents, Type selfType) {
- for (int i = 0; i < parents.length; i++) {
- if (!checkClassType(constrs[i].pos, parents[i])) return;
- Symbol bsym = parents[i].symbol();
- if (i == 0) {
- if ((bsym.flags & (JAVA | INTERFACE)) == (JAVA | INTERFACE))
- error(constrs[0].pos, "superclass may not be a Java interface");
- } else {
- if ((bsym.flags & (JAVA | INTERFACE)) == JAVA)
- error(constrs[i].pos, "Java class may not be used as mixin");
- Type[] 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");
- }
- 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?
- Scope.Entry e = context.scope.lookupEntry(bsym.name);
- if (e.sym != bsym || e.owner != context.scope) {
- // we are not within same statement sequence
- Context c = context;
- while (c != Context.NONE && c.owner != bsym)
- c = c.outer;
- 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());
- }
- for (int j = 0; j < i; j++) {
- if (parents[i].symbol() == parents[j].symbol())
- error(constrs[i].pos, parents[i].symbol() + " is inherited twice");
- }
- }
- }
-
- /** Check that type is a class type.
- */
- private boolean checkClassType(int pos, Type tp) {
- switch (tp.unalias()) {
- case TypeRef(_, Symbol sym, _):
- if (sym.kind == CLASS) return true;
- else if (sym.kind == ERROR) return false;
- break;
- case ErrorType:
- return false;
- }
- error(pos, "class type expected");
- return false;
- }
-
- /** Check that type is an object type
- */
- private Type checkObjectType(int pos, Type tp) {
- if (tp.isObjectType()) return tp;
- else {
- if (tp != Type.ErrorType) error(pos, "object type expected");
- return Type.ErrorType;
- }
- }
-
- /** Check that type is eta-expandable (i.e. no `def' or `*' parameters)
- */
- void checkEtaExpandable(int pos, Type tp) {
- switch (tp) {
- case MethodType(Symbol[] params, Type restype):
- for (int i = 0; i < params.length; i++) {
- if ((params[i].flags & DEF) != 0)
- error(pos, "method with `def' parameters needs to be fully applied");
- if ((params[i].flags & REPEATED) != 0)
- error(pos, "method with `*' parameters needs to be fully applied");
- }
- checkEtaExpandable(pos, restype);
- }
- }
-
- /** Check that `sym' does not contain both `flag1' and `flag2'
- */
- void checkNoConflict(Symbol sym, int flag1, int flag2) {
- 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.
- */
- public void checkNonCyclic(int pos, Type tp) {
- switch (tp) {
- case TypeRef(Type pre, Symbol sym, Type[] 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 |= 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));
- sym.flags &= ~LOCKED;
- }
- break;
- case CompoundType(Type[] parents, Scope members):
- for (int i = 0; i < parents.length; i++) {
- checkNonCyclic(pos, parents[i]);
- }
- break;
- case SingleType(Type pre, Symbol sym):
- sym.initialize();
- if ((sym.flags & LOCKED) != 0) {
- error(pos, "cyclic aliasing or subtyping involving " + sym);
- }
- }
- }
-
- /** Check that type does not refer to components defined in current scope.
- */
- Type checkNoEscape(int pos, Type tp) {
- try {
- return checkNoEscapeMap.apply(tp);
- } catch (Type.Error ex) {
- if ((mode & EXPRmode) != 0 && infer.isFullyDefined(pt)) return pt;
- error(pos, ex.msg + " as part of " + tp.unalias());
- return Type.ErrorType;
- }
- }
- //where
- private Type.Map checkNoEscapeMap = new Type.Map() {
- public Type apply(Type t) {
- switch (t.unalias()) {
- case TypeRef(Type pre, Symbol sym, Type[] args):
- if (pre instanceof Type.ThisType) checkNoEscape(t, sym);
- break;
- case SingleType(ThisType(_), Symbol sym):
- checkNoEscape(t, sym);
- break;
- }
- return map(t);
- }
- private void checkNoEscape(Type t, Symbol sym) {
- Scope.Entry e = 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");
- }
- }
- };
-
- /** Check that there are no dependent parameter types among parameters
- */
- void checkNoEscapeParams(ValDef[][] vparams) {
- for (int i = 0; i < vparams.length; i++)
- for (int j = 0; j < vparams[i].length; j++)
- checkNoEscape(vparams[i][j].pos, vparams[i][j].tpe.type);
- }
-
- /** Check that tree represents a pure definition.
- */
- void checkPureDef(Tree tree, Symbol clazz) {
- if (!TreeInfo.isPureDef(tree) && tree.type != Type.ErrorType)
- error(tree.pos, clazz + " may contain only pure definitions");
- }
-
- /** Check that tree represents a pure constructor.
- */
- void checkPureConstr(Tree tree, Symbol clazz) {
- if (!TreeInfo.isPureConstr(tree) && tree.type != Type.ErrorType)
- error(tree.pos, clazz + " may invoke only pure superclass constructors");
- }
-
- /** Check that tree represents a trait constructor.
- */
- void checkTrait(Tree tree, Symbol clazz) {
- if (!tree.type.symbol().isTrait() && tree.type != Type.ErrorType)
- error(tree.pos, " " + clazz + " may inherit only traits as mixins");
- }
-
- /** Check that tree is a stable expression .p
- */
- Tree checkStable(Tree tree) {
- if (TreeInfo.isPureExpr(tree) || tree.type == Type.ErrorType)
- return tree;
- else
- return error(tree.pos, "stable identifier required, but " +
- tree + " found.");
- }
-
- /** Check that class can be instantiated.
- */
- void checkInstantiatable(int pos, Type tp) {
- Symbol clazz = 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 static class CheckDefined extends Traverser {
- Tree all;
- public void traverse(Tree tree) {
- assert tree.type != null : tree + " in " + all;
- if (tree.type != Type.ErrorType)
- super.traverse(tree);
- }
- }
-
- private static 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 Type matchQualType(Tree fn) {
- switch (fn) {
- case Select(Tree qual, _):
- if (fn.symbol() == definitions.ANY_MATCH)
- return qual.type.widen();
- break;
- case TypeApply(Tree fn1, _):
- return matchQualType(fn1);
- case Ident(_):
- if (fn.symbol() == definitions.ANY_MATCH)
- return context.enclClass.owner.typeOfThis();
- break;
- }
- return fn.type == Type.ErrorType ? Type.ErrorType : Type.NoType;
- }
-
- private boolean isSetterMethod(Symbol sym) {
- return sym != null &&
- !sym.isLocal() &&
- !sym.isStable() &&
- sym.type() instanceof Type.PolyType &&
- sym.typeParams().length == 0;
- }
-
-// Contexts -------------------------------------------------------------------
-
- /** Push new context associated with given tree, owner, and scope on stack.
- * Fields `imports' and, possibly, `enclClass' are inherited from parent.
- */
- void pushContext(Tree tree, Symbol owner, Scope scope) {
- context = new Context(tree, owner, scope, context);
- }
-
- /** Pop context from stack.
- */
- void popContext() {
- context = context.outer;
- }
-
-// Lazy Types ------------------------------------------------------------------
-
- /** A lazy type which, when forced returns the type of a symbol defined
- * in `tree'.
- */
- class LazyTreeType extends Type.LazyType {
- Tree tree;
- Unit u;
- Context c;
-
- LazyTreeType(Tree tree) {
- this.tree = tree;
- this.u = unit;
- this.c = context;
- }
- public void complete(Symbol sym) {
- //System.out.println("completing " + sym);//DEBUG
- //if (sym.isConstructor()) sym.constructorClass().initialize();
- //else if (sym.isModule()) sym.moduleClass().initialize();
- 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 extends LazyTreeType {
- LazyConstrMethodType(Tree tree) {
- super(tree);
- }
- public void complete(Symbol sym) {
- Symbol constr = tree.symbol().primaryConstructor();
- if (!sym.isInitialized())
- sym.setInfo(constr.type().instanceType().cloneType(constr, sym));
- }
- }
-
- /** A lazy type for self types
- */
- class LazySelfType extends LazyTreeType {
- Symbol clazz;
- LazySelfType(Symbol clazz, Tree tree) {
- super(tree);
- this.clazz = clazz;
- }
- public void complete(Symbol sym) {
- defineSelfType(sym, clazz, tree, u, c);
- }
- }
-
-// Entering Symbols ----------------------------------------------------------
-
- Tree transformPackageId(Tree tree) {
- if (tree.type != null) return tree;
- switch (tree) {
- case Ident(Name name):
- return tree
- .setSymbol(packageSymbol(tree.pos, context.owner, name))
- .setType(tree.symbol().type());
- case Select(Tree qual, Name name):
- Tree qual1 = transformPackageId(qual);
- Symbol sym = packageSymbol(tree.pos, qual1.symbol(), name);
- return copy.Select(tree, sym, qual1).setType(sym.type());
- default:
- return transform(tree);
- }
- }
-
- Symbol packageSymbol(int pos, Symbol base, Name name) {
- Symbol p = base.members().lookup(name);
- if (p.kind == NONE) {
- p = TermSymbol.newJavaPackageModule(name, base.moduleClass(), null);
- base.members().enter(p);
- } else if (!p.isPackage()) {
- error(pos, "package and class with same name");
- p = Symbol.ERROR;
- }
- return p;
- }
-
- /** If `tree' is a definition, create a symbol for it with a lazily
- * constructed type, and enter into current scope.
- */
- Symbol enterSym(Tree tree) {
- Symbol owner = context.owner;
- switch (tree) {
- case PackageDef(Tree packaged, Tree.Template templ):
- switch (templ) {
- case Template(_, Tree[] body):
- pushContext(tree, context.owner, context.scope);
- context.imports = null;
- ((PackageDef) tree).packaged = packaged = transformPackageId(packaged);
- popContext();
- Symbol pkg = checkStable(packaged).symbol();
- if (pkg != null && pkg.kind != ERROR) {
- if (pkg.isPackage()) {
- pushContext(templ, pkg.moduleClass(), pkg.members());
- enterSyms(body);
- popContext();
- } else {
- error(tree.pos, "only Java packages allowed for now");
- }
- }
- templ.setSymbol(Symbol.NONE);
- return null;
- default:
- throw new ApplicationError();
- }
-
- case ClassDef(int mods, Name name, AbsTypeDef[] tparams, ValDef[][] vparams, _, Tree.Template templ):
- ClassSymbol clazz = ClassSymbol.define(
- tree.pos, name, owner, mods, context.scope);
- if (clazz.isLocalClass()) unit.mangler.setMangledName(clazz);
- if (!clazz.primaryConstructor().isInitialized())
- clazz.primaryConstructor().setInfo(new LazyTreeType(tree));
- if ((mods & CASE) != 0) {
- if ((mods & ABSTRACT) == 0) {
- // enter case constructor method.
- Symbol cf = TermSymbol.define(
- tree.pos, name.toTermName(), owner,
- mods & ACCESSFLAGS | CASE, context.scope);
- enterInScope(cf);
- if (!cf.isInitialized() || cf.info().symbol().isModuleClass()) {
- cf.setInfo(new LazyConstrMethodType(tree));
- }
- }
- }
- return enterSym(tree, clazz);
-
- case ModuleDef(int mods, Name name, _, _):
- TermSymbol modul = TermSymbol.define(
- tree.pos, name, owner, mods, context.scope).makeModule();
- Symbol clazz = modul.moduleClass();
- if (!clazz.isInitialized())
- clazz.setInfo(new LazyTreeType(tree));
- if (clazz.isLocalClass()) unit.mangler.setMangledName(clazz);
- return enterSym(tree, modul);
-
- case ValDef(int mods, Name name, _, _):
- return enterSym(
- tree,
- TermSymbol.define(tree.pos, name, owner, mods, context.scope));
-
- case DefDef(int mods, Name name, _, _, _, _):
- Symbol sym;
- if (name == Names.CONSTRUCTOR) {
- Symbol clazz = context.enclClass.owner;
- if (!(context.tree instanceof Template) ||
- clazz.isModuleClass() ||
- clazz.isAnonymousClass() ||
- clazz.isCompoundSym() ||
- clazz.isPackage()) {
- error(tree.pos, "constructor definition not allowed here");
- }
- sym = context.enclClass.owner.addConstructor();
- } else {
- sym = TermSymbol.define(tree.pos, name, owner, mods, context.scope);
- }
- return enterSym(tree, sym);
-
- case AliasTypeDef(int mods, Name name, _, _):
- Symbol tsym = AliasTypeSymbol.define(tree.pos, name, owner, mods, context.scope);
- if (!tsym.primaryConstructor().isInitialized())
- tsym.primaryConstructor().setInfo(new LazyTreeType(tree));
- return enterSym(tree, tsym);
-
- case AbsTypeDef(int mods, Name name, _, _):
- return enterSym(
- tree,
- AbsTypeSymbol.define(tree.pos, name, owner, mods, context.scope));
-
- case Import(Tree expr, Name[] selectors):
- return enterImport(tree,
- new TermSymbol(
- tree.pos,
- Name.fromString("import " + expr),
- Symbol.NONE, SYNTHETIC));
-
- default:
- return null;
- }
- }//where
-
- /** Enter `sym' in current scope and make it the symbol of `tree'.
- */
- private Symbol enterSym(Tree tree, Symbol sym) {
- //if (global.debug) System.out.println("entering " + sym);//DEBUG
- if (!sym.isInitialized()) {
- //System.err.println("undefined: " + sym + ":" + sym.rawInfo());//DEBUG
- sym.setInfo(new LazyTreeType(tree));
- }
- if (!sym.isConstructor()) {
- Symbol owner = sym.owner();
- if (sym.kind == VAL && (sym.flags & (PRIVATE | SEALED)) == 0 &&
- owner != null && owner.kind == CLASS &&
- (owner.flags & FINAL) != 0) {
- sym.flags |= FINAL;
- }
- sym = enterInScope(sym);
- }
- tree.setSymbol(sym);
-
- // set the comment associated with a symbol
- String comment = (String) global.mapTreeComment.get(tree);
- if (comment != null)
- global.mapSymbolComment.put(sym, new Pair(comment, unit));
-
- return sym;
- }
-
- /** Make `sym' the symbol of import `tree' and create an entry in
- * current imports list.
- */
- private Symbol enterImport(Tree tree, Symbol sym) {
- sym.setInfo(new LazyTreeType(tree));
- tree.setSymbol(sym);
- context.imports = new ImportList(tree, context.scope, context.imports);
- return sym;
- }
-
- /** Enter symbol `sym' in current scope. Check for double definitions.
- * Handle overloading.
- */
- private Symbol enterInScope(Symbol sym) {
- // handle double and overloaded definitions
- Symbol result = sym;
- Scope.Entry e = context.scope.lookupEntry(sym.name);
- Symbol other = e.sym;
- if (sym == other) {
- if (global.debug) global.log("redefined: " + sym + ":" + sym.rawInfo());
- } else if (e.owner == context.scope) {
- if (other.isExternal()) {
- assert false : sym + " " + other;
- // symbol was preloaded from package;
- // need to overwrite definition.
- if (global.debug) global.log(sym + " overwrites " + other);
- sym.copyTo(other);
- if (sym.isModule())
- sym.moduleClass().copyTo(other.moduleClass());
- result = other;
- } else if (sym.owner().isPackage()) {
- 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)) {
- // it's an overloaded definition
- /*
- if (((sym.flags ^ other.flags) & SOURCEFLAGS) != 0) {
- // todo: refine, DEFERRED, MUTABLE and OVERRIDE should be
- // treated specially; maybe only PRIVATE and PROTECTED?
- error(sym.pos,
- "illegal overloaded definition of " + sym +
- ": modifier lists differ in " +
- Modifiers.Helper.toString(
- (sym.flags ^ other.flags) & SOURCEFLAGS));
- */
- 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 (result.owner().isPackage())
- global.compiledNow.put(result, unit.source);
- return result;
- }
-
- /** Enter all symbols in statement list
- */
- public void enterSyms(Tree[] stats) {
- for (int i = 0; i < stats.length; i++)
- enterSym(stats[i]);
- }
-
- Symbol[] enterParams(Tree[] params) {
- for (int i = 0; i < params.length; i++) {
- enterSym(params[i]);
- switch (params[i]) {
- case ValDef(int mods, _, _, _):
- if ((mods & REPEATED) != 0 && i != params.length - 1)
- error(params[i].pos,
- "`*' parameter must be the last parameter of a `('...`)' section");
- }
- }
- return Tree.symbolOf(params);
- }
-
- Symbol[][] enterParams(Tree[][] vparams) {
- Symbol[][] vparamSyms = new Symbol[vparams.length][];
- for (int i = 0; i < vparams.length; i++) {
- vparamSyms[i] = enterParams(vparams[i]);
- }
- return vparamSyms;
- }
-
- /** Re-enter type parameters in current scope.
- */
- void reenterParams(AbsTypeDef[] tparams, Symbol[] tsyms) {
- for (int i = 0; i < tparams.length; i++) {
- 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]);
- }
- }
-
- /** Re-enter type and value parameters in current scope.
- */
- void reenterParams(AbsTypeDef[] tparams, ValDef[][] vparamss, Type mt) {
- Type rest = mt;
- switch (rest) {
- case PolyType(Symbol[] tsyms, Type restp):
- reenterParams(tparams, tsyms);
- rest = restp;
- }
- for (int j = 0; j < vparamss.length; j++) {
- ValDef[] vparams = vparamss[j];
- switch (rest) {
- case MethodType(Symbol[] vsyms, Type restp):
- for (int i = 0; i < vparams.length; i++) {
- vsyms[i].pos = vparams[i].pos;
- vsyms[i].name = vparams[i].name;
- //necessary since vsyms might have been unpickled
- vparams[i].setSymbol(vsyms[i]);
- context.scope.enter(vsyms[i]);
- }
- rest = restp;
- }
- }
- }
-
-// Definining Symbols -------------------------------------------------------
-
- /** Define symbol associated with `tree' using given `unit' and `context'.
- */
- void defineSym(Tree tree, Unit unit, Context curcontext) {
- Unit savedUnit = this.unit;
- this.unit = unit;
- Context savedContext = this.context;
- this.context = curcontext;
- int savedMode = this.mode;
- this.mode = EXPRmode;
- Type savedPt = this.pt;
- this.pt = Type.AnyType;
-
- try {
- Symbol sym = tree.symbol();
- if (global.debug) global.log("defining " + sym);
- Type owntype;
- switch (tree) {
- case ClassDef(int mods, Name name, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
- pushContext(
- tree, sym.primaryConstructor(), new Scope(context.scope));
- Symbol[] tparamSyms = enterParams(tparams);
- Symbol[][] vparamSyms = enterParams(vparams);
- if (vparamSyms.length == 0)
- vparamSyms = new Symbol[][]{Symbol.EMPTY_ARRAY};
-
- if ((mods & CASE) != 0 && vparams.length > 0)
- templ.body = desugarize.addCaseElements(templ.body, vparams[0]);
-
- Type constrtype = makeMethodType(
- tparamSyms,
- vparamSyms,
- Type.typeRef(sym.owner().thisType(), sym, Symbol.type(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 |= INITIALIZED;
-
- if (tpe != Tree.Empty)
- sym.setTypeOfThis(new LazySelfType(sym, tpe));
-
- defineTemplate(templ, sym, new Scope());
- owntype = templ.type;
- popContext();
- break;
-
- case ModuleDef(int mods, Name name, Tree tpe, Tree.Template templ):
- Symbol clazz = sym.moduleClass();
- defineTemplate(templ, clazz, new Scope());
- clazz.setInfo(templ.type);
- ((ModuleDef) tree).tpe = tpe = transform(tpe, TYPEmode);
- if (tpe != Tree.Empty)
- clazz.setTypeOfThis(new LazySelfType(sym, tpe));
- owntype = (tpe == Tree.Empty) ? clazz.type() : tpe.type;
- break;
-
- case DefDef(int mods, Name name, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
- Symbol[] tparamSyms;
- Symbol[][] vparamSyms;
- Type restype;
- pushContext(tree, sym, new Scope(context.scope));
- if (name == Names.CONSTRUCTOR)
- context.enclClass.owner.flags |= INCONSTRUCTOR;
- tparamSyms = enterParams(tparams);
- vparamSyms = enterParams(vparams);
- if (tpe != Tree.Empty) {
- ((DefDef) tree).tpe = tpe = transform(tpe, TYPEmode);
- restype = tpe.type;
- } else if (name == Names.CONSTRUCTOR) {
- restype = context.enclClass.owner.type().subst(
- context.enclClass.owner.typeParams(), tparamSyms);
- context.enclClass.owner.flags &= ~INCONSTRUCTOR;
- } else {
- ((DefDef) tree).rhs = rhs = transform(rhs, EXPRmode);
- restype = rhs.type;
- if (!sym.isFinal()) restype = restype.deconst();
- // !!! restype = rhs.type.widen(); // !!!
- }
- restype = checkNoEscape(tpe.pos, restype);
- popContext();
- owntype = makeMethodType(tparamSyms, vparamSyms, restype);
- //System.out.println("methtype " + name + ":" + owntype);//DEBUG
- break;
-
- case ValDef(int mods, Name name, Tree tpe, Tree rhs):
- if (tpe != Tree.Empty) {
- ((ValDef) tree).tpe = tpe = transform(tpe, TYPEmode);
- owntype = tpe.type;
- } else {
- 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().type();
- } else {
- error(tree.pos, "missing parameter type");
- owntype = Type.ErrorType;
- }
- } else {
- if ((sym.flags & CASEACCESSOR) != 0) {
- rhs.type = rhs.symbol().type();
- } else {
- ((ValDef) tree).rhs = rhs = transform(rhs, EXPRmode);
- }
- owntype = rhs.type;
- if (sym.isVariable() || !sym.isFinal())
- owntype = owntype.deconst();
- // !!! owntype = rhs.type.widen(); // !!!
- }
- popContext();
- }
- break;
-
- case AliasTypeDef(int mods, Name name, AbsTypeDef[] tparams, Tree rhs):
- pushContext(tree, sym.primaryConstructor(), new Scope(context.scope));
- Symbol[] tparamSyms = enterParams(tparams);
- ((AliasTypeDef) tree).rhs = rhs = transform(rhs, TYPEmode);
- owntype = rhs.type;
- sym.primaryConstructor().setInfo(
- Type.PolyType(tparamSyms, owntype));
- popContext();
- break;
-
- case AbsTypeDef(int mods, Name name, Tree rhs, Tree lobound):
- //can't have `sym' as owner since checkNonCyclic would fail.
- ((AbsTypeDef) tree).rhs = rhs = transform(rhs, TYPEmode);
- ((AbsTypeDef) tree).lobound = lobound = transform(lobound, TYPEmode);
- owntype = rhs.type;
- sym.setLoBound(lobound.type);
- owntype.symbol().initialize();//to detect cycles todo: needed?
- break;
-
- case Import(Tree expr, Name[] selectors):
- ((Import) tree).expr = expr = transform(expr, EXPRmode | QUALmode);
- checkStable(expr);
- owntype = expr.type;
- Type tp = owntype.widen();
- for (int i = 0; i < selectors.length; i = i + 2) {
- 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 + " of type " + expr.type);
- }
- break;
-
- default:
- throw new ApplicationError();
- }
- sym.setInfo(owntype);
- validate(sym);
- if (global.debug) global.log("defined " + sym);
- } catch (Type.Error ex) {
- reportTypeError(tree.pos, ex);
- tree.type = Type.ErrorType;
- if (tree.hasSymbol()) {
- if (tree.symbol() != null) tree.symbol().setInfo(Type.ErrorType);
- else tree.setSymbol(Symbol.ERROR);
- }
- }
-
- 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.
- */
- void defineTemplate(Tree.Template templ, Symbol clazz, Scope members) {
- // attribute parent constructors
- Tree[] constrs = transformConstrInvocations(templ.pos, templ.parents);
- Type[] parents = Tree.typeOf(constrs);
-
- // enter all members
- pushContext(templ, clazz, members);
- templ.body = desugarize.Statements(templ.body, false);
- enterSyms(templ.body);
- popContext();
- templ.type = Type.compoundType(parents, members, clazz);
- }
-
- Type makeMethodType(Symbol[] tparams, Symbol[][] vparams, Type restpe) {
- if (tparams.length == 0 && vparams.length == 0) {
- return Type.PolyType(tparams, restpe);
- } else {
- Type result = restpe;
- for (int i = vparams.length - 1; i >= 0; i--)
- result = Type.MethodType(vparams[i], result);
- if (tparams.length != 0)
- result = Type.PolyType(tparams, result);
- return result;
- }
- }
-
- /** Define self type of class or module `sym'
- * associated with `tree' using given `unit' and `context'.
- */
- void defineSelfType(Symbol sym, Symbol clazz, Tree tree, Unit unit, Context curcontext) {
- Unit savedUnit = this.unit;
- this.unit = unit;
- Context savedContext = this.context;
- this.context = curcontext;
-
- Type selftype = transform(tree, TYPEmode).type;
- switch (selftype) {
- case CompoundType(Type[] parts, Scope members):
- Type[] parts1 = new Type[parts.length + 1];
- System.arraycopy(parts, 0, parts1, 0, parts.length);
- parts1[parts.length] = clazz.type();
- sym.setInfo(Type.compoundTypeWithOwner(clazz.owner().enclClass(), parts1, members));
- break;
- default:
- sym.setInfo(
- Type.compoundTypeWithOwner(
- clazz.owner().enclClass(), new Type[]{selftype, clazz.type()}, Scope.EMPTY));
- }
-
- this.unit = savedUnit;
- this.context= savedContext;
- }
-
-// Attribution and Transform -------------------------------------------------
-
- /** Turn tree type into stable type if possible and required by
- * context.
- */
- Tree mkStable(Tree tree, Type pre, int mode, Type pt) {
- switch (tree.type) {
- case ConstantType(_, AConstant value):
- return gen.Literal(tree.pos, value);
- case PolyType(Symbol[] tparams, Type restp):
- if (tparams.length == 0) {
- switch (restp) {
- case ConstantType(_, AConstant value):
- return gen.Literal(tree.pos, value);
- }
- }
- }
- if ((pt != null && pt.isStable() || (mode & QUALmode) != 0) &&
- pre.isStable()) {
- Symbol sym = tree.symbol();
- switch (tree.type) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- if ((mode & FUNmode) == 0) {
- try {
- infer.exprAlternative(tree, alts, alttypes, pt);
- sym = tree.symbol();
- } catch (Type.Error ex) {
- reportTypeError(tree.pos, ex);
- }
- }
- }
- if (sym.isStable()) {
- tree.setType(Type.singleType(pre, sym));
- }
- }
- return tree;
- }
-
- /** Adapt tree to given mode and given prototype
- */
- Tree adapt(Tree tree, int mode, Type pt) {
- //System.out.println(tree + ":" + tree.type + " adapt " + pt + " " + mode);//DEBUG
- switch (tree.type) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- // resolve overloading
- if ((mode & FUNmode) == 0) {
- try {
- infer.exprAlternative(tree, alts, alttypes, pt);
- } catch (Type.Error ex) {
- reportTypeError(tree.pos, ex);
- }
- switch (tree.type) {
- case OverloadedType(_, _):
- // overload resolution failed bcs no alternative matched prototype.
- typeError(tree.pos, tree.type, pt);
- tree.setSymbol(Symbol.ERROR).setType(Type.ErrorType);
- break;
- default:
- return adapt(tree, mode, pt);
- }
- }
- break;
-
- case PolyType(Symbol[] tparams, Type restp):
- // apply parameterless functions
- // instantiate polymorphic expressions
- if (tparams.length == 0) {
- return adapt(tree.setType(restp), mode, pt);
- } else if ((mode & (FUNmode | POLYmode)) == 0) {
- try {
- tree = infer.exprInstance(tree, tparams, restp, pt);
- } catch (Type.Error ex) {
- Context c = context;
- while (c != Context.NONE) {
- System.out.println("context: " + c.owner);
- c = c.outer;
- }
- tree = error(tree.pos, ex.msg);
- }
- return adapt(tree, mode, pt);
- }
- break;
-
- case MethodType(_, _):
- // convert unapplied methods to functions.
- if ((mode & (EXPRmode | FUNmode)) == EXPRmode &&
- infer.isCompatible(tree.type, pt)) {
- checkEtaExpandable(tree.pos, tree.type);
- return transform(desugarize.etaExpand(tree, tree.type), mode, pt);
- } else if ((mode & (CONSTRmode | FUNmode)) == CONSTRmode) {
- return error(tree.pos, "missing arguments for class constructor");
- }
- }
- if ((mode & PATTERNmode) != 0) {
- if (tree.isType()) {
- Symbol clazz = tree.type.withDefaultArgs().unalias().symbol();
-
- if (clazz.isCaseClass()) {
- // set type to instantiated case class constructor
- tree.type = tree.type.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)) {
- Symbol[] altconstr = clazz.allConstructors().alternativeSymbols();
- tree.type = tree.type.prefix().memberType(
- altconstr[altconstr.length - 1]);
- }
- switch (tree.type) {
- case PolyType(Symbol[] tparams, Type restp):
- try {
- infer.constructorInstance(tree, tparams, restp, pt);
- //System.out.println("constr inst " + ArrayApply.toString(tparams) + restp + " against " + pt + " = " + tree.type);//DEBUG
- } catch (Type.Error ex) {
- if (pt != Type.ErrorType) error(tree.pos, ex.msg);
- return tree.setType(Type.ErrorType);
- }
-/*
- if (!(tree.type instanceof Type.MethodType))
- tree = make.Apply(tree.pos, tree, Tree.EMPTY_ARRAY)
- .setType(tree.type);
-*/
- }
- } else if (clazz.isSubClass(definitions.SEQ_CLASS)) {
- // set type to instantiated sequence class constructor
- // todo: should we admit even supertypes of the target type?
- Type seqtp = pt.baseType(clazz);
- if (seqtp != Type.NoType) {
- tree.type = seqConstructorType(seqtp, pt);
- } else {
- return error(tree.pos, "expected pattern type " + pt +
- " does not conform to sequence " + clazz);
- }
- } else if (tree.type != Type.ErrorType) {
- return error(tree.pos, tree.type.symbol() +
- " is neither a case class constructor nor a sequence class constructor");
- }
- }
- if ((mode & FUNmode) != 0) {
- return tree;
- } else {
- Symbol sym = tree.symbol();
- // check that idents or selects are stable.
- switch (tree) {
- case Ident(_):
- case Select(_, _):
- checkStable(tree);
- }
- }
- } else if ((mode & EXPRmode) != 0) {
- if ((mode & FUNmode) != 0) {
- if (tree.type.isObjectType()) {
- // insert apply method
- Symbol applyMeth = tree.type.lookup(Names.apply);
- if (applyMeth != Symbol.NONE) {
- Type applyType = checkAccessible(
- tree.pos, applyMeth, tree.type.memberType(applyMeth),
- tree);
- tree = make.Select(tree.pos, tree, Names.apply)
- .setSymbol(applyMeth)
- .setType(applyType);
- return adapt(tree, mode, pt);
- }
- }
- } else if ((mode & QUALmode) == 0) {
- // check that packages and static modules are not used as values
- switch (tree) {
- case Ident(_):
- case Select(_, _):
- Symbol sym = tree.symbol();
- if (sym != null && sym.kind != ERROR && !sym.isValue()) {
- error(tree.pos, tree.symbol() + " is not a value");
- }
- }
- }
- }
-
- Type owntype = tree.type;
- if ((mode & (CONSTRmode | FUNmode)) == (CONSTRmode)) {
- owntype = owntype.instanceType();
- // this works as for superclass constructor calls the expected
- // type `pt' is always AnyType (see transformConstrInvocations).
- }
- if (!(owntype instanceof Type.PolyType || owntype.isSubType(pt))) {
- switch (tree) {
- case Literal(AConstant constant):
- int n = Integer.MAX_VALUE;
- switch (constant) {
- case INT(int value): n = value; break;
- case CHAR(char value): n = value; break;
- }
- AConstant value1 = null;
- if (pt.symbol() == definitions.BYTE_CLASS &&
- -128 <= n && n <= 127)
- value1 = AConstant.BYTE((byte) n);
- else if (pt.symbol() == definitions.SHORT_CLASS &&
- -32768 <= n && n <= 32767)
- value1 = AConstant.SHORT((short) n);
- else if (pt.symbol() == definitions.CHAR_CLASS &&
- 0 <= n && n <= 65535)
- value1 = AConstant.CHAR((char) n);
- if (value1 != null)
- return gen.Literal(tree.pos, value1);
- break;
- }
- if ((mode & EXPRmode) != 0) {
- if (pt.symbol() == definitions.UNIT_CLASS) {
- return gen.mkUnitBlock(tree);
- } else {
- Symbol coerceMeth = tree.type.lookup(Names.coerce);
- if (coerceMeth != Symbol.NONE) {
- Type coerceType = checkAccessible(
- tree.pos, coerceMeth, tree.type.memberType(coerceMeth),
- tree);
- tree = make.Select(tree.pos, tree, Names.coerce)
- .setSymbol(coerceMeth)
- .setType(coerceType);
- return adapt(tree, mode, pt);
- }
- }
- }
- if ((mode & CONSTRmode) == 0) {
- typeError(tree.pos, owntype, pt);
- Type.explainTypes(owntype, pt);
- tree.type = Type.ErrorType;
- } // for constructors, delay until after the `new'.
- }
- return tree;
- }
- //where
- Type seqConstructorType(Type paramtp, Type resulttp) {
- Symbol constr = resulttp.symbol().primaryConstructor();
- Symbol param = new TermSymbol(
- Position.NOPOS, Names.PATTERN_WILDCARD, constr, PARAM | REPEATED).setInfo(
- paramtp.baseType(definitions.SEQ_CLASS));
- return Type.MethodType(new Symbol[]{param}, resulttp);
- }
-
- /** 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.
- */
- Tree transformIdent(Tree tree, Name name) {
- //System.out.println("transforming " + name);//DEBUG
- // find applicable definition and assign to `sym'
- Symbol sym = Symbol.NONE;
- Type pre;
- Tree qual = Tree.Empty;
-
- int stopPos = Integer.MIN_VALUE;
- Context nextcontext = 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.thisSym().info().lookup(name);
- if (sym.kind != NONE) {
- stopPos = nextcontext.owner.pos;
- } else {
- nextcontext = nextcontext.outer;
- }
- }
- }
- }
-
- // find applicable import and assign to `sym1'
- ImportList nextimports = context.imports;
- ImportList lastimports = null;
- Symbol sym1 = Symbol.NONE;
-
-// System.out.println("name = " + name + ", pos = " + tree.pos + ", importlist = ");//DEBUG
-// for (ImportList imp = nextimports; imp != null; imp = imp.prev) {
-// new TextTreePrinter().print(" ").print(imp.tree).println().end();//DEBUG
-// }
-
- while (nextimports != null && nextimports.tree.pos >= tree.pos) {
- nextimports = nextimports.prev;
- }
- while (sym1.kind == NONE &&
- nextimports != null && nextimports.tree.pos > stopPos) {
- sym1 = nextimports.importedSymbol(name);
- lastimports = nextimports;
- nextimports = nextimports.prev;
- }
-
- // 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 tree.setSymbol(Symbol.ERROR).setType(Type.ErrorType);
- } else {
- if (sym.owner().kind == CLASS) {
- pre = nextcontext.enclClass.owner.thisType();
- if (!sym.owner().isPackage()) {
- Tree qual1 = 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.localThisType;
- }
- }
- } else if (sym.kind != NONE && !sym.isExternal()) {
- return error(tree.pos,
- "reference to " + name + " is ambiguous;\n" +
- "it is both defined in " + sym.owner() +
- " and imported subsequently by \n" + nextimports.tree);
- } else {
- // check that there are no other applicable imports in same scope.
- while (nextimports != null &&
- nextimports.enclscope == lastimports.enclscope) {
- if (!nextimports.sameImport(lastimports) &&
- nextimports.importedSymbol(name).kind != NONE) {
- return error(tree.pos,
- "reference to " + name + " is ambiguous;\n" +
- "it is imported twice in the same scope by\n " +
- lastimports.tree + "\nand " + nextimports.tree);
- }
- nextimports = nextimports.prev;
- }
- sym = sym1;
- qual = lastimports.importPrefix().duplicate();
- pre = qual.type;
- //new TextTreePrinter().print(name + " => ").print(lastimports.tree).print("." + name).println().end();//DEBUG
- tree = make.Select(tree.pos, qual, name);
- }
- Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type())
- .asSeenFrom(pre, sym.owner());
- if (qual != Tree.Empty)
- symtype = checkAccessible(tree.pos, sym, symtype, qual);
- if (symtype == Type.NoType)
- return error(tree.pos, "not found: " + decode(name));
- //System.out.println(name + ":" + symtype);//DEBUG
- return mkStable(tree.setSymbol(sym).setType(symtype), pre, mode, pt);
- }
-
- /** Attribute a selection where `tree' is `qual.name'.
- * `qual' is already attributed.
- */
- Tree transformSelect(Tree tree, Tree qual, Name name) {
- Symbol[] uninst = Symbol.EMPTY_ARRAY;
- switch (qual.type) {
- case PolyType(Symbol[] tparams, Type restype):
- qual = infer.mkTypeApply(qual, tparams, restype, Symbol.type(tparams));
- uninst = tparams;
- }
- Symbol sym = qual.type.lookup(name);
- if (sym.kind == NONE) {
- //System.out.println(qual.type + " has members " + qual.type.members());//DEBUG
-
- return error(tree.pos,
- decode(name) + " is not a member of " + qual.type.widen());
- } else {
- Type symtype = (sym.isType() ? sym.typeConstructor() : sym.type())
- .asSeenFrom(qual.type, sym.owner());
- if (symtype == Type.NoType)
- return error(tree.pos, "not found: " + decode(name));
- else
- symtype = checkAccessible(tree.pos, sym, symtype, qual);
- //System.out.println(sym.name + ":" + symtype);//DEBUG
- if (uninst.length != 0) {
- switch (symtype) {
- case PolyType(Symbol[] tparams, Type restype):
- symtype = Type.PolyType(
- tparams, Type.PolyType(uninst, restype));
- break;
- default:
- symtype = Type.PolyType(uninst, symtype);
- }
- }
- //System.out.println(qual.type + ".member: " + sym + ":" + symtype);//DEBUG
- Tree tree1;
- switch (tree) {
- case Select(_, _):
- tree1 = copy.Select(tree, sym, qual);
- break;
- case SelectFromType(_, _):
- tree1 = copy.SelectFromType(tree, sym, qual);
- break;
- default:
- throw new ApplicationError();
- }
- return mkStable(tree1.setType(symtype), qual.type, 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.
- */
- Tree transformVisitor(Tree tree, Type pattpe, Type pt) {
- //System.out.println("trans visitor with " + pattpe + "," + pt);//DEBUG
- switch (tree) {
- case Visitor(Tree.CaseDef[] cases):
- Tree.CaseDef[] cases1 = cases;
- for (int i = 0; i < cases.length; i++)
- cases1[i] = transformCase(cases[i], pattpe, pt);
-
- return copy.Visitor(tree, cases1)
- .setType(Type.lub(Tree.typeOf(cases1)));
- default:
- throw new ApplicationError();
- }
- }
-
- /** Attribute a case where `pattpe' is the expected type of the pattern
- * and `pt' is the expected type of the result.
- */
- Tree.CaseDef transformCase(Tree.CaseDef tree, Type pattpe, Type pt) {
- switch (tree) {
- case CaseDef(Tree pat, Tree guard, Tree body):
- pushContext(tree, context.owner, new Scope(context.scope));
- this.inAlternative = false; // no vars allowed below Alternative
- Tree pat1 = transform(pat, PATTERNmode, pattpe);
- Tree guard1 = (guard == Tree.Empty) ? Tree.Empty
- : transform(guard, EXPRmode, definitions.BOOLEAN_TYPE());
- Tree body1 = transform(body, EXPRmode, pt);
- popContext();
- return (Tree.CaseDef) copy.CaseDef(tree, pat1, guard1, body1)
- .setType(body1.type);
- default:
- throw new ApplicationError();
- }
- }
-
- Tree[] transformStatSeq(Tree[] stats, Symbol exprOwner) {
- Tree[] stats1 = stats;
- for (int i = 0; i < stats.length; i++) {
- Tree stat = stats[i];
- if (context.owner.isCompoundSym() && !TreeInfo.isDeclaration(stat)) {
- error(stat.pos, "only declarations allowed here");
- }
- Tree stat1;
- int mode = TreeInfo.isDefinition(stat) ? NOmode : EXPRmode;
- if (exprOwner.kind != NONE && !TreeInfo.isDefinition(stat)) {
- pushContext(stat, exprOwner, context.scope);
- stat1 = transform(stat, mode);
- popContext();
- } 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 Tree[stats.length];
- System.arraycopy(stats, 0, stats1, 0, i);
- }
- stats1[i] = stat1;
- }
- return stats1;
- }
-
- /** Attribute a sequence of constructor invocations.
- */
- Tree[] transformConstrInvocations(int pos, Tree[] constrs) {
- for (int i = 0; i < constrs.length; i++) {
- constrs[i] = transform(constrs[i], CONSTRmode | SUPERmode, Type.AnyType);
- Symbol f = TreeInfo.methSymbol(constrs[i]);
- if (f != null) {
- Symbol c = f.constructorClass();
- if (c.kind == CLASS) {
- c.initialize();//to detect cycles
- if (i > 0 && (c.flags & JAVA) == 0 && c.isExternal()) {
- // need to load tree for mixins
- new SourceCompleter(global, true).complete(c);
- }
- }
- }
- }
- return constrs;
- }
-
- void transformConstrInvocationArgs(Tree[] constrs) {
- for (int i = 0; i < constrs.length; i++) {
- switch (constrs[i]) {
- case Apply(Tree fn, Tree[] args):
- if (fn.type instanceof Type.MethodType)
- transformArgs(
- constrs[i].pos, TreeInfo.methSymbol(fn), Symbol.EMPTY_ARRAY,
- fn.type, EXPRmode, args, Type.AnyType);
- }
- }
- }
-
- /** Attribute a template
- */
- public Tree.Template transformTemplate(Tree.Template templ, Symbol owner) {
- if (global.debug) global.log("transforming template of " + owner);//debug
- if (templ.type == null)
- defineTemplate(templ, owner, owner.members());//may happen for mixins
- //System.out.println(owner.info());//DEBUG
- Tree[] parents = templ.parents;
- transformConstrInvocationArgs(parents);
- if (owner.kind != ERROR) {
- validateParentClasses(parents, owner.info().parents(), owner.typeOfThis());
- }
- pushContext(templ, owner, owner.members());
- templ.setSymbol(TermSymbol.newLocalDummy(owner));
- Tree[] body1 = transformStatSeq(templ.body, templ.symbol());
- popContext();
- if (owner.isTrait()) {
- for (int i = 0; i < parents.length; i++) {
- checkPureConstr(parents[i], owner);
- if (i >= 1) checkTrait(parents[i], owner);
- }
- for (int i = 0; i < templ.body.length; i++)
- checkPureDef(body1[i], owner);
- }
- Tree.Template templ1 = copy.Template(templ, parents, body1);
- templ1.setType(owner.type());
- return 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.
- */
- Type[] transformArgs(int pos, Symbol meth, Symbol[] tparams, Type methtype,
- int argMode, Tree[] args, Type pt) {
- //System.out.println("trans args " + meth + ArrayApply.toString(tparams) + ":" + methtype + "," + pt);//DEBUG
- Type[] argtypes = new Type[args.length];
- switch (methtype) {
- case MethodType(Symbol[] params, Type restp):
- Type[] formals = infer.formalTypes(params, args.length);
- if (formals.length != args.length) {
- error(pos, "wrong number of arguments for " +
- (meth == null ? "<function>" : meth) +
- ArrayApply.toString(formals, "(", ",", ")"));
- return null;
- }
- if (tparams.length == 0) {
- for (int i = 0; i < args.length; i++) {
- args[i] = transform(args[i], argMode, formals[i]);
- argtypes[i] = args[i].type.deconst();
- }
- } else {
- // targs: the type arguments inferred from the prototype
- Type[] targs = infer.protoTypeArgs(tparams, restp, pt, params);
-
- // argpts: prototypes for arguments
- Type[] argpts = new Type[formals.length];
- for (int i = 0; i < formals.length; i++)
- argpts[i] = formals[i].subst(tparams, targs);
-
- // transform arguments with [targs/tparams]formals as prototypes
- for (int i = 0; i < args.length; i++)
- args[i] = transform(
- args[i], argMode | POLYmode, formals[i].subst(tparams, targs));
-
- // targs1: same as targs except that every AnyType is mapped to
- // formal parameter type.
- Type[] targs1 = new Type[targs.length];
- for (int i = 0; i < targs.length; i++)
- targs1[i] = (targs[i] != Type.AnyType) ? targs[i]
- : tparams[i].type();
-
- for (int i = 0; i < args.length; i++) {
- argtypes[i] = args[i].type.deconst();
- switch (argtypes[i]) {
- case PolyType(Symbol[] tparams1, Type restype1):
- argtypes[i] = infer.argumentTypeInstance(
- tparams1, restype1,
- formals[i].subst(tparams, targs1),
- argpts[i]);
- }
- }
- }
- // desugarizing ident patterns
- if (params.length > 0 &&
- (params[params.length - 1].flags & REPEATED) != 0) {
- if (( mode & PATTERNmode ) != 0 ) {
- desug_allIdentPatterns( args, context.owner );
- } else {
- assert (args.length != params.length ||
- !(args[params.length-1] instanceof Tree.Sequence));
- }
- }
- return argtypes;
-
- case PolyType(Symbol[] tparams1, Type restp):
- Symbol[] tparams2;
- if (tparams.length == 0) tparams2 = tparams1;
- else {
- tparams2 = new Symbol[tparams.length + tparams1.length];
- System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
- System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
- }
- return transformArgs(pos, meth, tparams2, restp, argMode, args, pt);
-
- case Type.ErrorType:
- for (int i = 0; i < args.length; i++) {
- args[i] = transform(args[i], argMode, Type.ErrorType);
- argtypes[i] = args[i].type.deconst();
- }
- return argtypes;
-
- default:
- for (int i = 0; i < args.length; i++) {
- args[i] = transform(args[i], argMode, Type.AnyType);
- argtypes[i] = args[i].type.deconst();
- }
- return 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.
- */
- Tree transform(Tree tree, int mode, Type pt) {
- int savedMode = this.mode;
- Type savedPt = this.pt;
- this.mode = mode;
- this.pt = pt;
- Tree tree1 = adapt(transform(tree), mode, pt);
-
- assert tree.type != Type.AnyType : tree;//debug
-
- //new TextTreePrinter().print(tree1).print(": " + tree1.type).println().end();//DEBUG
-
- this.mode = savedMode;
- this.pt = savedPt;
- return tree1;
- }
-
- /** Transform expression or type with a given mode.
- */
- public Tree transform(Tree tree, int mode) {
- if ((mode & (EXPRmode | PATTERNmode | CONSTRmode)) != 0)
- return transform(tree, mode, Type.AnyType);
-
- int savedMode = this.mode;
- this.mode = mode;
- Tree tree1 = transform(tree);
- this.mode = savedMode;
-
- if ((mode & TYPEmode) != 0) {
- Symbol sym = tree1.symbol();
- if ((mode & FUNmode) == 0 &&
- sym != null && sym.typeParams().length != 0)
- return error(tree.pos, sym + " takes type parameters.");
-// else if (tree1.isType())
-// return gen.mkType(tree1.pos, tree1.type);
- }
- return tree1;
- }
-
- Tree[] transform(Tree[] trees, int mode) {
- for (int i = 0; i < trees.length; i++)
- trees[i] = transform(trees[i], mode);
- return trees;
- }
-
- /** The main attribution function
- */
- public Tree transform(Tree tree) {
- //System.out.println("transforming " + tree);//DEBUG
- if (tree.type != null) {
- checkDefined.all = tree; checkDefined.traverse(tree);//debug
- return tree;
- }
- Symbol sym = tree.symbol();
- if (sym != null && !sym.isInitialized()) sym.initialize();
- if (global.debug && TreeInfo.isDefinition(tree)) global.log("transforming definition of " + sym);
- try {
- switch (tree) {
-
- case Bad():
- return tree.setSymbol(Symbol.ERROR).setType(Type.ErrorType);
-
- case Empty:
- tree.type = Type.NoType;
- return tree;
-
- case PackageDef(Tree pkg, Tree.Template templ):
- switch (templ) {
- case Template(Tree[] parents, Tree[] body):
- Symbol pkgSym = pkg.symbol();
- if (pkgSym != null && pkgSym.isPackage()) {
- pushContext(templ, pkgSym, pkgSym.members());
- Tree[] body1 = transform(body);
- popContext();
- Tree.Template templ1 = copy.Template(templ, parents, body1);
- templ1.setType(Type.NoType).setSymbol(Symbol.NONE);
- return copy.PackageDef(tree, pkg, templ1)
- .setType(Type.NoType);
- }
- }
- return tree.setType(Type.ErrorType);
-
- case ClassDef(_, _, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree.Template templ):
- pushContext(
- tree, sym.primaryConstructor(), new Scope(context.scope));
- reenterParams(tparams, vparams, sym.primaryConstructor().type());
- Tree.AbsTypeDef[] tparams1 = transform(tparams);
- Tree.ValDef[][] vparams1 = transform(vparams);
- checkNoEscapeParams(vparams1);
- Tree tpe1 = transform(tpe, TYPEmode);
- if ((sym.flags & CASE) != 0 && vparams.length > 0 && templ.type == null)
- templ.body = desugarize.addCaseElements(templ.body, vparams[0]);
-
- Tree.Template templ1 = transformTemplate(templ, sym);
- checkNoEscape(tree.pos, sym.info());
- popContext();
- return copy.ClassDef(tree, sym, tparams1, vparams1, tpe1, templ1)
- .setType(Type.NoType);
-
- case ModuleDef(_, _, Tree tpe, Tree.Template templ):
- sym.moduleClass().initialize();
- Tree tpe1 = transform(tpe, TYPEmode);
- Tree.Template templ1 = transformTemplate(templ, sym.moduleClass());
- if (tpe1 != Tree.Empty && !templ1.type.isSubType(tpe1.type))
- error(tree.pos,
- sym + " does not implement " + tpe1.type);
- return copy.ModuleDef(tree, sym, tpe1, templ1)
- .setType(Type.NoType);
-
- case DefDef(_, Name name, Tree.AbsTypeDef[] tparams, Tree.ValDef[][] vparams, Tree tpe, Tree rhs):
- pushContext(tree, sym, new Scope(context.scope));
- reenterParams(tparams, vparams, sym.type());
- if (name == Names.CONSTRUCTOR)
- context.enclClass.owner.flags |= INCONSTRUCTOR;
- Tree.AbsTypeDef[] tparams1 = transform(tparams);
- Tree.ValDef[][] vparams1 = transform(vparams);
- checkNoEscapeParams(vparams1);
- Tree tpe1 = (tpe == Tree.Empty)
- ? gen.mkType(tree.pos, sym.type().resultType())
- : transform(tpe, TYPEmode);
- Tree rhs1 = rhs;
- if (rhs1 != Tree.Empty) {
- rhs1 = transform(
- rhs,
- (name == Names.CONSTRUCTOR) ? CONSTRmode : EXPRmode,
- (name == Names.CONSTRUCTOR) ? definitions.UNIT_TYPE() : tpe1.type);
- }
- popContext();
- context.enclClass.owner.flags &= ~INCONSTRUCTOR;
- sym.flags |= LOCKED;
- checkNonCyclic(tree.pos, tpe1.type);
- sym.flags &= ~LOCKED;
- return copy.DefDef(tree, sym, tparams1, vparams1, tpe1, rhs1)
- .setType(Type.NoType);
-
- case ValDef(_, _, Tree tpe, Tree rhs):
- Tree tpe1 = (tpe == Tree.Empty)
- ? gen.mkType(tree.pos, sym.type())
- : transform(tpe, TYPEmode);
- Tree rhs1 = rhs;
- if (rhs != Tree.Empty) {
- pushContext(tree, sym, context.scope);
- rhs1 = transform(rhs, EXPRmode, tpe1.type);
- popContext();
- } else if ((sym.flags & (MUTABLE | DEFERRED)) == MUTABLE) {
- rhs1 = gen.mkDefaultValue(tree.pos, sym.type());
- }
- sym.flags |= LOCKED;
- checkNonCyclic(tree.pos, tpe1.type);
- sym.flags &= ~LOCKED;
- return copy.ValDef(tree, sym, tpe1, rhs1)
- .setType(Type.NoType);
-
- case AbsTypeDef(_, _, Tree rhs, Tree lobound):
- Tree rhs1 = transform(rhs, TYPEmode);
- Tree lobound1 = transform(lobound, TYPEmode);
- checkNonCyclic(tree.pos, sym.type());
- return copy.AbsTypeDef(tree, sym, rhs1, lobound1)
- .setType(Type.NoType);
-
- case AliasTypeDef(_, _, AbsTypeDef[] tparams, Tree rhs):
- pushContext(tree, sym.primaryConstructor(), new Scope(context.scope));
- reenterParams(tparams, sym.typeParams());
- AbsTypeDef[] tparams1 = transform(tparams);
- Tree rhs1 = transform(rhs, TYPEmode);
- popContext();
- checkNonCyclic(tree.pos, sym.type());
- return copy.AliasTypeDef(tree, sym, tparams1, rhs1)
- .setType(Type.NoType);
-
- case Import(Tree expr, Name[] selectors):
- context.imports = new ImportList(tree, context.scope, context.imports);
- return Tree.Empty;
-
- case Block(Tree[] stats, Tree value):
- pushContext(tree, context.owner, new Scope(context.scope));
- Tree[] stats1 = desugarize.Statements(stats, true);
- enterSyms(stats1);
- context.imports = context.outer.imports;
- int curmode = mode;
- int start = 0;
- int valuemode = curmode;
- if ((curmode & CONSTRmode) != 0) {
- stats1[0] = transform(stats1[0], curmode, pt);
- context.enclClass.owner.flags &= ~INCONSTRUCTOR;
- start = 1;
- valuemode = (curmode & ~CONSTRmode) | EXPRmode;
- }
- for (int i = start; i < stats1.length; i++)
- stats1[i] = transform(stats1[i], EXPRmode);
- Tree value1 = transform(value, valuemode & ~FUNmode, pt);
- Type owntype = checkNoEscape(tree.pos, value1.type);
- popContext();
- return copy.Block(tree, stats1, value1)
- .setType(owntype);
-
- case Sequence( Tree[] trees ):
- for( int i = 0; i < trees.length; i++ ) {
- trees[ i ] = transform( trees[ i ],
- this.mode | SEQUENCEmode,
- pt);
- }
- return copy.Sequence( tree, trees ).setType( pt );
-
- case Alternative(Tree[] choices):
- boolean save = this.inAlternative;
- this.inAlternative = true;
-
- Tree[] newts = new Tree[ choices.length ];
- for (int i = 0; i < choices.length; i++ )
- newts[ i ] = transform( choices[ i ], this.mode, pt );
-
- //Type tpe = Type.lub( Tree.typeOf( newts ));
-
- this.inAlternative = save;
-
- return copy.Alternative( tree, newts )
- .setType( pt );
-
- case Bind( Name name, Tree body ):
- Symbol vble = null;
- if( name != Names.PATTERN_WILDCARD ) {
- vble = new TermSymbol(tree.pos,
- name,
- context.owner,
- 0x00000000 ).setType( pt );
- vble = enterInScope( vble );
- //System.out.println("Bind("+name+",...) enters in scope:"+vble.fullNameString());
-
- patternVars.put( vble, new Boolean( this.inAlternative ));
- //System.out.println("case Bind.. put symbol vble="+vble+" in scope and patternVars.");
- }
- body = transform( body );
- if( name != Names.PATTERN_WILDCARD ) {
- //assert body.type != null;
- if( TreeInfo.isSequenceValued( body ) ) {
- vble.setType( definitions.LIST_TYPE(pt) );
- } else {
- vble.setType( body.type );
- }
- return copy.Bind( tree, name, body )
- .setSymbol( vble ).setType( body.type );
- }
- return body;
- case Visitor(Tree.CaseDef[] cases):
- if (pt.symbol().isSubClass(definitions.PARTIALFUNCTION_CLASS)) {
- Type pft = pt.baseType(definitions.PARTIALFUNCTION_CLASS);
- Type[] pftargs = pft.typeArgs();
- if (pftargs.length == 2 && infer.isFullyDefined(pftargs[0])) {
- Type pattype = pftargs[0];
- Type restype = pftargs[1];
- Tree isDefinedAtVisitor = transformVisitor(
- desugarize.isDefinedAtVisitor(tree),
- pattype, definitions.BOOLEAN_TYPE());
- Tree applyVisitor = transformVisitor(tree, pattype, restype);
- if (!infer.isFullyDefined(restype))
- restype = applyVisitor.type.deconst();
- if (definitions.PARTIALFUNCTION_CLASS.isExternal())
- // need to load tree for mixins
- new SourceCompleter(global, true).complete(
- definitions.PARTIALFUNCTION_CLASS);
- return gen.mkPartialFunction(
- tree.pos, applyVisitor, isDefinedAtVisitor,
- pattype, restype, context.owner);
- } else {
- return error(tree.pos, "expected pattern type of cases could not be determined");
- }
- } else {
- return transform(desugarize.Visitor(tree));
- }
-
- case Assign(Apply(_, _), _):
- return transform(desugarize.Update(tree));
-
- case Assign(Tree lhs, Tree rhs):
- Tree lhs1 = transform(lhs, EXPRmode);
- Symbol varsym = lhs1.symbol();
- if (isSetterMethod(varsym)) {
- // todo: change this to require setters in same template
- return transform(desugarize.Assign(tree.pos, lhs, rhs));
- } else if (varsym != null && (varsym.flags & MUTABLE) != 0) {
- Tree rhs1 = transform(rhs, EXPRmode, lhs1.type);
- return copy.Assign(tree, lhs1, rhs1)
- .setType(definitions.UNIT_TYPE());
- } else {
- if (lhs1.type != Type.ErrorType)
- error(tree.pos, "assignment to non-variable ");
- return errorTree(tree.pos);
- }
-
- case If(Tree cond, Tree thenp, Tree elsep):
- Tree cond1 = transform(cond, EXPRmode, definitions.BOOLEAN_TYPE());
- Tree thenp1, elsep1;
- if (elsep == Tree.Empty) {
- thenp1 = transform(thenp, EXPRmode, definitions.UNIT_TYPE());
- elsep1 = gen.mkUnitLit(tree.pos);
- } else {
- thenp1 = transform(thenp, EXPRmode, pt);
- elsep1 = transform(elsep, EXPRmode, pt);
- }
- return copy.If(tree, cond1, thenp1, elsep1)
- .setType(Type.lub(new Type[]{thenp1.type, elsep1.type}));
-
- case Throw(Tree expr):
- Tree expr1 = transform(
- expr, EXPRmode, definitions.JAVA_THROWABLE_TYPE());
- return gen.Select(tree.pos, expr1, definitions.JAVA_THROWABLE_THROW);
-
- case Return(Tree expr):
- if (!context.owner.isInitialized()) {
- return error(tree.pos, "method with return needs result type");
- } else {
- Symbol enclFun = context.owner.enclMethod();
- if (enclFun.kind == VAL && !enclFun.isConstructor()) {
- Tree expr1 = transform(
- expr, EXPRmode, enclFun.type().resultType());
- return copy.Return(tree, expr1)
- .setSymbol(enclFun).setType(definitions.ALL_TYPE());
- } else {
- return error(tree.pos, "return outside method definition");
- }
- }
-
- case New(Tree.Template templ):
- switch (templ) {
- case Template(Tree[] parents, Tree[] body):
- if (parents.length == 1 && body.length == 0) {
- Tree parent1 = transform(parents[0], CONSTRmode, pt);
- Type owntype = parent1.type;
- Tree.Template templ1 = (Tree.Template)
- copy.Template(templ, Symbol.NONE, new Tree[]{parent1}, body)
- .setType(owntype);
- checkInstantiatable(tree.pos, owntype);
- return copy.New(tree, templ1)
- .setType(owntype.instanceType());
- } else {
- pushContext(tree, context.owner, new Scope(context.scope));
- Tree cd = make.ClassDef(
- templ.pos,
- 0,
- Names.ANON_CLASS_NAME.toTypeName(),
- Tree.AbsTypeDef_EMPTY_ARRAY,
- new ValDef[][]{Tree.ValDef_EMPTY_ARRAY},
- Tree.Empty,
- templ);
- //new TextTreePrinter().print(cd).println().end();//DEBUG
- enterSym(cd);
- cd = transform(cd);
- Symbol clazz = cd.symbol();
- if (clazz.kind != CLASS) return errorTree(tree.pos);
-
- // compute template's type with new refinement scope.
- Type[] parentTypes = clazz.info().parents();
- Scope refinement = new Scope();
- Type base = Type.compoundTypeWithOwner(context.enclClass.owner, parentTypes, Scope.EMPTY);
- Type owntype = Type.compoundType(
- parentTypes, refinement, clazz);
- Scope.SymbolIterator it = clazz.members().iterator();
- while (it.hasNext()) {
- Symbol sym1 = it.next();
- Symbol basesym1 = base.lookupNonPrivate(sym1.name);
- if (basesym1.kind != NONE &&
- !base.symbol().thisType().memberType(basesym1)
- .isSameAs(sym1.type()))
- refinement.enter(sym1);
- }
- if (refinement.isEmpty() &&
- parentTypes.length == 1)
- owntype = parentTypes[0];
- else
- owntype = checkNoEscape(tree.pos, owntype);
-
- Tree alloc =
- gen.New(
- gen.Apply(
- gen.mkLocalRef(
- tree.pos,
- clazz.primaryConstructor()),
- Tree.EMPTY_ARRAY))
- .setType(owntype);
- popContext();
- return make.Block(tree.pos, new Tree[]{cd}, alloc)
- .setType(owntype);
- }
- default:
- throw new ApplicationError();
- }
-
- case Typed(Tree expr, Tree tpe):
- switch( expr ) {
- case Ident(Name n):
- if ((n!=Names.PATTERN_WILDCARD)
- &&((mode & PATTERNmode) != 0)) {
- return transform( desugarize.TypedPattern( (Typed) tree ),
- mode,
- pt );
- }
- }
- Tree expr1;
- Tree tpe1;
- switch (tpe) {
- case Ident(TypeNames.WILDCARD_STAR):
- expr1 = transform(
- expr, mode & baseModes, definitions.SEQ_TYPE(pt));
- Type[] elemtps = expr1.type.baseType(definitions.SEQ_CLASS).
- typeArgs();
- Type elemtp = (elemtps.length == 1) ? elemtps[0]
- : Type.ErrorType;
- tpe1 = tpe.setType(elemtp);
- break;
- default:
- tpe1 = transform(tpe, TYPEmode);
- expr1 = transform(expr, mode & baseModes, tpe1.type);
- }
- return copy.Typed(tree, expr1, tpe1).setType(tpe1.type);
-
- case Function(Tree.ValDef[] vparams, Tree body):
- pushContext(tree, context.owner, new Scope(context.scope));
- Type restype = desugarize.preFunction(vparams, pt);
- enterParams(vparams);
- Tree.ValDef[] vparams1 = transform(vparams);
- Tree body1 = transform(body, EXPRmode, restype);
- if (!infer.isFullyDefined(restype)) restype = body1.type.deconst();
- popContext();
- return gen.mkFunction(
- tree.pos, vparams1, body1, restype, context.owner);
-
- case TypeApply(Tree fn, Tree[] args):
- Tree fn1 = transform(
- fn, (mode & (EXPRmode | CONSTRmode)) | FUNmode, Type.AnyType);
- Tree[] args1 = transform(args, TYPEmode);
- Type[] argtypes = Tree.typeOf(args1);
-
- // propagate errors in arguments
- for (int i = 0; i < argtypes.length; i++) {
- if (argtypes[i] == Type.ErrorType) {
- return tree.setType(Type.ErrorType);
- }
- }
-
- // resolve overloading
- switch (fn1.type) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- try {
- infer.polyAlternative(fn1, alts, alttypes, args.length);
- } catch (Type.Error ex) {
- reportTypeError(tree.pos, ex);
- }
- }
-
- // match against arguments
- switch (fn1.type) {
- case PolyType(Symbol[] tparams, Type restp):
- if (tparams.length == argtypes.length) {
- // constant fold asInstanceOf calls.
- switch (fn1) {
- case Select(Tree qual, Name name):
- if (fn1.symbol() == definitions.ANY_AS) {
- switch (qual.type()) {
- case ConstantType(_, AConstant value):
- value = constfold.cast(value, argtypes[0]);
- if (value != null)
- return gen.Literal(tree.pos, value);
- }
- }
- }
- return constfold.tryToFold(
- copy.TypeApply(tree, fn1, args1)
- .setType(restp.subst(tparams, argtypes)));
- }
- break;
- case ErrorType:
- return tree.setType(Type.ErrorType);
- }
- return error(tree.pos,
- infer.toString(fn1.symbol(), fn1.type) +
- " cannot be applied to " +
- ArrayApply.toString(argtypes, "[", ",", "]"));
-
- case Apply(Tree fn, Tree[] args):
- mode = mode & ~SEQUENCEmode;
- Tree fn1;
- int argMode;
- boolean selfcc = 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
- Symbol tsym = TreeInfo.methSymbol(fn1);
- if (tsym.kind != ERROR) {
- assert tsym.isType() : tsym;
- switch (fn1.type.withDefaultArgs().unalias()) {
- case TypeRef(Type pre, Symbol c, Type[] 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();
- Symbol constr = c.allConstructors();
- Tree fn0 = fn1;
- fn1 = gen.mkRef(fn1.pos, pre, constr);
- switch (fn1) {
- case Select(Tree fn1qual, _):
- fn1.type = checkAccessible(
- fn1.pos, constr, fn1.type, fn1qual);
- }
- if (tsym == c) {
- switch (fn0) {
- case AppliedType(_, Tree[] targs):
- fn1 = gen.TypeApply(fn1, targs);
- }
- } 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 instanceof AppliedType))
- fn1.type = Type.PolyType(
- tsym.typeParams(), fn1.type);
- }
- //System.out.println(TreeInfo.methSymbol(fn1) + ":" + tp + " --> " + fn1.type + " of " + fn1);//DEBUG
- selfcc = TreeInfo.isSelfConstrCall(fn0);
- }
- break;
- default:
- error(tree.pos,
- tsym + " is not a class; cannot be instantiated");
- }
- }
- }
-
- // if function is overloaded with one alternative
- // whose arity matches argument length, preselect this alternative.
- switch (fn1.type) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- int matching1 = -1;
- int matching2 = -1;
- for (int i = 0; i < alttypes.length; i++) {
- Type alttp = alttypes[i];
- switch (alttp) {
- case PolyType(_, Type restp): alttp = restp;
- }
- switch (alttp) {
- case MethodType(Symbol[] params, _):
- if (params.length == args.length ||
- params.length > 0 &&
- args.length >= params.length - 1 &&
- (params[params.length-1].flags & REPEATED) != 0) {
- matching2 = matching1;
- matching1 = i;
- }
- }
- }
- if (matching1 >= 0 && matching2 < 0)
- fn1.setSymbol(alts[matching1]).setType(alttypes[matching1]);
- }
-
- // handle the case of application of match to a visitor specially
- if (args.length == 1 && args[0] instanceof Visitor) {
- Type pattp = matchQualType(fn1);
- if (pattp == Type.ErrorType) {
- return tree.setType(Type.ErrorType);
- } else if (pattp != Type.NoType) {
- if (infer.isFullyDefined(pattp) &&
- !(fn1.type instanceof Type.PolyType &&
- pattp.containsSome(fn1.type.typeParams()))) {
- Tree fn2 = desugarize.postMatch(fn1, context.enclClass.owner);
- Tree arg1 = transformVisitor(args[0], pattp, pt);
- return copy.Apply(tree, fn2, new Tree[]{arg1})
- .setType(arg1.type);
- } else {
- return error(tree.pos, "expected pattern type of cases could not be determined");
- }
- }
- }
-
- // return prematurely if function is a superclass constructor
- // and no type arguments need to be inferred.
- if ((mode & SUPERmode) != 0 && fn1.type instanceof Type.MethodType)
- return copy.Apply(tree, fn1, args).setType(fn1.type.resultType());
-
- // type arguments with formals as prototypes if they exist.
- fn1.type = infer.freshInstance(fn1.type);
-
- Type[] argtypes = transformArgs(
- tree.pos, fn1.symbol(), Symbol.EMPTY_ARRAY, fn1.type, argMode, args, pt);
-
- // propagate errors in arguments
- if (argtypes == null) {
- return tree.setType(Type.ErrorType);
- }
- for (int i = 0; i < argtypes.length; i++) {
- if (argtypes[i] == Type.ErrorType) {
- return tree.setType(Type.ErrorType);
- }
- }
-
- // resolve overloading1g
- switch (fn1.type) {
- case OverloadedType(Symbol[] alts, Type[] alttypes):
- try {
- infer.methodAlternative(fn1, alts, alttypes, argtypes, pt);
- } catch (Type.Error ex) {
- reportTypeError(tree.pos, ex);
- }
- }
-
- // check that self constructors go backwards.
- if (selfcc) {
- Symbol constr = TreeInfo.methSymbol(fn1);
- if (constr != null && constr.kind == VAL &&
- !(constr.type() instanceof Type.OverloadedType) &&
- constr.pos > tree.pos)
- error(tree.pos,
- "illegal forward reference to self constructor");
- }
-
- switch (fn1.type) {
- case PolyType(Symbol[] tparams, Type 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.type);//DEBUG
- } catch (Type.Error ex) {
- reportTypeError(tree.pos, ex);
- }
-
- switch (fn1.type) {
- case MethodType(Symbol[] params, Type restp1):
- Type[] formals = infer.formalTypes(params, args.length);
- for (int i = 0; i < args.length; i++) {
- args[i] = adapt(args[i], argMode, formals[i]);
- switch( args[ i ] ) {
- case Typed(Tree arg, 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");
- }
- }
- }
- return constfold.tryToFold(
- copy.Apply(tree, fn1, args)
- .setType(restp1));
- }
- break;
- case MethodType(Symbol[] params, Type restp):
- // if method is monomorphic,
- // check that it can be applied to arguments.
- if (infer.isApplicable(fn1.type, argtypes, Type.AnyType)) {
- return constfold.tryToFold(
- copy.Apply(tree, fn1, args)
- .setType(restp));
- }
-
- // if method signature contains iterated type,
- // check that possible escaping of sequences happens in the right place
- if (params.length > 0 &&
- args.length >= params.length - 1 &&
- (params[params.length-1].flags & REPEATED) != 0) {
- System.err.println(" method sign contains iterated type! ");
- }
-
- }
-
- if (fn1.type == Type.ErrorType)
- return tree.setType(Type.ErrorType);
-
- //new TextTreePrinter().print(tree).println().end();//DEBUG
- return error(tree.pos,
- infer.applyErrorMsg(
- "", fn1, " cannot be applied to ", argtypes, pt));
-
- case Super(Name qualifier, Name mixin):
- Symbol clazz = qualifyingClass(tree, qualifier);
- tree.setSymbol(clazz);
- if (clazz == Symbol.ERROR) return tree.setType(Type.ErrorType);
- Type[] parents = clazz.parents();
- if (mixin == TypeNames.EMPTY) {
- return tree.setType(parents[0].instanceType());
- } else {
- for (int i = 1; i < parents.length; i++) {
- if (parents[i].symbol().name == mixin) {
- return tree.setType(parents[i].instanceType());
- }
- }
- return error(tree.pos,
- mixin + " does not name a mixin base class of " + clazz);
- }
-
- case This(Name name):
- Symbol clazz = qualifyingClass(tree, name);
- tree.setSymbol(clazz);
- if (clazz == Symbol.ERROR) return tree.setType(Type.ErrorType);
- return tree.setType(
- (pt != null && pt.isStable() || (mode & QUALmode) != 0)
- ? clazz.thisType() : clazz.typeOfThis());
-
- case Select(Tree qual, Name name):
- int qualmode = EXPRmode | POLYmode | QUALmode;
- Tree qual1 = transform(qual, qualmode);
- if (name.isTypeName())
- qual1 = checkStable(qual1);
- return transformSelect(
- tree, adapt(qual1, qualmode, Type.AnyType), name);
-
- case Ident(Name name):
- if (name == Names.CONSTRUCTOR) {
- assert (mode & CONSTRmode) != 0 : tree;
- return copy.Ident(tree, context.enclClass.owner)
- .setType(context.enclClass.owner.type());
- } else if (((mode & (PATTERNmode | FUNmode)) == PATTERNmode) &&
- name.isVariable()) {
-
- Symbol vble, vble2 = null;
-
- // if vble is bound with @, there is already a symbol
- if( name != Names.PATTERN_WILDCARD ) {
- vble2 = context.scope.lookup( name );
- }
- if ( patternVars.containsKey( vble2 ) )
- vble = vble2;
- else {
-
- vble = name == Names.PATTERN_WILDCARD
- ? definitions.PATTERN_WILDCARD
- : new TermSymbol(tree.pos,
- name,
- context.owner,
- 0).setType( pt );
-
- //if((( mode & SEQUENCEmode) != 0)&&( name != Names.PATTERN_WILDCARD )) {
- if( name != Names.PATTERN_WILDCARD ) {
- // x => x @ _ in sequence patterns
- tree = desugarize.IdentPattern( tree );
- }
-
- }
- if ( name != Names.PATTERN_WILDCARD ) enterInScope(vble);
- return tree.setSymbol(vble).setType(pt);
- } else {
- return transformIdent(tree, name);
- }
-
- case Literal(AConstant value):
- return tree.setType(Type.constantType(value));
-
- case LabelDef(Name name, Ident[] params, Tree body):
- assert params.length == 0;
- pushContext(tree, context.owner, new Scope(context.scope));
- Symbol lsym = new TermSymbol(tree.pos, name, context.owner, LABEL);
- lsym.setInfo(
- Type.MethodType(Symbol.EMPTY_ARRAY, definitions.UNIT_TYPE()));
- context.scope.enter(lsym);
- Tree body1 = transform(body, mode, pt);
- popContext();
- return copy.LabelDef(tree, lsym, params, body1)
- .setSymbol(lsym).setType(definitions.UNIT_TYPE());
-
- case TypeTerm():
- return tree;
-
- case SingletonType(Tree ref):
- Tree ref1 = transform(ref, EXPRmode | QUALmode, Type.AnyType);
- return copy.SingletonType(tree, ref1)
- .setType(checkObjectType(tree.pos, ref1.type.resultType()));
-
- case SelectFromType(Tree qual, Name name):
- Tree qual1 = transform(qual, TYPEmode);
- return transformSelect(tree, qual1, name);
-
- case CompoundType(Tree[] parents, Tree[] refinements):
- Tree[] parents1 = transform(parents, TYPEmode);
- Type[] ptypes = Tree.typeOf(parents);
- Scope members = new Scope();
- Type self = Type.compoundTypeWithOwner(context.enclClass.owner, ptypes, members);
- Symbol clazz = self.symbol();
- pushContext(tree, clazz, members);
- for (int i = 0; i < refinements.length; i++) {
- enterSym(refinements[i]).flags |= OVERRIDE;
- }
- Tree[] refinements1 = transformStatSeq(refinements, Symbol.NONE);
- popContext();
- return copy.CompoundType(tree, parents1, refinements1)
- .setType(self);
-
- case AppliedType(Tree tpe, Tree[] args):
- Tree tpe1 = transform(tpe, mode | FUNmode);
- Tree[] args1 = transform(args, TYPEmode);
- Type[] argtypes = Tree.typeOf(args);
- Symbol[] tparams = tpe1.type.symbol().typeParams();
- Type owntype = Type.ErrorType;
- if (tpe1.type != Type.ErrorType) {
- if (tparams.length == args.length)
- owntype = Type.appliedType(tpe1.type, argtypes);
- else if (tparams.length == 0)
- error(tree.pos, tpe1.type + " does not take type parameters");
- else error(tree.pos, "wrong number of type arguments for " +
- tpe1.type);
- }
- return copy.AppliedType(tree, tpe1, args1).setType(owntype);
-
- case FunType(_, _):
- return transform(desugarize.FunType(tree));
-
- default:
- throw new ApplicationError("illegal tree: " + tree);
- }
- } catch (Type.Error ex) {
- reportTypeError(tree.pos, ex);
- tree.type = Type.ErrorType;
- if (tree.hasSymbol()) {
- if (tree.symbol() != null) tree.symbol().setInfo(Type.ErrorType);
- else tree.setSymbol(Symbol.ERROR);
- }
- return tree;
- }
- }
- //where
- private Symbol qualifyingClass(Tree tree, Name name) {
- if (name == TypeNames.EMPTY) {
- Symbol clazz = context.enclClass.owner;
- if (clazz != null) return clazz;
- error(tree.pos, tree +
- " can be used only in a class, object, or template");
- } else {
- for (Context i = context; i != Context.NONE; i = i.outer) {
- Symbol sym = i.owner;
- if (sym.kind == CLASS && sym.name == name) return sym;
- }
- error(tree.pos, name + " is not an enclosing class");
- }
- return Symbol.ERROR;
- }
-
- // ///////////////
- // sequence helper function
- // ///////////////
-
- /** calls IdentPattern for every Ident(x) with x != _ in trees.
- * does *not* recurse through the trees
- * pre: Ident nodes are already attributed, symbol is in scope
- * post: all variables in trees are replaced by (attributed) binds.
- */
-
- public void desug_allIdentPatterns( Tree trees[], Symbol currentOwner ) {
- for( int i = 0; i < trees.length; i ++ )
- switch(trees[i]) {
- case Ident( Name name ):
- if( name != Names.PATTERN_WILDCARD ) {
- Symbol vble = context.scope.lookup( name );
- /*
- Symbol vble = new TermSymbol( trees[ i ].pos, name, currentOwner, 0)
- .setType( trees[ i ].type() );
-
- vble = enterInScope( vble );
- */
- trees[i] = desugarize.IdentPattern(trees[i]).setSymbol(vble)
- .setType(vble.type());
- } else {
- trees[i] = gen.Ident(trees[i].pos, definitions.PATTERN_WILDCARD);
- }
- }
- }
-
-}
-
diff --git a/sources/scalac/typechecker/AnalyzerPhase.java b/sources/scalac/typechecker/AnalyzerPhase.java
index d2a2ec2c41..d64a99d896 100644
--- a/sources/scalac/typechecker/AnalyzerPhase.java
+++ b/sources/scalac/typechecker/AnalyzerPhase.java
@@ -8,74 +8,21 @@
package scalac.typechecker;
-import ch.epfl.lamp.util.Position;
-import scalac.*;
-import scalac.util.*;
-import scalac.ast.*;
-import scalac.symtab.*;
-import scalac.checkers.*;
-import java.util.HashMap;
-import java.util.ArrayList;
+import scalac.Global;
+import scalac.Phase;
+import scalac.PhaseDescriptor;
+import scalac.Unit;
+import scalac.symtab.Symbol;
-public class AnalyzerPhase extends Phase {
-
- final Context startContext;
- final Context consoleContext;
- final HashMap/*<Unit,Context>*/ contexts = new HashMap();
- final ArrayList/*<Unit>*/ newSources = new ArrayList();
+public abstract class AnalyzerPhase extends Phase {
/** Initializes this instance. */
public AnalyzerPhase(Global global, PhaseDescriptor descriptor) {
super(global, descriptor);
- Definitions definitions = global.definitions;
- this.startContext = new Context(
- Tree.Empty,
- definitions.ROOT_CLASS,
- definitions.ROOT_CLASS.members(),
- Context.NONE);
- this.startContext.enclClass = this.startContext;
-
- if (!global.noimports) {
- addImport(startContext, definitions.getModule(Names.java_lang));
- addImport(startContext, definitions.getModule(Names.scala));
- }
-
- if (!global.noimports && !global.nopredefs) {
- addImport(startContext, definitions.getModule(Names.scala_Predef));
- }
-
- this.consoleContext = new Context(
- Tree.Empty,
- definitions.ROOT_CLASS,
- definitions.ROOT_CLASS.members(),
- startContext);
}
- public void addConsoleImport(Symbol module) {
- addImport(consoleContext, module);
- }
+ public abstract void addConsoleImport(Symbol module);
- private void addImport(Context context, Symbol module) {
- global.prevPhase();
- Tree tree = global.treeGen.mkImportAll(Position.NOPOS, module);
- global.nextPhase();
- context.imports = new ImportList(tree, new Scope(), context.imports);
- }
+ public abstract void lateEnter(Global global, Unit unit, Symbol symbol);
- public void apply(Unit[] units) {
- new Analyzer(global, this).apply(units);
- }
-
- public void lateEnter(Global global, Unit unit, Symbol symbol) {
- new Analyzer(global, this).lateEnter(unit, symbol);
- }
-
- public Checker[] postCheckers(Global global) {
- return new Checker[] {
- new CheckSymbols(global),
- new CheckTypes(global),
- new CheckOwners(global),
- new CheckNames(global)
- };
- }
}
diff --git a/sources/scalac/typechecker/Context.java b/sources/scalac/typechecker/Context.java
deleted file mode 100644
index 347e6d565d..0000000000
--- a/sources/scalac/typechecker/Context.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-**
-** $Id$
-\* */
-
-package scalac.typechecker;
-
-import scalac.symtab.*;
-import scalac.ast.Tree;
-
-public class Context {
- Tree tree; // Tree associated with this context
- Symbol owner; // The current owner
- Scope scope; // The current scope
- ImportList imports; // The current import list
- Context outer; // The next outer context
- Context enclClass = this; // The next outer context whose tree
- // is a class template
- int variance; // Variance relative to enclosing class.
- Symbol constructorClass; // Class for auxiliary constructor
-
- public Context() {}
-
- public Context(Tree tree, Context outer) {
- this(tree, outer.owner, outer.scope, outer);
- }
-
- public Context(Tree tree, Symbol owner, Scope scope, Context outer) {
- this.tree = tree;
- this.owner = owner;
- this.scope = scope;
- this.imports = outer.imports;
- if (tree instanceof Tree.Template ||
- tree instanceof Tree.CompoundType) this.enclClass = this;
- else this.enclClass = outer.enclClass;
- this.variance = outer.variance;
- this.constructorClass = outer.constructorClass;
- this.outer = outer;
- }
-
- public static Context NONE = new Context();
-
- Context outerContext(Symbol clazz) {
- Context c = this;
- while (c != Context.NONE && c.owner != clazz) c = c.outer;
- return c;
- }
-
- boolean isTopLevel() {
- switch (tree) {
- case Block(_, _):
- return false;
- case Template(_, _):
- return outer.tree instanceof Tree.PackageDef;
- case Empty:
- return true;
- default:
- return outer.isTopLevel();
- }
- }
-}
-
diff --git a/sources/scalac/typechecker/DeSugarize.java b/sources/scalac/typechecker/DeSugarize.java
deleted file mode 100644
index a996ae9fa4..0000000000
--- a/sources/scalac/typechecker/DeSugarize.java
+++ /dev/null
@@ -1,663 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-** **
-** $Id$
-\* */
-package scalac.typechecker;
-
-import java.io.*;
-import java.util.*;
-import scalac.*;
-import scalac.util.*;
-import scalac.symtab.*;
-import scalac.ast.*;
-import scalac.ast.printer.*;
-import Tree.*;
-
-/** A transformer for removing syntactic sugar. This transformer does
- * not need any type or symbol-table information.
- *
- * @author Martin Odersky
- * @version 2.0
- */
-public class DeSugarize implements Kinds, Modifiers {
-
- /** the global environment
- */
- protected Global global;
-
- /** the tree factory
- */
- protected TreeFactory make;
-
- /** The copying factory
- */
- protected TreeCopier copy;
-
- /** the tree generator
- */
- protected TreeGen gen;
-
- /** the type inferencer
- */
- protected Infer infer;
-
- /** the name creator
- */
- protected final FreshNameCreator freshNameCreator;
-
- /** the constructor
- */
- /** the constructor
- */
- public DeSugarize(TreeFactory make, TreeCopier copy, TreeGen gen,
- Infer infer, Global global) {
- this.global = global;
- this.make = make;
- this.copy = copy;
- this.gen = gen;
- this.infer = infer;
- this.freshNameCreator = global.freshNameCreator;
- }
- public DeSugarize(Analyzer analyzer, Global global) {
- this(analyzer.make, analyzer.copy, analyzer.gen, analyzer.infer, global);
- }
-
-// Auxiliary definitions and functions -------------------------------------------
-
- /** introduce fresh variable of the form "ds$56"
- */
- Name getvar() {
- return freshNameCreator.newName("ds", '$');
- }
-
- Name setterName(Name name) {
- return name.append(Names._EQ);
- }
-
- Name parameterName(int i) {
- return Name.fromString("x$" + i);
- }
-
- Name tupleSelectorName(int i) {
- return Name.fromString("_" + i);
- }
-
- /** extract variables from a pattern
- */
- void getVariables(Tree tree, ArrayList vars) {
- switch(tree) {
- case Ident(Name name):
- if (name.isVariable() && name != Names.PATTERN_WILDCARD) vars.add(name);
- break;
- case Typed(Tree expr, Tree type):
- getVariables(expr, vars);
- break;
- case Apply(Tree fn, Tree[] args):
- switch (fn) {
- case Apply(_, _): getVariables(fn, vars);
- }
- for (int i = 0; i < args.length; i++)
- getVariables(args[i], vars);
- break;
- case Sequence(Tree[] elems):
- for (int i = 0; i < elems.length; i++)
- getVariables(elems[i], vars);
- break;
- case Literal( _ ):
- break;
- case Bind( Name name, Tree t ):
- if (name.isVariable() && name != Names.PATTERN_WILDCARD) vars.add(name);
- getVariables( t, vars );
- break;
- case Alternative( Tree ts[] ):
- for (int i = 0; i < ts.length; i++)
- getVariables( ts[i], vars );
- break;
- default:
- throw new ApplicationError ("illegal pattern", tree);
- }
- }
-
-// Transform functions -----------------------------------------------------
-
- /** (T_1, ..., T_N) => T ==> scala.FunctionN[T_1, ..., T_N, +T]
- */
- public Tree FunType(Tree tree) {
- switch(tree) {
- case FunType(Tree[] argtpes, Tree restpe):
- Tree[] types = new Tree[argtpes.length + 1];
- System.arraycopy(argtpes, 0, types, 0, argtpes.length);
- types[argtpes.length] = restpe;
- return make.AppliedType(tree.pos,
- make.Select(tree.pos,
- make.Ident(tree.pos, Names.scala),
- Name.fromString("Function" + argtpes.length).toTypeName()),
- types);
- default:
- throw new ApplicationError("function type expected", tree);
- }
- }
-
- public Tree mkTuple(int pos, Tree[] trees) {
- if (trees.length == 0)
- return gen.mkUnitLit(pos);
- else
- return make.Apply(pos,
- make.Select(pos,
- make.Ident(pos, Names.scala),
- Name.fromString("Tuple" + trees.length)),
- trees);
- }
-
- /** Convert method to function type.
- */
- Type meth2fun(Type tp) {
- switch (tp) {
- case MethodType(Symbol[] params, Type restype):
- return global.definitions.FUNCTION_TYPE(
- Symbol.type(params), meth2fun(restype));
- default:
- return tp;
- }
- }
-
- /** If `pt' is a matching function type insert missing parameters
- * in `vparams' from it, and return result type,
- * else return AnyType.
- */
- public Type preFunction(ValDef[] vparams, Type pt) {
- switch (pt) {
- case TypeRef(Type pre, Symbol psym, Type[] ptargs):
- if (psym.fullName().startsWith(Names.scala_Function) &&
- ptargs.length == vparams.length + 1) {
- for (int i = 0; i < vparams.length; i++)
- assignType(vparams[i], ptargs[i]);
- return ptargs[vparams.length];
- }
- }
- return Type.AnyType;
- }
- //where
- void assignType(ValDef vparam, Type pt) {
- if (vparam.tpe == Tree.Empty && infer.isFullyDefined(pt))
- vparam.tpe = gen.mkType(vparam.pos, pt);
- }
-
- public Tree isDefinedAtVisitor(Tree tree) {
- switch (tree) {
- case Visitor(CaseDef[] cases):
- CaseDef lastCase = cases[cases.length - 1];
- switch (lastCase) {
- case CaseDef(Ident(Name name), Tree.Empty, Tree expr):
- if (name.isVariable())
- return make.Visitor(tree.pos,
- new CaseDef[]{
- make.CaseDef(lastCase.pos,
- lastCase.pat.duplicate(),
- Tree.Empty,
- gen.mkBooleanLit(lastCase.body.pos, true))});
- }
- CaseDef[] cases1 = new CaseDef[cases.length + 1];
- for (int i = 0; i < cases.length; i++) {
- switch (cases[i]) {
- case CaseDef(Tree pat, Tree guard, _):
- cases1[i] = (CaseDef) make.CaseDef(
- cases[i].pos,
- pat.duplicate(),
- guard.duplicate(),
- gen.mkBooleanLit(tree.pos, true));
- }
- }
- cases1[cases.length] = (CaseDef) make.CaseDef(
- tree.pos,
- gen.Ident(tree.pos, global.definitions.PATTERN_WILDCARD),
- Tree.Empty,
- gen.mkBooleanLit(tree.pos, false));
- return make.Visitor(tree.pos, cases1);
- default:
- throw new ApplicationError("visitor expected", tree);
- }
- }
-
- /** match => this.match
- * match[targs] => this.match[targs]
- * IMPORTANT: tree is already attributed and attributes need to be preserved.
- */
- public Tree postMatch(Tree tree, Symbol currentclazz) {
- switch (tree) {
- case Ident(Name name):
- return
- make.Select(tree.pos,
- gen.This(tree.pos, currentclazz),
- name).setSymbol(tree.symbol()).setType(tree.type);
- case TypeApply(Tree fn, Tree[] args):
- return copy.TypeApply(tree, postMatch(fn, currentclazz), args);
- default:
- return tree;
- }
- }
-
- /** { cases } ==> (x => x.match {cases})
- * only called when match has to be added
- * no type for parameter x
- */
- public Tree Visitor(Tree tree) {
- switch(tree) {
- case Visitor(CaseDef[] cases):
- Name x = getvar();
- ValDef param = (ValDef) make.ValDef(
- tree.pos, PARAM, x, Tree.Empty, Tree.Empty);
- Tree xuse = make.Ident(tree.pos, x);
- // x.match {cases}
- Tree body = make.Apply(tree.pos,
- make.Select(tree.pos, xuse, Names.match),
- new Tree[]{tree});
- return make.Function(tree.pos, new ValDef[]{param}, body);
- default:
- throw new ApplicationError("visitor expected", tree);
- }
- }
-
- /** e = e' ==> e_=(e')
- */
- public Tree Assign(int pos, Tree lhs, Tree rhs) {
- Tree lhs1;
- switch (lhs) {
- case Ident(Name name):
- lhs1 = make.Ident(lhs.pos, setterName(name));
- break;
- case Select(Tree qual, Name name):
- lhs1 = make.Select(lhs.pos, qual, setterName(name));
- break;
- default:
- throw new ApplicationError();
- }
- return make.Apply(pos, lhs1, new Tree[]{rhs});
- }
-
- /** e(args) = e' ==> e.update(args ; e')
- */
- public Tree Update(Tree tree) {
- switch(tree) {
- case Assign(Apply(Tree fn, Tree[] args), Tree rhs):
- // e.update
- Tree update = make.Select(fn.pos, fn, Names.update);
- Tree[] args1 = new Tree[args.length + 1];
- System.arraycopy(args, 0, args1, 0, args.length);
- args1[args.length] = rhs;
- return make.Apply(tree.pos, update, args1);
- default:
- throw new ApplicationError();
- }
- }
-
- /** make a set of trees share the same documentation comment as a
- * given tree (used for pattern and val definitions)
- */
- Tree[] shareComment(Tree[] trees, Tree tree) {
- String comment = (String) global.mapTreeComment.get(tree);
- if (comment != null)
- for(int i = 0; i < trees.length; i++)
- global.mapTreeComment.put(trees[i], comment);
- return trees;
- }
-
- /** expand pattern definitions and variable definitions in templates.
- */
- public Tree[] Statements(Tree[] stats, boolean isLocal) {
- boolean change = false;
- for (int i = 0; i < stats.length && !change; i++) {
- switch (stats[i]) {
- case PatDef(_, _, _):
- change = true;
- break;
- case ValDef(int mods, _, _, _):
- change = !isLocal;
- }
- }
- if (change) {
- TreeList ts = new TreeList();
- for (int i = 0; i < stats.length; i++) {
- switch (stats[i]) {
- case PatDef(_, _, _):
- ts.append(Statements(this.PatDef(stats[i]), isLocal));
- break;
- case ValDef(_, _, _, _):
- if (!isLocal) {
- ts.append(this.ValDef(stats[i]));
- } else
- ts.append(stats[i]);
- break;
- default:
- ts.append(stats[i]);
- }
- }
- stats = ts.toArray();
- //TextTreePrinter p = new TextTreePrinter();//debug
- //p.print("desugarized:");//debug
- //for (int i = 0; i < stats.length; i++) p.print(stats[i]).println();//debug
- //p.end();//debug
- return stats;
- } else {
- return stats;
- }
- }
-
- /** expands pattern definitions
- * in case pattern is a simple (typed) identifier:
- * val x = e ==> val x = e
- * val x: T = e ==> val x: T = e
- *
- * in case there are no variables in pattern
- * val p = e ==> e.match (case p => ())
- *
- * in case there is exactly one variable in pattern
- * val x_1 = e.match (case p => (x_1))
- *
- * in case there are more variables in pattern
- * val p = e ==> private synthetic val t$ = e.match (case p => (x_1, ..., x_N))
- * val x_1 = t$._1
- * ...
- * val x_N = t$._N
- *
- */
- public Tree[] PatDef(Tree tree) {
- switch(tree) {
-
- case PatDef(int mods, Ident(Name name), Tree rhs):
- // val x = e ==> val x = e
- return shareComment(new Tree[]{
- make.ValDef(tree.pos, mods, name, Tree.Empty, rhs)}, tree);
-
- case PatDef(int mods, Typed(Ident(Name name), Tree type), Tree rhs):
- // val x: T = e ==> val x: T = e
- return shareComment(new Tree[]{
- make.ValDef(tree.pos, mods, name, type, rhs)}, tree);
-
- case PatDef(int mods, Tree pat, Tree rhs):
- int pos = tree.pos;
- ArrayList varlist = new ArrayList();
- getVariables(pat, varlist);
- Name[] vars = new Name[varlist.size()];
- varlist.toArray(vars);
-
- // Tuple_N(x_1, ..., x_N)
- Tree[] vtree = new Tree[vars.length];
- for (int i = 0; i < vars.length; i++) {
- vtree[i] = make.Ident(pos, vars[i]);
- }
- Tree tuple = vars.length == 1 ? vtree[0] : mkTuple(tree.pos, vtree);
-
- // e.match (case p => Tuple_N(x_1, ..., x_N))
- CaseDef[] cases = {make.CaseDef(pos, pat, Tree.Empty, tuple)};
- Tree match = make.Apply(pos,
- make.Select(pos, rhs, Names.match),
- new Tree[]{make.Visitor(pos, cases)});
-
- if (vars.length == 0) {
- // e.match (case p => ())
- print(pat, "patdef", match);
- return new Tree[]{match};
- } else if (vars.length == 1) {
- // val x_1 = e.match (case p => x_1)
- Tree valdef = make.ValDef(pos, mods, vars[0], Tree.Empty, match);
- print(pat, "patdef", valdef);
- return shareComment(new Tree[]{valdef}, tree);
- } else {
- // t$
- Name var = getvar();
-
- // private synthetic val t$ = e.match (case p => (x_1, ..., x_N))
- Tree[] res = new Tree[vars.length + 1];
- res[0] = make.ValDef(pos, PRIVATE | SYNTHETIC, var,
- Tree.Empty, match);
- for (int i = 0; i < vars.length; i ++) {
- // val x_i = t$._i
- res[i + 1] = make.ValDef(
- pos, mods, vars[i], Tree.Empty,
- make.Select(pos, make.Ident(pos, var), tupleSelectorName(i + 1)));
- }
- print(pat, "patdef", new Block(res, gen.mkUnitLit(pos)));//debug
- return shareComment(res, tree);
- }
- default:
- throw new ApplicationError("pattern definition expected", tree);
- }
- }
-
- public Tree[] ValDef(Tree tree) {
- switch (tree) {
- case ValDef(int mods, Name name, Tree tpe, Tree rhs):
- Name valname = Name.fromString(name + "$");
- Tree valdef1 = copy.ValDef(
- tree, (mods & (DEFERRED | MUTABLE | CASEACCESSOR | MODUL)) | PRIVATE,
- valname, tpe, rhs).setType(null);
- int mods1 = mods | ACCESSOR;
- if ((mods1 & MUTABLE) == 0) mods1 |= STABLE;
- Tree getter = make.DefDef(
- tree.pos, mods1, name,
- Tree.AbsTypeDef_EMPTY_ARRAY, Tree.ValDef_EMPTY_ARRAY_ARRAY,
- tpe.duplicate(),
- ((mods & DEFERRED) != 0) ? Tree.Empty
- : make.Ident(tree.pos, valname));
- if ((mods1 & MUTABLE) == 0) {
- if ((mods1 & DEFERRED) != 0) return shareComment(new Tree[]{getter}, tree);
- else return shareComment(new Tree[]{valdef1, getter}, tree);
- } else {
- Tree setter = make.DefDef(
- tree.pos, mods1, setterName(name),
- Tree.AbsTypeDef_EMPTY_ARRAY,
- new ValDef[][]{{
- (ValDef) make.ValDef(
- tree.pos, SYNTHETIC | PARAM, parameterName(0), tpe.duplicate(), Tree.Empty)}},
- gen.mkType(tree.pos, global.definitions.UNIT_TYPE()),
- ((mods1 & DEFERRED) != 0) ? Tree.Empty
- : make.Assign(
- tree.pos,
- make.Ident(tree.pos, valname),
- make.Ident(tree.pos, parameterName(0))));
- if ((mods1 & DEFERRED) != 0) return shareComment(new Tree[]{getter, setter}, tree);
- else return shareComment(new Tree[]{valdef1, getter, setter}, tree);
- }
- default:
- throw new ApplicationError();
- }
- }
-
- /** Expand partial function applications of type `type'.
- *
- * p.f(es_1)...(es_n)
- * ==> {
- * private synthetic val eta$f = p.f // if p is not stable
- * ...
- * private synthetic val eta$e_i = e_i // if e_i is not stable
- * ...
- *
- * (ps_1 => ... => ps_m => eta$f([es_1])...([es_m])(ps_1)...(ps_m))
- * }
- * tree is already attributed
- */
- public Tree etaExpand(Tree tree, Type type) {
- TreeList defs = new TreeList();
- Tree lambda =
- toFunction(toApply(liftoutPrefix(tree, defs), type), type);
- Tree result = make.Block(tree.pos, defs.toArray(), lambda);
- print(tree, "eta", result);//debug
- return result;
- }
-
- private static String preName = "eta$";
-
- /** Append to `defs' value definitions for all non-stable subexpressions
- * of the function application `tree'
- */
- public Tree liftoutPrefix(Tree tree, TreeList defs) {
- switch (tree) {
- case Ident(_):
- return tree;
-
- case Select(Tree qual, _):
- return copy.Select(tree, liftout(qual, defs)).setType(null);
-
- case TypeApply(Tree fn, Tree[] args):
- return copy.TypeApply(tree, liftoutPrefix(fn, defs), args).setType(null);
-
- case Apply(Tree fn, Tree[] args):
- return copy.Apply(tree, liftoutPrefix(fn, defs), liftout(args, defs))
- .setType(null);
-
- default:
- throw new ApplicationError();
- }
- }
-
- public Tree[] liftout(Tree[] trees, TreeList defs) {
- Tree[] trees1 = trees;
- for (int i = 0; i < trees.length; i++) {
- Tree tree = trees[i];
- Tree tree1 = liftout(tree, defs);
- if (tree1 != tree && trees1 == trees) {
- trees1 = new Tree[trees.length];
- System.arraycopy(trees, 0, trees1, 0, trees.length);
- }
- trees1[i] = tree1;
- }
- return trees1;
- }
-
- public Tree liftout(Tree tree, TreeList defs) {
- if (!TreeInfo.isPureExpr(tree)) {
- Name vname = Name.fromString(preName + defs.length());
- defs.append(
- make.ValDef(
- tree.pos, SYNTHETIC, vname, Tree.Empty, tree));
- return make.Ident(tree.pos, vname);
- } else {
- return tree;
- }
- }
-
- /** in patterns x => x @ _
- * precondition: name != '_'
- * post: returns *unattributed* Bind tree
- */
-
- public Tree IdentPattern( Tree tree ) {
- switch( tree ) {
- case Ident( Name name ):
- if( name == Names.PATTERN_WILDCARD )
- throw new ApplicationError("nothing to desugarize");
- return make.Bind( tree.pos,
- name,
- gen.Ident( tree.pos,
- global.definitions.PATTERN_WILDCARD ))
- .setType( tree.type );
- default:
- throw new ApplicationError("ident expected");
- }
- }
-
- /** in patterns x:T => x @ _ : T
- * pre: t is a typed variable.
- * post: returns *unattributed* Bind tree
- */
-
- public Tree TypedPattern( Tree.Typed t ) {
- switch( t ) {
- case Typed(Ident(Name name), Tree tpe):
- return make.Bind(t.pos,
- name,
- make.Typed(t.pos,
- gen.Ident( t.pos,
- global.definitions.PATTERN_WILDCARD ),
- tpe));
- default:
- throw new ApplicationError("unexpected Typed node");
- }
- }
-
-
- /** f, (syms_1)...(syms_n)T ==> f(ps_1)...(ps_n)
- */
- Tree toApply(Tree tree, Type type) {
- switch(type) {
- case MethodType(Symbol[] vparams, Type restpe):
- Tree res = make.Apply(tree.pos, tree, toIdents(vparams));
- return toApply(res, restpe);
- default:
- return tree;
- }
- }
-
- /** e, (syms_1)...(syms_n)T ==> (ps_1 => ... => ps_n => e)
- */
- Tree toFunction(Tree tree, Type type) {
- switch(type) {
- case MethodType(Symbol[] vparams, Type restpe):
- return //this.Function(
- make.Function(tree.pos, toVparams(vparams), toFunction(tree, restpe));
- //restpe);
- default:
- return tree;
- }
- }
-
- /** Extract value parameters from type.
- */
- ValDef[] toVparams(Symbol[] symbols) {
- ValDef[] vpars = new ValDef[symbols.length];
- for (int i = 0; i < symbols.length; i++) {
- vpars[i] = (ValDef)make.ValDef(
- symbols[i].pos, PARAM | SYNTHETIC, symbols[i].name,
- gen.mkType(symbols[i].pos, symbols[i].type()),
- Tree.Empty);
- }
- return vpars;
- }
-
- /** Extract value identifiers from method type.
- * It is assumed that all symbols are term symbols ==> make.Ident().
- */
- Tree[] toIdents(Symbol[] symbols) {
- Tree[] idents = new Ident[symbols.length];
- for (int i = 0; i < symbols.length; i++) {
- idents[i] = make.Ident(symbols[i].pos, symbols[i].name);
- }
- return idents;
- }
-
- /** Build value element definition name for case parameter.
- */
- public void addCaseElement(TreeList ts, ValDef vparam) {
- //vparam.symbol().initialize();
- ts.append(
- make.ValDef(
- vparam.pos, CASEACCESSOR, vparam.name, Tree.Empty,
- make.Ident(vparam.pos, vparam.name)
- .setSymbol(vparam.symbol())));
- }
-
- /** add case constructor, value defintiions and access functions.
- */
- public Tree[] addCaseElements(Tree[] body, ValDef[] vparams) {
- TreeList stats = new TreeList();
- for (int i = 0; i < vparams.length; i++) {
- addCaseElement(stats, vparams[i]);
- }
- stats.append(body);
- return stats.toArray();
- }
-
- //debug
- void print(Tree tree, String conv, Tree result) {
- if (global.log()) {
- new TextTreePrinter()
- .print(tree).println()
- .print(" --" + conv + "--> ").println()
- .print(result).println().end();
- }
- }
-}
diff --git a/sources/scalac/typechecker/ImportList.java b/sources/scalac/typechecker/ImportList.java
deleted file mode 100644
index c26bff092d..0000000000
--- a/sources/scalac/typechecker/ImportList.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/* ____ ____ ____ ____ ______ *\
-** / __// __ \/ __// __ \/ ____/ SOcos COmpiles Scala **
-** __\_ \/ /_/ / /__/ /_/ /\_ \ (c) 2002, LAMP/EPFL **
-** /_____/\____/\___/\____/____/ **
-**
-** $Id$
-\* */
-
-package scalac.typechecker;
-
-import scalac.*;
-import scalac.util.*;
-import scalac.symtab.*;
-import scalac.ast.*;
-
-/////////////////////////////////////////////////////////////////////////////
-// Import Lists
-/////////////////////////////////////////////////////////////////////////////
-
-class ImportList {
- Tree tree; // The import definition
- Scope enclscope; // The scope in which the import occurs.
- ImportList prev; // The previous active import list.
-
- ImportList(Tree tree, Scope enclscope, ImportList prev) {
- this.tree = tree;
- this.enclscope = enclscope;
- this.prev = prev;
- }
-
- public String toString() {
- String str = tree.symbol().toString();
- if (prev != null) str = prev + "; " + str;
- return str;
- }
-
- Tree importPrefix() {
- switch (tree) {
- case Import(Tree expr, _): return expr;
- default: throw new ApplicationError();
- }
- }
-
- Type importType() {
- return tree.symbol().type();
- }
-
- boolean sameImport(ImportList that) {
- return this.importType().isSameAs(that.importType());
- }
-
- Symbol importedSymbol(Name name) {
- Type t = this.importType();
- boolean renamed = false;
- switch (tree) {
- case Import(Tree expr, Name[] selectors):
- for (int i = 0; i < selectors.length; i = i + 2) {
- if (i + 1 < selectors.length && name.toTermName() == selectors[i + 1]) {
- if (name.isTypeName())
- return t.lookupNonPrivate(selectors[i].toTypeName());
- else
- return t.lookupNonPrivate(selectors[i]);
- } else if (name.toTermName() == selectors[i]) {
- renamed = true;
- } else if (selectors[i] == Names.IMPORT_WILDCARD && !renamed) {
- return t.lookupNonPrivate(name);
- }
- }
- return Symbol.NONE;
- default:
- throw new ApplicationError();
- }
- }
-}
diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java
index e5ca7f6d0d..8ccca5d586 100644
--- a/sources/scalac/typechecker/Infer.java
+++ b/sources/scalac/typechecker/Infer.java
@@ -8,1064 +8,13 @@
package scalac.typechecker;
-import scalac.Global;
-import scalac.ApplicationError;
-import scalac.*;
-import scalac.util.*;
-import scalac.ast.*;
-import scalac.symtab.*;
+import scalac.symtab.Symbol;
+import scalac.symtab.Type;
-public class Infer implements Modifiers, Kinds {
-
- Global global;
- Definitions definitions;
- TreeGen gen;
- TreeFactory make;
- Substituter substituter;
-
- public Infer(Global global, TreeGen gen, TreeFactory make) {
- this.global = global;
- this.definitions = global.definitions;
- this.gen = gen;
- this.make = make;
- this.substituter = new Substituter(global, gen);
- }
-
- public Infer(Transformer trans) {
- this(trans.global, trans.gen, trans.make);
- }
-
-// Error messages -------------------------------------------------------------
-
- public String applyErrorMsg(String msg1, Tree fn,
- String msg2, Type[] argtypes, Type pt) {
- return msg1 + toString(fn.symbol(), fn.type) + msg2 +
- ArrayApply.toString(argtypes, "(", ",", ")") +
- (pt == Type.AnyType ? "" : " with expected result type " + pt);
- }
-
- public String typeErrorMsg(String msg, Type found, Type req) {
- return msg +
- ";\n found : " + found.toLongString() +
- "\n required: " + req;
- }
-
- public String overloadResolveErrorMsg(Symbol sym1, Type tpe1, Symbol sym2, Type tpe2) {
- return "ambiguous reference to overloaded definition,\n" +
- "both " + sym1 + ": " + tpe1 + "\n" +
- "and " + sym2 + ": " + tpe2 + "\nmatch";
- }
-
- /** Give a string representation of symbol `sym' with type `tp'
- * for error diagnostics. `sym' may be null.
- */
- public String toString(Symbol sym, Type tp) {
- return
- (tp instanceof Type.OverloadedType ? "overloaded " : "") +
- (sym == null ? "expression" : sym) + " of type " + tp;
- }
-
-// Tree Substitution -------------------------------------------------------------
-
- static class Substituter extends Transformer {
-
- Symbol[] tparams;
- Type[] targs;
- TreeGen gen;
- Type.SubstTypeMap typeSubstituter;
-
- public Substituter(Global global, TreeGen gen) {
- super(global);
- this.gen = gen;
- }
-
- public Tree apply(Tree tree, Symbol[] tparams, Type[] targs) {
- this.tparams = tparams;
- this.targs = targs;
- this.typeSubstituter = new Type.SubstTypeMap(tparams, targs) {
- public boolean matches(Symbol sym1, Symbol sym2) {
- return
- sym1.name == sym2.name && sym1.owner() == sym2.owner();
- }
- };
- return transform(tree);
- }
-
- Type.Map elimInferredPolyMap = new Type.Map() {
- public Type apply(Type t) {
- switch (t) {
- case PolyType(Symbol[] tparams1, Type restp):
- if (tparams1.length == tparams.length &&
- tparams1[0] == tparams[0]) {
- for (int i = 1; i < tparams.length; i++)
- assert tparams1[i] == tparams[i];
- return apply(restp);
- }
- }
- return map(t);
- }
- };
-
- public Tree transform(Tree tree) {
-// System.out.println("[" + ArrayApply.toString(targs,"",",","") + "/" + ArrayApply.toString(tparams,"",",","") + "]" + tree + "@" + tree.symbol());//DEBUG
- if (tree.type != null) {
- tree.type = typeSubstituter.apply(
- elimInferredPolyMap.apply(tree.type));
- }
- switch (tree) {
- case Ident(Name name):
- if (name.isTypeName()) {
- Symbol sym = tree.symbol();
- for (int i = 0; i < tparams.length; i++) {
- if (typeSubstituter.matches(tparams[i], sym)) {
- return gen.mkType(tree.pos, targs[i]);
- }
- }
- }
- return tree;
-
- case TypeApply(Tree fun, Tree[] targs):
- boolean proceed = true;
- switch (fun.type) {
- case PolyType(Symbol[] tparams1, _):
- if (tparams1.length == tparams.length &&
- tparams1[0] == tparams[0] &&
- targs.length == tparams.length) {
- proceed = false;
- for (int i = 0; i < tparams.length; i++)
- if (!typeSubstituter.matches(targs[i].type.symbol(), tparams[i]))
- proceed = true;
- }
- }
- Tree fun1 = proceed ? transform(fun) : fun;
- Tree[] targs1 = transform(targs);
- return copy.TypeApply(tree, fun1, targs1);
-
-/*
- case TypeTerm():
- Symbol sym = tree.type.symbol();
- for (int i = 0; i < tparams.length; i++) {
- if (tparams[i].name == sym.name &&
- tparams[i].owner() == sym.owner()) {
- return gen.mkType(tree.pos, targs[i]);
- }
- }
- return tree;
-*/
- default:
- return super.transform(tree);
- }
- }
- }
-
-// Variance calculation ----------------------------------------------------------
-
- private static int flip(int v) {
- if (v == COVARIANT) return CONTRAVARIANT;
- else if (v == CONTRAVARIANT) return COVARIANT;
- else return v;
- }
-
- private static static int cut(int v) {
- if (v == VARIANCES) return v;
- else return 0;
- }
-
- /** Compute variances of all type parameters `tparams' in type `tp'.
- * A variance is taken from the four point lattice
- *
- * 0, Modifiers.COVARIANT, Modifiers.CONTRAVARIANT, Modifiers.VARIANCES.
- */
- private static int[] variance(Symbol[] tparams, Type tp) {
- int[] vs = new int[tparams.length];
- for (int i = 0; i < vs.length; i++) vs[i] = variance(tparams[i], tp);
- return vs;
- }
-
- /** Compute variances of all type parameters `tparams' in types `tps'.
- */
- private static int[] variance(Symbol[] tparams, Type[] tps) {
- int[] vs = new int[tparams.length];
- for (int i = 0; i < vs.length; i++) vs[i] = variance(tparams[i], tps);
- return vs;
- }
-
- /** Compute variance of type parameter `tparam' in types of all symbols `sym'.
- */
- private static int variance(Symbol tparam, Symbol[] syms) {
- int v = VARIANCES;
- for (int i = 0; i < syms.length; i++) {
- v = v & variance(tparam, syms[i]);
- }
- return v;
- }
-
- /** Compute variance of type parameter `tparam' in type of symbol `sym'.
- */
- private static int variance(Symbol tparam, Symbol sym) {
- switch (sym.kind) {
- case ERROR:
- return VARIANCES;
- case VAL:
- return variance(tparam, sym.info());
- case TYPE:
- return variance(tparam, sym.info()) &
- flip(variance(tparam, sym.loBound()));
- case ALIAS:
- return cut(variance(tparam, sym.info()));
- default:
- return 0;
- }
- }
-
- /** Compute variance of type parameter `tparam' in all types `tps'.
- */
- private static int variance(Symbol tparam, Type[] tps) {
- int v = VARIANCES;
- for (int i = 0; i < tps.length; i++) {
- v = v & variance(tparam, tps[i]);
- }
- return v;
- }
-
- /** Compute variance of type parameter `tparam' in all type arguments
- * `tps' which correspond to formal type parameters `tparams'.
- */
- private static int varianceInArgs(Symbol tvar, Type[] tps, Symbol[] tparams) {
- int v = VARIANCES;
- for (int i = 0; i < tps.length; i++) {
- if ((tparams[i].flags & COVARIANT) != 0) {
- v = v & variance(tvar, tps[i]);
- } else if ((tparams[i].flags & CONTRAVARIANT) != 0) {
- v = v & flip(variance(tvar, tps[i]));
- } else {
- v = v & cut(variance(tvar, tps[i]));
- }
- }
- return v;
- }
-
- /** Does given `tparam' occur with variance `v' in type?
- */
- private static int variance(Symbol tparam, Type tp) {
- switch (tp) {
- case ErrorType:
- case AnyType:
- case NoType:
- case ThisType(_):
- case ConstantType(_, _):
- return VARIANCES;
- case TypeRef(Type pre, Symbol sym, Type[] args):
- if (sym == tparam) return COVARIANT;
- else return variance(tparam, pre) &
- varianceInArgs(tparam, args, sym.typeParams());
- case SingleType(Type pre, Symbol sym):
- return cut(variance(tparam, pre));
- case CompoundType(Type[] parts, Scope members):
- return variance(tparam, parts) & variance(tparam, members.elements());
- case MethodType(Symbol[] params, Type restype):
- return flip(variance(tparam, params)) & variance(tparam, restype);
- case PolyType(Symbol[] tparams, Type restype):
- return flip(variance(tparam, tparams)) & variance(tparam, restype);
- default:
- throw new ApplicationError(tp.toString());
- }
- }
-
-// Type parameter inference -----------------------------------------------------
-
- private static class NoInstance extends RuntimeException {
- NoInstance(String msg) {
- super(msg);
- }
- }
-
- /** map every TypeVar to its constraint.inst field.
- * throw a NoInstance exception if a NoType or AnyType is encountered.
- */
- private static Type.Map instantiateMap = new Type.Map() {
- public Type apply(Type t) {
- return instantiate(t);
- }
- };
-
- private static Type instantiate(Type tp) throws NoInstance {
- switch (tp) {
- case AnyType:
- case NoType:
- throw new NoInstance("undetermined type");
- case TypeVar(Type origin, Type.Constraint constr):
- if (constr.inst != Type.NoType) return instantiate(constr.inst);
- else throw new NoInstance("no unique instantiation of type variable " +
- origin + " could be found");
- default:
- return instantiateMap.map(tp);
- }
- }
-
- /** Map type variable to its instance, or, if `covariant' is true,
- * to its upper bound;
- */
- private Type instantiateToBound(Type tp, int variance) {
- switch (tp) {
- case TypeVar(Type origin, Type.Constraint constr):
- try {
- if (constr.inst != Type.NoType) {
- return instantiate(constr.inst);
- } else if ((variance & COVARIANT) != 0 &&
- constr.hibounds != Type.List.EMPTY) {
- maximizeVar(tp);
- return instantiate(constr.inst);
- } else if ((variance & CONTRAVARIANT) != 0 &&
- constr.lobounds != Type.List.EMPTY) {
- minimizeVar(tp);
- return instantiate(constr.inst);
- }
- } catch (NoInstance ex) {
- }
- return Type.AnyType;
- default:
- throw new ApplicationError();
- }
- }
-
- /** The formal parameter types corresponding to `params'.
- * If `params' is a repeated parameter, a list of `length' copies
- * of its type is returned.
- */
- public Type[] formalTypes(Symbol[] params, int nargs) {
- Type[] result;
- if (params.length > 0 &&
- (params[params.length-1].flags & REPEATED) != 0) {
- Type[] args = params[params.length-1].type().typeArgs();
- if (args.length == 1) {
- Type ft = args[0];
- // last param has type Seq[T], we need T here
- Type[] formals = new Type[nargs];
- int i = 0;
- while (i < params.length-1) {
- formals[i] = params[i].type();
- i++;
- }
- while (i < nargs) {
- formals[i] = ft;
- i++;
- }
- return formals;
- }
- }
- return Symbol.type(params);
- }
-
- /** Is type fully defined, i.e. no embedded anytypes or typevars in it?
- */
- public boolean isFullyDefined(Type tp) {
- try {
- instantiate(tp);
- return true;
- } catch (NoInstance ex) {
- return false;
- }
- }
-
- /** Do type arguments `targs' conform to formal parameters `tparams'?
- */
- private boolean isWithinBounds(Symbol[] tparams, Type[] targs) {
- for (int i = 0; i < targs.length; i++) {
- Type hibound = tparams[i].info().subst(tparams, targs);
- if (!targs[i].isSubType(hibound)) {
- for (int j = 0; j < tparams.length; j++) {
- if (hibound.symbol() == tparams[j])
- return isWithinBounds(
- tparams,
- Type.subst(
- targs,
- new Symbol[]{tparams[j]},
- new Type[]{targs[i]}));
- }
- return false;
- }
- Type lobound = tparams[i].loBound().subst(tparams, targs);
- if (!lobound.isSubType(targs[i])) {
- for (int j = 0; j < tparams.length; j++) {
- if (lobound.symbol() == tparams[j])
- return isWithinBounds(
- tparams,
- Type.subst(
- targs,
- new Symbol[]{tparams[j]},
- new Type[]{targs[i]}));
- }
- return false;
- }
- }
- return true;
- }
+public abstract class Infer {
/** throw a type error if arguments not within bounds.
*/
- public void checkBounds(Symbol[] tparams, Type[] targs, String prefix) {
- if (!isWithinBounds(tparams, targs)) {
- throw new Type.Error(
- prefix + "type arguments " +
- ArrayApply.toString(targs, "[", ",", "]") + " do not conform to " +
- tparams[0].owner() + "'s type parameter bounds " +
- ArrayApply.toString(Symbol.defString(tparams), "[", ",", "]"));
- }
- }
+ public abstract void checkBounds(Symbol[] tparams, Type[] targs, String prefix);
- /** Instantiate variable to glb of its high bounds.
- */
- private void maximizeVar(Type tp) {
- switch (tp) {
- case TypeVar(Type origin, Type.Constraint constr):
- if (constr.inst == Type.NoType)
- constr.inst = Type.glb(constr.hibounds.toArray());
- break;
- default:
- throw new ApplicationError();
- }
- }
-
- /** Instantiate variable to lub of its low bounds.
- */
- private void minimizeVar(Type tp) {
- switch (tp) {
- case TypeVar(Type origin, Type.Constraint constr):
- if (constr.inst == Type.NoType)
- constr.inst = Type.lub(constr.lobounds.toArray());
- break;
- default:
- throw new ApplicationError();
- }
- }
-
- /** Solve constraint collected in types `tvars', instantiating `tvars[i]'
- * in the process.
- * @param tparams The type parameters corresponding to `tvars'
- * @param upper When `true' search for max solution else min.
- * @param variances The variances of type parameters; need to reverse
- * solution direction for all contravariant variables.
- * @param tvars All type variables to be instantiated.
- * @param i The index of the type variable to be instantiated.
- */
- private void solve(Symbol[] tparams, boolean upper, int[] variances, Type[] tvars, int i)
- throws NoInstance {
- if (tvars[i] != Type.NoType) {
- switch (tvars[i]) {
- case TypeVar(Type origin, Type.Constraint constr):
- if (constr.inst != Type.NoType) {
- constr.inst = tvars[i] = instantiate(constr.inst);
- } else {
- Type tvar = tvars[i];
- boolean up = (variances[i] != CONTRAVARIANT) ? upper
- : !upper;
- tvars[i] = Type.NoType;
- Type bound = up ? tparams[i].info() : tparams[i].loBound();
- boolean cyclic = false;
- for (int j = 0; j < tvars.length; j++) {
- if (bound.contains(tparams[j]) ||
- up && tparams[j].loBound().isSameAs(tparams[i].type()) ||
- !up && tparams[j].info().isSameAs(tparams[i].type())) {
- cyclic |= tvars[j] == Type.NoType;
- solve(tparams, upper, variances, tvars, j);
- }
- }
- if (!cyclic) {
- if (up) {
- if (bound.symbol() != Global.instance.definitions.ANY_CLASS)
- constr.hibounds = new Type.List(
- bound.subst(tparams, tvars), constr.hibounds);
- for (int j = 0; j < tvars.length; j++) {
- if (tparams[j].loBound().isSameAs(
- tparams[i].type())) {
- constr.hibounds = new Type.List(
- tparams[j].type().subst(tparams, tvars),
- constr.hibounds);
- }
- }
- } else {
- if (bound.symbol() != Global.instance.definitions.ALL_CLASS)
- constr.lobounds = new Type.List(
- bound.subst(tparams, tvars), constr.lobounds);
- for (int j = 0; j < tvars.length; j++) {
- if (tparams[j].info().isSameAs(
- tparams[i].type())) {
- constr.lobounds = new Type.List(
- tparams[j].type().subst(tparams, tvars),
- constr.lobounds);
- }
- }
- }
- }
- if (up) maximizeVar(tvar);
- else minimizeVar(tvar);
- tvars[i] = ((Type.TypeVar) tvar).constr.inst;
- }
- }
- }
- }
-
- /** Generate an array of fresh type variables corresponding to parameters
- * `tparams'
- */
- private Type[] freshVars(Symbol[] tparams) {
- Type[] tvars = new Type[tparams.length];
- for (int i = 0; i < tvars.length; i++) {
- tvars[i] = Type.TypeVar(tparams[i].type(), new Type.Constraint());
- }
- return tvars;
- }
-
- private Type.Map freshInstanceMap = new Type.Map() {
- public Type apply(Type t) {
- switch (t) {
- case PolyType(Symbol[] tparams, Type restp):
- Type restp1 = apply(restp);
- Symbol[] tparams1 = Symbol.EMPTY_ARRAY;
- Symbol[] newparams1 = Symbol.EMPTY_ARRAY;
- switch (restp1) {
- case PolyType(_, _):
- // If there is a nested polytype, we need to
- // substitute also its new type parameters for its old ones
- // here. Reason: The outer polytype may refer to type
- // variables of the inner one.
- tparams1 = restp.typeParams();
- newparams1 = restp1.typeParams();
- }
- Symbol[] newparams = new Symbol[tparams.length];
- for (int i = 0; i < tparams.length; i++)
- newparams[i] = tparams[i].cloneSymbol();
- for (int i = 0; i < tparams.length; i++) {
- newparams[i].setInfo(
- newparams[i].info()
- .subst(tparams, newparams)
- .subst(tparams1, newparams1));
- newparams[i].setLoBound(
- newparams[i].loBound()
- .subst(tparams, newparams)
- .subst(tparams1, newparams1));
- }
- return Type.PolyType(
- newparams, restp1.subst(tparams, newparams));
-
- case OverloadedType(_, _):
- return map(t);
- default:
- return t;
- }
- }
- };
-
- public Type freshInstance(Type tp) {
- return freshInstanceMap.apply(tp);
- }
-
- /** Automatically perform the following conversions on expression types:
- * A method type becomes the corresponding function type.
- * A nullary method type becomes its result type.
- */
- private Type normalize(Type tp) {
- switch (tp) {
- case MethodType(Symbol[] params, Type restype):
- return global.definitions.FUNCTION_TYPE(
- Symbol.type(params), normalize(restype));
- case PolyType(Symbol[] tparams, Type restype):
- if (tparams.length == 0) return normalize(restype);
- }
- return tp;
- }
-
- /** Is normalized type `tp' a subtype of prototype `pt'?
- */
- public boolean isCompatible(Type tp, Type pt) {
- Type tp1 = normalize(tp);
- if (tp1.isSubType(pt)) return true;
- Symbol coerceMeth = tp1.lookup(Names.coerce);
- if (coerceMeth.kind == NONE) return false;
- return canCoerce(tp1.memberType(coerceMeth), pt);
- }
- // where
- private boolean canCoerce(Type tp, Type pt) {
- switch (tp) {
- case OverloadedType(_, Type[] alttypes):
- for (int i = 0; i < alttypes.length; i++)
- if (canCoerce(alttypes[i], pt)) return true;
- return false;
- case PolyType(Symbol[] tparams, Type restype):
- return tparams.length == 0 && restype.isSubType(pt);
- default:
- return false;
- }
- }
-
- public boolean isCompatible(Type[] tps, Type[] pts) {
- for (int i = 0; i < tps.length; i++)
- if (!isCompatible(tps[i], pts[i])) return false;
- return true;
- }
-
- /** Type arguments mapped to `scala.All' are taken to be uninstantiated.
- * Map all those type arguments to their corresponding type parameters
- * and return all these type parameters as result.
- */
- private Symbol[] normalizeArgs(Type[] targs, Symbol[] tparams) {
- Type.List uninstantiated = Type.List.EMPTY;
- for (int i = 0; i < targs.length; i++) {
- if (targs[i].symbol() == Global.instance.definitions.ALL_CLASS) {
- targs[i] = tparams[i].type();
- uninstantiated = Type.List.append(uninstantiated, targs[i]);
- }
- }
- return Type.symbol(uninstantiated.toArray());
- }
-
- /** Return inferred type arguments of polymorphic expression, given
- * its type parameters and result type and a prototype `pt'.
- * If no minimal type variables exist that make the
- * instantiated type a subtype of `pt', return `null'.
- */
- private Type[] exprTypeArgs(Symbol[] tparams, Type restype, Type pt) {
- Type[] tvars = freshVars(tparams);
- Type insttype = restype.subst(tparams, tvars);
- if (isCompatible(insttype, pt)) {
- try {
- restype = normalize(restype);
- for (int i = 0; i < tvars.length; i++) {
- solve(tparams, false, variance(tparams, restype), tvars, i);
- }
- return tvars;
- } catch (NoInstance ex) {
- }
- }
- return null;
- }
-
- /** Return inferred proto-type arguments of function, given
- * its type and value parameters and result type, and a
- * prototype `pt' for the function result.
- * Type arguments need to be either determined precisely by
- * the prototype, or they are maximized, if they occur only covariantly
- * in the value parameter list.
- * If instantiation of a type parameter fails,
- * take Type.AnyType for the proto-type argument.
- */
- public Type[] protoTypeArgs(Symbol[] tparams, Type restype, Type pt,
- Symbol[] params) {
- Type[] tvars = freshVars(tparams);
- Type insttype = restype.subst(tparams, tvars);
- Type[] targs = new Type[tvars.length];
- for (int i = 0; i < tvars.length; i++) targs[i] = Type.AnyType;
- if (isCompatible(insttype, pt)) {
- try {
- for (int i = 0; i < tvars.length; i++) {
- targs[i] = instantiateToBound(
- tvars[i], variance(tparams[i], params));
- }
- } catch (NoInstance ex) {
- for (int i = 0; i < tvars.length; i++) targs[i] = Type.AnyType;
- }
- }
- return targs;
- }
-
- /** Return inferred type arguments, given type parameters, formal parameters,
- * argument types, result type and expected result type.
- * If this is not possible, throw a `NoInstance' exception, or, if
- * `needToSucceed' is false alternatively return `null'.
- * Undetermined type arguments are represented by `definitions.ALL_TYPE'.
- * No check that inferred parameters conform to their bounds is made here.
- */
- private Type[] methTypeArgs(Symbol[] tparams,
- Symbol[] params, Type[] argtypes,
- Type restp, Type pt,
- boolean needToSucceed) throws NoInstance {
- //System.out.println("methTypeArgs, tparams = " + ArrayApply.toString(tparams) + ", params = " + ArrayApply.toString(params) + ", type(params) = " + ArrayApply.toString(Symbol.type(params)) + ", argtypes = " + ArrayApply.toString(argtypes));//DEBUG
-
- Type[] tvars = freshVars(tparams);
- Type[] formals = formalTypes(params, argtypes.length);
- if (formals.length != argtypes.length) {
- if (needToSucceed)
- throw new NoInstance("parameter lists differ in length");
- return null;
- }
-
- // check first whether type variables can be fully defined from
- // expected result type.
- if (!isCompatible(restp.subst(tparams, tvars), pt)) {
- if (needToSucceed)
- throw new NoInstance("result type " + restp +
- " is incompatible with expected type " + pt);
- return null;
- }
- for (int i = 0; i < tvars.length; i++) {
- Type.TypeVar tvar = (Type.TypeVar) tvars[i];
- if (!isFullyDefined(tvar)) tvar.constr.inst = Type.NoType;
- }
-
- // Then define remaining type variables from argument types.
- for (int i = 0; i < argtypes.length; i++) {
- if (!isCompatible(argtypes[i].widen().subst(tparams, tvars),
- formals[i].subst(tparams, tvars))) {
- if (needToSucceed) {
- if (global.explaintypes) {
- Type.explainSwitch = true;
- argtypes[i].widen().subst(tparams, tvars).isSubType(
- formals[i].subst(tparams, tvars));
- Type.explainSwitch = false;
- }
- throw new NoInstance(
- typeErrorMsg(
- "argument expression's type is not compatible with formal parameter type",
- argtypes[i].widen().subst(tparams, tvars),
- formals[i].subst(tparams, tvars)));
- }
- return null;
- }
- }
- for (int i = 0; i < tvars.length; i++) {
- solve(tparams, false, variance(tparams, formals), tvars, i);
- }
- //System.out.println(" = " + ArrayApply.toString(tvars));//DEBUG
- return tvars;
- }
-
- /** Create and attribute type application node. Pass arguments for that
- * `tparams' prefix which is owned by the tree's symbol. If there are remaining
- * type parameters, substitute corresponding type arguments for them in the
- * tree. Such remaining type parameters always come from an inferred PolyType.
- */
- public Tree mkTypeApply(Tree tree, Symbol[] tparams, Type restype, Type[] targs) {
- Tree tree1 = tree;
- Symbol sym = tree.symbol();
- int i = 0;
- while (i < tparams.length && tparams[i].owner() == sym)
- i++;
- if (i < tparams.length) {
- //System.out.println("tpar " + tparams[i] + " of " + tparams[i].owner() + " <> " + sym);//DEBUG
- //new Printer().print(tree1);//DEBUG
- //System.out.println(ArrayApply.toString(targs) + "/" + i + "/" + ArrayApply.toString(tparams));//DEBUG
- Symbol[] tparams1 = new Symbol[tparams.length - i];
- System.arraycopy(tparams, i, tparams1, 0, tparams1.length);
- Type[] targs1 = new Type[tparams.length - i];
- System.arraycopy(targs, i, targs1, 0, targs1.length);
- tree1 = substituter.apply(tree1, tparams1, targs1);
- }
- if (0 < i) {
- Tree[] argtrees = new Tree[i];
- for (int j = 0; j < i; j++)
- argtrees[j] = gen.mkType(tree.pos, targs[j]);
- tree1 = make.TypeApply(tree.pos, tree1, argtrees);
- }
- //System.out.println(Sourcefile.files[Position.file(tree1.pos)] + ": ");
- return tree1.setType(restype.subst(tparams, targs));
- }
-
- /** Return the instantiated and normalized type of polymorphic expression
- * with type `[tparams]restype', given two prototypes `pt1', and `pt2'.
- * `pt1' is the strict first attempt prototype where type parameters
- * are left unchanged. `pt2' is the fall-back prototype where type parameters
- * are replaced by `AnyType's. We try to instantiate first to `pt1' and then,
- * if this fails, to `pt2'. If both attempts fail, a Type.Error is thrown.
- */
- public Type argumentTypeInstance(Symbol[] tparams, Type restype, Type pt1, Type pt2)
- throws Type.Error {
- switch (restype) {
- case PolyType(Symbol[] tparams1, Type restype1):
- Symbol[] tparams2 = new Symbol[tparams.length + tparams1.length];
- System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
- System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
- return argumentTypeInstance(tparams2, restype1, pt1, pt2);
- default:
- if (tparams.length != 0) {
- Type[] targs = exprTypeArgs(tparams, restype, pt1);
- if (targs == null)
- targs = exprTypeArgs(tparams, restype, pt2);
- if (targs == null)
- throw new Type.Error(
- typeErrorMsg(
- "polymorphic argument cannot be instantiated to formal parameter type",
- Type.PolyType(tparams, restype), pt2));
- checkBounds(tparams, targs, "inferred ");
- return restype.subst(tparams, targs);
- } else {
- return normalize(restype);
- }
- }
- }
-
- /** Instantiate expression `tree' of polymorphic type [tparams]restype,
- * using prototype `pt'.
- */
- public Tree exprInstance(Tree tree, Symbol[] tparams, Type restype, Type pt)
- throws Type.Error {
- switch (restype) {
- case PolyType(Symbol[] tparams1, Type restype1):
- Symbol[] tparams2 = new Symbol[tparams.length + tparams1.length];
- System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
- System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
- return exprInstance(tree, tparams2, restype1, pt);
- }
- Type[] targs = exprTypeArgs(tparams, restype, pt);
- if (targs == null)
- throw new Type.Error(
- "polymorphic expression of type " + tree.type +
- " cannot be instantiated from expected type " + pt);
- checkBounds(tparams, targs, "inferred ");
- return mkTypeApply(tree, tparams, restype, targs);
- }
-
- /** Instantiate method `tree' of polymorphic type [tparams]restype,
- * so that resulting method type can be applied to arguments with
- * types `argtypes' and its result type is compatible with `pt'.
- */
- public Tree methodInstance(Tree tree,
- Symbol[] tparams, Type restype,
- Type[] argtypes, Type pt)
- throws Type.Error {
- switch (restype) {
- case PolyType(Symbol[] tparams1, Type restype1):
- Symbol[] tparams2 = new Symbol[tparams.length + tparams1.length];
- System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
- System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
- return methodInstance(tree, tparams2, restype1, argtypes, pt);
- case MethodType(Symbol[] params, Type restpe):
- Type[] targs;
- try {
- targs = methTypeArgs(tparams, params, argtypes, restpe, pt, true);
- } catch (NoInstance ex) {
- throw new Type.Error(
- applyErrorMsg(
- "no type parameters for ", tree,
- " exist so that it can be applied to arguments ",
- Type.widen(argtypes), Type.AnyType) +
- "\n --- because ---\n" + ex.getMessage());
- }
- Symbol[] uninstantiated = normalizeArgs(targs, tparams);
- checkBounds(tparams, targs, "inferred ");
- Type restype1 = (uninstantiated.length == 0)
- ? restype
- : Type.MethodType(
- params, Type.PolyType(uninstantiated, restpe));
- return mkTypeApply(tree, tparams, restype1, targs);
- default:
- return tree;
- }
- }
-
- /** Instantiate constructor `tree' of polymorphic type [tparams]restype',
- * so that its the result type of `restype' matches prototype `pt'.
- * If constructor is polymorphic, maximize all type variables under this
- * condition.
- */
- public void constructorInstance(Tree tree,
- Symbol[] tparams, Type restype, Type pt)
- throws Type.Error {
- switch (restype) {
- case PolyType(Symbol[] tparams1, Type restype1):
- Symbol[] tparams2 = new Symbol[tparams.length + tparams1.length];
- System.arraycopy(tparams, 0, tparams2, 0, tparams.length);
- System.arraycopy(tparams1, 0, tparams2, tparams.length, tparams1.length);
- constructorInstance(tree, tparams2, restype1, pt);
- return;
- }
- Type[] tvars = freshVars(tparams);
- Type restype1 = restype.subst(tparams, tvars);
- Type ctpe1 = restype1.resultType();
- if (ctpe1.isSubType(pt)) {
- try {
- for (int i = 0; i < tvars.length; i++) {
- solve(tparams, true, variance(tparams, restype.resultType()),
- tvars, i);
- }
- checkBounds(tparams, tvars, "inferred ");
- tree.setType(restype.subst(tparams, tvars));
- //System.out.println("inferred constructor type: " + tree.type);//DEBUG
- } catch (NoInstance ex) {
- throw new Type.Error(
- "constructor of type " + ctpe1 +
- " can be instantiated in more than one way to expected type " +
- pt +
- "\n --- because ---\n" + ex.getMessage());
- }
- } else {
- throw new Type.Error(
- typeErrorMsg(
- "constructor cannot be instantiated to expected type",
- ctpe1, pt));
- }
- }
-
-// Overload Resolution -------------------------------------------------------------
-
- /** Is function type `ftpe' applicable to `argtypes' and
- * does its result conform to `pt'?
- */
- public boolean isApplicable(Type ftpe, Type[] argtypes, Type pt) {
- switch (ftpe) {
- case MethodType(Symbol[] params, Type restpe):
- // sequences ? List( a* )
- Type[] formals = formalTypes(params, argtypes.length);
- return
- isCompatible(restpe, pt) &&
- formals.length == argtypes.length &&
- isCompatible(argtypes, formals);
- case PolyType(Symbol[] tparams, MethodType(Symbol[] params, Type restpe)):
- try {
- Type[] targs = methTypeArgs(
- tparams, params, argtypes, restpe, pt, false);
- if (targs != null) {
- Symbol[] uninstantiated = normalizeArgs(targs, tparams);
- return
- isWithinBounds(tparams, targs) &&
- exprTypeArgs(uninstantiated, restpe.subst(tparams, targs), pt)
- != null;
- }
- } catch (NoInstance ex) {
- }
- }
- return false;
- }
-
- /** Does type `ftpe1' specialize type `ftpe2'
- * when both are alternatives in an overloaded function?
- */
- boolean specializes(Type ftpe1, Type ftpe2) {
- switch (ftpe1) {
- case MethodType(Symbol[] params, _):
- return isApplicable(ftpe2, Symbol.type(params), Type.AnyType);
- case PolyType(_, MethodType(Symbol[] params, _)):
- return isApplicable(ftpe2, Symbol.type(params), Type.AnyType);
- default:
- return false;
- }
- }
-
- /** Assign `tree' the type of the alternative which matches
- * prototype `pt', if it exists.
- * If several alternatives match `pt', take unique parameterless one.
- * Throw a Type.Error if several such alternatives exist.
- * If no alternative matches, leave `tree' unchanged.
- */
- public void exprAlternative(Tree tree, Symbol[] alts,
- Type[] alttypes, Type pt)
- throws Type.Error {
- // first, catch the case of a missing parameter
- // list for an overloaded constructor.
- if (alts.length > 0) {
- int i = 0;
- while (i < alts.length &&
- alts[i].isConstructor() &&
- alttypes[i] instanceof Type.MethodType)
- i++;
- if (i == alts.length)
- throw new Type.Error("missing arguments for " + alts[0]);
- }
- // second, do the normal case.
- int best = -1;
- for (int i = 0; i < alttypes.length; i++) {
- if (isCompatible(alttypes[i], pt) &&
- (best < 0 || improves(alttypes[i], alttypes[best], pt))) {
- best = i;
- }
- }
- for (int i = 0; i < alttypes.length; i++) {
- if (isCompatible(alttypes[i], pt) &&
- (best < 0 || improves(alttypes[i], alttypes[best], pt))) {
- best = i;
- }
- }
- if (best >= 0) {
- for (int i = 0; i < alttypes.length; i++) {
- if (isCompatible(alttypes[i], pt) &&
- best != i && !improves(alttypes[best], alttypes[i], pt)) {
- throw new Type.Error(overloadResolveErrorMsg(
- alts[best], alttypes[best], alts[i], alttypes[i]) +
- " expected type " + pt);
- }
- }
- tree.setSymbol(alts[best]).setType(alttypes[best]);
- }
- }
- //where
- private boolean improves(Type tp1, Type tp2, Type pt) {
- return
- !normalize(tp2).isSubType(pt) && normalize(tp1).isSubType(pt) ||
- tp2.isParameterized() &&
- (!tp1.isParameterized() || specializes(tp1, tp2));
- }
-
- /** Assign `tree' the type of an alternative
- * which is applicable to `argtypes', and whose result type is
- * a subtype of `pt' if it exists.
- * If several applicable alternatives exist, take the
- * most specialized one, or throw an error if no
- * most specialized applicable alternative exists.
- * If no alternative matches, leave `tree' unchanged,
- * try to select method with pt = AnyType.
- * If pt is AnyType, leave tree unchanged.
- */
- public void methodAlternative(Tree tree, Symbol[] alts, Type[] alttypes,
- Type[] argtypes, Type pt)
- throws Type.Error {
- if (alts.length == 1) {
- tree.setSymbol(alts[0]).setType(alttypes[0]);
- return;
- }
- int best = -1;
- for (int i = 0; i < alttypes.length; i++) {
- if (isApplicable(alttypes[i], argtypes, pt) &&
- (best < 0 || specializes(alttypes[i], alttypes[best]))) best = i;
- }
- if (best >= 0) {
- for (int i = 0; i < alttypes.length; i++) {
- if (i != best &&
- isApplicable(alttypes[i], argtypes, pt) &&
- !(specializes(alttypes[best], alttypes[i]) &&
- !specializes(alttypes[i], alttypes[best]))) {
- throw new Type.Error(
- overloadResolveErrorMsg(
- alts[best], alttypes[best], alts[i], alttypes[i]) +
- " argument types " +
- ArrayApply.toString(argtypes, "(", ",", ")") +
- ((pt == Type.AnyType) ? ""
- : " and expected result type " + pt));
- }
- }
- tree.setSymbol(alts[best]).setType(alttypes[best]);
- } else if (pt != Type.AnyType) {
- methodAlternative(tree, alts, alttypes, argtypes, Type.AnyType);
- }
- }
-
- /** Assign `tree' the type of unique polymorphic alternative with `nparams'
- * as the number of type parameters, if it exists.
- * Throw error if several such polymorphic alternatives exist.
- * If no alternative matches, leave `tree' unchanged.
- */
- public void polyAlternative(Tree tree,
- Symbol[] alts, Type[] alttypes, int nparams)
- throws Type.Error {
- if (alts.length == 1) {
- tree.setSymbol(alts[0]).setType(alttypes[0]);
- return;
- }
- int i = 0;
- while (i < alttypes.length &&
- !(alts[i].isValue() &&
- alttypes[i].typeParams().length == nparams)) {
- i++;
- }
- if (i < alttypes.length) {
- for (int j = i + 1; j < alttypes.length; j++) {
- if (alts[j].isValue() &&
- alttypes[j].typeParams().length == nparams)
- throw new Type.Error(overloadResolveErrorMsg(
- alts[i], alttypes[i], alts[j], alttypes[j]) +
- " polymorphic function with " + nparams + " parameters");
- }
- tree.setSymbol(alts[i]).setType(alttypes[i]);
- }
- }
}
-
diff --git a/sources/scalac/typechecker/RefCheck.java b/sources/scalac/typechecker/RefCheck.java
index 3ffe63cf40..63b092c4f0 100644
--- a/sources/scalac/typechecker/RefCheck.java
+++ b/sources/scalac/typechecker/RefCheck.java
@@ -43,7 +43,7 @@ public class RefCheck extends Transformer implements Modifiers, Kinds {
private Unit unit;
private Definitions defs = global.definitions;
- private Infer infer = new Infer(this);
+ private Infer infer = global.newInfer();
private Symbol enclClass;
public void apply(Unit unit) {