diff options
author | Rich Hickey <richhickey@gmail.com> | 2007-09-07 15:26:26 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2007-09-07 15:26:26 +0000 |
commit | b6cdf89042b44d0665ea760e8ab596c26817827e (patch) | |
tree | ac9b978b32ec189a55734503fd2d232ba29b70c2 /src | |
parent | 83a708fcac4cb37ed91ad4d32d70e54041b41dec (diff) |
added instance?
Diffstat (limited to 'src')
-rw-r--r-- | src/jvm/clojure/lang/BytecodeCompiler.java | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/src/jvm/clojure/lang/BytecodeCompiler.java b/src/jvm/clojure/lang/BytecodeCompiler.java index 61a8a5ad..234f9e09 100644 --- a/src/jvm/clojure/lang/BytecodeCompiler.java +++ b/src/jvm/clojure/lang/BytecodeCompiler.java @@ -39,6 +39,7 @@ static final Symbol THROW = Symbol.create("throw"); static final Symbol MONITOR_ENTER = Symbol.create("monitor-enter"); static final Symbol MONITOR_EXIT = Symbol.create("monitor-exit"); static final Symbol EQL_REF = Symbol.create("eql-ref?"); +static final Symbol INSTANCE = Symbol.create("instance?"); static final Symbol THISFN = Symbol.create("thisfn"); static final Symbol IFN = Symbol.create("clojure.lang", "IFn"); @@ -294,21 +295,7 @@ static abstract class HostExpr implements Expr{ throw new IllegalArgumentException("Malformed member expression, expecting (. target member)"); //determine static or instance //static target must be symbol, either fully.qualified.Classname or Classname that has been imported - String className = null; - if(RT.second(form) instanceof Symbol) - { - Symbol sym = (Symbol) RT.second(form); - if(sym.ns == null) //if ns-qualified can't be classname - { - if(sym.name.indexOf('.') > 0) - className = sym.name; - else - { - IPersistentMap imports = (IPersistentMap) RT.IMPORTS.get(); - className = (String) imports.valAt(sym); - } - } - } + String className = maybeClassName(RT.second(form)); //at this point className will be non-null if static Expr instance = null; if(className == null) @@ -336,6 +323,25 @@ static abstract class HostExpr implements Expr{ else throw new IllegalArgumentException("Malformed member expression"); } + + private static String maybeClassName(Object form){ + String className = null; + if(form instanceof Symbol) + { + Symbol sym = (Symbol) form; + if(sym.ns == null) //if ns-qualified can't be classname + { + if(sym.name.indexOf('.') > 0) + className = sym.name; + else + { + IPersistentMap imports = (IPersistentMap) RT.IMPORTS.get(); + className = (String) imports.valAt(sym); + } + } + } + return className; + } } static abstract class FieldExpr extends HostExpr{ @@ -757,6 +763,48 @@ static class ThrowExpr implements Expr{ } } +static class InstanceExpr implements Expr{ + final Expr expr; + final String className; + + + public InstanceExpr(Expr expr, String className){ + this.expr = expr; + this.className = className; + } + + public Object eval() throws Exception{ + return Class.forName(className).isInstance(expr.eval()) ? + RT.T : null; + } + + public void emit(C context, FnExpr fn, GeneratorAdapter gen){ + if(context != C.STATEMENT) + { + Label not = gen.newLabel(); + Label end = gen.newLabel(); + expr.emit(C.EXPRESSION, fn, gen); + gen.instanceOf(Type.getObjectType(className.replace('.', '/'))); + gen.ifZCmp(GeneratorAdapter.EQ, not); + gen.getStatic(RT_TYPE, "T", SYMBOL_TYPE); + gen.goTo(end); + gen.mark(not); + NIL_EXPR.emit(C.EXPRESSION, fn, gen); + gen.mark(end); + } + } + + public static Expr parse(C context, ISeq form) throws Exception{ + //(instance? x Classname) + if(form.count() != 3) + throw new Exception("wrong number of arguments, expecting: (instance? x Classname)"); + String className = HostExpr.maybeClassName(RT.third(form)); + if(className == null) + throw new IllegalArgumentException("Unable to resolve classname: " + RT.third(form)); + return new InstanceExpr(analyze(C.EXPRESSION, RT.second(form)), className); + } +} + static class EqlRefExpr implements Expr{ final Expr expr1; final Expr expr2; @@ -1586,6 +1634,8 @@ private static Expr analyzeSeq(C context, ISeq form, String name) throws Excepti return new MonitorExitExpr(analyze(C.EXPRESSION, RT.second(form))); else if(op.equals(EQL_REF)) return EqlRefExpr.parse(context, form); + else if(op.equals(INSTANCE)) + return InstanceExpr.parse(context, form); else return InvokeExpr.parse(context, form); } |