summaryrefslogtreecommitdiff
path: root/sources/scalac/atree
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2004-02-09 17:02:10 +0000
committerpaltherr <paltherr@epfl.ch>2004-02-09 17:02:10 +0000
commit3a273d52ed33784d3c06476ca4603b426b8a51df (patch)
treeba92b5395be0ff84d9d3f43bda9fca93187a0730 /sources/scalac/atree
parent0fe104ec4317992b1b0154a876c81bc0be1f5a02 (diff)
downloadscala-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.java254
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);
+ }
+
+ //########################################################################
}