summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-04-05 21:36:24 +0000
committerRich Hickey <richhickey@gmail.com>2008-04-05 21:36:24 +0000
commitdd837d94fca1f502f62def7d734d98bff3b0b20a (patch)
tree5d7242e721d69afb98054109573eb30f8d7f9486 /src
parenta8948f6cec04ecc8abfaf8b75be1fd8537e50222 (diff)
phase 1 enhanced host calls, no parens needed on args
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/Compiler.java48
-rw-r--r--src/jvm/clojure/lang/Reflector.java9
2 files changed, 39 insertions, 18 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index c1d29eee..15b7afcf 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -665,19 +665,30 @@ static public abstract class HostExpr implements Expr{
static class Parser implements IParser{
public Expr parse(C context, Object frm) throws Exception{
ISeq form = (ISeq) frm;
- //(. x fieldname-sym) or (. x (methodname-sym args...))
- if(RT.length(form) != 3)
- throw new IllegalArgumentException("Malformed member expression, expecting (. target member)");
+ //(. x fieldname-sym) or
+ //(. x 0-ary-method)
+ // (. x methodname-sym args+)
+ // (. x (methodname-sym args?))
+ if(RT.length(form) < 3)
+ 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
int line = (Integer) LINE.get();
Class c = maybeClass(RT.second(form), false);
- //at this point className will be non-null if static
+ //at this point c will be non-null if static
Expr instance = null;
if(c == null)
instance = analyze(context == C.EVAL ? context : C.EXPRESSION, RT.second(form));
-
- if(RT.third(form) instanceof Symbol) //field
+ boolean maybeField = RT.length(form) == 3 && RT.third(form) instanceof Symbol;
+ if(maybeField)
+ {
+ Symbol sym = (Symbol) RT.third(form);
+ if(c != null)
+ maybeField = Reflector.getMethods(c, 0, sym.name, true).size() == 0;
+ else if(instance != null && instance.hasJavaClass() && instance.getJavaClass() != null)
+ maybeField = Reflector.getMethods(instance.getJavaClass(), 0, sym.name, false).size() == 0;
+ }
+ if(maybeField) //field
{
Symbol sym = (Symbol) RT.third(form);
if(c != null)
@@ -685,19 +696,20 @@ static public abstract class HostExpr implements Expr{
else
return new InstanceFieldExpr(line, instance, sym.name);
}
- else if(RT.third(form) instanceof ISeq && RT.first(RT.third(form)) instanceof Symbol)
+ else
{
- Symbol sym = (Symbol) RT.first(RT.third(form));
+ ISeq call = (ISeq) ((RT.third(form) instanceof ISeq)?RT.third(form):RT.rest(RT.rest(form)));
+ if(!(RT.first(call) instanceof Symbol))
+ throw new IllegalArgumentException("Malformed member expression");
+ Symbol sym = (Symbol) RT.first(call);
PersistentVector args = PersistentVector.EMPTY;
- for(ISeq s = RT.rest(RT.third(form)); s != null; s = s.rest())
+ for(ISeq s = RT.rest(call); s != null; s = s.rest())
args = args.cons(analyze(context == C.EVAL ? context : C.EXPRESSION, s.first()));
if(c != null)
return new StaticMethodExpr(line, c, sym.name, args);
else
return new InstanceMethodExpr(line, instance, sym.name, args);
}
- else
- throw new IllegalArgumentException("Malformed member expression");
}
}
@@ -764,7 +776,7 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
final java.lang.reflect.Field field;
final String fieldName;
final int line;
- final static Method getInstanceFieldMethod = Method.getMethod("Object getInstanceField(Object,String)");
+ final static Method invokeNoArgInstanceMember = Method.getMethod("Object invokeNoArgInstanceMember(Object,String)");
final static Method setInstanceFieldMethod = Method.getMethod("Object setInstanceField(Object,String,Object)");
@@ -782,7 +794,7 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
}
public Object eval() throws Exception{
- return Reflector.getInstanceField(target.eval(), fieldName);
+ return Reflector.invokeNoArgInstanceMember(target.eval(), fieldName);
}
public void emit(C context, FnExpr fn, GeneratorAdapter gen){
@@ -800,7 +812,7 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
{
target.emit(C.EXPRESSION, fn, gen);
gen.push(fieldName);
- gen.invokeStatic(REFLECTOR_TYPE, getInstanceFieldMethod);
+ gen.invokeStatic(REFLECTOR_TYPE, invokeNoArgInstanceMember);
}
}
}
@@ -2581,8 +2593,8 @@ static public class FnExpr implements Expr{
//ClassVisitor cv = new TraceClassVisitor(cw, new PrintWriter(System.out));
cv.visit(V1_5, ACC_PUBLIC, internalName, null, isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFn", null);
String source = (String) SOURCE.get();
- int lineBefore = (Integer)LINE_BEFORE.get();
- int lineAfter = (Integer)LINE_AFTER.get() + 1;
+ int lineBefore = (Integer) LINE_BEFORE.get();
+ int lineAfter = (Integer) LINE_AFTER.get() + 1;
String smap = "SMAP\n" +
simpleName + ".java\n" +
"Clojure\n" +
@@ -2591,7 +2603,7 @@ static public class FnExpr implements Expr{
"+ 1 " + source + "\n" +
(String) SOURCE_PATH.get() + "\n" +
"*L\n" +
- String.format("%d#1,%d:%d\n",lineBefore,lineAfter-lineBefore,lineBefore) +
+ String.format("%d#1,%d:%d\n", lineBefore, lineAfter - lineBefore, lineBefore) +
"*E";
if(source != null && SOURCE_PATH.get() != null)
//cv.visitSource(source, null);
@@ -3234,7 +3246,7 @@ static class RecurExpr implements Expr{
IPersistentVector loopLocals = (IPersistentVector) LOOP_LOCALS.get();
if(context != C.RETURN || loopLocals == null)
throw new UnsupportedOperationException("Can only recur from tail position");
- if(IN_CATCH_FINALLY.get()!=null)
+ if(IN_CATCH_FINALLY.get() != null)
throw new UnsupportedOperationException("Cannot recur from catch/finally");
PersistentVector args = PersistentVector.EMPTY;
for(ISeq s = RT.seq(form.rest()); s != null; s = s.rest())
diff --git a/src/jvm/clojure/lang/Reflector.java b/src/jvm/clojure/lang/Reflector.java
index e213d743..35d9ab6d 100644
--- a/src/jvm/clojure/lang/Reflector.java
+++ b/src/jvm/clojure/lang/Reflector.java
@@ -200,6 +200,15 @@ public static Object setInstanceField(Object target, String fieldName, Object va
throw new IllegalArgumentException("No matching field found: " + fieldName);
}
+public static Object invokeNoArgInstanceMember(Object target, String name) throws Exception{
+ //favor method over field
+ List meths = getMethods(target.getClass(),0,name,false);
+ if(meths.size() > 0)
+ return invokeMatchingMethod(name, meths, target, RT.EMPTY_ARRAY);
+ else
+ return getInstanceField(target, name);
+}
+
public static Object invokeInstanceMember(Object target, String name) throws Exception{
//check for field first
Class c = target.getClass();