From a634b2280f86d4884062c67b29879dc95eda8fd7 Mon Sep 17 00:00:00 2001 From: mihaylov Date: Mon, 23 Feb 2004 18:45:52 +0000 Subject: - Major code cleanup. - Use the modified msil.jar with the Is* properties implemented as methods. !!! Mobile users should update their copy of msil.jar from ~linuxsoft/apps/msil/msil.jar --- sources/scalac/backend/msil/GenMSIL.java | 1341 ++++++++++---------- sources/scalac/backend/msil/GenMSILPhase.java | 2 - sources/scalac/backend/msil/TypeCreator.java | 360 +++--- .../scalac/symtab/classfile/CLRClassParser.java | 179 ++- .../scalac/symtab/classfile/CLRPackageParser.java | 79 +- 5 files changed, 1011 insertions(+), 950 deletions(-) diff --git a/sources/scalac/backend/msil/GenMSIL.java b/sources/scalac/backend/msil/GenMSIL.java index 417c4e2592..2a7749c8b0 100644 --- a/sources/scalac/backend/msil/GenMSIL.java +++ b/sources/scalac/backend/msil/GenMSIL.java @@ -18,6 +18,7 @@ import scalac.util.Name; import scalac.util.Names; import scalac.util.Debug; import scalac.ast.Tree; +import scalac.ast.TreeList; import scalac.atree.AConstant; import Tree.*; import scalac.symtab.Symbol; @@ -44,7 +45,7 @@ import java.util.Iterator; import java.io.IOException; /** - * Generates MS IL code via the Reflection.Emit API + * Generates MS IL code via Reflection.Emit-like API * (ch.epfl.lamp.compiler.msil.emit package) * * @author Nikolay Mihaylov @@ -53,67 +54,64 @@ public final class GenMSIL { //################################################################ - final Map assemblies; - // The position of the paramater in the parameter list - final Map/**/ params = new HashMap(); + private final Map/**/ params = new HashMap(); // The LocalBuilder corresponding to the local variable symbol - final Map/**/ locals = new HashMap(); + private final Map/**/ locals = new HashMap(); + + // mapping from LabelDef symbols to labels + private final Map/**/ sym2label = new HashMap(); - final Map/**/ sym2label = new HashMap(); + // the Assembly the program is compiled into. + private AssemblyBuilder currAssembly; - AssemblyBuilder defaultAssembly, currAssembly; - ModuleBuilder currModule; + // the main module of the assembly + private ModuleBuilder currModule; - ILGenerator code; + // used by TypeCreator.createType() + ModuleBuilder getCurrentModule() { return currModule; } - final Global global; - final TypeCreator tc; - final Definitions defs; - final Primitives primitives; - final ItemFactory items; + // the code generator for the current method + private ILGenerator code; - static final Item TRUE_ITEM = Item.CondItem(Test.True, null, null); - static final Item FALSE_ITEM = Item.CondItem(Test.False, null, null); + private final Global global; + private final TypeCreator tc; + private final Definitions defs; + private final Primitives primitives; + private final ItemFactory items; + + private static final Item TRUE_ITEM = Item.CondItem(Test.True, null, null); + private static final Item FALSE_ITEM = Item.CondItem(Test.False, null, null); /** + * The public constructor of the code generator. */ public GenMSIL(Global global, GenMSILPhase phase) { this.global = global; this.defs = global.definitions; this.primitives = global.primitives; - this.assemblies = phase.assemblies; - this.tc = new TypeCreator(this, phase); + this.tc = new TypeCreator(global, this, phase); this.items = new ItemFactory(this); } - - /** Generate .NET assembly */ - ModuleBuilder getPackage(String name) { - AssemblyBuilder assem = (AssemblyBuilder) assemblies.get(name); - if (assem == null) { - AssemblyName an = new AssemblyName(); - an.Name = name; - assem = AssemblyBuilder.DefineDynamicAssembly(an); - } - ModuleBuilder module = (ModuleBuilder) assem.GetModule(name); - if (module == null) { - module = assem.DefineDynamicModule(name, name + ".dll"); - } - assemblies.put(name, assem); - return module; - } - - - /** Initialize the code generator + /** + * Initialize the code generator. Called from GenMSILPhase + * before processing any compilation unit. */ - public void initGen() { + void initGen() { tc.init(); - currModule = getPackage("prog"); + AssemblyName an = new AssemblyName(); + an.Name = "prog"; + currAssembly = AssemblyBuilder.DefineDynamicAssembly(an); + currModule = (ModuleBuilder) currAssembly.GetModule(an.Name); + if (currModule == null) { + currModule = currAssembly.DefineDynamicModule(an.Name, an.Name + "Module"); + } } - /** Finilize the code generation + /** Finilize the code generation. Called from GenMSILPhase + * after processing all compilation units. */ public void finalizeGen() { if (mainObjectField != null && mainMethod != null) { @@ -131,35 +129,26 @@ public final class GenMSIL { code.Emit(OpCodes.Ret); } tc.createTypes(); - try { - Iterator iter = assemblies.values().iterator(); - while (iter.hasNext()) { - AssemblyBuilder assem = (AssemblyBuilder) iter.next(); -// log("Types defined in assembly: " + assem.FullName); -// Type[] types = assem.GetTypes(); -// for (int i = 0; i < types.length; i++) -// log("\t" + types[i]); - assem.Save(assem.GetName().Name + ".il"); - } - } + try { currAssembly.Save(currAssembly.GetName().Name + ".il"); } catch (IOException e) { - if (global.debug) e.printStackTrace(); + if (global.debug) e.printStackTrace(); // FIXME } } - FieldInfo mainObjectField = null; - MethodInfo mainMethod = null; + private FieldInfo mainObjectField = null; + private MethodInfo mainMethod = null; - /** Check if the given method is a main function + /* + * Check if the given method is a main function */ - void checkMain(MethodBase method) { - //log("checking method: " + method); - if ( ! currentClass.isModuleClass() ) + private void checkMain(MethodBase method) { + if ( !currentClass.isModuleClass() ) return; + // do not consider nested objects' main methods if (method.DeclaringType.DeclaringType != null) return; - if (method.IsConstructor || method.IsAbstract || + if (method.IsConstructor() || method.IsAbstract() || !method.Name.equals("main")) return; ParameterInfo[] params = method.GetParameters(); @@ -169,72 +158,77 @@ public final class GenMSIL { mainMethod = (MethodInfo) method; } - - Unit currUnit; + // keeps track of the current compilation unit for better error reporting + private Unit currUnit; /** + * The main entry point into the code generator. Called from GenMSILPhase + * for every compilation unit. */ public void apply(Unit unit) { currUnit = unit; - for (int i = 0; i < unit.body.length; i++) { - Tree tree = unit.body[i]; - Symbol sym = tree.symbol(); - switch (tree) { - case Empty: break; - case ClassDef(_, _, _, _, _, Template(_, Tree[] body)): - genClass(sym, body); - break; - case PackageDef(Tree packaged, Template impl): - //String packageName = packaged.symbol().fullNameString(); - //log("Package: " + dumpSym(packaged.symbol()));// + - //"; symbol.fullName() = " + packaged.symbol().fullName()); - //currModule = getPackage(packageName); - genPackage(currAssembly, impl.body); - break; - default: - throw new ApplicationError - ("Illegal top-level definition: " + Debug.show(tree)); + try { + for (int i = 0; i < unit.body.length; i++) { + Tree tree = unit.body[i]; + Symbol sym = tree.symbol(); + switch (tree) { + case Empty: break; + case ClassDef(_, _, _, _, _, Template(_, Tree[] body)): + genClass(sym, body); + break; + case PackageDef(_, Template(_ , Tree[] body)): + genPackage(body); + break; + default: + throw new ApplicationError + ("Illegal top-level definition: " + Debug.show(tree)); + } } + } catch (Throwable e) { + e.printStackTrace(); + finalizeGen(); + System.exit(1); } } - - /** Generate the code for Package definition + /** + * Generate the code for a Package definition. */ - void genPackage(AssemblyBuilder assembly, Tree[] body) { + private void genPackage(Tree[] body) { for (int i = 0; i < body.length; i++) { Symbol sym = body[i].symbol(); - //log("genPackage: " + dumpSym(body[i].symbol())); switch (body[i]) { case Empty: break; case ClassDef(_, _, _, _, _, Template(_, Tree[] classBody)): Type type = tc.getType(sym); + assert type instanceof TypeBuilder; if (type instanceof TypeBuilder) genClass(sym, classBody); break; - case PackageDef(Tree packaged, Template(_ , Tree[] body2)): - //log("genPackage: nested package: " + dumpSym(sym)); - genPackage(currAssembly, body2); + case PackageDef(_, Template(_ , Tree[] body2)): + genPackage(body2); break; default: - log("genPackage: Only class definitions expected in a package!: Found instead: " + - dumpSym(sym)); + throw new ApplicationError("Class definition expected: " + + Debug.show(sym)); } } } /** The symbol of the class that is currently being compiled. */ - Symbol currentClass; + private Symbol currentClass; /** The method that is currently being compiled. */ - MethodBase currentMethod; - + private MethodBase currentMethod; - protected void emitSymtab(Symbol clazz) { + /* + * Emit the symbol table for the class given class as an MSIL attribute. + */ + private void emitSymtab(Symbol clazz) { TypeBuilder type = (TypeBuilder) tc.getType(clazz); Pickle pickle = (Pickle)global.symdata.get(clazz.fullName()); if (pickle != null) { @@ -249,18 +243,13 @@ public final class GenMSIL { } } - /** Generate the code for a class definition + /* + * Generate the code for a class definition */ - void genClass(Symbol clazz, Tree[] body) { - //log("genClass: " + dumpSym(clazz)); - //log("\tsym.isExternal() = " + clazz.isExternal()); - //log("\tfullName = " + clazz.fullName()); - //log("\tqualifier = " + Debug.show(clazz.qualifier())); - //log("class members: " + clazz.members()); + private void genClass(Symbol clazz, Tree[] body) { Symbol outerClass = currentClass; currentClass = clazz; if ( clazz.isModule() || clazz.isModuleClass() ) { - //log("genClass: initializing module field for module " + dumpSym(clazz)); tc.getModuleField(clazz); } emitSymtab(clazz); @@ -281,12 +270,10 @@ public final class GenMSIL { break; case DefDef(_, _, _, ValDef[][] vparams, Tree tpe, Tree rhs): - //log("genClass.DefDef: " + dumpSym(sym)); - //log("DefDef: type = " + Debug.show(tpe.type)); currentMethod = tc.getMethod(sym); - if (!currentMethod.IsAbstract) { + if (!currentMethod.IsAbstract()) { checkMain(currentMethod); - genDef(sym, vparams[0], rhs, type2MSILType(tpe.type)); + genDef(sym, vparams[0], rhs, msilType(tpe.type)); } break; @@ -299,95 +286,118 @@ public final class GenMSIL { } //genClass() - boolean lastStatement; - static final boolean enableTailCalls = true; + /* + * Specifies if the currently processed tree node is the last expression + * in a function so the generated code can be optimized: emitting ret + * instead of branch, emitting tailcalls, etc. + */ + private boolean lastExpr; + + /* + * Specifies if the control flow may come through the current point + * in the instruction sequence. + */ + private boolean willReturn; + + private boolean enableTailCalls = true; - /** Generate the code for Methods + /* + * Generate code for constructors and methods. */ - void genDef(Symbol sym, ValDef[] parameters, Tree rhs, MSILType toType) { + private void genDef(Symbol sym, ValDef[] parameters, Tree rhs, MSILType toType) { MethodBase method = tc.getMethod(sym); - //log("genDef: " + method.getSignature()); params.clear(); locals.clear(); - int argOffset = method.IsStatic ? 0 : 1; + int argOffset = method.IsStatic() ? 0 : 1; for (int i = 0; i < parameters.length; i++) { params.put(parameters[i].symbol(), new Integer(i + argOffset)); } - if (method.IsConstructor) { - //log("genDef: " + method); + if (method.IsConstructor()) { ConstructorInfo ctor = (ConstructorInfo) method; code = ((ConstructorBuilder)ctor).GetILGenerator(); FieldInfo moduleField = tc.getModuleField(currentClass); if (moduleField != null && moduleField.DeclaringType.DeclaringType == null) { -// log("genDef: initializing " + moduleField + -// " for class " + method.DeclaringType); - - // emit the call to the superconstructor + Tree[] cstats = null; switch (rhs) { - case Block(Tree[] stats, _): - // this is the call to the super constructor - drop(gen(stats[0], MSILType.VOID)); + case Block(Tree[] stats, Tree value): + TreeList stms = new TreeList(); + for (int i = 0; i < stats.length; i++) { + switch (stats[i]) { + case Block(Tree[] stats2, Tree value2): + stms.append(stats2); + stms.append(value2); + break; + default: + stms.append(stats[i]); + } + } + switch (value) { + case Block(Tree[] stats2, Tree value2): + stms.append(stats2); + stms.append(value2); + break; + } + cstats = stms.toArray(); break; default: - drop(gen(rhs, MSILType.VOID)); + cstats = new Tree[]{rhs}; } + // emit the call to the superconstructor + drop(gen(cstats[0], MSILType.VOID)); + code.Emit(OpCodes.Ret); // conclude the instance constructor + ConstructorBuilder cctor = ((TypeBuilder)(method.DeclaringType)). DefineConstructor((short)(MethodAttributes.Static | MethodAttributes.Public), CallingConventions.Standard, Type.EmptyTypes); currentMethod = cctor; - ILGenerator ctorCode = code; code = cctor.GetILGenerator(); // initialize the static module reference code.Emit(OpCodes.Newobj, ctor); code.Emit(OpCodes.Stsfld, moduleField); - switch (rhs) { - case Block(Tree[] stats, Tree value): - int n = stats.length; - assert n > 0; - for (int i = 1; i < n; i++) - drop(gen(stats[i], MSILType.VOID)); - drop(gen(value, MSILType.VOID)); - break; + for (int i = 1; i < cstats.length; i++) { + drop(gen(cstats[i], MSILType.VOID)); } - code.Emit(OpCodes.Ret); - code = ctorCode; - } else + code.Emit(OpCodes.Ret); // conclude the static constructor + } else { drop(gen(rhs, MSILType.VOID)); - code.Emit(OpCodes.Ret); - } else if (!method.IsAbstract) { - lastStatement = true; + code.Emit(OpCodes.Ret); + } + } else if (!method.IsAbstract()) { + lastExpr = true; code = ((MethodBuilder)method).GetILGenerator(); Item item = gen(rhs, toType); if (returnsVoid(method)) drop(item); else - coerce(load(item), toType); // coerce??? + coerce(load(item), toType); // FIXME: coerce??? code.Emit(OpCodes.Ret); } - lastStatement = false; + lastExpr = false; code = null; } // genDef(); - /** check if the result type of a method is void + /* + * Check if the result type of a method is void */ - boolean returnsVoid(MethodBase method) { - return method.IsConstructor || + private boolean returnsVoid(MethodBase method) { + return method.IsConstructor() || (((MethodInfo)method).ReturnType == tc.VOID); } - /** emit the code for this' + /* + * Emit the code for this. */ - void emitThis() { - if (currentMethod.IsStatic) { - if (currentMethod.IsConstructor) { + private void emitThis() { + if (currentMethod.IsStatic()) { + if (currentMethod.IsConstructor()) { code.Emit(OpCodes.Ldsfld, tc.getModuleField(currentClass)); } else throw new ApplicationError @@ -397,190 +407,163 @@ public final class GenMSIL { } - Item gen(Tree tree) { - return gen(tree, type2MSILType(tree.type)); + /* + * Generate code for array of trees + */ + private Item gen(Tree[] trees, MSILType toType) { + int n = trees.length; + if (n == 0) + return items.VoidItem(); + boolean tmpLastExpr = lastExpr; lastExpr = false; + for (int i = 0; i < n-1; i++) { + drop(gen(trees[i], MSILType.VOID)); + } + lastExpr = tmpLastExpr; + return gen(trees[n-1], toType); } - /** Check if the Item is != null. */ - Item check(Item i) { - assert i != null; - return i; + /* + * Sanity checks for items. + */ + private Item check(Item item) { + assert item != null && item.type != null : "" + item; + return item; + } + + /* + * + */ + private Item genLoad(Tree tree, MSILType toType) { + return load(gen(tree, toType)); } /** the position of the treenode which is currently being processed. */ - int pos; + private int pos; - /** The main generator function. It keeps track of - * the current position in the tree for better error messages + /* + * The main generator function. It keeps track of + * the current position in the tree for better error messages */ - Item gen(Tree tree, MSILType toType) { + private Item gen(Tree tree, MSILType toType) { + willReturn = true; int tmpPos = pos; pos = tree.pos; Item i = null; //i = gen2(tree, toType); - try { i = gen2(tree, toType); } + try { i = check(gen2(tree, toType)); } catch (Throwable e) { - logErr(tree.pos, "GenMSIL.gen(): Exception caught!"); - /*if (global.debug)*/ e.printStackTrace(); - log("" + tree); + logErr(tree.pos, "Exception caught: " + e.getMessage() + + (global.debug ? "; Use -debug to get a stack trace." : "")); + if (global.debug) + e.printStackTrace(); System.exit(1); - throw (Error) e; } pos = tmpPos; return i; } - /** Generate the code corresponding to a tree node + /* + * Generate the code corresponding to the given tree node */ - Item gen2(Tree tree, MSILType toType) { + private Item gen2(Tree tree, MSILType toType) { Symbol sym = tree.hasSymbol() ? tree.symbol() : null; + Item item = null; switch (tree) { case Empty: return items.VoidItem(); case Block(Tree[] stats, Tree value): - boolean tmpLastStatement = lastStatement; lastStatement = false; + boolean tmpLastExpr = lastExpr; lastExpr = false; for (int i = 0; i < stats.length; i++) { drop(gen(stats[i], MSILType.VOID)); } - lastStatement = tmpLastStatement; - return gen(value, type2MSILType(value.type)); + lastExpr = tmpLastExpr; + return gen(value, toType); case ValDef(_, Name name, Tree tpe, Tree rhs): LocalBuilder local = code.DeclareLocal(tc.getType(sym)); - local.SetLocalSymInfo(name.toString()); + //local.SetLocalSymInfo(name.toString()); + local.SetLocalSymInfo(tree.symbol().name.toString()); locals.put(sym, local); if (rhs == Tree.Empty) return items.VoidItem(); - MSILType type = type2MSILType(tpe.type); - load(coerce(gen(rhs, type), type)); - return check(store(items.LocalItem(type, local))); - - case Ident(Name name): - //log("Ident: " + Debug.show(tree)); - MSILType type = type2MSILType(sym.type()); - if ( sym.isModule() ) // ??? - return load(items.StaticItem - (type2MSILType(tree.type), tc.getModuleField(sym))); - else { + MSILType type = msilType(tpe.type); + genLoad(rhs, type); + return check(store(items.LocalItem(local))); + + case Ident(_): + if (sym.isModule()) { + FieldInfo field = tc.getModuleField(sym); + // force the loading of the module + item = load(items.StaticItem(field)); + } else { + MSILType type = msilType(sym.info()); Integer slot = (Integer) params.get(sym); if (slot != null) { - return items.ArgItem(type, slot.intValue()); + item = items.ArgItem(type, slot.intValue()); } else { LocalBuilder local = (LocalBuilder) locals.get(sym); if (local != null) - return items.LocalItem(type, local); + item = items.LocalItem(local); + else + throw new ApplicationError("Ident = " + Debug.show(sym)); } - return items.SelectItem(type, - items.SelfItem(tc.getType(currentClass)), - tc.getField(sym)); } + return coerce(item, toType); - case Select(Tree qualifier, Name selector): + case Select(Tree qualifier, _): if (sym.isModule()) { - //log("gen: Select from a module: " + sym); - if (sym.isJava()) - logErr("gen.Select: Cannot treat Java class '" + - sym.fullNameString() + "' as value:\n\t" + - dumpSym(sym)); - else { // scala module - Type module = tc.getType(sym); - return items.StaticItem(MSILType.REF(module), - tc.getModuleField(sym)); - } - } - if (!qualifier.hasSymbol()) { -// log("gen2(): " + Debug.show(tree)); -// log("\tqualifier = " + Debug.show(qualifier)); - return items.SelectItem(type2MSILType(tree.type), - gen(qualifier), tc.getField(sym)); + assert !sym.isJava() : "Cannot treat Java class '" + + Debug.show(sym) + "' as value."; + return coerce(load(items.StaticItem(tc.getModuleField(sym))), toType); } -//??? if ((qualifier.symbol().flags & NOVAL) == NOVAL) { -// log("gen.Select: owner NOVAL"); -// return items.StaticItem(type2MSILType(tree.type), tc.getField(sym)); -// } + // check if the tree corresponds to a static Java field - if (qualifier.symbol().isModule() && sym.isJava()) { - //log("gen.Select: static Java field"); - return items.StaticItem - (type2MSILType(tree.type), tc.getField(sym)); - } - if ( qualifier.symbol().isModule() ) { // ????? - //log("gen: Select from a non-Java module: " + qualifier.symbol() + "::" + selector); - return items.SelectItem - (type2MSILType(tree.type), gen(qualifier), tc.getField(sym)); + if (sym.isStatic()) { + return items.StaticItem(tc.getField(sym)); } - if ( sym.isValue() || sym.isVariable() ) { - return items.SelectItem - (type2MSILType(sym.type()), - gen(qualifier, type2MSILType(qualifier.type)), - tc.getField(sym)); - } - - log("gen.Select: Dunno what to do with: " + dumpSym(sym)); - break; - + return items.SelectItem(genLoad(qualifier, msilType(qualifier)), + tc.getField(sym)); case Apply(Tree fun, Tree[] args): - return check(genApply(fun, args, type2MSILType(tree.type))); + return check(genApply(fun, args, toType)); case Assign(Tree lhs, Tree rhs): - boolean tmpLastStatement = lastStatement; lastStatement = false; - MSILType type = type2MSILType(lhs.type); + boolean tmpLastExpr = lastExpr; lastExpr = false; + MSILType type = msilType(lhs.type); Item var = gen(lhs, type); - load(gen(rhs, type)); - lastStatement = tmpLastStatement; + genLoad(rhs, type); + lastExpr = tmpLastExpr; return check(store(var)); - // !!! all Typed nodes are removed by phase ExplicitOuter - case Typed(Literal(AConstant value), Tree tpe): - log("Typed.Literal: " + Debug.show(tree)); - return items.LiteralItem(type2MSILType(tpe.type), value); - - // !!! all Typed nodes are removed by phase ExplicitOuter - case Typed(Tree expr, Tree tpe): - //log("gen.Typed: processing node: " + Debug.show(tree)); - return gen(expr, type2MSILType(tpe.type)); - case New(Template(Tree[] baseClasses, Tree[] body)): assert body.length == 0 : "Template should not have a body!"; switch (baseClasses[0]) { case Apply(Tree fun, Tree[] args): - //MethodBase mctor = tc.getMethod(fun.symbol()); - //log("GenMSIL.New: " + dumpSym(fun.symbol())); - //log("\t" + mctor); ConstructorInfo ctor = (ConstructorInfo) tc.getMethod(fun.symbol()); loadArgs(args, ctor.GetParameters()); code.Emit(OpCodes.Newobj, ctor); - return items.StackItem(MSILType.REF(ctor.DeclaringType)); + return coerce(items.StackItem(msilType(ctor.DeclaringType)), toType); default: - throw new ApplicationError("Dunno what to do!"); + throw new ApplicationError("Incorrect tree: " + + baseClasses[0].getClass()); } case This(_): return items.SelfItem(tc.getType(currentClass)); case Super(_, _): - //logErr("Not implemented yet: Super(" + Debug.show(sym) + ")"); - //log("gen.Super(_): Super.symbol() = " + dumpSym(sym)); - //log("gen.Super(tpe): tpe.symbol() = " + dumpSym(tpe.symbol())); - //log("gen.Super(tpe): tpe = " + Debug.show(tpe)); - //log("gen.Super(tpe): tpe.type() = " + Debug.show(tpe.type())); - //return items.VoidItem(); Item retItem = items.SelfItem(tc.getType(currentClass)); - //log("gen.Super: generated item: " + retItem); return retItem; case Literal(AConstant value): - //log("Literal: " + Debug.show(tree)); - //log("\ttype = " + Debug.show(tree.type)); - MSILType t = type2MSILType(tree.type); - //log("\tmsil type = " + t); - return items.LiteralItem(t, value); + if (toType == MSILType.VOID) + return items.VoidItem(); + return items.LiteralItem(toType, value); case If(Tree cond, Tree thenp, Tree elsep): - Item item = genIf(cond, thenp, elsep, toType); + item = genIf(cond, thenp, elsep, toType); return check(item); case LabelDef(_, Ident[] params, Tree rhs): @@ -591,12 +574,11 @@ public final class GenMSIL { case Switch(Tree test, int[] tags, Tree[] bodies, Tree otherwise): LocalBuilder testLoc = code.DeclareLocal(tc.INT); - Item loc = items.LocalItem(MSILType.I4, testLoc); - boolean tmpLastStatement = lastStatement; - lastStatement = false; - load(gen(test)); + Item loc = items.LocalItem(testLoc); + boolean tmpLastExpr = lastExpr; lastExpr = false; + genLoad(test, MSILType.I4); store(loc); - lastStatement = tmpLastStatement; + lastExpr = tmpLastExpr; Label exit = code.DefineLabel(); Label nextCase = code.DefineLabel(); assert tags.length == bodies.length; @@ -604,43 +586,38 @@ public final class GenMSIL { load(loc); loadI4(tags[i]); code.Emit(OpCodes.Bne_Un, nextCase); - load(gen(bodies[i])); - if (lastStatement) - code.Emit(OpCodes.Ret); - else + genLoad(bodies[i], toType); +// if (lastExpr) +// code.Emit(OpCodes.Ret); +// else + if (willReturn) code.Emit(OpCodes.Br, exit); code.MarkLabel(nextCase); nextCase = code.DefineLabel(); } - Item i = load(gen(otherwise)); + Item i = genLoad(otherwise, toType); code.MarkLabel(exit); return i; default: throw new ApplicationError("Dunno what to do: " + tree.getClass()); } - throw new ApplicationError - ("Dunno what to do with tree node: " + Debug.show(tree)); } //gen() - /** - * Generate code for conditional expressions. + /* Generate code for conditional expressions. */ - Item genIf(Tree condp, Tree thenp, Tree elsep, MSILType toType) { + private Item genIf(Tree condp, Tree thenp, Tree elsep, MSILType toType) { Item iThen = null; - //log("genIf: coerce to type: " + toType); - //log(" thenTree = " + Debug.show(thenp)); - //log(" elseTree = " + Debug.show(elsep)); if (elsep == Tree.Empty && toType == MSILType.VOID) { - boolean tmpLastStatement = lastStatement; lastStatement = false; - Item condi = gen(condp, type2MSILType(condp.type)); - Item.CondItem cond = mkCond(condi); //gen(cond, type2MSILType(cond.type))); - lastStatement = tmpLastStatement; + boolean tmpLastExpr = lastExpr; lastExpr = false; + Item condi = gen(condp, msilType(condp.type)); + Item.CondItem cond = mkCond(condi); + lastExpr = tmpLastExpr; if (cond.success == null) { Chain success = new Chain(code.DefineLabel(), null); branch(cond.test, success); - iThen = coerce(load(gen(thenp, toType)), toType); + iThen = genLoad(thenp, toType); resolve(success); resolve(cond.failure); } else { @@ -648,14 +625,14 @@ public final class GenMSIL { cond.failure : new Chain(code.DefineLabel(), null); branch(cond.test, fail); resolve(cond.success); - iThen = coerce(load(gen(thenp, toType)), toType); + iThen = genLoad(thenp, toType); resolve(fail); } } else { - boolean tmpLastStatement = lastStatement; lastStatement = false; - Item condi = gen(condp, type2MSILType(condp.type)); - Item.CondItem cond = mkCond(condi); //gen(cond, type2MSILType(cond.type))); - lastStatement = tmpLastStatement; + boolean tmpLastExpr = lastExpr; lastExpr = false; + Item condi = gen(condp, msilType(condp.type)); + Item.CondItem cond = mkCond(condi); + lastExpr = tmpLastExpr; Chain fail = cond.failure != null ? cond.failure : new Chain(code.DefineLabel(), null); @@ -664,34 +641,26 @@ public final class GenMSIL { Item thenItem = gen(thenp, toType); iThen = load(coerce(thenItem, toType)); Label exit = null; - if (lastStatement) + /*if (lastExpr) { code.Emit(OpCodes.Ret); - else { - if (lastStatement) - code.Emit(OpCodes.Ret); - else { - exit = code.DefineLabel(); - code.Emit(OpCodes.Br, exit); - } + } else */ + + if (willReturn) { + exit = code.DefineLabel(); + code.Emit(OpCodes.Br, exit); } resolve(fail); - Item iElse= null; - if (elsep == Tree.Empty) { - iElse = items.StaticItem(MSILType.REF(tc.SCALA_UNIT), - tc.RUNTIME_UNIT_VAL); - iElse = coerce(iElse, toType); - } else - iElse = load(coerce(gen(elsep, toType), toType)); + Item iElse = load(gen(elsep, toType)); resolve(exit); - //log("\tgenIf: 'then' item = " + iThen + "; 'else' item" + iElse); } return iThen; } //genIf - - Item coerce(Item item, MSILType toType) { - //log("coerce(): coercing item " + item + " to " + toType); - assert toType != null; + /* Coerce the item to the specified type. */ + private Item coerce(Item item, MSILType toType) { + assert item != null && toType != null : "" + item + " => " + toType; + if (item.type.equals(toType)) + return item; if (toType == MSILType.VOID) return drop(item); switch (item) { @@ -699,28 +668,33 @@ public final class GenMSIL { case SelfItem(): return item; case StackItem(): - if (item.type == MSILType.BOOL && toType == MSILType.I4) //????????? - return items.StackItem(toType); - if (item.type != toType) { - emitConvert(toType); - return items.StackItem(toType); - } + emitConvert(item.type, toType); + item.type = toType; return item; case LiteralItem(MSILType type, AConstant value): - //log("coercing Literal " + type + " -> " + toType); switch (type) { - case REF(_): return item; - default: - return (type == toType) ? item : items.LiteralItem(toType, value); + case REF(Type t): + assert type.isSubtypeOf(toType); } - //return (type == toType) ? item : items.LiteralItem(toType, value); - - default: - return coerce(load(item), toType); + item.type = toType; + return item; + case ArgItem(_): + case LocalItem(_): + if (item.type.isSubtypeOf(toType)) + return item; + break; + case CondItem(_, _, _): + if (item.type == MSILType.BOOL) + return item; + break; } + return coerce(load(item), toType); } - void emitConvert(MSILType toType) { + /***/ + private void emitConvert(MSILType fromType, MSILType toType) { + if (fromType.isSubtypeOf(toType)) + return; switch (toType) { case BOOL: code.Emit(OpCodes.Conv_I4); break; // TODO: is this correct/best? case I1: code.Emit(OpCodes.Conv_I1); break; @@ -730,63 +704,65 @@ public final class GenMSIL { case R4: code.Emit(OpCodes.Conv_R4); break; case R8: code.Emit(OpCodes.Conv_R8); break; case CHAR: code.Emit(OpCodes.Conv_U2); break; - case REF(_): break; - case ARRAY(_): break; default: - logErr("emitConvert: " + toType); + logErr("emitConvert: " + fromType + " => " + toType + + "; fromType.isSubtypeOf(toType) = " + + fromType.isSubtypeOf(toType)); } } /** Generate the code for an Apply node */ - Item genApply(Tree fun, Tree[] args, MSILType resType) { - boolean tmpLastStatement = lastStatement; lastStatement = false; + private Item genApply(Tree fun, Tree[] args, MSILType resType) { + boolean tmpLastExpr = lastExpr; lastExpr = false; Symbol sym = fun.symbol(); switch (fun) { case Ident(_): Label l = (Label)sym2label.get(sym); if (l != null) { - lastStatement = false; + lastExpr = false; for (int i = 0; i < args.length; i++) - load(gen(args[i])); + genLoad(args[i], msilType(args[i].type)); for (int i = args.length; i > 0; i--) code.Emit(OpCodes.Starg_S, i); code.Emit(OpCodes.Br, l); + willReturn = false; return items.VoidItem(); } - lastStatement = tmpLastStatement; + lastExpr = tmpLastExpr; emitThis(); return check(invokeMethod(sym, args, resType, true)); - case Select(Tree qualifier, Name selector): -// log("\tfun: " + Debug.show(fun)); -// log("\tqualifier: " + Debug.show(qualifier)); -// log("\tqualifier.symbol(): " + Debug.show(qualifier.symbol())); -// log("\tqualifier.type: " + Debug.show(qualifier.type)); + case Select(Tree qualifier, _): + // scala.Any.== if (sym == defs.ANY_EQEQ) { return genEq(qualifier, args[0]); } + // scala.Any.!= if (sym == defs.ANY_BANGEQ) { return negate(genEq(qualifier, args[0])); } + // java.lang.String.substring(int, int) + // needs emulation due to diffenerent semantics + // from System.String.Substring if (sym == tc.SYM_SUBSTRING_INT_INT) { assert args.length == 2; - load(gen(qualifier)); - load(gen(args[0])); + genLoad(qualifier, MSILType.STRING); + genLoad(args[0], MSILType.I4); code.Emit(OpCodes.Dup); code.Emit(OpCodes.Neg); - load(gen(args[1])); + genLoad(args[1], MSILType.I4); code.Emit(OpCodes.Add); code.Emit(OpCodes.Call, tc.SUBSTRING_INT_INT); - return items.StackItem(MSILType.STRING_REF); + return items.StackItem(MSILType.STRING); } if (sym == tc.SYM_COMPARE_TO_IGNORE_CASE) { assert args.length == 1; - load(gen(qualifier)); - load(gen(args[0])); + genLoad(qualifier, MSILType.STRING); + genLoad(args[0], MSILType.STRING); code.Emit(OpCodes.Ldc_I4_1); code.Emit(OpCodes.Call, tc.COMPARE_TO_IGNORE_CASE); - return items.StackItem(MSILType.STRING_REF); + return items.StackItem(MSILType.STRING); } if (isPrimitiveArrayOp(sym)) { Primitive prim = primitives.getPrimitive(sym); @@ -808,7 +784,7 @@ public final class GenMSIL { case NEW_DARRAY: //case NEW_OARRAY: code.Emit(OpCodes.Newarr, elemType); - return items.StackItem(MSILType.ARRAY(type2MSILType(elemType))); + return items.StackItem(MSILType.ARRAY(msilType(elemType))); case ZARRAY_GET: case BARRAY_GET: case SARRAY_GET: case CARRAY_GET: case IARRAY_GET: case LARRAY_GET: case FARRAY_GET: case DARRAY_GET: case OARRAY_GET: @@ -827,77 +803,61 @@ public final class GenMSIL { Tree right = args.length > 0 ? args[0] : Tree.Empty; return primitiveOp(qualifier, sym, right, resType); } - + MSILType convTo = primitiveConvert(sym); + if (convTo != null) { + assert args.length == 1; + genLoad(args[0], convTo); + return items.StackItem(convTo); + } switch (qualifier.type) { case TypeRef(_, _, _): case SingleType(_, _): case ThisType(_): -// log("genApply.Select: " + dumpSym(sym)); -// log("\tfun: " + Debug.show(fun)); -// log("\tqualifier: " + Debug.show(qualifier)); -// log("\tqualifier.symbol(): " + Debug.show(qualifier.symbol())); -// log("\tqualifier.type: " + Debug.show(qualifier.type)); - MethodBase method = tc.getMethod(sym); - //log("genApply: method = " + method); boolean virtualCall = false; - if (!method.IsStatic || becomesStatic(sym)) { - //log("genApply.Select: qualifier = " + Debug.show(qualifier)); - //log("genApply.Select: qualifier.type() = " + - //Debug.show(qualifier.type())); - /// FIXME after the Super attribution is correct + if (!method.IsStatic() || becomesStatic(sym)) { + // FIXME: after the Super attribution is correct switch (qualifier) { case Super(_, _): load(items.SelfItem(tc.getType(currentClass))); break; default: - load(gen(qualifier)); + genLoad(qualifier, msilType(qualifier)); virtualCall = true; } - //load(gen(qualifier)); } - lastStatement = tmpLastStatement; + lastExpr = tmpLastExpr; return check(invokeMethod(sym, args, resType, virtualCall)); default: - log("\tfun: " + Debug.show(fun)); - log("\tqualifier: " + Debug.show(qualifier)); - log("\tqualifier.symbol(): " + Debug.show(qualifier.symbol())); - log("\tqualifier.type: " + Debug.show(qualifier.type)); - throw new ApplicationError(); + throw new ApplicationError(Debug.show(fun)); } // switch(qualifier.type) case TypeApply(Tree tfun, Tree[] targs): final Symbol tsym = tfun.symbol(); if (primitives.isPrimitive(tsym)) { -// log("genApply.TypeApply: primitive " + primitives.getPrimitive(tsym).tag + -// " = " + dumpSym(tsym)); - return primitiveOp(((Select)tfun).qualifier, tsym, targs[0], resType); + return primitiveOp(((Select)tfun).qualifier, + tsym, targs[0], resType); } - log("genApply.TypeApply.Select: Dunno how to process TypeApply: " - + Debug.show(fun)); - log("\tTypeApply.fun: " + Debug.show(tfun)); - log("\tTypeApply.fun.symbol(): " + tsym); - throw new ApplicationError(); + throw new ApplicationError(Debug.show(fun)); default: - throw new ApplicationError - ("genApply: Unknown function node: " + Debug.show(fun)); + throw new ApplicationError(Debug.show(fun)); } // switch (fun) } //genApply() /** Generate code for scala's '==' */ - Item genEq(Tree left, Tree right) { + private Item genEq(Tree left, Tree right) { LocalBuilder tmpLocal = (LocalBuilder)locals.get(defs.ANY_EQEQ); if (tmpLocal == null) { tmpLocal = code.DeclareLocal(tc.OBJECT); locals.put(defs.ANY_EQEQ, tmpLocal); } Label l1 = code.DefineLabel(), l2 = code.DefineLabel(); - load(gen(left)); - load(gen(right)); + genLoad(left, MSILType.OBJECT); + genLoad(right, MSILType.OBJECT); code.Emit(OpCodes.Stloc, tmpLocal); code.Emit(OpCodes.Dup); code.Emit(OpCodes.Ldnull); @@ -917,7 +877,7 @@ public final class GenMSIL { * @param t2 * @return the arithmetic coercion type for types t1 and t2 */ - MSILType arithmCoercion(MSILType t1, MSILType t2) { + private MSILType arithmCoercion(MSILType t1, MSILType t2) { if (t1 == t2) return t1; int i, j, n = MSILType.ARITHM_PRECISION.length; for (i = 0; i < n; i++) @@ -934,7 +894,8 @@ public final class GenMSIL { return null; } - boolean isPrimitiveOp(Symbol sym) { + /** Is it a primitive (bot not an array) operation*/ + private boolean isPrimitiveOp(Symbol sym) { switch (primitives.getPrimitive(sym)) { case POS: case NEG: case NOT: case ADD: case SUB: case MUL: case DIV: case MOD: @@ -952,7 +913,8 @@ public final class GenMSIL { } } - boolean isPrimitiveArrayOp(Symbol sym) { + /* Is this a primitive Array operation. */ + private boolean isPrimitiveArrayOp(Symbol sym) { switch (primitives.getPrimitive(sym)) { case NEW_ZARRAY: case NEW_BARRAY: case NEW_SARRAY: case NEW_CARRAY: case NEW_IARRAY: case NEW_LARRAY: @@ -972,13 +934,33 @@ public final class GenMSIL { } } - //------------------------------------------------------------------------ - Item primitiveOp(Tree left, Symbol opSym, Tree right, MSILType resType) + /* Is this a primitive conversion operation. */ + private MSILType primitiveConvert(Symbol sym) { + switch (primitives.getPrimitive(sym)) { + case B2B: case S2B: case C2B: case I2B: case L2B: case F2B: case D2B: + return MSILType.I1; + case B2S: case S2S: case C2S: case I2S: case L2S: case F2S: case D2S: + return MSILType.I2; + case B2C: case S2C: case C2C: case I2C: case L2C: case F2C: case D2C: + return MSILType.CHAR; + case B2I: case S2I: case C2I: case I2I: case L2I: case F2I: case D2I: + return MSILType.I4; + case B2L: case S2L: case C2L: case I2L: case L2L: case F2L: case D2L: + return MSILType.I8; + case B2F: case S2F: case C2F: case I2F: case L2F: case F2F: case D2F: + return MSILType.R4; + case B2D: case S2D: case C2D: case I2D: case L2D: case F2D: case D2D: + return MSILType.R8; + default: + return null; + } + } + + /* Generate code for primitive operations. */ + private Item primitiveOp(Tree left, Symbol opSym, Tree right, MSILType resType) { assert primitives.isPrimitive(opSym); Primitive op = primitives.getPrimitive(opSym); -// log("primaryOp(): primitive index = " + op.tag); -// log("\t" + dumpSym(opSym)); // treat some special cases switch (op) { @@ -986,78 +968,70 @@ public final class GenMSIL { return invokeMethod(opSym, new Tree[]{right}, resType, false); case CONCAT: - load(gen(left)); - load(gen(right)); + genLoad(left, MSILType.OBJECT); + genLoad(right, MSILType.OBJECT); code.Emit(OpCodes.Call, tc.CONCAT_OBJECT_OBJECT); - return items.StackItem(MSILType.STRING_REF); + return items.StackItem(MSILType.STRING); case ADD: if (tc.getType(right.type) == tc.STRING) { log("primaryOp().ADD: string concat!"); - load(gen(left)); - load(gen(right)); + genLoad(left, MSILType.OBJECT); + genLoad(right, MSILType.OBJECT); code.Emit(OpCodes.Call, tc.CONCAT_OBJECT_OBJECT); - return items.StackItem(MSILType.STRING_REF); + return items.StackItem(MSILType.STRING); } break; case IS: -// log("primitiveOp(): Any.is"); - load(gen(left)); + genLoad(left, MSILType.OBJECT); final Type type = tc.getType(right.type); code.Emit(OpCodes.Isinst, type); - return mkCond(items.StackItem(MSILType.REF(type))); + return mkCond(items.StackItem(msilType(type))); case AS: -// log("primitiveOp(): Any.as"); - Item i = load(gen(left)); + Item i = genLoad(left, MSILType.OBJECT); final Type type = tc.getType(right.type); if (!i.type.isType(type) && type != tc.OBJECT) { - //log("genApply: casting item: " + i + " to type: " + type); code.Emit(OpCodes.Castclass, type); } - return items.StackItem(MSILType.REF(type)); + return items.StackItem(msilType(type)); case SYNCHRONIZED: // TODO: reuse temporary local variable whenever possible LocalBuilder tmp = code.DeclareLocal(tc.OBJECT); - load(gen(left)); - //code.Emit(OpCodes.Dup); + genLoad(left, MSILType.OBJECT); code.Emit(OpCodes.Stloc, tmp); code.Emit(OpCodes.Ldloc, tmp); code.Emit(OpCodes.Call, tc.MONITOR_ENTER); - load(gen(right)); + genLoad(right, MSILType.OBJECT); code.Emit(OpCodes.Ldloc, tmp); code.Emit(OpCodes.Call, tc.MONITOR_EXIT); return items.StackItem(MSILType.OBJECT); } Item iLeft = null; - + MSILType tleft = msilType(left); switch (left) { case Apply(Tree fun , Tree[] args): Primitive p = primitives.getPrimitive(fun.symbol()); - //log("primitiveOp: primitive.tag = " + p.tag); switch (p) { case BOX: assert args.length == 1; - iLeft = gen(args[0]); + iLeft = gen(args[0], msilType(args[0])); break; - default: - iLeft = gen(left); } break; default: - iLeft = gen(left); + iLeft = gen(left, tleft); } switch (op) { case THROW: - //log("primitiveOp().THROW: " + Debug.show(left)); load(iLeft); code.Emit(OpCodes.Throw); code.Emit(OpCodes.Ldnull); - return items.StackItem(MSILType.NULL_REF); + return items.StackItem(MSILType.OBJECT); case POS: return load(coerce(iLeft, resType)); case NEG: @@ -1121,74 +1095,80 @@ public final class GenMSIL { merge(failure, rcond.failure)); return rcond; } - MSILType toType = arithmCoercion(primitiveType(left.type), - primitiveType(right.type)); + + MSILType toType = arithmCoercion(iLeft.type, primitiveType(right.type)); load(coerce(iLeft, toType)); - load(coerce(gen(right, toType), toType)); + genLoad(right, toType); + Item res = null; switch (op) { - case ADD: code.Emit(OpCodes.Add); return items.StackItem(resType); - case SUB: code.Emit(OpCodes.Sub); return items.StackItem(resType); - case MUL: code.Emit(OpCodes.Mul); return items.StackItem(resType); - case DIV: code.Emit(OpCodes.Div); return items.StackItem(resType); - case MOD: code.Emit(OpCodes.Rem); return items.StackItem(resType); - - case OR: code.Emit(OpCodes.Or); return items.StackItem(resType); - case XOR: code.Emit(OpCodes.Xor); return items.StackItem(resType); - case AND: code.Emit(OpCodes.And); return items.StackItem(resType); - - case LSL: code.Emit(OpCodes.Shl); return items.StackItem(resType); - case LSR: code.Emit(OpCodes.Shr); return items.StackItem(resType); - case ASR: code.Emit(OpCodes.Shr_Un); return items.StackItem(resType); - - case EQ: return items.CondItem(Test.Binary(Test.EQ, toType), null, null); - case NE: return items.CondItem(Test.Binary(Test.NE, toType), null, null); - case LT: return items.CondItem(Test.Binary(Test.LT_IS, toType), null, null); - case LE: return items.CondItem(Test.Binary(Test.LE_IS, toType), null, null); - case GT: return items.CondItem(Test.Binary(Test.GT_IS, toType), null, null); - case GE: return items.CondItem(Test.Binary(Test.GE_IS, toType), null, null); - + case ADD: code.Emit(OpCodes.Add); res = items.StackItem(toType); break; + case SUB: code.Emit(OpCodes.Sub); res = items.StackItem(toType); break; + case MUL: code.Emit(OpCodes.Mul); res = items.StackItem(toType); break; + case DIV: code.Emit(OpCodes.Div); res = items.StackItem(toType); break; + case MOD: code.Emit(OpCodes.Rem); res = items.StackItem(toType); break; + + case OR: code.Emit(OpCodes.Or); res = items.StackItem(toType); break; + case XOR: code.Emit(OpCodes.Xor); res = items.StackItem(toType); break; + case AND: code.Emit(OpCodes.And); res = items.StackItem(toType); break; + + case LSL: code.Emit(OpCodes.Shl); res = items.StackItem(toType); break; + case LSR: code.Emit(OpCodes.Shr); res = items.StackItem(toType); break; + case ASR: code.Emit(OpCodes.Shr_Un); res = items.StackItem(toType); break; + + case EQ: + res = items.CondItem(Test.Binary(Test.EQ, toType), null, null); + break; + case NE: + res = items.CondItem(Test.Binary(Test.NE, toType), null, null); + break; + case LT: + res = items.CondItem(Test.Binary(Test.LT_IS, toType), null, null); + break; + case LE: + res = items.CondItem(Test.Binary(Test.LE_IS, toType), null, null); + break; + case GT: + res = items.CondItem(Test.Binary(Test.GT_IS, toType), null, null); + break; + case GE: + res = items.CondItem(Test.Binary(Test.GE_IS, toType), null, null); + break; + default: + throw new ApplicationError(Debug.show(op)); } - log("primitiveOp(): dunno what to do with primitive: " + Debug.show(op)); - return items.StackItem(resType); + return coerce(res, resType); } - - void loadArgs(Tree[] args, ParameterInfo[] params) { - boolean tmpLastStatement = lastStatement; - lastStatement = false; + /* + * Load function arguments on the stack. + */ + private void loadArgs(Tree[] args, ParameterInfo[] params) { + boolean tmpLastExpr = lastExpr; lastExpr = false; for (int i = 0; i < args.length; i++) { - MSILType toType = type2MSILType(params[i].ParameterType); //type2MSILType(args[i].type); - load(coerce(gen(args[i], toType), toType)); + MSILType toType = msilType(params[i].ParameterType); //msilType(args[i].type); + genLoad(args[i], toType); } - lastStatement = tmpLastStatement; - } - - boolean isStaticMember(Symbol sym) { - return sym.owner().isModuleClass() && sym.owner().isJava(); + lastExpr = tmpLastExpr; } + /* + * Tells if a non-static method is translated to a static one. + */ private boolean becomesStatic(Symbol sym) { MethodBase method = tc.getMethod(sym); - //return method.IsStatic && method.DeclaringType == tc.MONITOR; - boolean becomesStatic = !isStaticMember(sym) && method.IsStatic; -// if (becomesStatic) { -// log("method becomes static from: " + dumpSym(sym)); -// log("the new method is " + method); -// } - return becomesStatic; + return !sym.isStatic() && method.IsStatic(); } - /** Generate code for method invocation + /* + * Generate code for method invocation */ - Item invokeMethod(Symbol fun, Tree[] args, MSILType resType, + private Item invokeMethod(Symbol fun, Tree[] args, MSILType resType, boolean virtualCall) { - //log("invokeMethod: " + dumpSym(fun)); MethodBase method = tc.getMethod(fun); - assert method != null : "Coudn't resolve method: " + dumpSym(fun); - //log("\tmethod found: " + method); + assert method != null : "Coudn't resolve method: " + Debug.show(fun); Item res = null; - if (method.IsStatic) { + if (method.IsStatic()) { ParameterInfo[] params = method.GetParameters(); if (becomesStatic(fun)) { assert params.length == args.length + 1; @@ -1201,7 +1181,7 @@ public final class GenMSIL { code.Emit(OpCodes.Call, (MethodInfo)method); res = returnsVoid(method) ? items.VoidItem() : items.StackItem(resType); - } else if (method.IsConstructor) { + } else if (method.IsConstructor()) { // used only for calls to super constructor //emitThis(); loadArgs(args, method.GetParameters()); @@ -1209,7 +1189,7 @@ public final class GenMSIL { res = items.VoidItem(); } else { loadArgs(args, method.GetParameters()); - if (enableTailCalls && lastStatement && method == currentMethod) + if (enableTailCalls && lastExpr && method == currentMethod) code.Emit(OpCodes.Tailcall); code.Emit(virtualCall ? OpCodes.Callvirt : OpCodes.Call, (MethodInfo)method); @@ -1218,32 +1198,17 @@ public final class GenMSIL { return check(res); } - /** + /* + * Returns the MSILType that corresponds to the given scala.symtab.Type */ - MSILType type2MSILType(scalac.symtab.Type type) { - switch (type) { - case UnboxedType(int kind): - return MSILType.fromKind(kind); - case TypeRef(_, Symbol s, _): - //log("TypeRef: " + dumpSym(s)); - return MSILType.REF(tc.getType(s)); - case ThisType(Symbol s): - //log("TypeRef: " + dumpSym(s)); - return MSILType.REF(tc.getType(s)); - case UnboxedArrayType(scalac.symtab.Type t): - return MSILType.ARRAY(type2MSILType(t)); - default: - log("type2MSILType: don't know how to convert type " + Debug.show(type)); - //return MSILType.NULL_REF; - return MSILType.OBJECT; - //logErr("type2MSILType: " + Debug.show(type)); - //throw new ApplicationError(); - } + private MSILType msilType(scalac.symtab.Type type) { + return msilType(tc.getType(type)); } - /** + /* + * Also used from class ItemFactory. */ - MSILType type2MSILType(Type type) { + MSILType msilType(Type type) { if (type == tc.BYTE) return MSILType.I1; if (type == tc.SHORT) return MSILType.I2; if (type == tc.INT) return MSILType.I4; @@ -1251,17 +1216,26 @@ public final class GenMSIL { if (type == tc.FLOAT) return MSILType.R4; if (type == tc.DOUBLE) return MSILType.R8; if (type == tc.CHAR) return MSILType.CHAR; + if (type == tc.VOID) return MSILType.VOID; if (type == tc.BOOLEAN)return MSILType.BOOL; - if (type == tc.STRING) return MSILType.STRING_REF; - MSILType mtype = MSILType.REF(type); - //log("type2MSILType: convert " + type + " to " + mtype); - return mtype; + if (type == tc.STRING) return MSILType.STRING; + if (type.IsArray()) + return MSILType.ARRAY(msilType(type.GetElementType())); + return MSILType.REF(type); } - /** + /* + * Returns the MSILType from the type atribute of a tree node */ - MSILType primitiveType(scalac.symtab.Type type) { - MSILType mtype = type2MSILType(type); + private MSILType msilType(Tree t) { + return msilType(t.type); + } + + /* + * Treat the scala boxed types as a primitive type + */ + private MSILType primitiveType(scalac.symtab.Type type) { + MSILType mtype = msilType(type); switch (mtype) { case REF(Type t): if (t == tc.SCALA_BYTE) return MSILType.I1; @@ -1271,17 +1245,19 @@ public final class GenMSIL { if (t == tc.SCALA_FLOAT) return MSILType.R4; if (t == tc.SCALA_DOUBLE) return MSILType.R8; if (t == tc.SCALA_CHAR) return MSILType.CHAR; + if (t == tc.SCALA_UNIT) return MSILType.VOID; if (t == tc.SCALA_BOOLEAN) return MSILType.BOOL; - return type2MSILType(t); + return msilType(t); case ARRAY(_): log("primitiveType: cannot convert " + mtype); return null; default: return mtype; } } - /** + /* + * Provides a translation for some types when used as array elements. */ - MSILType MSILArrayElemType(Type type) { - MSILType mtype = type2MSILType(type); + private MSILType MSILArrayElemType(Type type) { + MSILType mtype = msilType(type); switch (mtype) { case BOOL: return MSILType.I1; case CHAR: return MSILType.I4; @@ -1289,9 +1265,10 @@ public final class GenMSIL { } } - /** + /* + * */ - Type getArrayElemType(Primitive p) { + private Type getArrayElemType(Primitive p) { switch (p) { case NEW_ZARRAY: case ZARRAY_LENGTH: case ZARRAY_GET: case ZARRAY_SET: return tc.BOOLEAN; @@ -1316,9 +1293,10 @@ public final class GenMSIL { return null; } - /** + /* + * Emit code to load an array elemnt of the given type on the stack. */ - Item emitLdelem(MSILType type) { + private Item emitLdelem(MSILType type) { switch (type) { case I1: code.Emit(OpCodes.Ldelem_I1); break; case I2: code.Emit(OpCodes.Ldelem_I2); break; @@ -1333,9 +1311,11 @@ public final class GenMSIL { return items.StackItem(type); } - /** + /* + * Emit code to strore the value at the top of the stack from the given type + * to an array. */ - Item emitStelem(MSILType type) { + private Item emitStelem(MSILType type) { switch (type) { case I1: code.Emit(OpCodes.Stelem_I1); break; case I2: code.Emit(OpCodes.Stelem_I2); break; @@ -1350,9 +1330,10 @@ public final class GenMSIL { return items.StackItem(type); } - /** load an item onto the stack + /* + * Load the value of an item on the stack. */ - Item load(Item that) { + private Item load(Item that) { switch (that) { case VoidItem(): return that; @@ -1361,7 +1342,7 @@ public final class GenMSIL { return (StackItem) that; case LiteralItem(_, AConstant value): - return loadLiteral(value); + return loadLiteral(value, that.type); case SelfItem(): emitThis(); @@ -1385,28 +1366,13 @@ public final class GenMSIL { return items.StackItem(that.type); case StaticItem(FieldInfo field): - if (field.IsLiteral) - loadLiteral(that.type, field.getValue()); - else - code.Emit(OpCodes.Ldsfld, field); + assert !field.IsLiteral(); + code.Emit(OpCodes.Ldsfld, field); return items.StackItem(that.type); case SelectItem(Item qual, FieldInfo field): Item i = load(qual); -// switch (i.type) { -// case REF(Type t): -// if (t.IsInterface) { -// Symbol s = tc.getSymbol(t); -// s = (Symbol) global.PHASE.ADDINTERFACES.interfaceToClass.get(s); -// Type classType = tc.getType(s); -// log("load.SelectItem: warning: inserting class cast from " + t + " to " + classType); -// code.Emit(OpCodes.Castclass, classType); -// } -// break; -// default: -// } code.Emit(OpCodes.Ldfld, field); - //log("load(Item): SelectItem; type = " + that.type); return items.StackItem(that.type); case CondItem(Test test, Chain success, Chain failure): @@ -1414,11 +1380,11 @@ public final class GenMSIL { switch (test) { case Or(_): case And(_): - //log("Loading " + that); Label exit = null; - if (lastStatement) + /*if (lastExpr) code.Emit(OpCodes.Ret); - else { + else */ + if (willReturn) { exit = code.DefineLabel(); code.Emit(OpCodes.Br, exit); } @@ -1426,9 +1392,10 @@ public final class GenMSIL { resolve(failure); load(FALSE_ITEM); if (success != null) { - if (lastStatement) + /*if (lastExpr) code.Emit(OpCodes.Ret); - else + else*/ + if (willReturn) code.Emit(OpCodes.Br, exit); } } @@ -1437,7 +1404,6 @@ public final class GenMSIL { load(TRUE_ITEM); } resolve(exit); - //log("Loading " + that); break; } return items.StackItem(MSILType.BOOL); @@ -1448,9 +1414,10 @@ public final class GenMSIL { } - /** + /* + * Load the value of a test on the stack. */ - void load(Test test) { + private void load(Test test) { switch (test) { case False: code.Emit(OpCodes.Ldc_I4_0); @@ -1476,48 +1443,10 @@ public final class GenMSIL { } } - /** - * Generate the code for a literal + /* + * Load the value of an ALiteral on the stack. */ - Item.StackItem loadLiteral(MSILType type, Object obj) { - switch (type) { - case I1: - case I2: - case I4: - case CHAR: - return loadI4((obj instanceof Character) ? - (int)((Character) obj).charValue() : - ((Number)obj).intValue()); -// return loadI4((type == MSILType.CHAR) ? -// (int)((Character) obj).charValue() : -// ((Number)obj).intValue()); - case I8: - return loadI8(((Number)obj).longValue()); - case R4: - return loadR4(((Number)obj).floatValue()); - case R8: - return loadR8(((Number)obj).doubleValue()); - case BOOL: - return loadBool(((Boolean)obj).booleanValue()); - case VOID: - return loadUnit(); - case REF(Type refType): - if (obj == null) { - return loadNull(); - } else if (refType == tc.STRING) { - return loadString(obj.toString()); - } else { - throw new ApplicationError - ("loadLiteral(): unexpected literal type: " + refType + - "; value = " + obj); - } - default: - throw new ApplicationError - ("loadLiteral(): Unknown literal type: " + type); - } - } // genLiteral() - - Item.StackItem loadLiteral(AConstant constant) { + private Item.StackItem loadLiteral(AConstant constant) { switch (constant) { case UNIT: return loadUnit(); @@ -1546,17 +1475,43 @@ public final class GenMSIL { } } - Item.StackItem loadUnit() { - code.Emit(OpCodes.Ldsfld, tc.RUNTIME_UNIT_VAL); - return items.StackItem(MSILType.VOID); + /* + * Load the value of an ALiteral coerced to the given type. + */ + private Item.StackItem loadLiteral(AConstant constant, MSILType ofType) { + switch (ofType) { + case I1: + case I2: + case I4: + case CHAR: loadI4(constant.intValue()); return items.StackItem(MSILType.I4); + case I8: loadI8(constant.longValue()); return items.StackItem(MSILType.I8); + case R4: loadR4(constant.floatValue()); return items.StackItem(MSILType.R4); + case R8: loadR8(constant.doubleValue()); return items.StackItem(MSILType.R8); + default: + return loadLiteral(constant); + } + } + + /* + * Load boxed scala.Unit on the stack. + */ + private Item.StackItem loadUnit() { + code.Emit(OpCodes.Call, tc.RUNTIME_BOX_UNIT); + return items.StackItem(msilType(tc.RUNTIME_BOX_UNIT.ReturnType)); } - Item.StackItem loadBool(boolean value) { + /* + * Load a boolean value on the stack. + */ + private Item.StackItem loadBool(boolean value) { code.Emit(value ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); return items.StackItem(MSILType.BOOL); } - Item.StackItem loadI4(int value) { + /* + * Load a 32-bit integer literal on the stack. + */ + private Item.StackItem loadI4(int value) { switch (value) { case -1:code.Emit(OpCodes.Ldc_I4_M1); break; case 0: code.Emit(OpCodes.Ldc_I4_0); break; @@ -1577,34 +1532,50 @@ public final class GenMSIL { return items.StackItem(MSILType.I4); } - Item.StackItem loadI8(long value) { + /* + * Load a 64-bit integer value on the stack. + */ + private Item.StackItem loadI8(long value) { code.Emit(OpCodes.Ldc_I8, value); return items.StackItem(MSILType.I8); } - Item.StackItem loadR4(float value) { + /* + * Load a single precision floating point value on the stack. + */ + private Item.StackItem loadR4(float value) { code.Emit(OpCodes.Ldc_R4, value); return items.StackItem(MSILType.R4); } - Item.StackItem loadR8(double value) { + /* + * Load a double precision floating point value on the stack. + */ + private Item.StackItem loadR8(double value) { code.Emit(OpCodes.Ldc_R8, value); return items.StackItem(MSILType.R8); } - Item.StackItem loadString(String value) { + /* + * Load a string reference on the stack. + */ + private Item.StackItem loadString(String value) { code.Emit(OpCodes.Ldstr, value); - return items.StackItem(MSILType.STRING_REF); + return items.StackItem(MSILType.STRING); } - Item.StackItem loadNull() { + /* + * Load the 'null' reference on the stack. + */ + private Item.StackItem loadNull() { code.Emit(OpCodes.Ldnull); - return items.StackItem(MSILType.NULL_REF); + return items.StackItem(MSILType.OBJECT); } - /** + /* + * Store the value on the stack to the location specified by the item. */ - Item store(Item that) { + private Item store(Item that) { switch (that) { case ArgItem(int slot): code.Emit(OpCodes.Starg, slot); @@ -1615,7 +1586,7 @@ public final class GenMSIL { break; case StaticItem(FieldInfo field): - assert !field.IsLiteral; + assert !field.IsLiteral(); code.Emit(OpCodes.Stsfld, field); break; @@ -1630,9 +1601,11 @@ public final class GenMSIL { return items.VoidItem(); } - /** + + /* + * Discard the item. */ - Item drop(Item that) { + private Item drop(Item that) { switch (that) { case VoidItem(): case SelfItem(): @@ -1670,12 +1643,13 @@ public final class GenMSIL { default: drop(load(that)); } - return Item.VoidItem(); + return items.VoidItem(); } - /** + /* + * Generate a condition corresponding to the given item. */ - Item.CondItem mkCond(Item that) { + private Item.CondItem mkCond(Item that) { switch (that) { case CondItem(_, _, _): return (Item.CondItem) that; default: @@ -1684,24 +1658,27 @@ public final class GenMSIL { } } - /** + /* + * Negate a condition. */ - Item.CondItem negate(Item item) { + private Item.CondItem negate(Item item) { Item.CondItem cond = mkCond(item); // swap the failure and success chains return items.CondItem(negate(cond.test), cond.success, cond.failure); } - /** + /* + * Emit code to negate a boolean value on the stack. */ - void negate_load() { + private void negate_load() { code.Emit(OpCodes.Ldc_I4_1); code.Emit(OpCodes.Xor); } - /** + /* + * Negate a test. */ - Test negate(Test that) { + private Test negate(Test that) { switch (that) { case False: @@ -1727,9 +1704,10 @@ public final class GenMSIL { } } - /** + /* + * Emit code for the appropriate branch. */ - Label branch(Test test, Chain chain) { + private Label branch(Test test, Chain chain) { assert chain != null; Label label = chain.label; switch (test) { @@ -1753,9 +1731,10 @@ public final class GenMSIL { } } - /** + /* + * Merge two label chains. */ - static Chain merge(Chain c1, Chain c2) { + private static Chain merge(Chain c1, Chain c2) { if (c1 == null) return c2; if (c2 == null) return c1; Chain c = c1; @@ -1764,23 +1743,26 @@ public final class GenMSIL { return c1; } - /** + /* + * Resolve all labels int the chain to the current position in the code. */ - void resolve(Chain c) { + private void resolve(Chain c) { for (; c != null; c = c.next) code.MarkLabel(c.label); } - /** + /* + * Resolve a label to the current position in the code. */ - void resolve(Label l) { + private void resolve(Label l) { if (l != null) code.MarkLabel(l); } - /** + /* + * */ - static boolean negate_load(int opcode) { + private static boolean negate_load(int opcode) { switch (opcode) { case Test.LT_IS: return false; case Test.LE_IS: return true; @@ -1804,9 +1786,10 @@ public final class GenMSIL { } } - /** + /* + * */ - static OpCode load(int opcode) { + private static OpCode load(int opcode) { switch (opcode) { case Test.LT_IS: return OpCodes.Clt; case Test.LE_IS: return OpCodes.Cgt; // negate @@ -1830,9 +1813,10 @@ public final class GenMSIL { } } - /** + /* + * */ - static int negate(int opcode) { + private static int negate(int opcode) { switch (opcode) { case Test.LT_IS: return Test.GE_IS; case Test.LE_IS: return Test.GT_IS; @@ -1856,9 +1840,10 @@ public final class GenMSIL { } } - /** + /* + * */ - static OpCode branch(int opcode) { + private static OpCode branch(int opcode) { switch (opcode) { case Test.LT_IS: case Test.LT_RO: return OpCodes.Blt; @@ -1884,31 +1869,23 @@ public final class GenMSIL { /////////////////////////////////////////////////////////////////////////// - static String dumpSym(Symbol sym) { - if (sym == null) return ""; - if (sym == Symbol.NONE) return "NoSymbol"; - return "symbol = " + Debug.show(sym) + - "; owner = " + Debug.show(sym.owner()) + - "; info = " + Debug.show(sym.info()) + - "; kind = " + sym.kind + - "; flags = " + Integer.toHexString(sym.flags); - } - - /** + /* + * Print a message */ - void log(String message) { + private void log(String message) { global.reporter.printMessage(message); } - /** + /* + * */ - void logErr(int pos, String message) { + private void logErr(int pos, String message) { global.reporter.printMessage(currUnit.position(pos), message); } /** */ - void logErr(String message) { + private void logErr(String message) { System.err.println(message); throw new ApplicationError(); //log(1, message); @@ -1921,19 +1898,12 @@ public final class GenMSIL { global.log(message); } - /** - */ - void emitComment(String str) { - code.Emit(OpCodes.Ldstr, str); - code.Emit(OpCodes.Pop); - } - } // class GenMSIL - +/** + * Represents the supported types of the CLR. + */ class MSILType { - public case BOOL; - public case CHAR; public case I1; public case I2; public case U2; @@ -1941,16 +1911,19 @@ class MSILType { public case I8; public case R4; public case R8; - public case REF(Type t); - public case ARRAY(MSILType t); + public case BOOL; + public case CHAR; public case VOID; + public case REF(Type t) { assert !t.IsArray(); } + public case ARRAY(MSILType t) { assert t != null; } - public static final MSILType NULL_REF = REF(null); - public static final MSILType OBJECT = REF(Type.GetType("System.Object")); - public static final MSILType STRING_REF = REF(Type.GetType("System.String")); + private static final Type SYSTEM_OBJECT = Type.GetType("System.Object"); + public static final MSILType OBJECT = REF(SYSTEM_OBJECT); + public static final MSILType STRING = REF(Type.GetType("System.String")); public static final MSILType [] ARITHM_PRECISION = new MSILType[] {I1, I2, CHAR, I4, I8, R4, R8}; + public static MSILType fromKind(int kind) { switch (kind) { case TypeTags.BYTE: return I1; @@ -1962,17 +1935,56 @@ class MSILType { case TypeTags.DOUBLE: return R8; case TypeTags.BOOLEAN: return BOOL; case TypeTags.UNIT: return VOID; - case TypeTags.STRING: return STRING_REF; + case TypeTags.STRING: return STRING; default: throw new ApplicationError("Unknown kind: " + kind); } } + public boolean isReferenceType() { + switch (this) { + case REF(_): + case ARRAY(_): + return true; + default: + return false; + } + } public boolean isType(Type type) { switch (this) { case REF(Type t): return (type == t); + case ARRAY(MSILType t): + return type.IsArray() && t.isType(type.GetElementType()); + default: + return false; + } + } + + /** Is this type is a subtype of that. */ + public boolean isSubtypeOf(MSILType that) { + if (this == that + || (this.isReferenceType() && that.isType(SYSTEM_OBJECT))) + return true; + if (that == null) + return false; + switch (this) { + case BOOL: return that == I4; + case REF(Type t1): + switch (that) { + case REF(Type t2): + return t1.isSubtypeOf(t2); + default: + return false; + } + case ARRAY(MSILType t1): + switch (that) { + case ARRAY(MSILType t2): + return t1.isSubtypeOf(t2); + default: + return false; + } default: return false; } @@ -1998,7 +2010,8 @@ class MSILType { } -/** class representing the items +/** + * The items used for deferred code generation. */ class Item { public MSILType type; @@ -2018,20 +2031,27 @@ class Item { case VoidItem(): return "VoidItem: " + type; case StackItem(): return "StackItem: " + type ; case SelfItem(): return "this: " + type; - case LiteralItem(_, AConstant value): return "LiteralItem(" + value + "): " + type; - case ArgItem( int slot): return "ArgItem(" + slot + "): " + type; - case LocalItem( LocalBuilder local): return "LocalItem(" + local + "): " + type; - case StaticItem( FieldInfo field): return "StaticItem(" + field + "): " + type; - case SelectItem(_, FieldInfo field): return "SelectItem(" + field + "): " +type; + case LiteralItem(_, AConstant value): + return "LiteralItem(" + value + "): " + type; + case ArgItem( int slot): + return "ArgItem(" + slot + "): " + type; + case LocalItem( LocalBuilder local): + return "LocalItem(" + local + "): " + type; + case StaticItem( FieldInfo field): + return "StaticItem(" + field + "): " + type; + case SelectItem(_, FieldInfo field): + return "SelectItem(" + field + "): " +type; case CondItem(Test test, Chain success, Chain failure): - return "CondItem(" + test + ", " + success + ", " + failure + "): " + type; + return "CondItem(" + test + ", " + success + + ", " + failure + "): " + type; } return "??Item??"; } } -/** class implementing a chain (list) of labels +/** + * Class implementing a chain (list) of labels. */ class Chain { Label label; @@ -2040,6 +2060,9 @@ class Chain { } +/** + * Factory class for items. + */ class ItemFactory { GenMSIL coder; private static final Item.VoidItem VOID = Item.VoidItem(); @@ -2054,38 +2077,45 @@ class ItemFactory { public Item.StackItem StackItem(MSILType type) { Item.StackItem item = Item.StackItem(); item.type = type; + assert item.type != null; return item; } public Item.SelfItem SelfItem(Type t) { Item.SelfItem item = Item.SelfItem(); - item.type = MSILType.REF(t); + item.type = coder.msilType(t); + assert item.type != null; return item; } public Item.LiteralItem LiteralItem(MSILType type, AConstant value) { Item.LiteralItem item = Item.LiteralItem(type, value); item.type = type; + assert item.type != null; return item; } public Item.ArgItem ArgItem(MSILType type, int slot) { Item.ArgItem item = Item.ArgItem(slot); item.type = type; + assert item.type != null; return item; } - public Item.LocalItem LocalItem(MSILType type, LocalBuilder local) { + public Item.LocalItem LocalItem(LocalBuilder local) { Item.LocalItem item = Item.LocalItem(local); - item.type = type; + item.type = coder.msilType(local.LocalType); + assert item.type != null; return item; } - public Item.StaticItem StaticItem(MSILType type, FieldInfo field) { - assert field.IsStatic; + public Item.StaticItem StaticItem(FieldInfo field) { + assert field.IsStatic(); Item.StaticItem item = Item.StaticItem(field); - item.type = type; + item.type = coder.msilType(field.FieldType); + assert item.type != null; return item; } - public Item.SelectItem SelectItem(MSILType type, Item qualifier, FieldInfo field) { - assert !field.IsStatic; - Item.SelectItem item = Item.SelectItem(coder.load(qualifier), field); - item.type = type; + public Item.SelectItem SelectItem(Item qualifier, FieldInfo field) { + assert !field.IsStatic(); + Item.SelectItem item = Item.SelectItem(qualifier, field); + item.type = coder.msilType(field.FieldType); + assert item.type != null; return item; } public Item.CondItem CondItem(Test test, Chain success, Chain failure) { @@ -2095,7 +2125,8 @@ class ItemFactory { } } -/** class representing the possible tests in conditional item +/** + * Class representing the possible tests in conditional item */ class Test { diff --git a/sources/scalac/backend/msil/GenMSILPhase.java b/sources/scalac/backend/msil/GenMSILPhase.java index 343b67fec1..6ac3fff605 100644 --- a/sources/scalac/backend/msil/GenMSILPhase.java +++ b/sources/scalac/backend/msil/GenMSILPhase.java @@ -23,8 +23,6 @@ public class GenMSILPhase extends Phase { /** The tree to code translator */ private final GenMSIL translator; - final HashMap assemblies = new HashMap(); - final HashMap types2symbols = new HashMap(); final HashMap symbols2types = new HashMap(); final HashMap symbols2fields = new HashMap(); diff --git a/sources/scalac/backend/msil/TypeCreator.java b/sources/scalac/backend/msil/TypeCreator.java index 16250f0455..63f44bf3f8 100644 --- a/sources/scalac/backend/msil/TypeCreator.java +++ b/sources/scalac/backend/msil/TypeCreator.java @@ -43,73 +43,73 @@ import java.util.LinkedHashSet; final class TypeCreator { - final private GenMSIL gen; - final private Global global; - final private Definitions defs; - - final private ArrayList typeBuilders = new ArrayList(); - - final private Map types2symbols; - final private Map symbols2types; - final private Map symbols2fields; - final private Map symbols2methods; - final private Map symbols2moduleFields; - - static final String MODULE_S = "$MODULE"; - - final Type BYTE; - final Type CHAR; - final Type SHORT; - final Type INT; - final Type LONG; - final Type FLOAT; - final Type DOUBLE; - final Type BOOLEAN; - final Type VOID; - - final Type OBJECT; - final Type STRING; - final Type STRING_ARRAY; - - final Type MONITOR; - -// static final MethodInfo CONCAT_OBJECT; -// static final MethodInfo CONCAT_STRING_STRING; - final MethodInfo CONCAT_OBJECT_OBJECT; - final MethodInfo OBJECT_EQUALS; - final MethodInfo MONITOR_PULSE; - final MethodInfo MONITOR_PULSE_ALL; - final MethodInfo MONITOR_WAIT; - final MethodInfo MONITOR_WAIT_TIMEOUT; - final MethodInfo MONITOR_ENTER; - final MethodInfo MONITOR_EXIT; - - Type SCALA_BYTE; - Type SCALA_SHORT; - Type SCALA_INT; - Type SCALA_LONG; - Type SCALA_FLOAT; - Type SCALA_DOUBLE; - Type SCALA_CHAR; - Type SCALA_BOOLEAN; - Type SCALA_UNIT; - - FieldInfo RUNTIME_UNIT_VAL = null; - - Symbol SYM_SUBSTRING_INT_INT; - MethodInfo SUBSTRING_INT_INT; - Symbol SYM_COMPARE_TO_IGNORE_CASE; - MethodInfo COMPARE_TO_IGNORE_CASE; - - ConstructorInfo SCALA_SYMTAB_ATTR_CONSTR; - - final CLRPackageParser ti; + private final GenMSIL gen; + private final Global global; + private final Definitions defs; + + private final ArrayList typeBuilders = new ArrayList(); + + private final Map types2symbols; + private final Map symbols2types; + private final Map symbols2fields; + private final Map symbols2methods; + private final Map symbols2moduleFields; + + public static final String MODULE_S = "$MODULE"; + + public final Type BYTE; + public final Type CHAR; + public final Type SHORT; + public final Type INT; + public final Type LONG; + public final Type FLOAT; + public final Type DOUBLE; + public final Type BOOLEAN; + public final Type VOID; + public final Type ENUM; + + public final Type OBJECT; + public final Type STRING; + public final Type STRING_ARRAY; + + private final Type MONITOR; + + public final MethodInfo CONCAT_OBJECT_OBJECT; + public final MethodInfo OBJECT_EQUALS; + public final MethodInfo MONITOR_ENTER; + public final MethodInfo MONITOR_EXIT; + + private final MethodInfo MONITOR_PULSE; + private final MethodInfo MONITOR_PULSE_ALL; + private final MethodInfo MONITOR_WAIT; + private final MethodInfo MONITOR_WAIT_TIMEOUT; + + public Type SCALA_BYTE; + public Type SCALA_SHORT; + public Type SCALA_INT; + public Type SCALA_LONG; + public Type SCALA_FLOAT; + public Type SCALA_DOUBLE; + public Type SCALA_CHAR; + public Type SCALA_BOOLEAN; + public Type SCALA_UNIT; + + public MethodInfo RUNTIME_BOX_UNIT = null; + + public Symbol SYM_SUBSTRING_INT_INT; + public MethodInfo SUBSTRING_INT_INT; + public Symbol SYM_COMPARE_TO_IGNORE_CASE; + public MethodInfo COMPARE_TO_IGNORE_CASE; + + public ConstructorInfo SCALA_SYMTAB_ATTR_CONSTR; + + private final CLRPackageParser ti; //########################################################################## - TypeCreator(GenMSIL gen, GenMSILPhase phase) { + TypeCreator(Global global, GenMSIL gen, GenMSILPhase phase) { + this.global = global; this.gen = gen; - this.global = gen.global; this.defs = global.definitions; ti = CLRPackageParser.instance; @@ -129,6 +129,7 @@ final class TypeCreator { DOUBLE = Type.GetType("System.Double"); BOOLEAN = Type.GetType("System.Boolean"); VOID = Type.GetType("System.Void"); + ENUM = Type.GetType("System.Enum"); OBJECT = Type.GetType("System.Object"); STRING = Type.GetType("System.String"); @@ -152,7 +153,11 @@ final class TypeCreator { } private boolean initialized = false; - void init() { + + /* + * Called from GenMSIL + */ + public void init() { if (initialized) return; @@ -169,7 +174,8 @@ final class TypeCreator { SCALA_BOOLEAN = getType("scala.Boolean"); SCALA_UNIT = getType("scala.Unit"); - RUNTIME_UNIT_VAL = getType("scala.runtime.RunTime").GetField("UNIT_VAL"); + RUNTIME_BOX_UNIT = getType("scala.runtime.RunTime") + .GetMethod("box_uvalue", Type.EmptyTypes); // initialize type mappings map(defs.ANY_CLASS, OBJECT); @@ -243,6 +249,19 @@ final class TypeCreator { translateMethod(JSTRING, "replace", jChar2, STRING, "Replace"); translateMethod(JSTRING, "toCharArray", STRING, "ToCharArray"); + translateMethod(defs.getClass(Name.fromString("java.lang.Byte")).module() + , "parseByte", jString1, BYTE, "Parse"); + translateMethod(defs.getClass(Name.fromString("java.lang.Short")).module() + , "parseShort", jString1, SHORT, "Parse"); + translateMethod(defs.getClass(Name.fromString("java.lang.Integer")).module() + , "parseInt", jString1, INT, "Parse"); + translateMethod(defs.getClass(Name.fromString("java.lang.Long")).module() + , "parseLong", jString1, LONG, "Parse"); + translateMethod(defs.getClass(Name.fromString("java.lang.Float")).module() + , "parseFloat", jString1, FLOAT, "Parse"); + translateMethod(defs.getClass(Name.fromString("java.lang.Double")).module() + , "parseDouble", jString1, DOUBLE, "Parse"); + SYM_SUBSTRING_INT_INT = lookupMethod(JSTRING, "substring", jInt2); SUBSTRING_INT_INT = STRING.GetMethod("Substring", new Type[]{INT,INT}); @@ -256,8 +275,10 @@ final class TypeCreator { SCALA_SYMTAB_ATTR_CONSTR = scalaSymtab.GetConstructors()[0]; } // init() - // looks up a method according to the signature - Symbol lookupMethod(Symbol clazz, String name, + /* + * Looks up the method with the corresponding signature + */ + private Symbol lookupMethod(Symbol clazz, String name, scalac.symtab.Type[] paramTypes) { Symbol[] methods = clazz.members(). @@ -280,7 +301,10 @@ final class TypeCreator { return null; } // Symbol lookupMethod(...) - static String methodSignature(Symbol sym) { + /* + * Format the signature of a method for better diagnostic printing. + */ + private static String methodSignature(Symbol sym) { switch (sym.info()) { case MethodType(Symbol[] vparams, scalac.symtab.Type result): StringBuffer s = new StringBuffer(); @@ -295,45 +319,31 @@ final class TypeCreator { s.append(")"); return s.toString(); default: - return "Symbol doesn't have a method type: " + dumpSym(sym); + return "Symbol doesn't have a method type: " + Debug.show(sym); } } - String paramList(scalac.symtab.Type[] paramTypes) { - if (paramTypes.length == 0) - return "()"; - StringBuffer s = new StringBuffer("("); - for (int i = 0; i < paramTypes.length; i++) { - if (i > 0) - s.append(", "); - s.append(paramTypes[i]); - } - s.append(")"); - return s.toString(); - } - /** * Create a mapping from method with symbol 'sym' * to the method newClazz.newName(params) */ - void mapMethod(Symbol sym, Type newClazz, String name, Type[] params) { + private void mapMethod(Symbol sym, Type newClazz, String name, Type[] params) { MethodInfo method = newClazz.GetMethod(name, params); assert method != null : "Cannot find translation for: " + methodSignature(sym); symbols2methods.put(sym, method); - //log("translateMethod: " + methodSignature(sym) + " -> " + method); } /** - * create mapping between the specified two methods only + * Create mapping between the specified two methods only */ - void translateMethod(Symbol clazz, String name, - scalac.symtab.Type[] paramTypes, + private void translateMethod(Symbol clazz, String name, + scalac.symtab.Type[] paramTypes, Type newClazz, String newName, Type[] newParamTypes) { Symbol sym = lookupMethod(clazz, name, paramTypes); assert sym != null : "Cannot find method: " + name + " in class " + - dumpSym(clazz); + Debug.show(clazz); mapMethod(sym, newClazz, newName, newParamTypes); } @@ -341,8 +351,8 @@ final class TypeCreator { * Lookup the method and create mapping for all overloaded alternatives * to the corresponding methods in 'newClazz' */ - void translateMethod(Symbol clazz, String name, - Type newClazz, String newName) + private void translateMethod(Symbol clazz, String name, + Type newClazz, String newName) { Symbol sym = clazz.lookup(Name.fromString(name)); assert sym != null : "Cannot find method: " + name; @@ -350,8 +360,9 @@ final class TypeCreator { } /** + * */ - void translateMethod(Symbol clazz, String name, + private void translateMethod(Symbol clazz, String name, scalac.symtab.Type[] paramTypes, Type newClazz, String newName) { @@ -362,8 +373,10 @@ final class TypeCreator { newClazz, newName, newParamTypes); } - // create a mapping for the two methods - void translateMethod(Symbol sym, Type newClazz, String newName) { + /* + * Create a mapping for the two methods. + */ + private void translateMethod(Symbol sym, Type newClazz, String newName) { switch (sym.info()) { case MethodType(Symbol[] vparams, scalac.symtab.Type result): Type[] params = new Type[vparams.length]; @@ -380,7 +393,8 @@ final class TypeCreator { } } - /** Finilizes ('bakes') the newly created types + /** + * Finalizes ('bakes') the newly created types */ public void createTypes() { Iterator iter = typeBuilders.iterator(); @@ -388,32 +402,26 @@ final class TypeCreator { ((TypeBuilder)iter.next()).CreateType(); } - /** - * creates bidirectional mapping from symbols to types + * Creates bidirectional mapping from symbols to types. */ - public void map(Symbol sym, Type type) { + private void map(Symbol sym, Type type) { symbols2types.put(sym, type); if (sym.isClass()) types2symbols.put(type, sym); } - Symbol getSymbol(Type t) { - return (Symbol) types2symbols.get(t); - } - /** - * Return the System.Type object with the given name + * Return the System.Type object with the given name. */ - Type getType(String name) { + private Type getType(String name) { return ti.getType(name); } - /** * Return the System.Type object corresponding to the type of the symbol */ - Type getType(Symbol sym) { + public Type getType(Symbol sym) { if (sym == null) return null; Type type = (Type) symbols2types.get(sym); if (type != null) @@ -432,8 +440,8 @@ final class TypeCreator { if (sym.owner().isClass()) { Type outer = getType(sym.owner()); if (outer == null) - throw new RuntimeException("Cannot find type: " - + dumpSym(owner)); + throw new ApplicationError("Cannot find type: " + + Debug.show(owner)); type = (Type) symbols2types.get(sym); if (type != null) return type; @@ -441,15 +449,19 @@ final class TypeCreator { return createType(sym); String name = sym.nameString() + (sym.isModuleClass() ? "$" : ""); - //log("getType: looking up nested type " + outer + "." + name); type = outer.GetNestedType(name); } else { String fullname = sym.type().symbol().fullNameString() + (sym.isModuleClass() ? "$" : ""); type = getType(fullname); } - if (type == null) - type = createType(sym); + if (type == null) { + if (!sym.isExternal()) + type = createType(sym); + else + global.fail("Cannot find type " + Debug.show(sym) + + "; use the '-r' option to specify its assembly"); + } break; case UnboxedArrayType(scalac.symtab.Type elemtp): @@ -457,56 +469,52 @@ final class TypeCreator { break; default: - //log("getType: Going through the type: " + dumpSym(sym)); type = getType(sym.info()); } } - assert type != null : "Unable to find type: " + dumpSym(sym); + assert type != null : "Unable to find type: " + Debug.show(sym); map(sym, type); return type; } - /** Retrieve the MSIL Type from the scala type + /** + * Retrieve the System.Type from the scala type. */ public Type getType(scalac.symtab.Type type) { - //log("getType: " + Debug.show(type)); switch (type) { + case ThisType(Symbol s): + return getType(s); + case TypeRef(_, Symbol s, _): + return getType(s); case CompoundType(_, _): return getType(type.symbol()); - case UnboxedType(int kind): return getTypeFromKind(kind); - - case TypeRef(_, Symbol s, _): - return getType(s); - case UnboxedArrayType(scalac.symtab.Type elemtp): - // force the creation of the type return ti.mkArrayType(getType(elemtp)); case NoType: return VOID; - default: global.fail("getType: " + Debug.show(type)); } return null; } - - /** Creates a TypeBuilder object corresponding to the symbol + /** + * Creates the TypeBuilder for a class. */ public Type createType(Symbol clazz) { + assert !clazz.isExternal() : "Can not create type " + Debug.show(clazz); Type type = (Type)symbols2types.get(clazz); assert type == null : "Type " + type + - " already defined for symbol: " + dumpSym(clazz); + " already defined for symbol: " + Debug.show(clazz); - //log("TypeCreator.createType(): creating type for " + dumpSym(clazz)); final Symbol owner = clazz.owner(); final String typeName = (owner.isClass() ? clazz.nameString() : clazz.fullNameString()) + (clazz.isModuleClass() ? "$" : ""); - final ModuleBuilder module = gen.currModule; + final ModuleBuilder module = gen.getCurrentModule(); final scalac.symtab.Type classType = clazz.info(); switch (classType) { @@ -582,7 +590,8 @@ final class TypeCreator { } // createType() - /** Returns the MethodBase object corresponding to the symbol + /** + * Returns the MethodBase object corresponding to the symbol. */ public MethodBase getMethod(Symbol sym) { MethodBase method = (MethodBase) symbols2methods.get(sym); @@ -598,9 +607,6 @@ final class TypeCreator { method = (MethodBase) symbols2methods.get(sym); if (method != null) return method; - //System.err.println("getMethod2: resolving " + dumpSym(sym)); - //System.err.println("getMethod2: sym.owner() = " + dumpSym(sym.owner())); - //System.err.println("getMethod2: method owner = " + owner); switch (sym.info()) { case MethodType(Symbol[] vparams, scalac.symtab.Type result): Type[] params = new Type[vparams.length]; @@ -609,7 +615,6 @@ final class TypeCreator { if (sym.isInitializer()) { // The owner of a constructor is the outer class // so get the result type of the constructor - //log("Resolving constructor: " + dumpSym(sym)); Type type = getType(sym.owner()); method = type.GetConstructor(params); } else { @@ -617,7 +622,6 @@ final class TypeCreator { if (sym.name == Names.toString) name = "ToString"; else if (sym.name == Names.hashCode) name = "GetHashCode"; else if (sym.name == Names.equals) name = "Equals"; - //log("Resolving method " + dumpSym(sym)); Type type = getType(sym.owner()); method = type.GetMethod(name, params); } @@ -628,17 +632,15 @@ final class TypeCreator { } assert method != null : "Cannot find method: " + methodSignature(sym); symbols2methods.put(sym, method); - //log("getMethod2: method found: " + method); return method; } - /** create the method corresponding to the symbol + /** + * Create the method corresponding to the symbol. */ - MethodBase createMethod(Symbol sym) { + private MethodBase createMethod(Symbol sym) { MethodBase method = null; - //log("createMethod: " + dumpSym(sym)); - //log("createMethod: sym.owner() = " + dumpSym(sym.owner())); switch (sym.info()) { case MethodType(Symbol[] vparams, scalac.symtab.Type result): TypeBuilder type = (TypeBuilder)getType(sym.owner()); @@ -646,17 +648,17 @@ final class TypeCreator { (type, sym.name, sym.info(), translateMethodAttributes(sym)); break; default: - assert false : "Symbol doesn't have a method type: " + dumpSym(sym); + assert false : "Symbol doesn't have a method type: " + Debug.show(sym); } assert method != null; symbols2methods.put(sym, method); return method; } - /** + * Helper method to createMethod(Symbol) */ - MethodBase createMethod(TypeBuilder type, Name name, + private MethodBase createMethod(TypeBuilder type, Name name, scalac.symtab.Type symType, short attr) { MethodBase method = null; @@ -707,9 +709,6 @@ final class TypeCreator { if (m != null && m instanceof FieldInfo) { field = (FieldInfo)m; } else { - //log("getField: resolving symbol: " + dumpSym(sym)); - //log("-->symbol.type() = " + Debug.show(sym.type())); - //log("-->symbol.info()" + Debug.show(sym.info())); Type owner = getType(sym.owner()); field = owner.GetField(sym.name.toString()); if (field == null) { @@ -722,18 +721,15 @@ final class TypeCreator { System.out.println("\t" + fields[i]); } } - assert field != null : "Cannot find field: " + dumpSym(sym); + assert field != null : "Cannot find field: " + Debug.show(sym); symbols2fields.put(sym, field); return field; } - /** + /* + * */ public FieldInfo createField(Symbol sym) { - //FieldBuilder field; - //log("createField: resolving symbol: " + dumpSym(sym)); - //log("-->symbol.type() = " + Debug.show(sym.type())); - //log("-->symbol.info()" + Debug.show(sym.info())); TypeBuilder owner = (TypeBuilder) getType(sym.owner()); FieldInfo field = (FieldInfo) symbols2fields.get(sym); if (field != null) { @@ -743,44 +739,42 @@ final class TypeCreator { field = owner.DefineField(sym.name.toString(), getType(sym.type()), translateFieldAttributes(sym)); Object o = symbols2fields.put(sym, field); - assert o == null : "Cannot re-define field: " + dumpSym(sym); + assert o == null : "Cannot re-define field: " + Debug.show(sym); return field; } - - /** + /* + * */ - FieldInfo getModuleField(Type type) { + private FieldInfo getModuleField(Type type) { Symbol sym = (Symbol) types2symbols.get(type); assert sym != null; return getModuleField(sym); } + /* + * + */ private Symbol getTypeSymbol(scalac.symtab.Type type) { switch (type) { case TypeRef(_, Symbol s, _): return s; default: - logErr("Strange type: " + Debug.show(type)); + throw new ApplicationError("Cannot get symbol for: " + + Debug.show(type)); } - return null; } - /** * @return the field descriptor of the object instance */ - FieldInfo getModuleField(Symbol sym) { + public FieldInfo getModuleField(Symbol sym) { FieldInfo moduleField = null; if (sym.isModule() || sym.isModuleClass()) { moduleField = (FieldInfo) symbols2moduleFields.get(sym); if (moduleField == null) { - //log("TypeCreator.getModuleField - " + dumpSym(sym)); - //log("\t-->type = " + Debug.show(sym.type())); - //log("\t-->info = " + Debug.show(sym.info())); Symbol s = getTypeSymbol(sym.type()); if (sym != s) { - //log("getModuleField: going through: " + dumpSym(s)); moduleField = getModuleField(s); } else { Type type = getType(sym); @@ -800,16 +794,13 @@ final class TypeCreator { symbols2moduleFields.put(sym, moduleField); } } else { - //throw new ApplicationError("getModuleField: not a module: " + - //dumpSym(sym)); } return moduleField; } - /** Translates Scala modifiers into TypeAttributes */ - public static int translateTypeAttributes(int mods, boolean nested) { + private static int translateTypeAttributes(int mods, boolean nested) { int attr = TypeAttributes.AutoLayout | TypeAttributes.AnsiClass; if (Modifiers.Helper.isInterface(mods)) @@ -839,10 +830,10 @@ final class TypeCreator { return attr; } - - /** Translates Scala modifiers into FieldAttributes + /* + * Translates Scala modifiers into FieldAttributes */ - public static short translateFieldAttributes(Symbol field) { + private static short translateFieldAttributes(Symbol field) { int mods = field.flags; int attr = 0; @@ -861,10 +852,10 @@ final class TypeCreator { return (short)attr; } - - /** Translates Scala modifiers into MethodAttributes + /* + * Translates Scala modifiers into MethodAttributes */ - public static short translateMethodAttributes(Symbol method) + private static short translateMethodAttributes(Symbol method) { int mods = method.flags; if (method.owner().isInterface()) @@ -888,9 +879,10 @@ final class TypeCreator { return (short)attr; } - /** Retrieves the primitive datatypes given their kind + /* + * Retrieves the primitive datatypes given their kind */ - final Type getTypeFromKind(int kind) { + private Type getTypeFromKind(int kind) { switch (kind) { case TypeTags.CHAR: return CHAR; case TypeTags.BYTE: return BYTE; @@ -907,26 +899,4 @@ final class TypeCreator { } } - static String dumpSym(Symbol sym) { - if (sym == null) return ""; - if (sym == Symbol.NONE) return "NoSymbol"; - return "symbol = " + Debug.show(sym) + - " symbol.name = " + sym.name + - "; owner = " + Debug.show(sym.owner()) + - //"; type = " + Debug.show(sym.type()) + - "; info = " + Debug.show(sym.info()) + - "; kind = " + sym.kind + - "; flags = " + Integer.toHexString(sym.flags); - } - - void log(String message) { - System.out.println(message); - //log(1, message); - //global.reporter.printMessage(message); - } - - void logErr(String message) { - System.err.println(message); - } - } // class TypeCreator diff --git a/sources/scalac/symtab/classfile/CLRClassParser.java b/sources/scalac/symtab/classfile/CLRClassParser.java index 913484895e..57f0f3068e 100644 --- a/sources/scalac/symtab/classfile/CLRClassParser.java +++ b/sources/scalac/symtab/classfile/CLRClassParser.java @@ -12,8 +12,10 @@ import scalac.Global; import scalac.symtab.Symbol; import scalac.symtab.TermSymbol; import scalac.symtab.ClassSymbol; +import scalac.symtab.AliasTypeSymbol; import scalac.symtab.Scope; import scalac.symtab.Modifiers; +import scalac.symtab.Type.*; import scalac.util.Name; import scalac.util.Names; import scalac.util.Debug; @@ -27,6 +29,10 @@ public class CLRClassParser extends ClassParser { protected final CLRPackageParser importer; +// private static final int bindingFlags = BindingFlags.DeclaredOnly +// | BindingFlags.Instance | BindingFlags.Static +// | BindingFlags.Public | BindingFlags.NonPublic; + public CLRClassParser(Global global, CLRPackageParser importer) { super(global); this.importer = importer; @@ -34,23 +40,26 @@ public class CLRClassParser extends ClassParser { protected void doComplete(Symbol clazz) { try { doComplete0(clazz); } - catch (AssertionError e) { - System.err.println("While processing " + Debug.show(clazz)); - throw e; + catch (Throwable e) { + System.err.println("\nWhile processing " + Debug.show(clazz)); + e.printStackTrace(); + System.exit(1); } } protected void doComplete0(Symbol clazz) { clazz.owner().initialize(); //??? + long msec = System.currentTimeMillis(); + if (make == null) make = new JavaTypeCreator(global.definitions); - Type type = Type.GetType(clazz.fullNameString()); -// System.out.println("completing class " + clazz.fullNameString() -// + " from type " + type); + Type type = (Type)importer.getMember(clazz); + if (type == null) + type = Type.GetType(clazz.fullNameString()); clazz.flags = translateAttributes(type); - Type[] ifaces = type.GetInterfaces(); // FIXME: ensure only the declared interfaces are taken into account + Type[] ifaces = type.getInterfaces(); scalac.symtab.Type[] baseTypes = new scalac.symtab.Type[ifaces.length+1]; baseTypes[0] = type.BaseType == null ? global.definitions.ANYREF_TYPE() : getCLRType(type.BaseType); @@ -71,23 +80,66 @@ public class CLRClassParser extends ClassParser { staticsClass, scalac.symtab.Type.EMPTY_ARRAY)); } scalac.symtab.Type ctype = clazz.typeConstructor(); + + // import nested types + Type[] nestedTypes = type.getNestedTypes(); + for (int i = 0; i < nestedTypes.length; i++) { + Type ntype = nestedTypes[i]; + if (ntype.IsNestedPrivate() || ntype.IsNestedAssembly() + || ntype.IsNestedFamANDAssem()) + continue; + int j = ntype.FullName.lastIndexOf('.'); + String n = (j < 0 ? ntype.FullName : ntype.FullName.substring(j + 1)) + .replace('+', '#'); + Name classname = Name.fromString(n).toTypeName(); + Name aliasname = Name.fromString(ntype.Name).toTypeName(); + // put the class at the level of its outermost class + ClassSymbol nclazz = new ClassSymbol(classname, clazz.owner(), this); + importer.map(nclazz, ntype); + // create an alias in the module of the outer class + AliasTypeSymbol alias = + new AliasTypeSymbol(Position.NOPOS, aliasname, clazz.module(), + translateAttributes(ntype)); + nclazz.allConstructors().setInfo(staticsParser(nclazz)); + nclazz.module().setInfo(staticsParser(nclazz)); + // + alias.setInfo(scalac.symtab.Type + .typeRef(clazz.owner().thisType(), + nclazz, scalac.symtab.Type.EMPTY_ARRAY)); + alias.allConstructors() + .setInfo(MethodType(Symbol.EMPTY_ARRAY, nclazz.info())); +// statics.enter(nclazz); +// Scope.Entry e = statics.lookupEntry(clazz.module().name); +// if (e != Scope.Entry.NONE) +// statics.unlink(e); +// statics.enter(nclazz.module()); + + Scope.Entry e = statics.lookupEntry(alias.name); // Why is this ??? + if (e != Scope.Entry.NONE) + statics.unlink(e); + statics.enter(alias); + } + // read field information - int bindingFlags = BindingFlags.DeclaredOnly - | BindingFlags.Instance | BindingFlags.Static - | BindingFlags.Public | BindingFlags.NonPublic; - FieldInfo[] fields = type.GetFields(bindingFlags); + FieldInfo[] fields = type.getFields(); for (int i = 0; i < fields.length; i++) { + if (fields[i].IsPrivate() || fields[i].IsAssembly() + || fields[i].IsFamilyAndAssembly()) + continue; int mods = translateAttributes(fields[i]); Name name = Name.fromString(fields[i].Name); scalac.symtab.Type fieldType = getCLRType(fields[i].FieldType); - Symbol owner = fields[i].IsStatic ? staticsClass : clazz; + if (fields[i].IsLiteral()) + fieldType = make.constantType(fieldType, fields[i].getValue()); + Symbol owner = fields[i].IsStatic() ? staticsClass : clazz; Symbol field = new TermSymbol(Position.NOPOS, name, owner, mods); field.setFirstInfo(fieldType); - (fields[i].IsStatic ? statics : members).enterOrOverload(field); + (fields[i].IsStatic() ? statics : members).enterOrOverload(field); importer.map(field, fields[i]); } - PropertyInfo[] props = type.GetProperties(bindingFlags); + //PropertyInfo[] props = type.GetProperties(bindingFlags); + PropertyInfo[] props = type.getProperties(); for (int i = 0; i < props.length; i++) { MethodInfo getter = props[i].GetGetMethod(true); MethodInfo setter = props[i].GetSetMethod(true); @@ -97,22 +149,20 @@ public class CLRClassParser extends ClassParser { scalac.symtab.Type proptype = getCLSType(props[i].PropertyType); if (proptype == null) continue; -// if (type.FullName.equals("System.Collections.ArrayList")) -// System.out.println("getter found: " + getter); Name n = Name.fromString(props[i].Name); scalac.symtab.Type mtype = scalac.symtab.Type.PolyType(Symbol.EMPTY_ARRAY, proptype); int mods = translateAttributes(getter); - Symbol owner = getter.IsStatic ? staticsClass : clazz; + Symbol owner = getter.IsStatic() ? staticsClass : clazz; Symbol method = new TermSymbol(Position.NOPOS, n, owner, mods); setParamOwners(mtype, method); method.setFirstInfo(mtype); - (getter.IsStatic ? statics : members).enterOrOverload(method); + (getter.IsStatic() ? statics : members).enterOrOverload(method); importer.map(method, getter); if (setter == null) continue; - assert getter.IsStatic == setter.IsStatic; + assert getter.IsStatic() == setter.IsStatic(); assert setter.ReturnType == importer.VOID; mtype = methodType(setter, getCLSType(importer.VOID)); if (mtype == null) @@ -122,13 +172,17 @@ public class CLRClassParser extends ClassParser { method = new TermSymbol(Position.NOPOS, n, owner, mods); setParamOwners(mtype, method); method.setFirstInfo(mtype); - (setter.IsStatic ? statics : members).enterOrOverload(method); + (setter.IsStatic() ? statics : members).enterOrOverload(method); importer.map(method, setter); } - MethodInfo[] methods = type.GetMethods(bindingFlags); + //MethodInfo[] methods = type.GetMethods(bindingFlags); + MethodInfo[] methods = type.getMethods(); for (int i = 0; i < methods.length; i++) { - if (importer.getSymbol(methods[i]) != null) + if ((importer.getSymbol(methods[i]) != null) + || methods[i].IsPrivate() + || methods[i].IsAssembly() + || methods[i].IsFamilyAndAssembly()) continue; scalac.symtab.Type rettype = getCLSType(methods[i].ReturnType); if (rettype == null) @@ -143,25 +197,26 @@ public class CLRClassParser extends ClassParser { else if (name.equals("ToString")) n = Names.toString; else n = Name.fromString(name); int mods = translateAttributes(methods[i]); - Symbol owner = methods[i].IsStatic ? staticsClass : clazz; + Symbol owner = methods[i].IsStatic() ? staticsClass : clazz; Symbol method = new TermSymbol(Position.NOPOS, n, owner, mods); setParamOwners(mtype, method); method.setFirstInfo(mtype); - (methods[i].IsStatic ? statics : members).enterOrOverload(method); + (methods[i].IsStatic() ? statics : members).enterOrOverload(method); importer.map(method, methods[i]); } - ConstructorInfo[] constrs = type.GetConstructors(bindingFlags); + //ConstructorInfo[] constrs = type.GetConstructors(bindingFlags); + ConstructorInfo[] constrs = type.getConstructors(); for (int i = 0; i < constrs.length; i++) { - if (constrs[i].IsStatic || constrs[i].IsPrivate - || constrs[i].IsAssembly || constrs[i].IsFamilyAndAssembly) + if (constrs[i].IsStatic() || constrs[i].IsPrivate() + || constrs[i].IsAssembly() || constrs[i].IsFamilyAndAssembly()) continue; scalac.symtab.Type mtype = methodType(constrs[i], ctype); if (mtype == null) continue; Symbol constr = clazz.primaryConstructor(); if (constr.isInitialized()) constr = clazz.addConstructor(); - int mods = translateAttributes(methods[i]); + int mods = translateAttributes(constrs[i]); TermSymbol.newConstructor(clazz, mods).copyTo(constr); setParamOwners(mtype, constr); constr.setFirstInfo(mtype); @@ -178,19 +233,9 @@ public class CLRClassParser extends ClassParser { constr.flags |= Modifiers.PRIVATE; } - // import nested types - Type[] nestedTypes = type.GetNestedTypes(); - for (int i = 0; i < nestedTypes.length; i++) { - Name n = Name.fromString(nestedTypes[i].Name).toTypeName(); - ClassSymbol nclazz = new ClassSymbol(n, clazz, this); - nclazz.allConstructors().setInfo(staticsParser(nclazz)); - nclazz.module().setInfo(staticsParser(nclazz)); - members.enter(nclazz); - Scope.Entry e = members.lookupEntry(clazz.module().name); - if (e != Scope.Entry.NONE) - members.unlink(e); - members.enter(nclazz.module()); - } + global.operation("loaded class " + Debug.show(clazz) + + " from [" + type.Assembly.GetName().Name + "]" + type + + " in " + (System.currentTimeMillis() - msec) + "ms"); } /** Return a method type for */ @@ -221,7 +266,8 @@ public class CLRClassParser extends ClassParser { protected scalac.symtab.Type getClassType(Type type) { assert type != null; - scalac.symtab.Type res = make.classType(Name.fromString(type.FullName)); + scalac.symtab.Type res = + make.classType(Name.fromString(type.FullName.replace('+', '.'))); if (res == scalac.symtab.Type.ErrorType) global.error("unknown class reference " + type.FullName); return res; @@ -230,9 +276,11 @@ public class CLRClassParser extends ClassParser { protected scalac.symtab.Type getCLSType(Type type) { if (type == importer.BYTE || type == importer.USHORT || type == importer.UINT || type == importer.ULONG - || type.IsPointer - || (type.IsArray && getCLSType(type.GetElementType()) == null)) + || type.IsPointer() + || (type.IsArray() && getCLSType(type.GetElementType()) == null)) return null; + //Symbol s = importer.getSymbol(type); + //scalac.symtab.Type t = s != null ? s.typeConstructor() : getCLRType(type); return getCLRType(type); } @@ -259,51 +307,52 @@ public class CLRClassParser extends ClassParser { return make.floatType(); if (type == importer.DOUBLE) return make.doubleType(); - if (type.IsArray) + if (type.IsArray()) return make.arrayType(getCLRType(type.GetElementType())); - return getClassType(type); + Symbol s = importer.getSymbol(type); + return s != null ? s.typeConstructor() : getClassType(type); } protected static int translateAttributes(Type type) { - int mods = 0; - if (type.IsNotPublic || type.IsNestedPrivate - || type.IsNestedAssembly || type.IsNestedFamANDAssem) + int mods = Modifiers.JAVA; + if (type.IsNotPublic() || type.IsNestedPrivate() + || type.IsNestedAssembly() || type.IsNestedFamANDAssem()) mods |= Modifiers.PRIVATE; - else if (type.IsNestedFamily || type.IsNestedFamORAssem) + else if (type.IsNestedFamily() || type.IsNestedFamORAssem()) mods |= Modifiers.PROTECTED; - if (type.IsAbstract) + if (type.IsAbstract()) mods |= Modifiers.ABSTRACT; - if (type.IsSealed) + if (type.IsSealed()) mods |= Modifiers.FINAL; - if (type.IsInterface) + if (type.IsInterface()) mods |= Modifiers.INTERFACE | Modifiers.TRAIT | Modifiers.ABSTRACT; - return mods | Modifiers.JAVA; + return mods; } protected static int translateAttributes(FieldInfo field) { - int mods = 0; - if (field.IsPrivate || field.IsAssembly || field.IsFamilyAndAssembly) + int mods = Modifiers.JAVA; + if (field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly()) mods |= Modifiers.PRIVATE; - else if (field.IsFamily || field.IsFamilyOrAssembly) + else if (field.IsFamily() || field.IsFamilyOrAssembly()) mods |= Modifiers.PROTECTED; - if (field.IsInitOnly) + if (field.IsInitOnly()) mods |= Modifiers.FINAL; else mods |= Modifiers.MUTABLE; - return mods | Modifiers.JAVA; + return mods; } - protected static int translateAttributes(MethodInfo method) { - int mods = 0; - if (method.IsPrivate || method.IsAssembly || method.IsFamilyAndAssembly) + protected static int translateAttributes(MethodBase method) { + int mods = Modifiers.JAVA; + if (method.IsPrivate() || method.IsAssembly() || method.IsFamilyAndAssembly()) mods |= Modifiers.PRIVATE; - else if (method.IsFamily || method.IsFamilyOrAssembly) + else if (method.IsFamily() || method.IsFamilyOrAssembly()) mods |= Modifiers.PROTECTED; - if (method.IsAbstract) + if (method.IsAbstract()) mods |= Modifiers.DEFERRED; - return mods | Modifiers.JAVA; + return mods; } } diff --git a/sources/scalac/symtab/classfile/CLRPackageParser.java b/sources/scalac/symtab/classfile/CLRPackageParser.java index 801197c925..7fec1879e5 100644 --- a/sources/scalac/symtab/classfile/CLRPackageParser.java +++ b/sources/scalac/symtab/classfile/CLRPackageParser.java @@ -78,27 +78,28 @@ public class CLRPackageParser extends MetadataParser { Assembly mscorlib = findAssembly("mscorlib.dll"); Type.initMSCORLIB(mscorlib); - BYTE = Type.GetType("System.SByte"); - UBYTE = Type.GetType("System.Byte"); - CHAR = Type.GetType("System.Char"); - SHORT = Type.GetType("System.Int16"); - USHORT = Type.GetType("System.UInt16"); - INT = Type.GetType("System.Int32"); - UINT = Type.GetType("System.UInt32"); - LONG = Type.GetType("System.Int64"); - ULONG = Type.GetType("System.UInt64"); - FLOAT = Type.GetType("System.Single"); - DOUBLE = Type.GetType("System.Double"); - BOOLEAN = Type.GetType("System.Boolean"); - VOID = Type.GetType("System.Void"); - - OBJECT = Type.GetType("System.Object"); - STRING = Type.GetType("System.String"); - STRING_ARRAY = Type.GetType("System.String[]"); + BYTE = getType("System.SByte"); + UBYTE = getType("System.Byte"); + CHAR = getType("System.Char"); + SHORT = getType("System.Int16"); + USHORT = getType("System.UInt16"); + INT = getType("System.Int32"); + UINT = getType("System.UInt32"); + LONG = getType("System.Int64"); + ULONG = getType("System.UInt64"); + FLOAT = getType("System.Single"); + DOUBLE = getType("System.Double"); + BOOLEAN = getType("System.Boolean"); + VOID = getType("System.Void"); + //ENUM = getType("System.Enum"); + + OBJECT = getType("System.Object"); + STRING = getType("System.String"); + STRING_ARRAY = getType("System.String[]"); findAssembly("vjslib.dll"); findAssembly("scala.dll"); - findAssembly("scalalib.dll"); + //findAssembly("scalalib.dll"); findAllAssemblies(); Type[] types = Type.EmptyTypes; @@ -115,22 +116,19 @@ public class CLRPackageParser extends MetadataParser { types = btypes; } this.types = types; - -// for (int i = 0; i < types.length; i++) -// System.out.println(types[i]); - initialized = true; } - java.util.Map syms2members = new HashMap(); - java.util.Map members2syms = new HashMap(); + private java.util.Map syms2members = new HashMap(); + private java.util.Map members2syms = new HashMap(); //########################################################################## public void map(Symbol sym, MemberInfo m) { syms2members.put(sym, m); members2syms.put(m, sym); + //System.out.println("" + sym + " => " + m); } public MemberInfo getMember(Symbol sym) { @@ -142,7 +140,9 @@ public class CLRPackageParser extends MetadataParser { } public Type getType(String name) { - return Type.GetType(name); + Type t = Type.GetType(name); + //assert t != null : name; + return t; } public Type mkArrayType(Type elemType) { @@ -158,33 +158,45 @@ public class CLRPackageParser extends MetadataParser { /** Load the assembly with the given name */ - Assembly findAssembly(String name) { + private Assembly findAssembly(String name) { // see if the assembly is referenced directly + File file = null; + Assembly assem = null; for (Iterator assems = assemrefs.iterator(); assems.hasNext();) { String assemname = (String)assems.next(); - File f = new File(assemname); - if (!f.getName().equals(name)) + file = new File(assemname); + if (!file.getName().equals(name)) continue; - Assembly assem = Assembly.LoadFrom(f.getPath()); + assem = Assembly.LoadFrom(file.getPath()); if (assem != null) { assems.remove(); assemblies.add(assem); return assem; } } + // look in directories specified with the '-r' option for (Iterator assems = assemrefs.iterator(); assems.hasNext();) { File d = new File((String)assems.next()); if (!d.isDirectory()) continue; - File f = new File(d, name); - if (f.exists()) { - Assembly assem = Assembly.LoadFrom(f.getPath()); + file = new File(d, name); + if (file.exists()) { + assem = Assembly.LoadFrom(file.getPath()); if (assem != null) { assemblies.add(assem); return assem; } } } + // try in the current directory + file = new File(".", name); + if (file.exists()) { + assem = Assembly.LoadFrom(file.getPath()); + if (assem != null) { + assemblies.add(assem); + return assem; + } + } global.fail("Cannot find assembly " + name + "; use the -r option to specify its location"); return null; @@ -192,7 +204,7 @@ public class CLRPackageParser extends MetadataParser { /** Load the rest of the assemblies specified with the '-r' option */ - void findAllAssemblies() { + private void findAllAssemblies() { //System.out.println("assembly references left: " + assemrefs); for (Iterator assems = assemrefs.iterator(); assems.hasNext();) { File f = new File((String)assems.next()); @@ -250,6 +262,7 @@ public class CLRPackageParser extends MetadataParser { if (e != Scope.Entry.NONE) members.unlink(e); members.enter(clazz.module()); + map(clazz, types[i]); } else { importCLRNamespace(name, p, members, pp); } -- cgit v1.2.3