summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/boot.clj18
-rw-r--r--src/jvm/clojure/lang/AFn.java10
-rw-r--r--src/jvm/clojure/lang/Compiler.java63
-rw-r--r--src/jvm/clojure/lang/IFn.java2
-rw-r--r--src/jvm/clojure/lang/Keyword.java4
-rw-r--r--src/jvm/clojure/lang/RT.java4
-rw-r--r--src/jvm/clojure/lang/Ref.java11
-rw-r--r--src/jvm/clojure/lang/Reflector.java7
-rw-r--r--src/jvm/clojure/lang/Var.java11
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();
}