From 2f18309e792ec6d8005bfc98a366657d60de1998 Mon Sep 17 00:00:00 2001 From: paltherr Date: Wed, 4 Feb 2004 20:50:44 +0000 Subject: - 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 --- sources/scala/tools/scalai/Code.java | 15 +-- sources/scala/tools/scalai/Compiler.java | 13 ++- sources/scala/tools/scalai/Evaluator.java | 114 +++++++++++++++++---- sources/scala/tools/scalai/ExpressionCompiler.java | 48 ++++----- sources/scala/tools/scalai/Interpreter.java | 8 +- 5 files changed, 138 insertions(+), 60 deletions(-) (limited to 'sources') 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/*>*/ 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/*>*/ 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); // !!! } //######################################################################## -- cgit v1.2.3