diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-03-23 17:38:09 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-03-23 17:38:09 +0000 |
commit | 26dc63797bf65aeedb91d01dbf6edf2f339e972a (patch) | |
tree | a7d9c60040358cfe5adc370201fc56eec10c3a15 /src | |
parent | f99b85789d1a5f2d78231c3da03627bfe8ac0b5b (diff) |
made IFn extend Runnable, stricter overload resolution, accessible macro metadata via *macro-meta*, more type hints in boot.clj
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.clj | 18 | ||||
-rw-r--r-- | src/jvm/clojure/lang/AFn.java | 10 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 63 | ||||
-rw-r--r-- | src/jvm/clojure/lang/IFn.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Keyword.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Ref.java | 11 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Reflector.java | 7 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Var.java | 11 |
9 files changed, 106 insertions, 24 deletions
diff --git a/src/boot.clj b/src/boot.clj index 62de5ae2..7d6dfd29 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -308,7 +308,7 @@ ([#^Object x] (if (nil? x) "" (. x (toString)))) ([x & ys] - (loop [sb (new StringBuilder (str x)) more ys] + (loop [sb (new StringBuilder #^String (str x)) more ys] (if more (recur (. sb (append (str (first more)))) (rest more)) (str sb))))) @@ -1734,7 +1734,7 @@ make-proxy [classes method-map] (defn ns-publics "Returns a map of the public intern mappings for the namespace." [#^clojure.lang.Namespace ns] - (filter-key val (fn [v] (and (instance? clojure.lang.Var v) + (filter-key val (fn [#^clojure.lang.Var v] (and (instance? clojure.lang.Var v) (= ns (. v ns)) (. v (isPublic)))) (ns-map ns))) @@ -1776,14 +1776,14 @@ make-proxy [classes method-map] (defn ns-refers "Returns a map of the refer mappings for the namespace." [#^clojure.lang.Namespace ns] - (filter-key val (fn [v] (and (instance? clojure.lang.Var v) + (filter-key val (fn [#^clojure.lang.Var v] (and (instance? clojure.lang.Var v) (not= ns (. v ns)))) (ns-map ns))) (defn ns-interns "Returns a map of the intern mappings for the namespace." [#^clojure.lang.Namespace ns] - (filter-key val (fn [v] (and (instance? clojure.lang.Var v) + (filter-key val (fn [#^clojure.lang.Var v] (and (instance? clojure.lang.Var v) (= ns (. v ns)))) (ns-map ns))) @@ -2004,9 +2004,11 @@ make-proxy [classes method-map] (let ~lets ~@body))))))) new-sigs (map psig sigs)] - (if name - (list* 'fn* name new-sigs) - (cons 'fn* new-sigs)))) + (with-meta + (if name + (list* 'fn* name new-sigs) + (cons 'fn* new-sigs)) + *macro-meta*))) (defmacro comment "Ignores body, yields nil" @@ -2208,7 +2210,7 @@ make-proxy [classes method-map] (defn slurp "Reads the file named by f into a string and returns it." - [f] + [#^String f] (with-open r (new java.io.BufferedReader (new java.io.FileReader f)) (let [sb (new StringBuilder)] (loop [c (. r (read))] diff --git a/src/jvm/clojure/lang/AFn.java b/src/jvm/clojure/lang/AFn.java index 11db130a..49dd5242 100644 --- a/src/jvm/clojure/lang/AFn.java +++ b/src/jvm/clojure/lang/AFn.java @@ -31,6 +31,16 @@ public Object call() throws Exception{ return invoke(); } +public void run(){ + try + { + invoke(); + } + catch(Exception e) + { + throw new RuntimeException(e); + } +} public int compare(Object o1, Object o2){ try diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 83eab86a..efc1ce27 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -136,7 +136,7 @@ static for(int j = 0; j < MAX_POSITIONAL_ARITY; j++) a[j] = OBJECT_TYPE; a[MAX_POSITIONAL_ARITY] = Type.getType("[Ljava/lang/Object;"); - ARG_TYPES[MAX_POSITIONAL_ARITY+1] = a; + ARG_TYPES[MAX_POSITIONAL_ARITY + 1] = a; } @@ -950,7 +950,7 @@ static class InstanceMethodExpr extends MethodExpr{ ArrayList<Class[]> params = new ArrayList(); for(int i = 0; i < methods.size(); i++) params.add(((java.lang.reflect.Method) methods.get(i)).getParameterTypes()); - methodidx = getMatchingParams(params, args); + methodidx = getMatchingParams(methodName,params, args); } java.lang.reflect.Method m = (java.lang.reflect.Method) (methodidx >= 0 ? methods.get(methodidx) : null); @@ -1049,7 +1049,7 @@ static class StaticMethodExpr extends MethodExpr{ ArrayList<Class[]> params = new ArrayList(); for(int i = 0; i < methods.size(); i++) params.add(((java.lang.reflect.Method) methods.get(i)).getParameterTypes()); - methodidx = getMatchingParams(params, args); + methodidx = getMatchingParams(methodName,params, args); } method = (java.lang.reflect.Method) (methodidx >= 0 ? methods.get(methodidx) : null); if(method == null && RT.booleanCast(RT.WARN_ON_REFLECTION.get())) @@ -1689,8 +1689,22 @@ static class ClassExpr implements Expr{ } } -static int getMatchingParams(ArrayList<Class[]> paramlists, IPersistentVector argexprs) throws Exception{ +static boolean subsumes(Class[] c1, Class[] c2){ //presumes matching lengths + for(int i=0;i<c1.length;i++) + { + if(c2[i].isPrimitive() && c1[i] == Object.class) + continue; + if(!c2[i].isAssignableFrom(c1[i])) + return false; + } + return true; +} + +static int getMatchingParams(String methodName, ArrayList<Class[]> paramlists, IPersistentVector argexprs) + throws Exception{ + //presumes matching lengths + int matchIdx = -1; for(int i = 0; i < paramlists.size(); i++) { boolean match = true; @@ -1702,9 +1716,19 @@ static int getMatchingParams(ArrayList<Class[]> paramlists, IPersistentVector ar match = Reflector.paramArgTypeMatch(paramlists.get(i)[p], aclass); } if(match) - return i; + { + if(matchIdx == -1) + matchIdx = i; + else + { + if(subsumes(paramlists.get(i),paramlists.get(matchIdx))) + matchIdx = i; + else if(!subsumes(paramlists.get(matchIdx),paramlists.get(i))) + throw new IllegalArgumentException("More than one matching method found: " + methodName); + } + } } - return -1; + return matchIdx; } static class NewExpr implements Expr{ @@ -1737,7 +1761,7 @@ static class NewExpr implements Expr{ int ctoridx = 0; if(ctors.size() > 1) { - ctoridx = getMatchingParams(params, args); + ctoridx = getMatchingParams(c.getName(),params, args); } this.ctor = ctoridx >= 0 ? (Constructor) ctors.get(ctoridx) : null; @@ -2324,7 +2348,7 @@ static class InvokeExpr implements Expr{ } MethodExpr.emitArgsAsArray(restArgs, fn, gen); } - gen.invokeInterface(IFN_TYPE, new Method("invoke", OBJECT_TYPE, ARG_TYPES[Math.min(MAX_POSITIONAL_ARITY+1, + gen.invokeInterface(IFN_TYPE, new Method("invoke", OBJECT_TYPE, ARG_TYPES[Math.min(MAX_POSITIONAL_ARITY + 1, args.count())])); if(context == C.STATEMENT) gen.pop(); @@ -2376,6 +2400,7 @@ static class FnExpr implements Expr{ String internalName; String thisName; Type fntype; + final Object tag; //localbinding->itself IPersistentMap closes = PersistentHashMap.EMPTY; //Keyword->KeywordExpr @@ -2400,8 +2425,12 @@ static class FnExpr implements Expr{ final static Method getClassLoaderMethod = Method.getMethod("ClassLoader getClassLoader()"); final static Method getConstantsMethod = Method.getMethod("Object[] getConstants(int)"); + public FnExpr(Object tag){ + this.tag = tag; + } + static Expr parse(C context, ISeq form, String name) throws Exception{ - FnExpr fn = new FnExpr(); + FnExpr fn = new FnExpr(tagOf(form)); FnMethod enclosingMethod = (FnMethod) METHOD.get(); //fn.thisName = name; String basename = enclosingMethod != null ? @@ -2410,8 +2439,8 @@ static class FnExpr implements Expr{ if(RT.second(form) instanceof Symbol) name = ((Symbol) RT.second(form)).name; fn.simpleName = ((name != null ? - munge(name) : "fn") - + "__" + RT.nextID()); + munge(name) : "fn") + + "__" + RT.nextID()); fn.name = basename + fn.simpleName; fn.internalName = fn.name.replace('.', '/'); fn.fntype = Type.getObjectType(fn.internalName); @@ -2663,7 +2692,7 @@ static class FnExpr implements Expr{ } public Class getJavaClass() throws Exception{ - return IFn.class; + return (tag != null) ? HostExpr.tagToClass(tag) : IFn.class; } private void emitLocal(GeneratorAdapter gen, LocalBinding lb){ @@ -3232,7 +3261,15 @@ private static Expr analyzeSeq(C context, ISeq form, String name) throws Excepti Var v = isMacro(op); if(v != null) { - return analyze(context, v.applyTo(form.rest())); + try + { + Var.pushThreadBindings(RT.map(RT.MACRO_META, ((IObj) form).meta())); + return analyze(context, v.applyTo(form.rest())); + } + finally + { + Var.popThreadBindings(); + } } IParser p; if(op.equals(FN)) diff --git a/src/jvm/clojure/lang/IFn.java b/src/jvm/clojure/lang/IFn.java index 353ce96d..98b677cb 100644 --- a/src/jvm/clojure/lang/IFn.java +++ b/src/jvm/clojure/lang/IFn.java @@ -14,7 +14,7 @@ package clojure.lang; import java.util.concurrent.Callable; -public interface IFn extends Callable{ +public interface IFn extends Callable, Runnable{ public Object invoke() throws Exception; diff --git a/src/jvm/clojure/lang/Keyword.java b/src/jvm/clojure/lang/Keyword.java index 2541a4a6..897efe3e 100644 --- a/src/jvm/clojure/lang/Keyword.java +++ b/src/jvm/clojure/lang/Keyword.java @@ -47,6 +47,10 @@ public Object call() throws Exception{ return throwArity(); } +public void run(){ + throw new UnsupportedOperationException(); +} + public Object invoke() throws Exception{ return throwArity(); } diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index 905f0d84..cf6c75f0 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -13,6 +13,7 @@ package clojure.lang; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.Callable; import java.util.*; import java.util.regex.Matcher; import java.io.*; @@ -79,6 +80,7 @@ Symbol.create("Comparable"), Comparable.class, Symbol.create("Iterable"), Iterable.class, Symbol.create("Readable"), Readable.class, Symbol.create("Runnable"), Runnable.class, +Symbol.create("Callable"), Callable.class, Symbol.create("Exception"), Exception.class // Symbol.create("Collection"), "java.util.Collection", // Symbol.create("Comparator"), "java.util.Comparator", @@ -108,6 +110,7 @@ final static public Var IN = new LineNumberingPushbackReader(new InputStreamReader(System.in))); final static Keyword TAG_KEY = Keyword.intern(null, "tag"); final static public Var AGENT = Var.intern(CLOJURE_NS, Symbol.create("*agent*"), null); +final static public Var MACRO_META = Var.intern(CLOJURE_NS, Symbol.create("*macro-meta*"), null); static Keyword LINE_KEY = Keyword.intern(null, "line"); static Keyword FILE_KEY = Keyword.intern(null, "file"); //final static public Var CURRENT_MODULE = Var.intern(Symbol.create("clojure", "current-module"), @@ -188,6 +191,7 @@ static { Keyword dockw = Keyword.intern(null, "doc"); OUT.setTag(Symbol.create("java.io.OutputStreamWriter")); + CURRENT_NS.setTag(Symbol.create("clojure.lang.Namespace")); Var v; v = Var.intern(CLOJURE_NS, IN_NAMESPACE, inNamespace); v.setMeta(map(dockw, "Sets *ns* to the namespace named by the symbol, creating it if needed.")); diff --git a/src/jvm/clojure/lang/Ref.java b/src/jvm/clojure/lang/Ref.java index 8b175c45..8db93312 100644 --- a/src/jvm/clojure/lang/Ref.java +++ b/src/jvm/clojure/lang/Ref.java @@ -165,6 +165,17 @@ public Object call() throws Exception{ return invoke(); } +public void run(){ + try + { + invoke(); + } + catch(Exception e) + { + throw new RuntimeException(e); + } +} + public Object invoke() throws Exception{ return fn().invoke(); } diff --git a/src/jvm/clojure/lang/Reflector.java b/src/jvm/clojure/lang/Reflector.java index 4a1cf7c1..412b36dd 100644 --- a/src/jvm/clojure/lang/Reflector.java +++ b/src/jvm/clojure/lang/Reflector.java @@ -48,10 +48,13 @@ static Object invokeMatchingMethod(String methodName, List methods, Object targe Class[] params = m.getParameterTypes(); if(isCongruent(params, args)) { + if(boxedArgs != null) + throw new IllegalArgumentException("More than one matching method found: " + methodName); + boxedArgs = boxArgs(params, args); - break; + //break; } - else + else if(boxedArgs == null) m = null; } } diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java index 37f3bacd..b0b3fd26 100644 --- a/src/jvm/clojure/lang/Var.java +++ b/src/jvm/clojure/lang/Var.java @@ -260,6 +260,17 @@ public Object call() throws Exception{ return invoke(); } +public void run(){ + try + { + invoke(); + } + catch(Exception e) + { + throw new RuntimeException(e); + } +} + public Object invoke() throws Exception{ return fn().invoke(); } |