diff options
author | paltherr <paltherr@epfl.ch> | 2004-02-09 17:02:10 +0000 |
---|---|---|
committer | paltherr <paltherr@epfl.ch> | 2004-02-09 17:02:10 +0000 |
commit | 3a273d52ed33784d3c06476ca4603b426b8a51df (patch) | |
tree | ba92b5395be0ff84d9d3f43bda9fca93187a0730 /sources/scalac/atree | |
parent | 0fe104ec4317992b1b0154a876c81bc0be1f5a02 (diff) | |
download | scala-3a273d52ed33784d3c06476ca4603b426b8a51df.tar.gz scala-3a273d52ed33784d3c06476ca4603b426b8a51df.tar.bz2 scala-3a273d52ed33784d3c06476ca4603b426b8a51df.zip |
- Added translation of primitive methods of Any...
- Added translation of primitive methods of Any, AnyRef, String and
Throwable
Diffstat (limited to 'sources/scalac/atree')
-rw-r--r-- | sources/scalac/atree/ATreeFromSTree.java | 254 |
1 files changed, 253 insertions, 1 deletions
diff --git a/sources/scalac/atree/ATreeFromSTree.java b/sources/scalac/atree/ATreeFromSTree.java index 180551ec9f..cf62f951fa 100644 --- a/sources/scalac/atree/ATreeFromSTree.java +++ b/sources/scalac/atree/ATreeFromSTree.java @@ -10,6 +10,8 @@ package scalac.atree; import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; import scalac.Unit; import scalac.ast.Tree; @@ -17,7 +19,10 @@ import scalac.ast.Tree.Ident; import scalac.ast.Tree.Template; import scalac.symtab.Definitions; import scalac.symtab.Symbol; +import scalac.symtab.TermSymbol; +import scalac.symtab.Type; import scalac.util.Debug; +import scalac.util.Name; /** This class translates syntax trees into attributed trees. */ public class ATreeFromSTree { @@ -31,6 +36,12 @@ public class ATreeFromSTree { /** The attributed tree factory */ private final ATreeFactory make; + /** A mapping from primitive classes to initialization state */ + private final Map/*<Symbol,Boolean>*/ states; + + /** A mapping from primitive methods to generators */ + private final Map/*<Symbol,Generator>*/ generators; + //######################################################################## // Public Constructors @@ -38,6 +49,26 @@ public class ATreeFromSTree { public ATreeFromSTree(Definitions definitions) { this.definitions = definitions; this.make = new ATreeFactory(); + this.states = new HashMap(); + this.generators = new HashMap(); + Symbol[] classes = { + definitions.ANY_CLASS, + definitions.JAVA_OBJECT_CLASS, + definitions.JAVA_STRING_CLASS, + definitions.JAVA_THROWABLE_CLASS, + definitions.ARRAY_CLASS, + definitions.UNIT_CLASS, + definitions.BOOLEAN_CLASS, + definitions.BYTE_CLASS, + definitions.SHORT_CLASS, + definitions.CHAR_CLASS, + definitions.INT_CLASS, + definitions.LONG_CLASS, + definitions.FLOAT_CLASS, + definitions.DOUBLE_CLASS, + }; + for (int i = 0; i < classes.length; i++) + states.put(classes[i], Boolean.FALSE); } //######################################################################## @@ -242,7 +273,19 @@ public class ATreeFromSTree { /** Translates the application. */ private ACode apply(Tree tree, AFunction function,Tree[]targs,Tree[]vargs){ - return make.Apply(tree, function,Tree.typeOf(targs),expression(vargs)); + Type[] types = Tree.typeOf(targs); + switch (function) { + case Method(ACode object, Symbol method, AInvokeStyle style): + if (!style.isDynamic()) break; + Symbol clasz = method.owner(); + Object state = states.get(clasz); + if (state == null) break; + if (state != Boolean.TRUE) addGeneratorsOf(clasz); + Object generator = generators.get(method); + if (generator == null) break; + return generate((Generator)generator, tree, object, types, vargs); + } + return make.Apply(tree, function, types, expression(vargs)); } //######################################################################## @@ -302,4 +345,213 @@ public class ATreeFromSTree { } //######################################################################## + // Private Methods - Translating constants + + /** Translates the constant. */ + private AConstant constant(Object value) { + if (value instanceof Boolean ) return make.BOOLEAN((Boolean )value); + if (value instanceof Byte ) return make.BYTE (((Byte )value)); + if (value instanceof Short ) return make.SHORT ((Short )value); + if (value instanceof Character) return make.CHAR ((Character)value); + if (value instanceof Integer ) return make.INT ((Integer )value); + if (value instanceof Long ) return make.LONG ((Long )value); + if (value instanceof Float ) return make.FLOAT ((Float )value); + if (value instanceof Double ) return make.DOUBLE ((Double )value); + if (value instanceof String ) return make.STRING ((String )value); + throw Debug.abort("illegal constant", value +" -- "+ value.getClass()); + } + + //######################################################################## + // Private Methods - Generating code for primitive methods + + /** Applies generator to given object and arguments. */ + private ACode generate(Generator generator, Tree tree, ACode object, + Type[] targs, Tree[] vargs) + { + switch (generator) { + + case ANYID: + assert targs.length == 0 && vargs.length == 1: tree; + return make.EQ(tree, ATypeKind.REF, object, expression(vargs[0])); + + case ANYEQ: + Symbol lf = newLocal(tree, definitions.ANY_TYPE()); + Symbol rg = newLocal(tree, definitions.ANY_TYPE()); + return make.Block(tree, + new Symbol[] {lf, rg}, + new ACode[] { + store(tree, lf, object), + store(tree, rg, expression(vargs[0]))}, + make.If(tree, + make.EQ(tree, ATypeKind.REF, load(tree, lf)), + make.EQ(tree, ATypeKind.REF, load(tree, rg)), + make.Apply(tree, + AFunction.Method( + load(tree, lf), + definitions.ANY_EQUALS, + AInvokeStyle.Dynamic), + Type.EMPTY_ARRAY, + new ACode[] {load(tree, rg)}))); + + case ANYNE: + Symbol lf = newLocal(tree, definitions.ANY_TYPE()); + Symbol rg = newLocal(tree, definitions.ANY_TYPE()); + return make.Block(tree, + new Symbol[] {lf, rg}, + new ACode[] { + store(tree, lf, object), + store(tree, rg, expression(vargs[0]))}, + make.If(tree, + make.EQ(tree, ATypeKind.REF, load(tree, lf)), + make.NE(tree, ATypeKind.REF, load(tree, rg)), + make.NOT(tree, + ATypeKind.BOOL, + make.Apply(tree, + AFunction.Method( + load(tree, lf), + definitions.ANY_EQUALS, + AInvokeStyle.Dynamic), + Type.EMPTY_ARRAY, + new ACode[] {load(tree, rg)})))); + + case ISAS(boolean cast): + assert targs.length == 1 && vargs.length == 0: tree; + return make.IsAs(tree, object, targs[0], cast); + + case SYNCHRONIZED: + assert targs.length == 1 && vargs.length == 1: tree; + return make.Synchronized(tree, object, expression(vargs[0])); + + case THROW: + assert targs.length == 0 && vargs.length == 0: tree; + return make.Throw(tree, object); + + case CONCAT(ATypeKind prefix): + assert targs.length == 0 && vargs.length == 1: tree; + ATypeKind suffix = kind(vargs[0].type()); + ACode argument = expression(vargs[0]); + return make.CONCAT(tree, prefix, suffix, object, argument); + + default: + throw Debug.abort("unknown case", generator); + } + } + + /** Generates a load operation with given variable. */ + private ACode load(Tree tree, Symbol local) { + assert local.owner().isNone(): Debug.show(local); + return make.Load(tree, ALocation.Local(local, false)); + } + + /** Generates a store operation with given variable and value. */ + private ACode store(Tree tree, Symbol local, ACode value) { + assert local.owner().isNone(): Debug.show(local); + return make.Store(tree, ALocation.Local(local, false), value); + } + + /** Creates a variable with tree's position and given type. */ + private Symbol newLocal(Tree tree, Type type) { + Symbol owner = Symbol.NONE; // !!! + Name name = Name.fromString("local"); // !!! + return new TermSymbol(tree.pos, name, owner, 0).setType(type); + } + + /** Returns the type kind of given type. */ + private ATypeKind kind(Type type) { + switch (type) { + case SingleType(_, _): + case ConstantType(_, _): + return kind(type.singleDeref()); + case TypeRef(_, Symbol clasz, _): + if (clasz == definitions.BOOLEAN_CLASS) return ATypeKind.BOOL; + if (clasz == definitions.BYTE_CLASS) return ATypeKind.I1; + if (clasz == definitions.SHORT_CLASS) return ATypeKind.I2; + if (clasz == definitions.CHAR_CLASS) return ATypeKind.U2; + if (clasz == definitions.INT_CLASS) return ATypeKind.I4; + if (clasz == definitions.LONG_CLASS) return ATypeKind.I8; + if (clasz == definitions.FLOAT_CLASS) return ATypeKind.R4; + if (clasz == definitions.DOUBLE_CLASS) return ATypeKind.R8; + if (clasz == definitions.JAVA_STRING_CLASS) return ATypeKind.STR; + return ATypeKind.REF; + default: + return ATypeKind.REF; + } + } + + //######################################################################## + // Private Methods - Collecting primitive methods + + /** Associates generators to primitive methods of given class. */ + private void addGeneratorsOf(Symbol clasz) { + if (clasz == definitions.ANY_CLASS) { + addGenerator(definitions.ANY_EQ, Generator.ANYID); + addGenerator(definitions.ANY_EQEQ, Generator.ANYEQ); + addGenerator(definitions.ANY_BANGEQ, Generator.ANYNE); + addGenerator(definitions.ANY_IS, Generator.ISAS(false)); + addGenerator(definitions.ANY_AS, Generator.ISAS(true)); + } + if (clasz == definitions.JAVA_OBJECT_CLASS) { + addGenerator(definitions.ANYREF_SYNCHRONIZED, Generator.SYNCHRONIZED); + } + if (clasz == definitions.JAVA_STRING_CLASS) { + addGenerator(definitions.JAVA_STRING_PLUS, Generator.CONCAT(ATypeKind.STR)); + } + if (clasz == definitions.JAVA_THROWABLE_CLASS) { + addGenerator(definitions.JAVA_THROWABLE_THROW, Generator.THROW); + } + if (clasz == definitions.ARRAY_CLASS) { + // !!! addAll(defs.ARRAY_CLASS, Names.length, Primitive.LENGTH, 1); + // !!! addAll(defs.ARRAY_CLASS, Names.apply, Primitive.APPLY, 2); + // !!! addAll(defs.ARRAY_CLASS, Names.update, Primitive.UPDATE, 1); + } + if (clasz == definitions.UNIT_CLASS) { + // !!! + } + if (clasz == definitions.BOOLEAN_CLASS) { + // !!! + } + if (clasz == definitions.BYTE_CLASS) { + // !!! + } + if (clasz == definitions.SHORT_CLASS) { + // !!! + } + if (clasz == definitions.CHAR_CLASS) { + // !!! + } + if (clasz == definitions.INT_CLASS) { + // !!! + } + if (clasz == definitions.LONG_CLASS) { + // !!! + } + if (clasz == definitions.FLOAT_CLASS) { + // !!! + } + if (clasz == definitions.DOUBLE_CLASS) { + // !!! + } + states.put(clasz, Boolean.TRUE); + } + + /** Associates given generator to given primitive method. */ + private void addGenerator(Symbol method, Generator generator) { + generators.put(method, generator); + } + + //######################################################################## + // Private Class - Code generators + + /** Code generators for primitive methods. */ + private static class Generator { + case ANYID; + case ANYEQ; + case ANYNE; + case ISAS(boolean cast); + case SYNCHRONIZED; + case THROW; + case CONCAT(ATypeKind prefix); + } + + //######################################################################## } |