From d19cd4e6791347cfbcd161c02a49eebef4aab686 Mon Sep 17 00:00:00 2001 From: paltherr Date: Thu, 19 Feb 2004 13:08:48 +0000 Subject: - Removed java version of files translated to s... - Removed java version of files translated to scala --- config/list/compiler.lst | 12 - sources/scala/tools/dtd2scala/DeclToScala.scala | 6 +- sources/scala/tools/scalac/Global.scala | 7 +- sources/scala/tools/scalac/ast/parser/Parser.scala | 4 +- .../scala/tools/scalac/ast/parser/Scanner.scala | 143 +- sources/scala/tools/scalac/ast/parser/Tokens.scala | 153 +- sources/scala/tools/scalac/typechecker/Infer.scala | 3 +- .../scala/tools/scaladoc/HTMLGeneratorPhases.java | 4 +- sources/scala/tools/scaladoc/Main.scala | 4 +- sources/scala/tools/scaladoc/ScalaSearch.java | 4 +- sources/scalac/CompilerPhases.java | 6 +- sources/scalac/Global.java | 12 +- sources/scalac/ast/Tree.java.tmpl | 18 +- sources/scalac/ast/TreeGen.java | 59 +- sources/scalac/ast/parser/Parser.java | 2124 --------------- sources/scalac/ast/parser/ParserPhase.java | 39 - sources/scalac/ast/parser/Scanner.java | 867 ------- sources/scalac/ast/parser/TokenData.java | 44 - sources/scalac/ast/parser/Tokens.java | 92 - sources/scalac/ast/printer/HTMLTreePrinter.java | 176 -- sources/scalac/ast/printer/TextTreePrinter.java | 813 ------ sources/scalac/typechecker/Analyzer.java | 2698 -------------------- sources/scalac/typechecker/AnalyzerPhase.java | 69 +- sources/scalac/typechecker/Context.java | 65 - sources/scalac/typechecker/DeSugarize.java | 663 ----- sources/scalac/typechecker/ImportList.java | 74 - sources/scalac/typechecker/Infer.java | 1059 +------- sources/scalac/typechecker/RefCheck.java | 2 +- 28 files changed, 216 insertions(+), 9004 deletions(-) delete mode 100644 sources/scalac/ast/parser/Parser.java delete mode 100644 sources/scalac/ast/parser/ParserPhase.java delete mode 100644 sources/scalac/ast/parser/Scanner.java delete mode 100644 sources/scalac/ast/parser/TokenData.java delete mode 100644 sources/scalac/ast/parser/Tokens.java delete mode 100644 sources/scalac/ast/printer/HTMLTreePrinter.java delete mode 100644 sources/scalac/ast/printer/TextTreePrinter.java delete mode 100644 sources/scalac/typechecker/Analyzer.java delete mode 100644 sources/scalac/typechecker/Context.java delete mode 100644 sources/scalac/typechecker/DeSugarize.java delete mode 100644 sources/scalac/typechecker/ImportList.java diff --git a/config/list/compiler.lst b/config/list/compiler.lst index a94d3ac248..0d55e231a9 100644 --- a/config/list/compiler.lst +++ b/config/list/compiler.lst @@ -7,18 +7,12 @@ ApplicationError.java CompilerCommand.java CompilerPhases.java Global.java -Main.java Phase.java PhaseDescriptor.java Unit.java ast/parser/PatternNormalizer.java -ast/parser/Parser.java -ast/parser/ParserPhase.java -ast/parser/Scanner.java ast/parser/SourceRepresentation.java -ast/parser/TokenData.java -ast/parser/Tokens.java ast/DefaultTreeFactory.java ast/LazyTreeCopier.java @@ -34,8 +28,6 @@ ast/TreeInfo.java ast/TreeList.java ast/TreeSymbolCloner.java -ast/printer/HTMLTreePrinter.java -ast/printer/TextTreePrinter.java ast/printer/TreePrinter.java atree/AArithmeticOp.java @@ -151,12 +143,8 @@ transformer/matching/TestRegTraverser.java transformer/matching/VariableTraverser.java transformer/matching/WordAutomInScala.java -typechecker/Analyzer.java typechecker/AnalyzerPhase.java typechecker/ConstantFolder.java -typechecker/Context.java -typechecker/DeSugarize.java -typechecker/ImportList.java typechecker/Infer.java typechecker/RefCheck.java typechecker/RefCheckPhase.java diff --git a/sources/scala/tools/dtd2scala/DeclToScala.scala b/sources/scala/tools/dtd2scala/DeclToScala.scala index a77def66d7..2fd33d7721 100644 --- a/sources/scala/tools/dtd2scala/DeclToScala.scala +++ b/sources/scala/tools/dtd2scala/DeclToScala.scala @@ -1,5 +1,5 @@ import scalac.util.Name ; -import scalac.ast.parser.Scanner ; /* for keywords */ +import scala.tools.scalac.ast.parser.Tokens ; /* for keywords */ package scala.tools.dtd2scala { @@ -127,7 +127,7 @@ private def cooked( ckd:StringBuffer, raw:String, off:int ):String = { }; }; - if( toy.isKeyword(raw)) { + if( Tokens.isKeyword(raw)) { val _ = ckd.append('$'); }; ckd.toString() @@ -149,7 +149,7 @@ private def cookedCap( raw:String ):String = { cooked( ckd, raw, 1); } - private val toy:Scanner = new Scanner(); + Tokens; // initialize tokens } diff --git a/sources/scala/tools/scalac/Global.scala b/sources/scala/tools/scalac/Global.scala index f0bf5ff96e..6d3ec6a9fd 100644 --- a/sources/scala/tools/scalac/Global.scala +++ b/sources/scala/tools/scalac/Global.scala @@ -13,6 +13,7 @@ package scala.tools.scalac { import ast.printer._; import java.io.PrintWriter; +import typechecker.Infer; /** The global environment of a compiler run * @@ -21,9 +22,11 @@ class Global(args: CompilerCommand, interpret: boolean) extends scalac_Global(ar def this(args: CompilerCommand) = this(args, false); - protected override def newTextTreePrinter(writer: PrintWriter): TreePrinter = + override def newInfer(): Infer = + new Infer(this, treeGen, make); + override def newTextTreePrinter(writer: PrintWriter): TreePrinter = new TextTreePrinter(writer); - protected override def newHTMLTreePrinter(writer: PrintWriter): TreePrinter = + override def newHTMLTreePrinter(writer: PrintWriter): TreePrinter = new HTMLTreePrinter(writer); } diff --git a/sources/scala/tools/scalac/ast/parser/Parser.scala b/sources/scala/tools/scalac/ast/parser/Parser.scala index 3e7342eb9a..baa8ca728e 100644 --- a/sources/scala/tools/scalac/ast/parser/Parser.scala +++ b/sources/scala/tools/scalac/ast/parser/Parser.scala @@ -106,8 +106,8 @@ class Parser(unit: Unit) { val errpos = if ((s.pos >>> Position.COLUMN_BITS) > (s.lastpos >>> Position.COLUMN_BITS)) s.lastpos else s.pos; - syntaxError(errpos, s.token2string(token) + " expected but " + - s.token2string(s.token) + " found.", true); + syntaxError(errpos, Tokens.token2string(token) + " expected but " + + Tokens.token2string(s.token) + " found.", true); } if (s.token == token) s.nextToken(); pos diff --git a/sources/scala/tools/scalac/ast/parser/Scanner.scala b/sources/scala/tools/scalac/ast/parser/Scanner.scala index 27dd6c2725..047adbfe85 100644 --- a/sources/scala/tools/scalac/ast/parser/Scanner.scala +++ b/sources/scala/tools/scalac/ast/parser/Scanner.scala @@ -46,16 +46,6 @@ class Scanner(_unit: Unit) extends TokenData { val CR = SourceFile.CR; val SU = SourceFile.SU; - /** the names of all tokens - */ - var tokenName = new Array[Name](128); - var numToken = 0; - - /** keyword array; maps from name indices to tokens - */ - var key: Array[byte] = _; - var maxKey = 0; - /** we need one token lookahead */ val next = new TokenData(); @@ -93,7 +83,7 @@ class Scanner(_unit: Unit) extends TokenData { */ token = EMPTY; nextch(); - init(); + Tokens; // initialize tokens nextToken(); def nextch(): unit = { @@ -459,14 +449,9 @@ class Scanner(_unit: Unit) extends TokenData { } } - /** returns true if argument corresponds to a keyword. - * Used in dtd2scala tool. - */ - def isKeyword(str: String) = Name.fromString(str).index <= maxKey; - def treatIdent(start: int, end: int) = { name = Name.fromAscii(buf, start, end - start); - token = if (name.index <= maxKey) key(name.index) else IDENTIFIER; + token = name2token(name); } /** generate an error at the given position @@ -787,61 +772,6 @@ class Scanner(_unit: Unit) extends TokenData { } /* end XML tokenizing */ - def name2token(name: Name): int = - if (name.index <= maxKey) key(name.index) else IDENTIFIER; - - def token2string(token: int): String = token match { - case IDENTIFIER => - "identifier"/* + \""+name+"\""*/ - case CHARLIT => - "character literal" - case INTLIT => - "integer literal" - case LONGLIT => - "long literal" - case FLOATLIT => - "float literal" - case DOUBLELIT => - "double literal" - case STRINGLIT => - "string literal" - case SYMBOLLIT => - "symbol literal" - case LPAREN => - "'('" - case RPAREN => - "')'" - case LBRACE => - "'{'" - case RBRACE => - "'}'" - case LBRACKET => - "'['" - case RBRACKET => - "']'" - case EOF => - "eof" - case ERROR => - "something" - case SEMI => - "';'" - case COMMA => - "','" - case CASECLASS => - "case class" - case CASEOBJECT => - "case object" - case _ => - try { - "'" + tokenName(token).toString() + "'" - } catch { - case _: ArrayIndexOutOfBoundsException => - "'<" + token + ">'" - case _: NullPointerException => - "'<(" + token + ")>'" - } - } - override def toString() = token match { case IDENTIFIER => "id(" + name + ")" @@ -864,74 +794,5 @@ class Scanner(_unit: Unit) extends TokenData { case _ => token2string(token) } - - protected def enterKeyword(s: String, tokenId: int) = { - while (tokenId > tokenName.length) { - val newTokName = new Array[Name](tokenName.length * 2); - System.arraycopy(tokenName, 0, newTokName, 0, newTokName.length); - tokenName = newTokName; - } - val n = Name.fromString(s); - tokenName(tokenId) = n; - if (n.index > maxKey) maxKey = n.index; - if (tokenId >= numToken) numToken = tokenId + 1; - } - - protected def init() = { - initKeywords(); - key = new Array[byte](maxKey+1); - for (val i <- Iterator.range(0, maxKey)) - key(i) = IDENTIFIER; - for (val j <- Iterator.range(0, numToken)) - if (tokenName(j) != null) key(tokenName(j).index) = j.asInstanceOf[byte]; - } - - protected def 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/scala/tools/scalac/ast/parser/Tokens.scala b/sources/scala/tools/scalac/ast/parser/Tokens.scala index c94e4b7c22..e7a1f6875c 100644 --- a/sources/scala/tools/scalac/ast/parser/Tokens.scala +++ b/sources/scala/tools/scalac/ast/parser/Tokens.scala @@ -6,15 +6,27 @@ ** $Id$ \* */ -package scala.tools.scalac.ast.parser; +import scalac.util.Name; + +package scala.tools.scalac.ast.parser { object Tokens { + + /** The token names */ + private var tokenName = new Array[Name](128); + private var numToken = 0; + + /** Keyword array; maps from name indices to tokens */ + private var key: Array[byte] = _; + private var maxKey = 0; + + /** special tokens */ val EMPTY = -3; val UNDEF = -2; val ERROR = -1; val EOF = 0; - /* literals */ + /** literals */ val CHARLIT = 1; val INTLIT = 2; val LONGLIT = 3; @@ -23,10 +35,10 @@ object Tokens { val STRINGLIT = 6; val SYMBOLLIT = 7; - /* identifier */ + /** identifier */ val IDENTIFIER = 10; - /* keywords */ + /** keywords */ val IF = 20; val FOR = 21; val ELSE = 22; @@ -66,7 +78,7 @@ object Tokens { val WHILE = 56; val RETURN = 57; - /* special symbols */ + /** special symbols */ val COMMA = 61; val SEMI = 62; val DOT = 63; @@ -80,13 +92,140 @@ object Tokens { val HASH = 71; val AT = 72; - /* parenthesis */ + /** parenthesis */ val LPAREN = 90; val RPAREN = 91; val LBRACKET = 92; val RBRACKET = 93; val LBRACE = 94; val RBRACE = 95; -} + /** Returns true if argument corresponds to a keyword. */ + def isKeyword(str: String) = Name.fromString(str).index <= maxKey; + + /** Returns the token corresponding to given name. */ + def name2token(name: Name): int = + if (name.index <= maxKey) key(name.index) else IDENTIFIER; + + /** Returns the string representation of given token. */ + def token2string(token: int): String = token match { + case IDENTIFIER => + "identifier"/* + \""+name+"\""*/ + case CHARLIT => + "character literal" + case INTLIT => + "integer literal" + case LONGLIT => + "long literal" + case FLOATLIT => + "float literal" + case DOUBLELIT => + "double literal" + case STRINGLIT => + "string literal" + case SYMBOLLIT => + "symbol literal" + case LPAREN => + "'('" + case RPAREN => + "')'" + case LBRACE => + "'{'" + case RBRACE => + "'}'" + case LBRACKET => + "'['" + case RBRACKET => + "']'" + case EOF => + "eof" + case ERROR => + "something" + case SEMI => + "';'" + case COMMA => + "','" + case CASECLASS => + "case class" + case CASEOBJECT => + "case object" + case _ => + try { + "'" + tokenName(token).toString() + "'" + } catch { + case _: ArrayIndexOutOfBoundsException => + "'<" + token + ">'" + case _: NullPointerException => + "'<(" + token + ")>'" + } + } + // Enter keywords + 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); + + // Build keyword array + key = new Array[byte](maxKey+1); + for (val i <- Iterator.range(0, maxKey)) + key(i) = IDENTIFIER; + for (val j <- Iterator.range(0, numToken)) + if (tokenName(j) != null) key(tokenName(j).index) = j.asInstanceOf[byte]; + + private def enterKeyword(s: String, tokenId: int) = { + while (tokenId > tokenName.length) { + val newTokName = new Array[Name](tokenName.length * 2); + System.arraycopy(tokenName, 0, newTokName, 0, newTokName.length); + tokenName = newTokName; + } + val n = Name.fromString(s); + tokenName(tokenId) = n; + if (n.index > maxKey) maxKey = n.index; + if (tokenId >= numToken) numToken = tokenId + 1; + } + +} + +} diff --git a/sources/scala/tools/scalac/typechecker/Infer.scala b/sources/scala/tools/scalac/typechecker/Infer.scala index c0bf52441f..72c6888692 100644 --- a/sources/scala/tools/scalac/typechecker/Infer.scala +++ b/sources/scala/tools/scalac/typechecker/Infer.scala @@ -9,6 +9,7 @@ import java.lang.Object; import scalac.{Global => scalac_Global} +import scalac.typechecker.{Infer => scalac_Infer} import scalac.ApplicationError; import scalac.util._; import scalac.ast._; @@ -18,7 +19,7 @@ import scala.tools.scalac.util.NewArray; package scala.tools.scalac.typechecker { -class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) { +class Infer(global: scalac_Global, gen: TreeGen, make: TreeFactory) extends scalac_Infer { import Modifiers._, Kinds._; diff --git a/sources/scala/tools/scaladoc/HTMLGeneratorPhases.java b/sources/scala/tools/scaladoc/HTMLGeneratorPhases.java index 7d97bd9593..a25eddc242 100644 --- a/sources/scala/tools/scaladoc/HTMLGeneratorPhases.java +++ b/sources/scala/tools/scaladoc/HTMLGeneratorPhases.java @@ -8,14 +8,14 @@ package scala.tools.scaladoc; -import scalac.CompilerPhases; +import scala.tools.scalac.CompilerPhases$class; import scalac.PhaseDescriptor; /** * The class HTMLGeneratorPhases defines the set * of processing phases belonging the the HTML generator tool. */ -public class HTMLGeneratorPhases extends CompilerPhases { +public class HTMLGeneratorPhases extends CompilerPhases$class { //######################################################################## // Public Fields diff --git a/sources/scala/tools/scaladoc/Main.scala b/sources/scala/tools/scaladoc/Main.scala index d75d436290..e4c95f121e 100644 --- a/sources/scala/tools/scaladoc/Main.scala +++ b/sources/scala/tools/scaladoc/Main.scala @@ -6,7 +6,7 @@ // $Id$ -import scalac.Global; +import scala.tools.scalac.Global$class; import scalac.util.Reporter; package scala.tools.scaladoc { @@ -30,7 +30,7 @@ object Main { val command = new HTMLGeneratorCommand( PRODUCT, VERSION, reporter, new HTMLGeneratorPhases()); if (command.parse(args) && command.files.list.size() > 0) { - val global = new Global(command); + val global = new Global$class(command); global.compile(command.files.toArray(), false); global.stop("total"); global.reporter.printSummary(); diff --git a/sources/scala/tools/scaladoc/ScalaSearch.java b/sources/scala/tools/scaladoc/ScalaSearch.java index de70ccaba0..b23371cd4e 100644 --- a/sources/scala/tools/scaladoc/ScalaSearch.java +++ b/sources/scala/tools/scaladoc/ScalaSearch.java @@ -33,7 +33,7 @@ import scalac.util.NameTransformer; import java.io.*; import scalac.ast.printer.*; import ch.epfl.lamp.util.SourceFile; -import scalac.ast.parser.Parser; +import scala.tools.scalac.ast.parser.Parser$class; import scalac.Unit; /** @@ -499,7 +499,7 @@ public class ScalaSearch { sourceFile = new SourceFile("tmp.scala", in); } catch(IOException e) { } Unit tmpUnit = new Unit(global, sourceFile, false); - tmpUnit.body = new Parser(tmpUnit).parse(); + tmpUnit.body = new Parser$class(tmpUnit).parse(); //TreePrinter treePrinter = new TextTreePrinter(System.out); //treePrinter.print(tmpUnit); global.PHASE.ANALYZER.phase().apply(new Unit[]{ tmpUnit }); 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(" " + 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 or - * 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/**/ 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/**/ 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(""); - out.println(""); - out.println(""); - out.println(""); - out.println(""); - out.println("Scala tree"); - out.println(""); - out.println(""); - - started = true; - } - - public void end() { - assert started; - - out.println(""); - out.println(""); - 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("
"); - 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(""); - } - - 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/**/ 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(""); - protected static final Text TXT_UNKNOWN = Text.Simple(""); - protected static final Text TXT_NULL = Text.Simple(""); - protected static final Text TXT_OBJECT_COMMENT - = Text.Simple("/*object*/ "); - protected static final Text TXT_EMPTY = Text.Simple(""); - - 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(""); - 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(" => "); - 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 ? "" : 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/**/ contexts = new HashMap(); - final ArrayList/**/ 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) { -- cgit v1.2.3