diff options
Diffstat (limited to 'sources/scalac')
-rw-r--r-- | sources/scalac/ast/LazyTreeFactory.java | 10 | ||||
-rw-r--r-- | sources/scalac/ast/Transformer.java | 5 | ||||
-rw-r--r-- | sources/scalac/ast/Traverser.java | 4 | ||||
-rw-r--r-- | sources/scalac/ast/Tree.java | 12 | ||||
-rw-r--r-- | sources/scalac/ast/TreeCopyFactory.java | 3 | ||||
-rw-r--r-- | sources/scalac/ast/TreeCreator.java | 7 | ||||
-rw-r--r-- | sources/scalac/ast/TreeFactory.java | 3 | ||||
-rw-r--r-- | sources/scalac/ast/parser/Parser.java | 143 | ||||
-rw-r--r-- | sources/scalac/ast/parser/Scanner.java | 35 | ||||
-rw-r--r-- | sources/scalac/ast/parser/Tokens.java | 6 | ||||
-rw-r--r-- | sources/scalac/ast/printer/TextTreePrinter.java | 7 | ||||
-rw-r--r-- | sources/scalac/symtab/Definitions.java | 13 | ||||
-rw-r--r-- | sources/scalac/symtab/Modifiers.java | 15 | ||||
-rw-r--r-- | sources/scalac/symtab/Symbol.java | 12 | ||||
-rw-r--r-- | sources/scalac/symtab/Type.java | 28 | ||||
-rw-r--r-- | sources/scalac/transformer/UnCurry.java | 14 | ||||
-rw-r--r-- | sources/scalac/typechecker/Analyzer.java | 119 | ||||
-rw-r--r-- | sources/scalac/typechecker/DeSugarize.java | 56 | ||||
-rw-r--r-- | sources/scalac/typechecker/Infer.java | 25 | ||||
-rw-r--r-- | sources/scalac/util/Names.java | 6 |
20 files changed, 271 insertions, 252 deletions
diff --git a/sources/scalac/ast/LazyTreeFactory.java b/sources/scalac/ast/LazyTreeFactory.java index 43cef5652a..26f5f9a98f 100644 --- a/sources/scalac/ast/LazyTreeFactory.java +++ b/sources/scalac/ast/LazyTreeFactory.java @@ -397,16 +397,6 @@ public class LazyTreeFactory extends AbstractTreeCopyFactory { return tree; } - public Tree TupleType(Tree tree, - Tree[] types) { - TupleType t = (TupleType)tree; - if (t.types == types) - return t; - tree = make.TupleType(t.pos, types); - attribute(tree, t); - return tree; - } - public Tree AppliedType(Tree tree, Tree tpe, Tree[] args) { diff --git a/sources/scalac/ast/Transformer.java b/sources/scalac/ast/Transformer.java index 1789801c7e..5425f2ebf3 100644 --- a/sources/scalac/ast/Transformer.java +++ b/sources/scalac/ast/Transformer.java @@ -312,9 +312,6 @@ public class Transformer extends Phase { return copy.CompoundType(tree, transform(parents), transform(refinements)); - case TupleType(Tree[] types): - return copy.TupleType(tree, - transform(types)); case AppliedType(Tree tpe, Tree[] args): return copy.AppliedType(tree, transform(tpe), @@ -389,8 +386,6 @@ public class Transformer extends Phase { case CompoundType(Tree[] baseTypes, Tree[] refinements): - case TupleType(Tree[] types): - case AppliedType(Tree tpe, Tree[] args): default: diff --git a/sources/scalac/ast/Traverser.java b/sources/scalac/ast/Traverser.java index 5c39d9e315..ad40be1f06 100644 --- a/sources/scalac/ast/Traverser.java +++ b/sources/scalac/ast/Traverser.java @@ -185,10 +185,6 @@ public class Traverser { traverse(refinements); return; - case TupleType(Tree[] types): - traverse(types); - return; - case AppliedType(Tree tpe, Tree[] args): traverse(tpe); traverse(args); diff --git a/sources/scalac/ast/Tree.java b/sources/scalac/ast/Tree.java index 80304ea78e..6ee74544e1 100644 --- a/sources/scalac/ast/Tree.java +++ b/sources/scalac/ast/Tree.java @@ -309,17 +309,6 @@ public class Tree { } } -/** tuple type (~ Tuple) - */ - public case TupleType(Tree[] types) { - if (types != null) { - for (int i = 0; i < types.length; i++) { - if (!types[i].isType()) - throw new ApplicationError("TupleType requires types."); - } - } - } - /** applied type */ public case AppliedType(Tree tpe, Tree[] args) { @@ -755,7 +744,6 @@ public class Tree { case SelectFromType(_, _): case CompoundType(_, _): case FunType(_, _): - case TupleType(_): case AppliedType(_, _): case CovariantType(_): return true; diff --git a/sources/scalac/ast/TreeCopyFactory.java b/sources/scalac/ast/TreeCopyFactory.java index 5a9074c39f..76294fd583 100644 --- a/sources/scalac/ast/TreeCopyFactory.java +++ b/sources/scalac/ast/TreeCopyFactory.java @@ -152,9 +152,6 @@ public interface TreeCopyFactory { Tree[] baseTypes, Tree[] refinements); - public Tree TupleType(Tree tree, - Tree[] types); - public Tree AppliedType(Tree tree, Tree tpe, Tree[] args); diff --git a/sources/scalac/ast/TreeCreator.java b/sources/scalac/ast/TreeCreator.java index 6cb8afa1d8..e9bb124465 100644 --- a/sources/scalac/ast/TreeCreator.java +++ b/sources/scalac/ast/TreeCreator.java @@ -269,13 +269,6 @@ public class TreeCreator implements TreeFactory { return t; } - public Tree TupleType(int pos, - Tree[] types) { - Tree t = new TupleType(types); - t.pos = pos; - return t; - } - public Tree AppliedType(int pos, Tree tpe, Tree[] args) { diff --git a/sources/scalac/ast/TreeFactory.java b/sources/scalac/ast/TreeFactory.java index 31ee67042e..a5d6b914bc 100644 --- a/sources/scalac/ast/TreeFactory.java +++ b/sources/scalac/ast/TreeFactory.java @@ -143,9 +143,6 @@ public interface TreeFactory { Tree[] baseTypes, Tree[] refinements); - public Tree TupleType(int pos, - Tree[] types); - public Tree AppliedType(int pos, Tree tpe, Tree[] args); diff --git a/sources/scalac/ast/parser/Parser.java b/sources/scalac/ast/parser/Parser.java index cd491e2af9..f9aa54cb3a 100644 --- a/sources/scalac/ast/parser/Parser.java +++ b/sources/scalac/ast/parser/Parser.java @@ -141,10 +141,11 @@ public class Parser implements Tokens { boolean isExprIntro() { switch (s.token) { case CHARLIT: case INTLIT: case LONGLIT: - case FLOATLIT: case DOUBLELIT: case STRINGLIT: case NULL: - case IDENTIFIER: case THIS: case SUPER: - case IF: case FOR: case NEW: case USCORE: - case LPAREN: case LBRACKET: case LBRACE: + case FLOATLIT: case DOUBLELIT: case STRINGLIT: + case SYMBOLLIT: case NULL: case IDENTIFIER: + case THIS: case SUPER: case IF: + case FOR: case NEW: case USCORE: + case LPAREN: case LBRACE: return true; default: return false; @@ -191,12 +192,44 @@ public class Parser implements Tokens { return make.Select(pos, make.Ident(pos, Names.scala), Names.Any.toTypeName()); } + /** Create tree representing type scala.Seq + */ + Tree scalaSeqType(int pos) { + return make.Select(pos, make.Ident(pos, Names.scala), Names.Seq.toTypeName()); + } + /** Create tree representing constructor scala.Object */ Tree scalaObjectConstr(int pos) { return make.Select(pos, make.Ident(pos, Names.scala), Names.Object.toConstrName()); } + /** Create tree representing method scala.Symbol + */ + Tree scalaSymbol(int pos) { + return make.Select(pos, make.Ident(pos, Names.scala), Names.Symbol); + } + + /** Create tree representing method scala.Labelled + */ + Tree scalaLabelled(int pos) { + return make.Select(pos, make.Ident(pos, Names.scala), Names.Labelled); + } + + /** Create tree representing method scala.Predef.List + */ + Tree scalaPredefList(int pos) { + return make.Select(pos, + make.Select(pos, make.Ident(pos, Names.scala), Names.Predef), + Names.List); + } + + /** Create tree representing type scala.List + */ + Tree scalaListType(int pos) { + return make.Select(pos, make.Ident(pos, Names.scala), Names.List.toTypeName()); + } + /** Create tree for for-comprehension <for (enums) do body> or * <for (enums) yield body> where mapName and flatmapName are chosen * corresponding to whether this is a for-do or a for-yield. @@ -364,6 +397,7 @@ public class Parser implements Tokens { static final Name PLUS = Name.fromString("+"); static final Name BANG = Name.fromString("!"); static final Name TILDE = Name.fromString("~"); + static final Name STAR = Name.fromString("*"); Name ident() { if (s.token == IDENTIFIER) { @@ -431,9 +465,10 @@ public class Parser implements Tokens { } /** SimpleExpr ::= literal + * | symbol [ArgumentExprs] * | null */ - Tree literal() { + Tree literal(boolean isPattern) { Tree t; switch (s.token) { case CHARLIT: @@ -457,6 +492,23 @@ public class Parser implements Tokens { case NULL: t = make.Ident(s.pos, Names.null_); break; + case SYMBOLLIT: + Tree symt = scalaSymbol(s.pos); + if (isPattern) symt = convertToTypeId(symt); + t = make.Apply(s.pos, + symt, + new Tree[]{make.Literal(s.pos, s.name.toString())}); + s.nextToken(); + if (s.token == LPAREN || s.token == LBRACE) { + Tree labt = scalaLabelled(s.pos); + if (isPattern) labt = convertToTypeId(labt); + Tree listt = isPattern ? scalaListType(s.pos) + : scalaPredefList(s.pos); + t = make.Apply(s.pos, + labt, + new Tree[]{t, make.Apply(s.pos, listt, argumentExprs())}); + } + return t; default: return syntaxError("illegal literal", true); } @@ -549,7 +601,6 @@ public class Parser implements Tokens { * | SimpleType `#' Id * | StableId * | StableRef `.' type - * | `[' Types `]' * | `(' Type `)' */ Tree simpleType() { @@ -559,11 +610,6 @@ public class Parser implements Tokens { s.nextToken(); t = type(); accept(RPAREN); - } else if (s.token == LBRACKET) { - s.nextToken(); - Tree[] ts = types(); - accept(RBRACKET); - t = make.TupleType(pos, ts); } else { t = convertToTypeId(stableRef(false, true)); } @@ -744,7 +790,6 @@ public class Parser implements Tokens { * | super `.' Id * | SimpleExpr `.' Id * | `(' [Expr] `)' - * | `[' [Exprs] `]' * | BlockExpr * | SimpleExpr `@' TypeArgs * | SimpleExpr ArgumentExprs @@ -760,8 +805,9 @@ public class Parser implements Tokens { case FLOATLIT: case DOUBLELIT: case STRINGLIT: + case SYMBOLLIT: case NULL: - t = literal(); + t = literal(false); break; case IDENTIFIER: case THIS: @@ -794,14 +840,6 @@ public class Parser implements Tokens { } } break; - case LBRACKET: - int pos = s.skipToken(); - Tree[] ts; - if (s.token == RBRACKET) ts = Tree.EMPTY_ARRAY; - else ts = exprs(); - t = make.Tuple(pos, ts); - accept(RBRACKET); - break; case LBRACE: t = blockExpr(); break; @@ -816,12 +854,10 @@ public class Parser implements Tokens { case DOT: t = make.Select(s.skipToken(), t, ident()); break; - case AT: - int pos = s.skipToken(); - t = make.TypeApply(pos, t, typeArgs()); + case LBRACKET: + t = make.TypeApply(s.pos, t, typeArgs()); break; case LPAREN: - case LBRACKET: case LBRACE: t = make.Apply(s.pos, t, argumentExprs()); break; @@ -832,19 +868,12 @@ public class Parser implements Tokens { } /** ArgumentExprs ::= `(' [Exprs] `)' - * | `[' [Exprs] `]' * | BlockExpr */ Tree[] argumentExprs() { Tree[] ts = Tree.EMPTY_ARRAY; if (s.token == LBRACE) { ts = new Tree[]{blockExpr()}; - } else if (s.token == LBRACKET) { - int pos = s.skipToken(); - if (s.token != RBRACKET) - ts = exprs(); - accept(RBRACKET); - ts = new Tree[]{make.Tuple(pos, ts)}; } else { accept(LPAREN); if (s.token != RPAREN) @@ -982,15 +1011,14 @@ public class Parser implements Tokens { * | null * | StableId {ArgumentPatterns} * | `(' Pattern `)' - * | `[' [Patterns] `]' */ Tree simplePattern() { switch (s.token) { case IDENTIFIER: case THIS: Tree t = stableId(); - while (s.token == LPAREN || s.token == LBRACKET) { - t = make.Apply(s.pos, convertToConstr(t), argumentPatterns()); + while (s.token == LPAREN) { + t = make.Apply(s.pos, convertToTypeId(t), argumentPatterns()); } return t; case USCORE: @@ -1001,45 +1029,28 @@ public class Parser implements Tokens { case FLOATLIT: case DOUBLELIT: case STRINGLIT: + case SYMBOLLIT: case NULL: - return literal(); + return literal(true); case LPAREN: s.nextToken(); Tree t = pattern(); accept(RPAREN); return t; - case LBRACKET: - return tuplePattern(); default: return syntaxError("illegal start of pattern", true); } } - /** SimplePattern ::= `[' [Patterns] ']' - */ - Tree tuplePattern() { - int pos = accept(LBRACKET); - Tree[] ts; - if (s.token == RBRACKET) ts = Tree.EMPTY_ARRAY; - else ts = patterns(); - accept(RBRACKET); - return make.Tuple(pos, ts); - } - - /** ArgumentPatterns ::= `(' [Patterns] `)' - * | `[' [Patterns] `]' + /** ArgumentPatterns ::= `[' [Patterns] `]' */ Tree[] argumentPatterns() { - if (s.token == LBRACKET) { - return new Tree[]{tuplePattern()}; - } else { - Tree[] ts = Tree.EMPTY_ARRAY; - accept(LPAREN); - if (s.token != RPAREN) - ts = patterns(); - accept(RPAREN); - return ts; - } + Tree[] ts = Tree.EMPTY_ARRAY; + accept(LPAREN); + if (s.token != RPAREN) + ts = patterns(); + accept(RPAREN); + return ts; } ////////// MODIFIERS //////////////////////////////////////////////////////////// @@ -1133,7 +1144,7 @@ public class Parser implements Tokens { return (ValDef[])params.copyTo(new ValDef[params.length()]); } - /** Param ::= [def] Id `:' Type + /** Param ::= [def] Id `:' Type [`*'] */ ValDef param() { int pos = s.pos; @@ -1144,7 +1155,13 @@ public class Parser implements Tokens { } Name name = ident(); accept(COLON); - return (ValDef)make.ValDef(pos, mods, name, type(), Tree.Empty); + Tree tp = type(); + if (s.token == IDENTIFIER && s.name == STAR) { + s.nextToken(); + mods |= Modifiers.REPEATED; + tp = make.AppliedType(tp.pos, scalaSeqType(tp.pos), new Tree[]{tp}); + } + return (ValDef)make.ValDef(pos, mods, name, tp, Tree.Empty); } /** TypeParamClauseOpt ::= [`[' TypeSig {`,' TypeSig} `]'] diff --git a/sources/scalac/ast/parser/Scanner.java b/sources/scalac/ast/parser/Scanner.java index 0e4af3a09d..a86014d650 100644 --- a/sources/scalac/ast/parser/Scanner.java +++ b/sources/scalac/ast/parser/Scanner.java @@ -113,7 +113,7 @@ public class Scanner extends TokenData { case YIELD: case DO: case COMMA: case SEMI: case DOT: case COLON: case EQUALS: case ARROW: - case LARROW: case SUBTYPE: case AT: + case LARROW: case SUBTYPE: case HASH: case AS: case IS: case RPAREN: case RBRACKET: case RBRACE: break; @@ -249,7 +249,31 @@ public class Scanner extends TokenData { case '\'': nextch(); litlen = 0; - getlitch(); + 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': + index = bp; + putch(ch); + nextch(); + if (ch != '\'') { + getIdentRest(index); + token = SYMBOLLIT; + return; + } + break; + default: + getlitch(); + } if (ch == '\'') { nextch(); token = CHARLIT; @@ -668,6 +692,8 @@ public class Scanner extends TokenData { return "double literal"; case STRINGLIT: return "string literal"; + case SYMBOLLIT: + return "symbol literal"; case LPAREN: return "'('"; case RPAREN: @@ -688,11 +714,15 @@ public class Scanner extends TokenData { return "';'"; case COMMA: return "','"; + case CASECLASS: + return "case class"; default: try { return "'" + tokenName[token].toString() + "'"; } catch (ArrayIndexOutOfBoundsException e) { return "'<" + token + ">'"; + } catch (NullPointerException e) { + return "'<(" + token + ")>'"; } } } @@ -782,7 +812,6 @@ public class Scanner extends TokenData { enterKeyword("<:", SUBTYPE); enterKeyword("yield", YIELD); enterKeyword("do", DO); - enterKeyword("@", AT); enterKeyword("#", HASH); enterKeyword("trait", TRAIT); enterKeyword("as", AS); diff --git a/sources/scalac/ast/parser/Tokens.java b/sources/scalac/ast/parser/Tokens.java index 6c3bef6a55..2fa82eb5f3 100644 --- a/sources/scalac/ast/parser/Tokens.java +++ b/sources/scalac/ast/parser/Tokens.java @@ -21,6 +21,7 @@ public interface Tokens { FLOATLIT = 4, DOUBLELIT = 5, STRINGLIT = 6, + SYMBOLLIT = 7, /* identifier */ IDENTIFIER = 10, @@ -66,11 +67,10 @@ public interface Tokens { USCORE = 64, COLON = 65, EQUALS = 66, - LARROW = 57, + LARROW = 67, ARROW = 68, SUBTYPE = 69, - AT = 70, - HASH = 71, + HASH = 70, /* parenthesis */ LPAREN = 90, diff --git a/sources/scalac/ast/printer/TextTreePrinter.java b/sources/scalac/ast/printer/TextTreePrinter.java index 6cb7ac368c..58010b8412 100644 --- a/sources/scalac/ast/printer/TextTreePrinter.java +++ b/sources/scalac/ast/printer/TextTreePrinter.java @@ -170,7 +170,6 @@ public class TextTreePrinter implements TreePrinter { protected static final Text TXT_COMMA = Text.Simple(","); protected static final Text TXT_EQUAL = Text.Simple("="); protected static final Text TXT_SUBTYPE = Text.Simple("<:"); - protected static final Text TXT_AT = 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("("); @@ -251,7 +250,6 @@ public class TextTreePrinter implements TreePrinter { print(KW_PACKAGE); print(Text.Space); print(packaged); - print(Text.Space); printTemplate(KW_WITH, impl, true); break; @@ -412,7 +410,6 @@ public class TextTreePrinter implements TreePrinter { case TypeApply(Tree fun, Tree[] targs): print(fun); - print(TXT_AT); printArray(targs, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP); printType(tree); break; @@ -492,10 +489,6 @@ public class TextTreePrinter implements TreePrinter { printArray(refinements, TXT_WITH_BLOCK_BEGIN, TXT_BLOCK_END, Text.Newline); break; - case TupleType(Tree[] types): - printArray(types, TXT_LEFT_BRACKET, TXT_RIGHT_BRACKET, TXT_COMMA_SP); - break; - case AppliedType(Tree tpe, Tree[] args): print(tpe); indent(); diff --git a/sources/scalac/symtab/Definitions.java b/sources/scalac/symtab/Definitions.java index 6d67edac42..f9e5a6f0ec 100644 --- a/sources/scalac/symtab/Definitions.java +++ b/sources/scalac/symtab/Definitions.java @@ -125,6 +125,8 @@ public class Definitions { public final Symbol STRING_CLASS; public final Type STRING_TYPE; + public final Symbol SEQ_CLASS; + /** string concatenation pseudo-methods of classes scala.Any and * java.lang.String */ @@ -261,6 +263,8 @@ public class Definitions { STRING_TYPE = monoType(STRING_CLASS); SCALA.members().enter(STRING_CLASS); + SEQ_CLASS = getClass(Names.scala_Seq); + /* ANY_PLUS_STRING = new TermSymbol( Position.NOPOS, Names.PLUS, ANY_CLASS, Modifiers.FINAL); @@ -410,12 +414,7 @@ public class Definitions { argtps1); } - public Type tupleType(Type[] args) { - assert args.length > 0; - Type[] args1 = new Type[args.length]; - for (int i = 0; i < args.length; i++) - args1[i] = Type.covarType(args[i]); - return Type.appliedType( - getType(Name.fromString("scala.Tuple" + args.length)), args1); + public Type seqType(Type argtpe) { + return Type.appliedType(getType(Names.scala_Seq), new Type[]{argtpe}); } } diff --git a/sources/scalac/symtab/Modifiers.java b/sources/scalac/symtab/Modifiers.java index 3fc119419e..38f5a042d6 100644 --- a/sources/scalac/symtab/Modifiers.java +++ b/sources/scalac/symtab/Modifiers.java @@ -22,13 +22,14 @@ public interface Modifiers { int ABSTRACTCLASS = 0x00000080; // abstract class int DEF = 0x00000100; // a def parameter - int SYNTHETIC = 0x00000200; - int DEPRECATED = 0x00000400; - int JAVA = 0x00000800; // symbol was defined by a Java class - - int MODUL = 0x00001000; // symbol is module or class implementing a module - int MUTABLE = 0x00002000; // symbol is a mutable variable. - int PARAM = 0x00004000; // symbol is a (type) parameter to a method + int REPEATED = 0x00000200; // a repeated parameter + int SYNTHETIC = 0x00000400; + int DEPRECATED = 0x00000800; + + int JAVA = 0x00001000; // symbol was defined by a Java class + int MODUL = 0x00002000; // symbol is module or class implementing a module + int MUTABLE = 0x00004000; // symbol is a mutable variable. + int PARAM = 0x00008000; // symbol is a (type) parameter to a method int INITIALIZED = 0x00010000; // symbol's definition is complete int LOCKED = 0x00020000; // temporary flag to catch cyclic dependencies diff --git a/sources/scalac/symtab/Symbol.java b/sources/scalac/symtab/Symbol.java index f13192848b..4b31aeef9c 100644 --- a/sources/scalac/symtab/Symbol.java +++ b/sources/scalac/symtab/Symbol.java @@ -269,7 +269,7 @@ public abstract class Symbol implements Modifiers, Kinds { /** Is this symbol the primary constructor of a type? */ public final boolean isPrimaryConstructor() { - return isConstructor() && this == constructorClass().constructor(); + return isConstructor() && this == primaryConstructorClass().constructor(); } public boolean isGenerated() { @@ -332,7 +332,7 @@ public abstract class Symbol implements Modifiers, Kinds { */ public Symbol classOwner() { Symbol owner = owner(); - Symbol clazz = owner.constructorClass(); + Symbol clazz = owner.primaryConstructorClass(); if (clazz.constructor() == owner) return clazz; else return owner; } @@ -353,10 +353,10 @@ public abstract class Symbol implements Modifiers, Kinds { return sym; } - /* If this is a constructor, return the class it constructs. + /* If this is a primary constructor, return the class it constructs. * Otherwise return the symbol itself. */ - public Symbol constructorClass() { + public Symbol primaryConstructorClass() { return this; } @@ -874,8 +874,8 @@ public class TermSymbol extends Symbol { return other; } - public Symbol constructorClass() { - return isConstructor() ? clazz : this; + public Symbol primaryConstructorClass() { + return isConstructor() && clazz != null ? clazz : this; } public Symbol moduleClass() { diff --git a/sources/scalac/symtab/Type.java b/sources/scalac/symtab/Type.java index e9d2e93864..54f690f7bb 100644 --- a/sources/scalac/symtab/Type.java +++ b/sources/scalac/symtab/Type.java @@ -428,33 +428,18 @@ public class Type implements Modifiers, Kinds, TypeTags { } } - /** Is this type of the form scala.Tuple_N[+T_0, ..., +T_N-1]? - */ - public boolean isTupleType() { - switch (this) { - case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym.owner() == Global.instance.definitions.SCALA_CLASS && - sym.name.startsWith(Names.Tuple)) { - for (int i = 0; i < args.length; i++) - if (!args[i].isCovarType()) return false; - return true; - } - } - return false; - } - /** Is this type of the form scala.FunctionN[T_1, ..., T_n, +T]? */ public boolean isFunctionType() { switch (this) { case TypeRef(Type pre, Symbol sym, Type[] args): - if (sym.fullName().startsWith(Names.Function)) + if (sym.fullName().startsWith(Names.Function)) { for (int i = 0; i < args.length - 1; i++) if (args[i].isCovarType()) return false; - return args.length > 0 && args[args.length - 1].isCovarType(); - default: - return false; + return args.length > 0 && args[args.length - 1].isCovarType(); + } } + return false; } // Members and Lookup ------------------------------------------------------- @@ -814,7 +799,7 @@ public class Type implements Modifiers, Kinds, TypeTags { if (pre == NoType || clazz.kind != CLASS) return this; Symbol sym = symbol(); - Symbol ownclass = sym.owner().constructorClass(); + Symbol ownclass = sym.owner().primaryConstructorClass(); if (ownclass.isSubClass(clazz) && pre.symbol().isSubClass(ownclass)) { switch (pre.baseType(ownclass)) { @@ -2018,9 +2003,6 @@ public class Type implements Modifiers, Kinds, TypeTags { case TypeRef(Type pre, Symbol sym, Type[] args): if (sym.isRoot()) return "<root>"; if (!Global.instance.debug) { - if (isTupleType()) - return ArrayApply.toString( - dropVarianceMap.map(args), "[", ",", "]"); if (isFunctionType()) { Type[] params = new Type[args.length - 1]; System.arraycopy(args, 0, params, 0, params.length); diff --git a/sources/scalac/transformer/UnCurry.java b/sources/scalac/transformer/UnCurry.java index 21fe579130..40e23e7282 100644 --- a/sources/scalac/transformer/UnCurry.java +++ b/sources/scalac/transformer/UnCurry.java @@ -64,6 +64,8 @@ public class UnCurry extends OwnerTransformer * - for every argument to a def parameter `def x: T': * if argument is not a reference to a def parameter: * convert argument `e' to (expansion of) `() => e' + * - for every argument list that corresponds to a repeated parameter + * (a_1, ..., a_n) => (Tuple(a_1, ..., a_n)) */ public Tree transform(Tree tree) { //uncurry type and symbol @@ -103,7 +105,7 @@ public class UnCurry extends OwnerTransformer // argument to parameterless function e => ( => e) Type ftype = fn.type; Tree fn1 = transform(fn); - Tree[] args1 = transformArgs(args, ftype); + Tree[] args1 = transformArgs(tree.pos, args, ftype); switch (fn1) { case Apply(Tree fn2, Tree[] args2): Tree[] newargs = new Tree[args1.length + args2.length]; @@ -141,15 +143,19 @@ public class UnCurry extends OwnerTransformer /** Transform arguments `args' to method with type `methtype'. */ - private Tree[] transformArgs(Tree[] args, Type methtype) { + private Tree[] transformArgs(int pos, Tree[] args, Type methtype) { switch (methtype) { case MethodType(Symbol[] params, _): + if (params.length == 1 && (params[0].flags & REPEATED) != 0) { + args = new Tree[]{ + make.Tuple(pos, args).setType(params[0].type())}; + } for (int i = 0; i < args.length; i++) { args[i] = transformArg(args[i], params[i]); } return args; case PolyType(_, Type restp): - return transformArgs(args, restp); + return transformArgs(pos, args, restp); default: throw new ApplicationError(methtype); } @@ -174,7 +180,7 @@ public class UnCurry extends OwnerTransformer } } return transform(gen.mkUnitFunction( - arg, descr.uncurry(arg.type), currentOwner)); + arg, descr.uncurry(arg1.type), currentOwner)); } else return arg1; } } diff --git a/sources/scalac/typechecker/Analyzer.java b/sources/scalac/typechecker/Analyzer.java index 9442110dfd..d4414100bd 100644 --- a/sources/scalac/typechecker/Analyzer.java +++ b/sources/scalac/typechecker/Analyzer.java @@ -8,6 +8,7 @@ // todo: (0) propagate target type in cast. // todo: (1) check that only stable defs override stable defs +// todo: eliminate Typed nodes. package scalac.typechecker; @@ -196,6 +197,12 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // Name resolution ----------------------------------------------------------- + String decode(Name name) { + if (name.isTypeName()) return "type " + name; + else if (name.isConstrName()) return "constructor " + name; + else return name.toString(); + } + /** Is `sym' accessible as a member of tree `site' in current context? */ boolean isAccessible(Symbol sym, Tree site) { @@ -408,6 +415,8 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { 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); } @@ -877,7 +886,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } Symbol[] enterParams(Tree[] params) { - enterSyms(params); + for (int i = 0; i < params.length; i++) { + enterSym(params[i]); + switch (params[i]) { + case ValDef(int mods, _, _, _): + if ((mods & REPEATED) != 0 && params.length > 1) + error(params[i].pos, + "`*' parameter must be the only parameter a `('...`)' section"); + } + } return Tree.symbolOf(params); } @@ -970,7 +987,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // evaluate what was found if (sym1.kind == NONE) { if (sym.kind == NONE) { - return error(tree, "not found: " + NameTransformer.decode(name)); + return error(tree, "not found: " + decode(name)); } else { sym.flags |= ACCESSED; if (sym.owner().kind == CLASS) @@ -1026,9 +1043,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if (sym.kind == NONE) { //System.out.println(qual.type + " has members " + qual.type.members());//DEBUG return error(tree, - NameTransformer.decode(name) + " is not a member of " + qual.type.widen()); + decode(name) + " is not a member of " + qual.type.widen()); } else if (!isAccessible(sym, qual)) { - return error(tree, name + " cannot be accessed in " + qual.type.widen()); + return error(tree, sym + " cannot be accessed in " + qual.type.widen()); } else { sym.flags |= (ACCESSED | SELECTOR); Type symtype = qual.type.memberType(sym); @@ -1063,6 +1080,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { 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: @@ -1228,8 +1246,9 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { } 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, params[i].type()); + args[i] = adapt(args[i], argMode, formals[i]); } return copy.Apply(tree, fn1, args) .setType(restp1); @@ -1270,14 +1289,15 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Type[] argtypes = new Type[args.length]; switch (methtype) { case MethodType(Symbol[] params, Type restp): - if (params.length != args.length) { + Type[] formals = infer.formalTypes(params, args.length); + if (formals.length != args.length) { error(pos, "wrong number of arguments" + (meth == null ? "" : " for " + meth)); return null; } if (tparams.length == 0) { for (int i = 0; i < args.length; i++) { - args[i] = transform(args[i], argMode, params[i].type()); + args[i] = transform(args[i], argMode, formals[i]); argtypes[i] = args[i].type; } } else { @@ -1285,15 +1305,14 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { Type[] targs = infer.protoTypeArgs(tparams, restp, pt, params); // argpts: prototypes for arguments - Type[] argpts = new Type[params.length]; - for (int i = 0; i < params.length; i++) - argpts[i] = params[i].type().subst(tparams, targs); + 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]params.type as prototypes + // transform arguments with [targs/tparams]formals as prototypes for (int i = 0; i < args.length; i++) args[i] = transform( - args[i], argMode | POLYmode, - params[i].type().subst(tparams, targs)); + args[i], argMode | POLYmode, formals[i].subst(tparams, targs)); // targs1: same as targs except that every AnyType is mapped to // formal parameter type. @@ -1308,7 +1327,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case PolyType(Symbol[] tparams1, Type restype1): argtypes[i] = infer.argumentTypeInstance( tparams1, restype1, - params[i].type().subst(tparams, targs1), + formals[i].subst(tparams, targs1), argpts[i]); } } @@ -1406,18 +1425,29 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { if ((mode & PATTERNmode) != 0) { // set type to instantiated case class constructor if (tree.type == Type.ErrorType) return tree; - Symbol clazz = tree.symbol().constructorClass(); - if (!clazz.isCaseClass()) - error(tree, clazz + " is not a case class"); - tree.type = clazz.constructor().type(); - switch (tree.type) { - case PolyType(Symbol[] tparams, Type restp): - try { - infer.constructorInstance(tree, tparams, restp, pt); - } catch (Type.Error ex) { - if (pt != Type.ErrorType) error(tree.pos, ex.msg); - tree.setType(Type.ErrorType); + Symbol clazz = tree.type.unalias().symbol(); + if (clazz.isCaseClass()) { + tree.type = clazz.constructor().type(); + switch (tree.type) { + case PolyType(Symbol[] tparams, Type restp): + try { + infer.constructorInstance(tree, tparams, restp, pt); + } catch (Type.Error ex) { + if (pt != Type.ErrorType) error(tree.pos, ex.msg); + tree.setType(Type.ErrorType); + } } + } else if (clazz.isSubClass(definitions.SEQ_CLASS)) { + Type seqtp = dropVarArgs(pt.baseType(clazz)); + if (seqtp != Type.NoType) { + tree.type = seqConstructorType(seqtp, pt); + } else { + error(tree, "expected pattern type " + pt + + " does not conform to sequence " + clazz); + } + } else { + error(tree, tree.symbol() + + " is neither a case class constructor nor a sequence class constructor"); } return tree; } else if ((mode & EXPRmode) != 0 && tree.type.isObjectType()) { @@ -1443,6 +1473,34 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { // check type against prototype return tree.setType(checkType(tree.pos, tree.type, pt)); } + //where + Type dropVarArgs(Type tp) { + switch (tp) { + case TypeRef(Type pre, Symbol sym, Type[] targs): + Type[] targs1 = targs; + for (int i = 0; i < targs.length; i++) { + Type targ = targs[i]; + Type targ1 = targ.dropVariance(); + if (targ != targ1 && targs1 == targs) { + targs1 = new Type[targs.length]; + System.arraycopy(targs, 0, targs1, 0, i); + } + targs1[i] = targ1; + } + if (targs1 == targs) return tp; + else return Type.TypeRef(pre, sym, targs1); + default: + return tp; + } + } + + Type seqConstructorType(Type paramtp, Type resulttp) { + Symbol constr = resulttp.symbol().constructor(); + Symbol param = new TermSymbol( + Position.NOPOS, Names.WILDCARD, constr, PARAM | REPEATED).setInfo( + paramtp); + return Type.MethodType(new Symbol[]{param}, resulttp); + } /** Transform expression or type with a given mode. */ @@ -1471,6 +1529,7 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { /** The main attribution function */ public Tree transform(Tree tree) { + if (mode == PATTERNmode) new TextTreePrinter().print("pattern ").print(tree).print(" with pt = ").print(pt.toString()).println().end();//debug Symbol sym = tree.symbol(); if (sym != null && !sym.isInitialized()) sym.initialize(); if (global.debug && TreeInfo.isDefinition(tree)) @@ -1690,12 +1749,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { return copy.Typed(tree, expr1, tpe1) .setType(tpe1.type); - case Tuple(Tree[] trees): - Tree tree1 = transform(desugarize.Tuple(tree), mode, pt); - if (trees.length > 0 && (mode & EXPRmode) != 0) - tree1 = desugarize.postTuple(tree1); - return tree1; - case Function(Tree.ValDef[] vparams, Tree body): pushContext(tree, context.owner, new Scope(context.scope)); Type restype = desugarize.preFunction(vparams, pt); @@ -1899,10 +1952,6 @@ public class Analyzer extends Transformer implements Modifiers, Kinds { case FunType(_, _): return transform(desugarize.FunType(tree)); - case TupleType(Tree[] types): - Tree tree1 = desugarize.mkTupleType(tree.pos, types); - return transform(desugarize.mkTupleType(tree.pos, types)); - default: throw new ApplicationError("illegal tree: " + tree); } diff --git a/sources/scalac/typechecker/DeSugarize.java b/sources/scalac/typechecker/DeSugarize.java index fda3d0f492..665e648419 100644 --- a/sources/scalac/typechecker/DeSugarize.java +++ b/sources/scalac/typechecker/DeSugarize.java @@ -98,10 +98,6 @@ public class DeSugarize implements Kinds, Modifiers { for (int i = 0; i < args.length; i++) getVariables(args[i], vars); break; - case Tuple(Tree[] elems): - for (int i = 0; i < elems.length; i++) - getVariables(elems[i], vars); - break; default: throw new ApplicationError ("illegal pattern", tree); } @@ -109,20 +105,6 @@ public class DeSugarize implements Kinds, Modifiers { // Transform functions ----------------------------------------------------- - /** [T_1, ..., T_N] => scala.TupleN[+T_1, ..., +T_N] - */ - public Tree mkTupleType(int pos, Tree[] types) { - assert types.length > 0; - Tree[] types1 = new Tree[types.length]; - for (int i = 0; i < types.length; i++) - types1[i] = make.CovariantType(pos, types[i]); - return make.AppliedType(pos, - gen.mkTycon(pos, - global.definitions.getType( - Name.fromString("scala.Tuple" + types.length))), - types1); - } - /** (T_1, ..., T_N) => T ==> scala.FunctionN[T_1, ..., T_N, +T] */ public Tree FunType(Tree tree) { @@ -141,30 +123,12 @@ public class DeSugarize implements Kinds, Modifiers { } } - /** [] ==> scala.Nil() - * [e_1,...,e_N] ==> scala.TupleN(e_1,...,e_n) (N >= 1) - * mode is either EXPRmode or PATmode - */ - public Tree Tuple(Tree tree) { - switch(tree) { - case Tuple(Tree[] trees): - Name n = trees.length == 0 ? Names.Nil - : Name.fromString("Tuple" + trees.length); - Tree select = make.Select(tree.pos, - make.Ident(tree.pos, Names.scala), n.toConstrName()); - return make.Apply(tree.pos, select, trees); - - default: - throw new ApplicationError("tuple expected", tree); - } - } - - /** constr call C of type TupleN[T_1,...,T_N] ==> (C: TupleN[+T_1,...,+T_N]) - */ - Tree postTuple(Tree tree) { - Type[] targs = tree.type.typeArgs(); - if (targs.length == 0) return tree; - else return gen.Typed(tree, global.definitions.tupleType(targs)); + public Tree mkTuple(int pos, Tree[] trees) { + Name n = trees.length == 0 ? Names.Unit + : Name.fromString("Tuple" + trees.length); + Tree select = make.Select(pos, + make.Ident(pos, Names.scala), n.toConstrName()); + return make.Apply(pos, select, trees); } /** Convert method to function type. @@ -407,14 +371,14 @@ public class DeSugarize implements Kinds, Modifiers { Name[] vars = new Name[varlist.size()]; varlist.toArray(vars); - // (x_1, ..., x_N) + // 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 = this.Tuple(make.Tuple(tree.pos, vtree)); + Tree tuple = mkTuple(tree.pos, vtree); - // e.match (case p => (x_1, ..., x_N)) + // 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), @@ -621,7 +585,7 @@ public class DeSugarize implements Kinds, Modifiers { return idents; } - /** Build value element definitions and return its name. + /** Build value element definition name for case parameter. */ void addCaseElement(TreeList ts, ValDef vparam) { //System.out.println("add case for " + vparam.name);//DEBUG diff --git a/sources/scalac/typechecker/Infer.java b/sources/scalac/typechecker/Infer.java index b9f2071cc0..8dd769b640 100644 --- a/sources/scalac/typechecker/Infer.java +++ b/sources/scalac/typechecker/Infer.java @@ -469,6 +469,22 @@ public class Infer implements Modifiers, Kinds { } } + /** The formal parameter types corresponding to `params'. + * If `params' is a repeated parameter, a list of `length' copies + * of its type is returned. + */ + Type[] formalTypes(Symbol[] params, int length) { + Type[] result; + if (params.length == 1 && (params[0].flags & REPEATED) != 0) { + Type[] formals = new Type[length]; + Type ft = params[0].type().typeArgs()[0]; + for (int i = 0; i < length; i++) formals[i] = ft; + return formals; + } else { + return Symbol.type(params); + } + } + /** Return inferred type arguments, given type parameters, formal parameters and * argument types. * If this is not possible, throw a `NoInstance' exception, or, if @@ -481,13 +497,13 @@ public class Infer implements Modifiers, Kinds { //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 = Symbol.type(params); + Type[] formals = formalTypes(params, argtypes.length); if (formals.length != argtypes.length) { if (needToSucceed) throw new NoInstance("parameter lists differ in length"); return null; } - for (int i = 0; i < formals.length; i++) { + for (int i = 0; i < argtypes.length; i++) { if (!isCompatible(argtypes[i].subst(tparams, tvars), formals[i].subst(tparams, tvars))) { if (needToSucceed) @@ -679,10 +695,11 @@ public class Infer implements Modifiers, Kinds { boolean isApplicable(Type ftpe, Type[] argtypes, Type pt) { switch (ftpe) { case MethodType(Symbol[] params, Type restpe): + Type[] formals = formalTypes(params, argtypes.length); return isCompatible(restpe, pt) && - params.length == argtypes.length && - Type.isSubType(argtypes, Symbol.type(params)); + formals.length == argtypes.length && + Type.isSubType(argtypes, formals); case PolyType(Symbol[] tparams, MethodType(Symbol[] params, Type restpe)): try { Type[] targs = methTypeArgs( diff --git a/sources/scalac/util/Names.java b/sources/scalac/util/Names.java index a05aad45de..e824dc6ffe 100644 --- a/sources/scalac/util/Names.java +++ b/sources/scalac/util/Names.java @@ -38,12 +38,16 @@ public class Names { public static final Name Float = Name.fromString("Float"); public static final Name Function = Name.fromString("Function"); public static final Name Int = Name.fromString("Int"); + public static final Name Labelled = Name.fromString("Labelled"); + public static final Name List = Name.fromString("List"); public static final Name Long = Name.fromString("Long"); public static final Name Nil = Name.fromString("Nil"); public static final Name Object = Name.fromString("Object"); public static final Name Predef = Name.fromString("Predef"); + public static final Name Seq = Name.fromString("Seq"); public static final Name Short = Name.fromString("Short"); public static final Name String = Name.fromString("String"); + public static final Name Symbol = Name.fromString("Symbol"); public static final Name Throwable = Name.fromString("Throwable"); public static final Name True = Name.fromString("True"); public static final Name Tuple = Name.fromString("Tuple"); @@ -86,7 +90,9 @@ public class Names { public static final Name scala_Object = Name.fromString("scala.Object"); public static final Name scala_Predef = Name.fromString("scala.Predef"); public static final Name scala_Ref = Name.fromString("scala.Ref"); + public static final Name scala_Seq = Name.fromString("scala.Seq"); public static final Name scala_Short = Name.fromString("scala.Short"); + public static final Name scala_Symbol = Name.fromString("scala.Symbol"); public static final Name scala_Tuple = Name.fromString("scala.Tuple"); public static final Name scala_Unit = Name.fromString("scala.Unit"); public static final Name scala_runtime = Name.fromString("scala.runtime"); |