diff options
author | paltherr <paltherr@epfl.ch> | 2003-09-11 12:03:13 +0000 |
---|---|---|
committer | paltherr <paltherr@epfl.ch> | 2003-09-11 12:03:13 +0000 |
commit | c4b7a33f58721756974e79f6df392f9f90825cfe (patch) | |
tree | 9cd774cdf215bcdb95e0979264c9942fa5f5ab08 /sources/scalac/ast/TreeGen.java | |
parent | 3551973214371050c0517d65c1c0371ad37785aa (diff) | |
download | scala-c4b7a33f58721756974e79f6df392f9f90825cfe.tar.gz scala-c4b7a33f58721756974e79f6df392f9f90825cfe.tar.bz2 scala-c4b7a33f58721756974e79f6df392f9f90825cfe.zip |
- Reviewed and cleaned TreeGen.
- Fixed some errors.
- Removed "dangerous" methods in TreeGen.
- Renamed some methods in TreeGen.
Diffstat (limited to 'sources/scalac/ast/TreeGen.java')
-rw-r--r-- | sources/scalac/ast/TreeGen.java | 1014 |
1 files changed, 518 insertions, 496 deletions
diff --git a/sources/scalac/ast/TreeGen.java b/sources/scalac/ast/TreeGen.java index 62c5fbf6c8..ac99d4f58b 100644 --- a/sources/scalac/ast/TreeGen.java +++ b/sources/scalac/ast/TreeGen.java @@ -8,268 +8,293 @@ package scalac.ast; -import java.io.*; -import java.util.*; import scalac.*; import scalac.symtab.*; -import scalac.typechecker.Infer; import scalac.util.*; import Tree.*; -/** A helper class for building trees +/** + * This class provides method to build attributed trees. * - * @author Martin Odersky, Christine Roeckl - * @version 1.0 + * @author Martin Odersky, Christine Roeckl + * @version 1.0 */ public class TreeGen implements Kinds, Modifiers, TypeTags { - /********************************************************************************/ - /********************************************************************************/ - /** VARIABLES **/ + //######################################################################## + // Private Fields - /** the global environment - */ - protected final Global global; + /** The global environment */ + private final Global global; - /** the global definitions - */ - protected final Definitions definitions; + /** The global definitions */ + private final Definitions definitions; - /** the tree factory - */ + /** The tree factory */ public final TreeFactory make; - /** the type inferencer - */ - final Infer infer; + //######################################################################## + // Public Constructors - /************************************************************************/ - /************************************************************************/ - /** CONSTRUCTORS **/ + /** Initializes this instance. */ + public TreeGen(Global global) { + this(global, global.make); + } + /** Initializes this instance. */ public TreeGen(Global global, TreeFactory make) { this.global = global; this.definitions = global.definitions; this.make = make; - this.infer = new Infer(global, this, make); } - public TreeGen(Global global) { - this(global, global.make); + //######################################################################## + // Public Methods - Building types + + /** Builds type references corresponding to given symbols. */ + public Tree[] mkTypeRefs(int pos, Symbol[] syms) { + if (syms.length == 0) return Tree.EMPTY_ARRAY; + Tree[] trees = new Tree[syms.length]; + for (int i = 0; i < trees.length; i++) + trees[i] = mkTypeRef(pos, syms[i]); + return trees; } - /*************************************************************************/ - /*************************************************************************/ - /** METHODS **/ + /** Builds a type reference corresponding to given symbol. */ + public Tree mkTypeRef(int pos, Symbol sym) { + assert sym.kind == TYPE: Debug.show(sym); + sym.flags |= ACCESSED; + return mkType(pos, sym.nextType()); + } - public Type deref(Type tp) { - switch (tp) { - case PolyType(Symbol[] tparams, Type restp): - if (tparams.length == 0) return restp; - } - return tp; + /** Builds trees corresponding to given types. */ + public Tree[] mkTypes(int pos, Type[] types) { + if (types.length == 0) return Tree.EMPTY_ARRAY; + Tree[] trees = new Tree[types.length]; + for (int i = 0; i < trees.length; i++) + trees[i] = mkType(pos, types[i]); + return trees; } - /** Create a dummy symbol to be used for templates. - */ - public Symbol localDummy(int pos, Symbol owner) { - return new TermSymbol(pos, Names.LOCAL(owner), owner, 0) - .setInfo(Type.NoType); + /** Builds a tree corresponding to given type. */ + public Tree mkType(int pos, Type type) { + return TypeTerm(pos, type); } - public Tree mkStable(Tree tree) { - Symbol sym = tree.symbol(); - if (sym.isStable()) { - switch (tree) { - case Ident(_): - tree.setType(Type.singleType(sym.owner().thisType(), sym)); - break; - case Select(Tree qual, _): - if (qual.type.isStable()) - tree.setType(Type.singleType(qual.type, sym)); - } - } - return tree; + /** Builds a TypeTerm node corresponding to given type. */ + public TypeTerm TypeTerm(int pos, Type type) { + TypeTerm tree = make.TypeTerm(pos); + tree.setType(type); + return tree; } - public Tree mkRef(int pos, Type pre, Symbol sym) { - if (pre.isSameAs(Type.localThisType) || pre.symbol().isRoot()) - return Ident(pos, sym); - else - return Select(pos, mkStableId(pos, pre), sym); + //######################################################################## + // Public Methods - Building constants + + /** Builds a unit literal. */ + public Tree mkUnitLit(int pos) { + return make.Block(pos, Tree.EMPTY_ARRAY). + setType(definitions.UNIT_TYPE); } - public Tree mkRef(int pos, Symbol sym) { - return mkRef(pos, sym.owner().thisType(), sym); + /** Builds a boolean literal. */ + public Tree mkBooleanLit(int pos, boolean value) { + return make.Literal(pos, value ? Boolean.TRUE : Boolean.FALSE). + setType(definitions.BOOLEAN_TYPE); } - /** Build and attribute stable identifier tree corresponding to given prefix. - */ - public Tree mkStableId(int pos, Type pre) { - switch (pre.expandModuleThis()) { - case ThisType(Symbol sym): - return This(pos, sym); - case SingleType(Type pre1, Symbol sym): - return mkStable(mkRef(pos, pre1, sym)); - default: - throw new ApplicationError(pre); - } + /** Builds a byte literal. */ + public Tree mkByteLit(int pos, byte value) { + return make.Literal(pos, new Byte(value)). + setType(definitions.BYTE_TYPE); } - /** Build and attribute ident nodes with given symbols. - */ - public Tree[] mkIdents(int pos, Symbol[] syms) { - if (syms.length == 0) return Tree.EMPTY_ARRAY; - Tree[] trees = new Tree[syms.length]; - for (int i = 0; i < trees.length; i++) - trees[i] = Ident(pos, syms[i]); - return trees; + /** Builds a short literal. */ + public Tree mkShortLit(int pos, short value) { + return make.Literal(pos, new Short(value)). + setType(definitions.SHORT_TYPE); } - /** Build and attribute type idents with given symbols. - */ - public Tree[] mkTypeIdents(int pos, Symbol[] syms) { - if (syms.length == 0) return Tree.EMPTY_ARRAY; - Tree[] trees = new Tree[syms.length]; - for (int i = 0; i < trees.length; i++) - trees[i] = mkTypeIdent(pos, syms[i]); - return trees; + /** Builds a character literal. */ + public Tree mkCharLit(int pos, char value) { + return make.Literal(pos, new Character(value)). + setType(definitions.CHAR_TYPE); } - /** Build and attribute type ident with given symbol. - */ - public Tree mkTypeIdent(int pos, Symbol sym) { - assert sym.kind == TYPE: Debug.show(sym); - sym.flags |= ACCESSED; - return mkType(pos, sym.nextType()); + /** Builds an integer literal */ + public Tree mkIntLit(int pos, int value) { + return make.Literal(pos, new Integer(value)). + setType(definitions.INT_TYPE); } - /** Build and attribute tree corresponding to given type. - */ - public Tree mkType(int pos, Type type) { - return TypeTerm(pos, type); + /** Builds a long literal. */ + public Tree mkLongLit(int pos, long value) { + return make.Literal(pos, new Long(value)). + setType(definitions.LONG_TYPE); } - /** Build and attribute tree array corresponding to given type array. - */ - public Tree[] mkTypes(int pos, Type[] types) { - Tree[] res = new Tree[types.length]; - for (int i = 0; i < types.length; i++) { - res[i] = mkType(pos, types[i]); - } - return res; + /** Builds a float literal. */ + public Tree mkFloatLit(int pos, float value) { + return make.Literal(pos, new Float(value)). + setType(definitions.FLOAT_TYPE); } - /** Build and attribute tree corresponding to given type. - */ - public Tree TypeTerm(int pos, Type type) { - return make.TypeTerm(pos).setType(type); + /** Builds a double literal. */ + public Tree mkDoubleLit(int pos, double value) { + return make.Literal(pos, new Double(value)). + setType(definitions.DOUBLE_TYPE); } - /** Build and attribute tree corresponding to symbol's declaration. - */ - public Tree mkDef(int pos, Symbol sym) { - switch (sym.kind) { - case ERROR: - return make.Bad(pos, Symbol.ERROR).setType(Type.ErrorType); - case TYPE: - return AbsTypeDef(pos, sym); - case ALIAS: - return AliasTypeDef(pos, sym); - case VAL: - if (sym.isMethod()) return DefDef(pos, sym, Tree.Empty); - else return ValDef(pos, sym, Tree.Empty); - default: - throw new ApplicationError(); - } + /** Builds a string literal. */ + public Tree mkStringLit(int pos, String value) { + return make.Literal(pos, value).setType(definitions.JAVA_STRING_TYPE); } - /** Build and attribute tree array corresponding to given symbol's declarations. - */ - public Tree[] mkDefs(int pos, Symbol[] syms) { - Tree[] res = new Tree[syms.length]; - for (int i = 0; i < syms.length; i++) { - res[i] = mkDef(pos, syms[i]); + /** Builds a null literal. */ + public Tree mkNullLit(int pos) { + return Ident(pos, definitions.NULL); + } + + /** Builds a zero literal. */ + public Tree mkZeroLit(int pos) { + return Ident(pos, definitions.ZERO); + } + + /** Builds a default zero value according to given type tag. */ + public Tree mkDefaultValue(int pos, int tag) { + switch (tag) { + case UNIT : return mkUnitLit(pos); + case BOOLEAN: return mkBooleanLit(pos, false); + case BYTE : return mkByteLit(pos, (byte)0); + case SHORT : return mkShortLit(pos, (short)0); + case CHAR : return mkCharLit(pos, '\0'); + case INT : return mkIntLit(pos, 0); + case LONG : return mkLongLit(pos, 0l); + case FLOAT : return mkFloatLit(pos, 0f); + case DOUBLE : return mkDoubleLit(pos, 0d); + default : throw Debug.abort("unknown type tag: " + tag); } - return res; } - /** Build a boolean constant tree. - */ - public Tree mkBooleanLit(int pos, boolean bool) { - return make.Literal(pos, bool ? Boolean.TRUE : Boolean.FALSE). - setType(definitions.BOOLEAN_TYPE); + /** Builds a default zero value according to given type. */ + public Tree mkDefaultValue(int pos, Type type) { + if (type.isSubType(definitions.ANYREF_TYPE)) return mkNullLit(pos); + switch (type.unbox()) { + case UnboxedType(int tag): return mkDefaultValue(pos, tag); + } + return mkZeroLit(pos); } - /** Build a string literal - */ - public Tree mkStringLit(int pos, String str) { - return make.Literal(pos, str).setType(definitions.JAVA_STRING_TYPE); + //######################################################################## + // Public Methods - Building references + + /** Builds references corresponding to given symbols. */ + public Tree[] mkRefs(int pos, Symbol[] syms) { + if (syms.length == 0) return Tree.EMPTY_ARRAY; + Tree[] trees = new Tree[syms.length]; + for (int i = 0; i < trees.length; i++) + trees[i] = mkRef(pos, syms[i]); + return trees; } - /** Build an integer literal - */ - public Tree mkIntLit(int pos, int value) { - return make.Literal(pos, new Integer(value)).setType(definitions.INT_TYPE); + /** Builds a reference corresponding to given symbol. */ + public Tree mkRef(int pos, Symbol sym) { + return mkRef(pos, sym.owner().thisType(), sym); } - /** Build a default zero value according to type - */ - public Tree mkDefaultValue(int pos, Type tp) { - if (tp.isSubType(definitions.ANYREF_TYPE)) { - return Ident(pos, definitions.NULL); - } else { - switch (tp.unbox()) { - case UnboxedType(BOOLEAN): - return mkBooleanLit(pos, false); - case UnboxedType(BYTE): - case UnboxedType(SHORT): - case UnboxedType(CHAR): - case UnboxedType(INT): - return mkIntLit(pos, 0); - case UnboxedType(LONG): - return make.Literal(pos, new Long(0)).setType(definitions.LONG_TYPE); - case UnboxedType(FLOAT): - return make.Literal(pos, new Float(0)).setType(definitions.FLOAT_TYPE); - case UnboxedType(DOUBLE): - return make.Literal(pos, new Double(0)).setType(definitions.DOUBLE_TYPE); - case UnboxedType(UNIT): - return Block(pos, Tree.EMPTY_ARRAY); - default: - return Ident(pos, definitions.ZERO); - } - } + /** Builds a reference corresponding to given prefix & symbol. */ + public Tree mkRef(int pos, Type pre, Symbol sym) { + if (pre.isSameAs(Type.localThisType) || pre.symbol().isRoot()) + return Ident(pos, sym); + else + return Select(pos, mkStableId(pos, pre), sym); } + /** Builds a reference corresponding to given stable prefix. */ + public Tree mkStableId(int pos, Type pre) { + switch (pre.expandModuleThis()) { + case ThisType(Symbol sym): + return This(pos, sym); + case SingleType(Type pre1, Symbol sym): + return mkRef(pos, pre1, sym); + default: + throw Debug.abort("illegal case", pre); + } + } - /** Build a call to a primary constructor. - */ - public Tree mkPrimaryConstr(int pos, Type type) { - return mkPrimaryConstr(pos, type, Tree.EMPTY_ARRAY); + /** Builds a This node corresponding to given class. */ + public This This(int pos, Symbol clazz) { + assert clazz.isClass(): Debug.show(clazz); + This tree = make.This(pos, clazz); + global.nextPhase(); + tree.setType(clazz.thisType()); + global.prevPhase(); + return tree; } - public Tree mkPrimaryConstr(int pos, Type type, Tree[] args) { - switch (type) { - case TypeRef(Type prefix, Symbol clazz, Type[] targs): - global.nextPhase(); - Symbol constr = clazz.primaryConstructor(); - global.prevPhase(); - return mkApply(mkRef(pos, prefix, constr), targs, args); - default: - throw Debug.abort("invalid type", type); - } + /** Builds a Super node corresponding to given class. */ + public Super Super(int pos, Symbol clazz) { + assert clazz.isClass(): Debug.show(clazz); + Super tree = make.Super(pos, clazz, TypeNames.EMPTY); + global.nextPhase(); + tree.setType(clazz.thisType()); + global.prevPhase(); + return tree; } - /** Build an array of calls to primary constructors. + /** Builds an Ident node corresponding to given symbol. */ + public Ident Ident(int pos, Symbol sym) { + assert sym.isTerm(): Debug.show(sym); + sym.flags |= ACCESSED; + Ident tree = make.Ident(pos, sym); + global.nextPhase(); + if (sym.isStable()) + tree.setType(Type.singleType(sym.owner().thisType(), sym)); + else + tree.setType(sym.type()); + global.prevPhase(); + return tree; + } + + /** + * Builds a Select node corresponding to given symbol selected + * from given qualifier. + */ + public Select Select(int pos, Tree qual, Symbol sym) { + assert sym.isTerm(): Debug.show(sym); + sym.flags |= ACCESSED | SELECTOR; + Select tree = make.Select(pos, sym, qual); + global.nextPhase(); + if (sym.isStable() && qual.type.isStable()) + tree.setType(Type.singleType(qual.type, sym)); + else + tree.setType(qual.type.memberType(sym)); + global.prevPhase(); + return tree; + } + public Select Select(Tree qual, Symbol sym) { + return Select(qual.pos, qual, sym); + } + + //######################################################################## + // Public Methods - Building applications + + /** + * Builds calls to primary constructors of given types with given + * value arguments. */ - public Tree[] mkPrimaryConstrs(int pos, Type[] types, Tree[][] args) { - assert types.length == args.length: Debug.show(types, " -- ", args); + public Tree[] mkPrimaryConstrs(int pos, Type[] types, Tree[][] vargs) { + assert types.length == vargs.length: Debug.show(types, " -- ", vargs); Tree[] trees = new Tree[types.length]; for (int i = 0; i < trees.length; i++) - trees[i] = mkPrimaryConstr(pos, types[i], args[i]); + trees[i] = mkPrimaryConstr(pos, types[i], vargs[i]); return trees; } + /** + * Builds calls to primary constructors of given types with no + * value arguments. + */ public Tree[] mkPrimaryConstrs(int pos, Type[] types) { Tree[] trees = new Tree[types.length]; for (int i = 0; i < trees.length; i++) @@ -277,396 +302,393 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { return trees; } - - /** Build parameter sections corresponding to type. + /** + * Builds a call to the primary constructor of given type with + * given value arguments. Missing type arguments are extracted + * from the given type. */ - public ValDef[][] mkParams(Type type) { + public Tree mkPrimaryConstr(int pos, Type type, Tree[] vargs) { switch (type) { - case PolyType(Symbol[] tparams, Type restype): - return mkParams(restype); - case MethodType(Symbol[] vparams, Type restype): - ValDef[] params1 = mkParams(vparams); - ValDef[][] paramss = mkParams(restype); - if (paramss.length == 0) { - return new ValDef[][]{params1}; - } else { - ValDef[][] paramss1 = new ValDef[paramss.length + 1][]; - paramss1[0] = params1; - System.arraycopy(paramss, 0, paramss1, 1, paramss.length); - return paramss1; - } - default: - return new ValDef[][]{}; - } + case TypeRef(Type pre, Symbol clazz, Type[] targs): + return mkPrimaryConstr(pos, pre, clazz, targs, vargs); + default: + throw Debug.abort("invalid type", type); + } } - /** Build parameter section corresponding to given array of symbols . + /** + * Builds a call to the primary constructor of given type with no + * value arguments. Missing type arguments are extracted from the + * given type. */ - public ValDef[] mkParams(Symbol[] symbols) { - ValDef[] res = new ValDef[symbols.length]; - for (int i = 0; i < symbols.length; i++) { - res[i] = mkParam(symbols[i]); - } - return res; + public Tree mkPrimaryConstr(int pos, Type type) { + return mkPrimaryConstr(pos, type, Tree.EMPTY_ARRAY); } - /** Build parameter corresponding to given symbol . + /** + * Builds a call to the primary constructor of given class with + * given type and value arguments. */ - public ValDef mkParam(Symbol sym) { - return ValDef(sym.pos, sym, Tree.Empty); + public Tree mkPrimaryConstr(int pos, Type pre, Symbol clazz, Type[] targs, + Tree[] vargs) + { + global.nextPhase(); + Symbol constr = clazz.primaryConstructor(); + global.prevPhase(); + return mkApply(mkRef(pos, constr), targs, vargs); } - - /** Build type parameter section corresponding to given array of symbols . - */ - public AbsTypeDef[] mkTypeParams(Symbol[] symbols) { - AbsTypeDef[] res = new AbsTypeDef[symbols.length]; - for (int i = 0; i < symbols.length; i++) { - res[i] = mkTypeParam(symbols[i]); - } - return res; + public Tree mkPrimaryConstr(int pos, Symbol clazz,Type[]targs,Tree[]vargs){ + return mkPrimaryConstr(pos,clazz.owner().thisType(),clazz,targs,vargs); } - /** Build type parameter corresponding to given symbol . + /** + * Builds a call to the primary constructor of given class with + * given type arguments and no value arguments. */ - public AbsTypeDef mkTypeParam(Symbol sym) { - return AbsTypeDef(sym.pos, sym); + public Tree mkPrimaryConstr(int pos, Type pre, Symbol clazz, Type[] targs){ + return mkPrimaryConstr(pos, pre, clazz, targs, Tree.EMPTY_ARRAY); + } + public Tree mkPrimaryConstr(int pos, Symbol clazz, Type[] targs) { + return mkPrimaryConstr(pos, clazz.owner().thisType(), clazz, targs); } - /** Build abstract type definition corresponding to given symbol . + /** + * Builds a call to the primary constructor of given class with no + * type and value arguments. */ - public AbsTypeDef AbsTypeDef(int pos, Symbol sym) { - Global.instance.nextPhase(); - Type symtype = sym.info(); - Global.instance.prevPhase(); - AbsTypeDef res = make.AbsTypeDef( - pos, sym, TypeTerm(pos, symtype), TypeTerm(pos, sym.loBound())); - res.setType(definitions.UNIT_TYPE); - return res; + public Tree mkPrimaryConstr(int pos, Type pre, Symbol clazz) { + return mkPrimaryConstr(pos, pre, clazz, Type.EMPTY_ARRAY); } - - public AbsTypeDef AbsTypeDef(Symbol sym) { - return AbsTypeDef(sym.pos, sym); + public Tree mkPrimaryConstr(int pos, Symbol clazz) { + return mkPrimaryConstr(pos, clazz.owner().thisType(), clazz); } - /** Build type definition corresponding to given symbol . - */ - public AliasTypeDef AliasTypeDef(int pos, Symbol sym) { - Global.instance.nextPhase(); - Type symtype = sym.info(); - Global.instance.prevPhase(); - AliasTypeDef res = make.AliasTypeDef( - pos, - sym, - mkTypeParams(sym.typeParams()), - TypeTerm(pos, symtype)); - res.setType(definitions.UNIT_TYPE); - return res; + /** Builds an application with given function and arguments. */ + public Tree mkApply(int pos, Tree fn, Type[] targs, Tree[] vargs) { + if (targs.length != 0) fn = TypeApply(pos, fn, mkTypes(pos, targs)); + return Apply(pos, fn, vargs); } - - public AliasTypeDef AliasTypeDef(Symbol sym) { - return AliasTypeDef(sym.pos, sym); + public Tree mkApply(Tree fn, Type[] targs, Tree[] vargs) { + return mkApply(fn.pos, fn, targs, vargs); } - - /** Build and attribute block with given statements, starting - * at given position. The type is the type of the last - * statement in the block. - */ - public Tree Block(int pos, Tree[] stats) { - Type tp = (stats.length == 0) ? definitions.UNIT_TYPE - : stats[stats.length - 1].type; - return make.Block(pos, stats).setType(tp); + public Tree mkApply(int pos, Tree fn, Tree[] targs, Tree[] vargs) { + if (targs.length != 0) fn = TypeApply(pos, fn, targs); + return Apply(pos, fn, vargs); + } + public Tree mkApply(Tree fn, Tree[] targs, Tree[] vargs) { + return mkApply(fn.pos, fn, targs, vargs); } - /** Build and attribute non-empty block with given statements. + /** + * Builds an application with given function and type arguments + * and with no value arguments. */ - public Tree Block(Tree[] stats) { - return Block(stats[0].pos, stats); + public Tree mkApply(int pos, Tree fn, Type[] targs) { + return mkApply(pos, fn, targs, Tree.EMPTY_ARRAY); } - - public Tree Typed(Tree tree, Type tp) { - return make.Typed(tree.pos, tree, TypeTerm(tree.pos, tp)).setType(tp); + public Tree mkApply(Tree fn, Type[] targs) { + return mkApply(fn.pos, fn, targs); } - - /** Build and attribute the assignment lhs = rhs - */ - public Tree Assign(int pos, Tree lhs, Tree rhs) { - return make.Assign(pos, lhs, rhs).setType(definitions.UNIT_TYPE); + public Tree mkApply(int pos, Tree fn, Tree[] targs) { + return mkApply(pos, fn, targs, Tree.EMPTY_ARRAY); } - - public Tree Assign(Tree lhs, Tree rhs) { - return Assign(lhs.pos, lhs, rhs); + public Tree mkApply(Tree fn, Tree[] targs) { + return mkApply(fn.pos, fn, targs); } - /** Build and attribute new B, given constructor expression B. - */ - public Tree New(int pos, Tree constr) { - Symbol local = localDummy(pos, Symbol.NONE); - Template templ = make.Template( - pos, local, new Tree[]{constr}, Tree.EMPTY_ARRAY); - templ.setType(constr.type); - return make.New(pos, templ).setType(constr.type); + /** Builds a TypeApply node with given function and arguments. */ + public TypeApply TypeApply(int pos, Tree fn, Tree[] targs) { + switch (fn.type) { + case PolyType(Symbol[] tparams, Type result): + TypeApply tree = make.TypeApply(pos, fn, targs); + assert tparams.length == targs.length: tree; + global.nextPhase(); + tree.setType(result.subst(tparams, Tree.typeOf(targs))); + global.prevPhase(); + return tree; + default: + throw Debug.abort("illegal case", fn.type); + } } - - public Tree New(Tree constr) { - return New(constr.pos, constr); + public TypeApply TypeApply(Tree fn, Tree[] targs) { + return TypeApply(fn.pos, fn, targs); } - - /** Build an allocation new P.C[TARGS](ARGS) - * given a (singleton) type P, class C, type arguments TARGS and arguments ARGS - */ - public Tree New(int pos, Type pre, Symbol clazz, - Type[] targs, Tree[] args) { - Tree constr = mkRef(pos, pre, clazz.primaryConstructor()); - return New(mkApply(constr, mkTypes(pos, targs), args)); + /** Builds an Apply node with given function and arguments. */ + public Apply Apply(int pos, Tree fn, Tree[] vargs) { + switch (fn.type) { + case Type.MethodType(Symbol[] vparams, Type result): + Apply tree = make.Apply(pos, fn, vargs); + // !!! assert vparams.length == vargs.length: tree + " --- " + Debug.show(vparams) + " --- " + Debug.show(vargs); + tree.setType(result); + return tree; + default: + throw Debug.abort("illegal case", fn); + } } - - /** Build a monomorphic allocation new P.C(ARGS) - * given a prefix P, class C and arguments ARGS - */ - public Tree New(int pos, Type pre, Symbol clazz, Tree[] args) { - return New(pos, pre, clazz, Type.EMPTY_ARRAY, args); + public Apply Apply(Tree fn, Tree[] vargs) { + return Apply(fn.pos, fn, vargs); } - /** Build application with given function, type args and value - * args. - */ - public Tree mkApply(int pos, Tree fn, Type[] targs, Tree[] args) { - if (targs.length != 0) fn = TypeApply(pos, fn, mkTypes(pos, targs)); - return Apply(pos, fn, args); + /** Builds an Apply node with given function and no arguments. */ + public Apply Apply(int pos, Tree fn) { + return Apply(pos, fn, Tree.EMPTY_ARRAY); } - - public Tree mkApply(Tree fn, Type[] targs, Tree[] args) { - return mkApply(fn.pos, fn, targs, args); + public Apply Apply(Tree fn) { + return Apply(fn.pos, fn); } - public Tree mkApply(int pos, Tree fn, Tree[] targs, Tree[] args) { - if (targs.length != 0) fn = TypeApply(pos, fn, targs); - return Apply(pos, fn, args); - } + //######################################################################## + // Public Methods - Building expressions - public Tree mkApply(Tree fn, Tree[] targs, Tree[] args) { - return mkApply(fn.pos, fn, targs, args); + /** Builds a cast with given value and type. */ + public Tree mkAsInstanceOf(int pos, Tree value, Type type) { + return mkApply(pos, Select(value, definitions.AS), new Type[] {type}); } - - /** Build and attribute application node with given function - * and argument trees. - */ - public Tree Apply(int pos, Tree fn, Tree[] args) { - try { - switch (fn.type) { - case Type.OverloadedType(Symbol[] alts, Type[] alttypes): - global.nextPhase(); - infer.methodAlternative(fn, alts, alttypes, - Tree.typeOf(args), Type.AnyType); - global.prevPhase(); - } - switch (fn.type) { - case Type.MethodType(Symbol[] vparams, Type restpe): - return make.Apply(pos, fn, args).setType(restpe); - } - } catch (Type.Error ex) { - } - throw new ApplicationError("method type required", fn.type); + public Tree mkAsInstanceOf(Tree value, Type type) { + return mkAsInstanceOf(value.pos, value, type); } - public Tree Apply(Tree fn, Tree[] args) { - return Apply(fn.pos, fn, args); + /** Builds a Block node with given statements. */ + public Tree Block(int pos, Tree[] stats) { + Block tree = make.Block(pos, stats); + tree.setType(stats.length == 0 + ? definitions.UNIT_TYPE + : stats[stats.length - 1].type); + return tree; } - /** Build and attribute type application node with given function - * and argument trees. - */ - public Tree TypeApply(int pos, Tree fn, Tree[] args) { - try { - switch (fn.type) { - case Type.OverloadedType(Symbol[] alts, Type[] alttypes): - global.nextPhase(); - infer.polyAlternative(fn, alts, alttypes, args.length); - global.prevPhase(); - } - switch (fn.type) { - case Type.PolyType(Symbol[] tparams, Type restpe): - global.nextPhase(); - restpe = restpe.subst(tparams, Tree.typeOf(args)); - global.prevPhase(); - return make.TypeApply(pos, fn, args).setType(restpe); - } - } catch (Type.Error ex) { - } - throw new ApplicationError("poly type required", fn.type); + /** Builds a Block node with given non-empty statements list. */ + public Tree Block(Tree[] stats) { + return Block(stats[0].pos, stats); } - public Tree TypeApply(Tree fn, Tree[] args) { - return TypeApply(fn.pos, fn, args); + /** Builds an Assign node corresponding to "<lhs> = <rhs>". */ + public Assign Assign(int pos, Tree lhs, Tree rhs) { + Assign tree = make.Assign(pos, lhs, rhs); + tree.setType(definitions.UNIT_TYPE); + return tree; } - - public Tree If(int pos, Tree cond, Tree thenpart, Tree elsepart) { - return - make.If(pos, cond, thenpart, elsepart).setType(thenpart.type); + public Assign Assign(Tree lhs, Tree rhs) { + return Assign(lhs.pos, lhs, rhs); } - public Tree If(Tree cond, Tree thenpart, Tree elsepart) { + /** Builds an If node with given condition and branches. */ + public If If(int pos, Tree cond, Tree thenpart, Tree elsepart) { + If tree = make.If(pos, cond, thenpart, elsepart); + global.nextPhase(); + if (thenpart.type.isSameAs(elsepart.type)) + tree.setType(thenpart.type); + else + tree.setType(Type.lub(new Type[] {thenpart.type, elsepart.type})); + global.prevPhase(); + return tree; + } + public If If(Tree cond, Tree thenpart, Tree elsepart) { return If(cond.pos, cond, thenpart, elsepart); } - /** Build and applied type node with given function - * and argument trees. - public Tree AppliedType(int pos, Tree fn, Tree[] args) { - return make.AppliedType(pos, fn, args) - .setType(Type.appliedType(fn.type, Tree.typeOf(args))); + /** Builds a New node corresponding to "new <constr>". */ + public Tree New(int pos, Tree constr) { + Symbol local = localDummy(pos, Symbol.NONE); // !!! + Template templ = make.Template( + pos, local, new Tree[]{constr}, Tree.EMPTY_ARRAY); // !!! + templ.setType(constr.type); + New tree = make.New(pos, templ); + tree.setType(constr.type); + return tree; } - - public Tree AppliedType(Tree fn, Tree[] args) { - return AppliedType(fn.pos, fn, args); + public Tree New(Tree constr) { + return New(constr.pos, constr); } - */ - /** Build and attribute select node of given symbol. - * It is assumed that the prefix is not empty. - */ - public Tree Select(int pos, Tree qual, Symbol sym) { - assert sym.kind != NONE; - Global.instance.nextPhase(); - Type symtype = qual.type.memberType(sym); - Global.instance.prevPhase(); - sym.flags |= ACCESSED | SELECTOR; - return make.Select(pos, sym, qual).setType(deref(symtype)); + /** Builds a Typed nodes with given value and type. */ + public Typed Typed(int pos, Tree value, Type type) { + Typed tree = make.Typed(pos, value, TypeTerm(pos, type)); + tree.setType(type); + return tree; } - - public Tree Select(Tree qual, Symbol sym) { - return Select(qual.pos, qual, sym); + public Typed Typed(Tree value, Type type) { + return Typed(value.pos, value, type); } - public Tree Select(Tree qual, Name name) { - Symbol sym = qual.type.lookup(name); - assert (sym.kind != NONE && sym != Symbol.ERROR) : name + " from " + qual.type; - return Select(qual, sym); - } + //######################################################################## + // Public Methods - Building definitions - /** Build and attribute ident node with given symbol. - */ - public Tree Ident(int pos, Symbol sym) { - assert sym.isTerm(): Debug.show(sym); - sym.flags |= ACCESSED; - return make.Ident(pos, sym).setType(deref(sym.nextType())); + /** Builds the type parameter section of given symbol. */ + public AbsTypeDef[] mkTypeParamsOf(Symbol sym) { + Symbol[] tparams = sym.nextTypeParams(); + AbsTypeDef[] trees = new AbsTypeDef[tparams.length]; + for (int i = 0; i < tparams.length; i++) + trees[i] = mkTypeParam(tparams[i]); + return trees; } - public Tree Ident(Symbol sym) { - return Ident(sym.pos, sym); + /** Builds the value parameter section of given symbol. */ + public ValDef[][] mkParamsOf(Symbol sym) { + global.nextPhase(); + if (sym.isClass()) sym = sym.primaryConstructor(); + Type type = sym.type(); + global.prevPhase(); + ValDef[][] treess = Tree.ValDef_EMPTY_ARRAY_ARRAY; + while (true) { + switch (type) { + case PolyType(_, Type result): + type = result; + continue; + case MethodType(Symbol[] vparams, Type result): + ValDef[] trees = new ValDef[vparams.length]; + for (int i = 0; i < vparams.length; i++) + trees[i] = mkParam(vparams[i]); + ValDef[][] array = new ValDef[treess.length + 1][]; + for (int i = 0; i < treess.length; i++) array[i] = treess[i]; + array[treess.length] = trees; + treess = array; + type = result; + continue; + default: + return treess; + } + } } - /** Build and attribute this node with given symbol. - */ - public Tree This(int pos, Symbol sym) { - return make.This(pos, sym).setType(sym.thisType()); + /** Builds the type parameter corresponding to given symbol. */ + public AbsTypeDef mkTypeParam(Symbol sym) { + return AbsTypeDef(sym); } - /** Build and attribute super node with given type. - */ - public Tree Super(int pos, Symbol sym) { - return make.Super(pos, sym, TypeNames.EMPTY).setType(sym.thisType()); + /** Builds the value parameter corresponding to given symbol. */ + public ValDef mkParam(Symbol sym) { + return ValDef(sym, Tree.Empty); } - /** Build and attribute value/variable/let definition node whose signature - * corresponds to given symbol and which has given rhs. - */ - public ValDef ValDef(int pos, Symbol sym, Tree rhs) { + /** Builds a definition for given interface with given body. */ + public Tree mkInterfaceDef(Symbol clazz, Tree[] body) { Global.instance.nextPhase(); - Type symtype = sym.type(); + clazz.info(); // needed until isInterface() triggers flag updates + assert clazz.isInterface(): Debug.show(clazz); + Type[] parents = clazz.parents(); Global.instance.prevPhase(); - ValDef res = make.ValDef(pos, sym, TypeTerm(pos, symtype), rhs); - res.setType(definitions.UNIT_TYPE); - return res; + return ClassDef_(clazz, mkPrimaryConstrs(clazz.pos, parents), body); } - public ValDef ValDef(Symbol sym, Tree rhs) { - return ValDef(sym.pos, sym, rhs); + /** Builds a ClassDef node for given class with given template. */ + public ClassDef ClassDef(Symbol clazz, Template template) { + ClassDef tree = make.ClassDef( + clazz.pos, + clazz, + mkTypeParamsOf(clazz), + mkParamsOf(clazz), + Tree.Empty, + template); + tree.setType(definitions.UNIT_TYPE); + return tree; } - /** Build and attribute value/variable/let definition node whose signature - * corresponds to given symbol and which has given body. + /** + * Builds a ClassDef node for given class with given parent + * constructors, local symbol and body. */ - public Tree DefDef(int pos, Symbol sym, Tree body) { - Global.instance.nextPhase(); - Type symtype = sym.type(); - Global.instance.prevPhase(); - return make.DefDef(pos, - sym, - mkTypeParams(symtype.typeParams()), - mkParams(symtype), - TypeTerm(pos, symtype.resultType()), - body) - .setType(definitions.UNIT_TYPE); + public ClassDef ClassDef(Symbol clazz, Tree[] constrs, Symbol local, + Tree[] body) + { + Template templ = make.Template(local.pos, local, constrs, body); + templ.setType(clazz.nextInfo()); // !!! + return ClassDef(clazz, templ); } - public Tree DefDef(Symbol sym, Tree rhs) { - return DefDef(sym.pos, sym, rhs); + /** Builds a ValDef node for given symbol and with given rhs. */ + public ValDef ValDef(Symbol sym, Tree rhs) { + ValDef tree = make.ValDef( + sym.pos, + sym, + TypeTerm(sym.pos, sym.nextType()), + rhs); + tree.setType(definitions.UNIT_TYPE); + return tree; + } + + /** Builds a DefDef node for given symbol with given body. */ + public DefDef DefDef(Symbol sym, Tree body) { + DefDef tree = make.DefDef( + sym.pos, + sym, + mkTypeParamsOf(sym), + mkParamsOf(sym), + TypeTerm(sym.pos, sym.nextType().resultType()), + body); + tree.setType(definitions.UNIT_TYPE); + return tree; + } + + /** Builds an AbsTypeDef node for given symbol. */ + public AbsTypeDef AbsTypeDef(Symbol sym) { + AbsTypeDef tree = make.AbsTypeDef( + sym.pos, + sym, + TypeTerm(sym.pos, sym.nextInfo()), + TypeTerm(sym.pos, sym.loBound())); + tree.setType(definitions.UNIT_TYPE); + return tree; } - /** Generate class definition from class symbol, and template. - */ - public Tree ClassDef(int pos, Symbol clazz, Template template) { - Global.instance.nextPhase(); - Type constrtype = clazz.primaryConstructor().info(); - Global.instance.prevPhase(); - return make.ClassDef( - pos, - clazz, - mkTypeParams(constrtype.typeParams()), - mkParams(constrtype), - Tree.Empty, - template) - .setType(definitions.UNIT_TYPE); + /** Builds an AliasTypeDef node for given symbol. */ + public AliasTypeDef AliasTypeDef(Symbol sym) { + AliasTypeDef tree = make.AliasTypeDef( + sym.pos, + sym, + mkTypeParamsOf(sym), + TypeTerm(sym.pos, sym.nextInfo())); + tree.setType(definitions.UNIT_TYPE); + return tree; } - public Tree ClassDef(Symbol clazz, Template template) { - return ClassDef(clazz.pos, clazz, template); - } + //######################################################################## + //######################################################################## + //######################################################################## - /** Generate class definition from class symbol, parent constructors, and body. - */ - public Tree ClassDef(int pos, Symbol clazz, Tree[] constrs, Symbol local, Tree[] body) { - Global.instance.nextPhase(); - Type clazzinfo = clazz.info(); - Global.instance.prevPhase(); - switch (clazzinfo) { - case CompoundType(Type[] parents, Scope members): - Template templ = make.Template(pos, local, constrs, body); - templ.setType(clazzinfo); - return ClassDef(pos, clazz, templ); - default: - throw Debug.abort("illegal case", clazzinfo); - } - } + //######################################################################## + // !!! to add - public Tree ClassDef(int pos, Symbol clazz, Tree[] constrs, Tree[] body) { - return ClassDef(pos, clazz, constrs, localDummy(pos, clazz), body); + /** Builds a Template node with given symbol, parents and body. */ + public Template Template(int pos, Symbol local, Tree[]parents, Tree[]body){ + Template tree = make.Template(pos, local, parents, body); + tree.setType(Type.NoType); + return tree; } - - public Tree ClassDef(Symbol clazz, Tree[] constrs, Symbol local, Tree[] body) { - return ClassDef(clazz.pos, clazz, constrs, local, body); + public Template Template(Symbol local, Tree[] parents, Tree[] body) { + return Template(local.pos, local, parents, body); } - public Tree ClassDef(Symbol clazz, Tree[] constrs, Tree[] body) { - return ClassDef(clazz.pos, clazz, constrs, body); + + //######################################################################## + // !!! to remove + + public ClassDef ClassDef_(Symbol clazz, Tree[] constrs, Tree[] body) { + return ClassDef(clazz, constrs, localDummy(clazz.pos, clazz), body); } - /** Generate class definition from interface symbol */ - public Tree mkInterfaceDef(Symbol clazz, Tree[] body) { - Global.instance.nextPhase(); - Type[] parents = clazz.parents(); - assert clazz.isInterface(): Debug.show(clazz); - Global.instance.prevPhase(); - return ClassDef(clazz, mkPrimaryConstrs(clazz.pos, parents), body); + public Tree Select__(Tree qual, Name name) { + Symbol sym = qual.type.lookup(name); + assert (sym.kind != NONE && sym != Symbol.ERROR) : name + " from " + qual.type; + return Select(qual, sym); } + //######################################################################## + // !!! not yet reviewed + + /** Create a dummy symbol to be used for templates. + */ + public Symbol localDummy(int pos, Symbol owner) { + return new TermSymbol(pos, Names.LOCAL(owner), owner, 0) + .setInfo(Type.NoType); + } /** Build the expansion of (() => expr) */ - public Tree mkUnitFunction(Tree expr, Type tp, Symbol owner) { - return mkFunction(expr.pos, Tree.ValDef_EMPTY_ARRAY, expr, tp, owner); + public Tree mkUnitFunction(Tree expr, Type type, Symbol owner) { + return mkFunction(expr.pos, Tree.ValDef_EMPTY_ARRAY, expr, type, owner); } /** Build the expansion of ((vparams_1, ..., vparams_n) => body) @@ -712,9 +734,9 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { changeOwner(body, owner, applyMeth); Tree[] parentTrees = mkPrimaryConstrs(pos, parentTypes); Tree[] memberTrees = { DefDef(applyMeth, body) }; - Tree classDef = ClassDef(clazz, parentTrees, memberTrees); - Tree alloc = New(pos, Type.localThisType, clazz, Tree.EMPTY_ARRAY) - .setType(parentTypes[1]); + Tree classDef = ClassDef_(clazz, parentTrees, memberTrees); + Tree alloc = New(pos, mkPrimaryConstr(pos, clazz)) + .setType(parentTypes[1]); // !!! return Block(new Tree[]{classDef, alloc}); } @@ -735,9 +757,9 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { pattype, restype, clazz, owner), makeVisitorMethod(pos, Names.isDefinedAt, isDefinedAtVisitor, pattype, definitions.BOOLEAN_TYPE, clazz, owner)}; - Tree classDef = ClassDef(clazz, parentTrees, memberTrees); - Tree alloc = New(pos, Type.localThisType, clazz, Tree.EMPTY_ARRAY) - .setType(parentTypes[1]); + Tree classDef = ClassDef_(clazz, parentTrees, memberTrees); + Tree alloc = New(pos, mkPrimaryConstr(pos, clazz)) + .setType(parentTypes[1]); // !!! return Block(new Tree[]{classDef, alloc}); } //where @@ -752,7 +774,7 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { changeOwner(visitor, prevOwner, meth); Tree body = mkApply( - Select(Ident(param), definitions.MATCH), + Select(Ident(pos, param), definitions.MATCH), new Tree[]{mkType(pos, pattype), mkType(pos, restype)}, new Tree[]{visitor}); return DefDef(meth, body); @@ -779,14 +801,14 @@ public class TreeGen implements Kinds, Modifiers, TypeTags { */ public Tree postfixApply(Tree obj, Tree fn, Symbol owner) { if (TreeInfo.isPureExpr(obj) || TreeInfo.isPureExpr(fn)) { - return Apply(Select(fn, Names.apply), new Tree[]{obj}); + return Apply(Select__(fn, Names.apply), new Tree[]{obj}); } else { Name tmpname = global.freshNameCreator.newName("tmp", '$'); Symbol tmp = new TermSymbol( obj.pos, tmpname, owner, SYNTHETIC | FINAL) .setInfo(obj.type); Tree tmpdef = ValDef(tmp, obj); - Tree expr = postfixApply(Ident(tmp), fn, owner); + Tree expr = postfixApply(Ident(obj.pos, tmp), fn, owner); return Block(new Tree[]{tmpdef, expr}); } } |