summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpaltherr <paltherr@epfl.ch>2004-02-04 20:50:44 +0000
committerpaltherr <paltherr@epfl.ch>2004-02-04 20:50:44 +0000
commit2f18309e792ec6d8005bfc98a366657d60de1998 (patch)
treec275e1ae289c3226d98bad627fe19ff08fa8a70f
parent9441412e0c3456f523fd7e936221c418d322b4fc (diff)
downloadscala-2f18309e792ec6d8005bfc98a366657d60de1998.tar.gz
scala-2f18309e792ec6d8005bfc98a366657d60de1998.tar.bz2
scala-2f18309e792ec6d8005bfc98a366657d60de1998.zip
- Added proxy field in ScalaTemplate
- Merged Code.IsScala and Code.IsJava into Code.IsAs and added cast - field Added Evaluator.templates and Compiler.templates Rewrote - isInstanceOf and asInstanceOf evaluation code Implemented generation - and evaluation of Code.CreateArray
-rw-r--r--sources/scala/tools/scalai/Code.java15
-rw-r--r--sources/scala/tools/scalai/Compiler.java13
-rw-r--r--sources/scala/tools/scalai/Evaluator.java114
-rw-r--r--sources/scala/tools/scalai/ExpressionCompiler.java48
-rw-r--r--sources/scala/tools/scalai/Interpreter.java8
5 files changed, 138 insertions, 60 deletions
diff --git a/sources/scala/tools/scalai/Code.java b/sources/scala/tools/scalai/Code.java
index 141efdfd4b..ee4e3a1a88 100644
--- a/sources/scala/tools/scalai/Code.java
+++ b/sources/scala/tools/scalai/Code.java
@@ -10,6 +10,7 @@
package scala.tools.scalai;
import scalac.symtab.Symbol;
+import scalac.symtab.Type;
import scalac.util.Debug;
public class Code {
@@ -22,6 +23,7 @@ public class Code {
public case Label(Symbol symbol, Variable[] variables, Code expression);
public case Create(ScalaTemplate template);
+ public case CreateArray(Class component, Code size);
public case Invoke(Code target, Function function, Code[] arguments, int pos);
public case Load(Code target, Variable variable);
public case Store(Code target, Variable variable, Code expression);
@@ -32,8 +34,7 @@ public class Code {
public case And(Code lf, Code rg);
public case Switch(Code test, int[] tags, Code[] bodies, Code otherwise);
- public case IsScala(Code target, Symbol symbol);
- public case IsJava(Code target, Class clasz);
+ public case IsAs(Code target, Type type, Class base, boolean cast);
public case Literal(Object value);
public case Self;
@@ -68,6 +69,9 @@ public class Code {
case Create(ScalaTemplate template):
return "Create(" + template + ")";
+ case CreateArray(Class component, Code size):
+ return "CreateArray(" + component.getName() + "," + size + ")";
+
case Invoke(Code target, Function function, Code[] arguments, int pos):
StringBuffer buffer = new StringBuffer();
buffer.append("Invoke(" + target + "," + function + "," + "[\n");
@@ -104,11 +108,8 @@ public class Code {
buffer.append(")");
return buffer.toString();
- case IsScala(Code target, Symbol symbol):
- return "IsScala(" + target + "," + symbol + ")";
-
- case IsJava(Code target, Class clasz):
- return "IsJava(" + target + "," + clasz + ")";
+ case IsAs(Code target, Type type, Class base, boolean cast):
+ return "IsAs(" + type + "," + type + "," + base + "," + cast +")";
case Literal(Object value):
return "Literal(" + value + ")";
diff --git a/sources/scala/tools/scalai/Compiler.java b/sources/scala/tools/scalai/Compiler.java
index 963af1ad53..c084df61dd 100644
--- a/sources/scala/tools/scalai/Compiler.java
+++ b/sources/scala/tools/scalai/Compiler.java
@@ -45,11 +45,12 @@ public class Compiler {
private final Constants constants;
private final ClassLoader loader;
private final Environment environment;
+ private final Map/*<Class,Set<ScalaTemplate>>*/ templates;
private final Evaluator evaluator; // !!! remove
private final Map any_methods;
private final Map sources;
- public Compiler(Global global, Evaluator evaluator) {
+ public Compiler(Global global, Map templates, Evaluator evaluator) {
this.global = global;
this.definitions = global.definitions;
this.constants = new Constants();
@@ -57,6 +58,7 @@ public class Compiler {
scala.runtime.RunTime.setClassLoader(loader);
JavaMirror mirror = new JavaMirror(definitions, loader);
this.environment = new Environment(this, mirror);
+ this.templates = templates;
this.evaluator = evaluator;
this.any_methods = new HashMap();
this.sources = new HashMap();
@@ -232,7 +234,12 @@ public class Compiler {
for (int i = 0; i < body.length; i++) {
addTemplateMember(source, methods, fields, body[i]);
}
- return new ScalaTemplate(evaluator, symbol, constructor, methods, fields.toArray());
+ ScalaTemplate template = new ScalaTemplate(
+ evaluator, symbol, proxy, constructor, methods, fields.toArray());
+ Set set = (Set)templates.get(proxy);
+ if (set == null) templates.put(proxy, set = new HashSet());
+ set.add(template);
+ return template;
}
//########################################################################
@@ -260,7 +267,7 @@ public class Compiler {
public CodeContainer compile(SourceFile source, Symbol owner, Tree tree, Symbol[] params) {
ExpressionContext context = new ExpressionContext(environment, source, owner);
- ExpressionCompiler worker = new ExpressionCompiler(definitions, constants, context, params);
+ ExpressionCompiler worker = new ExpressionCompiler(definitions, global.primitives, constants, context, params);
return worker.compile(tree);
}
diff --git a/sources/scala/tools/scalai/Evaluator.java b/sources/scala/tools/scalai/Evaluator.java
index 8b5958e252..7f8b1a4b32 100644
--- a/sources/scala/tools/scalai/Evaluator.java
+++ b/sources/scala/tools/scalai/Evaluator.java
@@ -9,6 +9,11 @@
package scala.tools.scalai;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import java.lang.reflect.Array;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
@@ -21,6 +26,7 @@ import ch.epfl.lamp.util.SourceFile;
import scala.runtime.RunTime;
import scalac.symtab.Symbol;
+import scalac.symtab.Type;
import scalac.util.Debug;
public class Evaluator {
@@ -68,13 +74,15 @@ public class Evaluator {
//########################################################################
// Private Fields
+ private final Map/*<Class,Set<ScalaTemplate>>*/ templates;
private final EvaluatorException trace;
private EvaluationStack stack;
//########################################################################
// Public Constructors
- public Evaluator() {
+ public Evaluator(Map templates) {
+ this.templates = templates;
this.trace = new EvaluatorException();
this.stack = null;
}
@@ -192,15 +200,18 @@ public class Evaluator {
return invoke(null, template.getConstructor(),
new Object[] {template.getHandler()});
- case IsScala(Code target, Symbol symbol):
- Object object = evaluate(target);
- if (object == null || !isScalaObject(object)) return Boolean.FALSE;
- Symbol actual = getScalaObject(object).template.getSymbol();
- return new Boolean(actual.isSubClass(symbol));
+ case CreateArray(Class component, Code size):
+ Object length = evaluate(size);
+ assert length instanceof Integer : length.getClass();
+ return Array.newInstance(component, ((Integer)length).intValue());
- case IsJava(Code target, Class clasz):
+ case IsAs(Code target, Type type, Class clasz, boolean cast):
Object object = evaluate(target);
- return new Boolean(clasz.isInstance(object));
+ if (object == null) return cast ? null : Boolean.FALSE;
+ boolean test = isInstanceOf(object, type, clasz);
+ return cast
+ ? (test ? object : throw_(getCastException(object, type)))
+ : (test ? Boolean.TRUE : Boolean.FALSE);
case Or(Code lf, Code rg):
Object object = evaluate(lf);
@@ -298,11 +309,11 @@ public class Evaluator {
case HashCode:
assert args.length == 0 : Debug.show(args);
- return new Integer(getHandlerObject(object).hashCode());
+ return new Integer(getScalaObject(object).hashCode());
case ToString:
assert args.length == 0 : Debug.show(args);
- return getHandlerObject(object).toString();
+ return getScalaObject(object).toString();
default:
throw Debug.abort("illegal function", function);
@@ -480,20 +491,83 @@ public class Evaluator {
//########################################################################
// Private Methods - !!!
- private boolean isScalaObject(Object object) {
- return Proxy.isProxyClass(object.getClass()); // !!! add more checks ?
- }
-
private ScalaObject getScalaObject(Object object) {
- Object handler = getHandlerObject(object);
- assert handler instanceof ScalaObject : handler.getClass();
+ assert object instanceof Proxy: object.getClass();
+ Object handler = object == null
+ ? throw_(new NullPointerException())
+ : Proxy.getInvocationHandler(object);
+ assert handler instanceof ScalaObject: handler.getClass();
return (ScalaObject)handler;
}
- private Object getHandlerObject(Object object) {
- if (object == null) return throw_(new NullPointerException());
- assert object instanceof Proxy : object.getClass();
- return Proxy.getInvocationHandler(object);
+ private Symbol getScalaSymbol(Object object) {
+ Class clasz = object.getClass();
+ if (!(object instanceof Proxy)) return null;
+ Object handler = Proxy.getInvocationHandler(object);
+ if (!(handler instanceof ScalaObject)) return null;
+ return ((ScalaObject)handler).template.getSymbol();
+ }
+
+ private boolean isInstanceOf(Object object, Type type, Class base) {
+ Class clasz = object.getClass();
+ switch (type) {
+ case TypeRef(_, Symbol symbol, _):
+ Symbol scala = getScalaSymbol(object);
+ if (scala != null) return scala.isSubClass(symbol);
+ return base.isAssignableFrom(clasz);
+ case UnboxedArrayType(Type element):
+ return base.isAssignableFrom(clasz);
+ default:
+ throw Debug.abort("illegal case", type);
+ }
+ }
+
+ private String getSignature(Object object) {
+ Symbol symbol = getScalaSymbol(object);
+ if (symbol != null) return symbol.toString();
+ Class clasz = object.getClass();
+ if (!clasz.isArray()) return clasz.toString();
+ return "class " + getClassName(clasz);
+ }
+
+ private String getSignature(Type type) {
+ return "class " + getTypeName(type);
+ }
+
+ private String getClassName(Class clasz) {
+ if (clasz.isArray())
+ return getClassName(clasz.getComponentType()) + "[]";
+ Set scalas = (Set)templates.get(clasz);
+ if (scalas == null) return clasz.getName();
+ StringBuffer buffer = new StringBuffer();
+ boolean separator = false;
+ if (scalas.size() != 1) buffer.append('(');
+ for (Iterator i = scalas.iterator(); i.hasNext(); separator = true) {
+ if (separator) buffer.append(" | ");
+ ScalaTemplate scala = (ScalaTemplate)i.next();
+ buffer.append(scala.getSymbol().fullName());
+ }
+ if (scalas.size() != 1) buffer.append(')');
+ return buffer.toString();
+ }
+
+ private String getTypeName(Type type) {
+ switch (type) {
+ case TypeRef(_, Symbol symbol, _):
+ return symbol.fullNameString();
+ case UnboxedArrayType(Type element):
+ return getTypeName(element) + "[]";
+ case UnboxedType(_):
+ return type.toString();
+ default:
+ throw Debug.abort("illegal case");
+ }
+ }
+
+ private ClassCastException getCastException(Object object, Type type) {
+ String from = getSignature(object);
+ String to = getSignature(type);
+ return new ClassCastException(from + " is not an instance of " + to);
}
//########################################################################
diff --git a/sources/scala/tools/scalai/ExpressionCompiler.java b/sources/scala/tools/scalai/ExpressionCompiler.java
index 2cc87880cc..a937e2ca82 100644
--- a/sources/scala/tools/scalai/ExpressionCompiler.java
+++ b/sources/scala/tools/scalai/ExpressionCompiler.java
@@ -14,8 +14,10 @@ import java.util.ArrayList;
import scalac.ast.Tree;
import scalac.atree.AConstant;
-import scalac.symtab.Symbol;
+import scalac.backend.Primitives;
import scalac.symtab.Definitions;
+import scalac.symtab.Symbol;
+import scalac.symtab.Type;
import scalac.util.Debug;
import scalac.util.Name;
@@ -25,14 +27,16 @@ public class ExpressionCompiler {
// Private Fields
private final Definitions definitions;
+ private final Primitives primitives;
private final Constants constants;
private final ExpressionContext context;
//########################################################################
// Public Constructors
- public ExpressionCompiler(Definitions definitions, Constants constants, ExpressionContext context, Symbol[] params) {
+ public ExpressionCompiler(Definitions definitions, Primitives primitives, Constants constants, ExpressionContext context, Symbol[] params) {
this.definitions = definitions;
+ this.primitives = primitives;
this.constants = constants;
this.context = context;
for (int i = 0; i < params.length; i++)
@@ -166,8 +170,7 @@ public class ExpressionCompiler {
return code;
case Apply(TypeApply(Tree tfun, Tree[] targs), Tree[] vargs):
- assert vargs.length == 0 : Debug.show(tree);
- return tapply(tfun, tfun.symbol(), targs);
+ return tapply(tfun, tfun.symbol(), targs, vargs);
case Apply(Tree vfun, Tree[] vargs):
return vapply(vfun, vfun.symbol(), vargs);
@@ -228,32 +231,21 @@ public class ExpressionCompiler {
//########################################################################
// Private Methods - apply
- private Code tapply(Tree target, Symbol symbol, Tree[] trees) {
+ private Code tapply(Tree target, Symbol symbol, Tree[] targs, Tree[]vargs){
Code object = object(target);
- if (symbol == definitions.ANY_AS) {
- assert trees.length == 1 : Debug.show(trees);
- // !!! some AS should be kept; they might fail
- return object;
+ if (symbol == definitions.ANY_IS || symbol == definitions.ANY_AS) {
+ assert targs.length == 1: Debug.show(targs);
+ assert vargs.length == 0 : Debug.show(vargs);
+ boolean cast = symbol == definitions.ANY_AS;
+ Type type = targs[0].type();
+ return Code.IsAs(object, type, context.getClass(type), cast);
}
- if (symbol == definitions.ANY_IS) {
- assert trees.length == 1 : Debug.show(trees);
- //assert trees[0].hasSymbol() : trees[0];
- Symbol expect = trees[0].getType().symbol();
- // !!! BUG: expect is null for .is[Int]
- assert expect != null : trees[0];
- // !!! System.out.println("!!! IS " + expect);
- Template template = context.lookupTemplate(expect);
- switch (template) {
-
- case Global(_) :
- return Code.IsScala(object, expect);
-
- case JavaClass(Class clasz):
- return Code.IsJava(object, clasz);
-
- default:
- throw Debug.abort("illegal template", template);
- }
+ if (symbol == primitives.NEW_OARRAY) {
+ assert object == Code.Null: object;
+ assert targs.length == 1: Debug.show(targs);
+ assert vargs.length == 1 : Debug.show(vargs);
+ Class component = context.getClass(targs[0].type());
+ return Code.CreateArray(component, compute(vargs[0]));
}
throw Debug.abort("unknown method", symbol);
}
diff --git a/sources/scala/tools/scalai/Interpreter.java b/sources/scala/tools/scalai/Interpreter.java
index 79aa20f279..181dc75274 100644
--- a/sources/scala/tools/scalai/Interpreter.java
+++ b/sources/scala/tools/scalai/Interpreter.java
@@ -9,6 +9,9 @@
package scala.tools.scalai;
+import java.util.Map;
+import java.util.HashMap;
+
import scalac.Global;
import scalac.Phase;
import scalac.symtab.Definitions;
@@ -41,8 +44,9 @@ public class Interpreter {
public Interpreter(Global global) {
this.global = global;
- this.evaluator = new Evaluator();
- this.compiler = new Compiler(global, evaluator); // !!!
+ Map templates = new HashMap();
+ this.evaluator = new Evaluator(templates);
+ this.compiler = new Compiler(global, templates, evaluator); // !!!
}
//########################################################################