summaryrefslogtreecommitdiff
path: root/src/jvm/clojure
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-03-23 17:38:09 +0000
committerRich Hickey <richhickey@gmail.com>2008-03-23 17:38:09 +0000
commit26dc63797bf65aeedb91d01dbf6edf2f339e972a (patch)
treea7d9c60040358cfe5adc370201fc56eec10c3a15 /src/jvm/clojure
parentf99b85789d1a5f2d78231c3da03627bfe8ac0b5b (diff)
made IFn extend Runnable, stricter overload resolution, accessible macro metadata via *macro-meta*, more type hints in boot.clj
Diffstat (limited to 'src/jvm/clojure')
-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
8 files changed, 96 insertions, 16 deletions
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();
}