summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-10-11 01:02:30 +0000
committerRich Hickey <richhickey@gmail.com>2008-10-11 01:02:30 +0000
commit2faa08e4d42feac84230d52272de6f10b0caa434 (patch)
treec7d483d174889fc61d4c3041aedb90bc1913b001 /src
parent53ec9af4fd879482a6b8e04cff029d5db9634870 (diff)
refined ## to #=, now takes either
#=classname #=(classname. ctor-args*) #=(classname/staticMethod args*) #=(varname args*) and calls with _unevaluated_ args
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/boot.clj39
-rw-r--r--src/jvm/clojure/lang/Compiler.java194
-rw-r--r--src/jvm/clojure/lang/LispReader.java73
-rw-r--r--src/jvm/clojure/lang/Repl.java20
4 files changed, 236 insertions, 90 deletions
diff --git a/src/clj/clojure/boot.clj b/src/clj/clojure/boot.clj
index 7fd1a22c..f721ec33 100644
--- a/src/clj/clojure/boot.clj
+++ b/src/clj/clojure/boot.clj
@@ -3438,13 +3438,16 @@
(prefer-method print-method clojure.lang.IPersistentList clojure.lang.ISeq)
-(defmethod print-method java.util.List [o, #^Writer w]
- (.write w "##(")
+(defn print-ctor [o print-args #^Writer w]
+ (.write w "#=(")
(.write w (.getName (class o)))
(.write w ". ")
- (print-sequential "[" print-method " " "]" o w)
+ (print-args o w)
(.write w ")"))
+(defmethod print-method java.util.List [o, #^Writer w]
+ (print-ctor o #(print-sequential "[" print-method " " "]" %1 %2) w))
+
(prefer-method print-method clojure.lang.IPersistentList java.util.List)
(prefer-method print-method clojure.lang.IPersistentVector java.util.List)
@@ -3476,7 +3479,7 @@
(dotimes n (count v)
(print-method (nth v n) w)
(when (< n (dec (count v)))
- (.append w \ )))
+ (.append w \space)))
(.append w \])
nil)
@@ -3485,23 +3488,21 @@
(print-sequential
"{"
(fn [e #^Writer w]
- (do (print-method (key e) w) (.append w \ ) (print-method (val e) w)))
+ (do (print-method (key e) w) (.append w \space) (print-method (val e) w)))
", "
"}"
(seq m) w))
(defmethod print-method java.util.Map [m, #^Writer w]
- (.write w "##(")
- (.write w (.getName (class m)))
- (.write w ". ")
- (print-sequential
- "{"
- (fn [e #^Writer w]
- (do (print-method (key e) w) (.append w \ ) (print-method (val e) w)))
- ", "
- "}"
- (seq m) w)
- (.write w ")"))
+ (print-ctor m
+ #(print-sequential
+ "{"
+ (fn [e #^Writer w]
+ (do (print-method (key e) w) (.append w \space) (print-method (val e) w)))
+ ", "
+ "}"
+ (seq %1) %2)
+ w))
(prefer-method print-method clojure.lang.IPersistentMap java.util.Map)
@@ -3528,7 +3529,7 @@
nil)
(defmethod print-method Class [#^Class c, #^Writer w]
- (.write w "##")
+ (.write w "#=")
(.write w (.getName c)))
(defmethod print-method java.math.BigDecimal [b, #^Writer w]
@@ -3539,3 +3540,7 @@
(.append w \#)
(print-method (str p) w))
+(defmacro declare
+ "defs the supplied var names with no bindings, useful for making forward declarations."
+ [& names] `(do ~@(map #(list 'def %) names)))
+
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 06da69ae..2dd92a25 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -268,7 +268,7 @@ static class DefExpr implements Expr{
final static Method setMetaMethod = Method.getMethod("void setMeta(clojure.lang.IPersistentMap)");
final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String, String)");
- public DefExpr(String source,int line,Var var, Expr init, Expr meta, boolean initProvided){
+ public DefExpr(String source, int line, Var var, Expr init, Expr meta, boolean initProvided){
this.source = source;
this.line = line;
this.var = var;
@@ -354,7 +354,7 @@ static class DefExpr implements Expr{
IPersistentMap mm = sym.meta();
mm = (IPersistentMap) RT.assoc(mm, RT.LINE_KEY, LINE.get()).assoc(RT.FILE_KEY, SOURCE.get());
Expr meta = analyze(context == C.EVAL ? context : C.EXPRESSION, mm);
- return new DefExpr((String) SOURCE.get(),(Integer) LINE.get(),
+ return new DefExpr((String) SOURCE.get(), (Integer) LINE.get(),
v, analyze(context == C.EVAL ? context : C.EXPRESSION, RT.third(form), v.sym.name),
meta, RT.count(form) == 3);
}
@@ -846,8 +846,9 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
this.line = line;
if(field == null && RT.booleanCast(RT.WARN_ON_REFLECTION.get()))
{
- ((PrintWriter)RT.ERR.get()).format("Reflection warning, line: %d - reference to field %s can't be resolved.\n", line,
- fieldName);
+ ((PrintWriter) RT.ERR.get())
+ .format("Reflection warning, line: %d - reference to field %s can't be resolved.\n", line,
+ fieldName);
}
}
@@ -1045,7 +1046,8 @@ static abstract class MethodExpr extends HostExpr{
}
catch(Exception e1)
{
- e1.printStackTrace((PrintWriter)RT.ERR.get()); //To change body of catch statement use File | Settings | File Templates.
+ e1.printStackTrace((PrintWriter) RT.ERR
+ .get()); //To change body of catch statement use File | Settings | File Templates.
}
}
@@ -1102,7 +1104,8 @@ static class InstanceMethodExpr extends MethodExpr{
if(method == null && RT.booleanCast(RT.WARN_ON_REFLECTION.get()))
{
- ((PrintWriter)RT.ERR.get()).format("Reflection warning, line: %d - call to %s can't be resolved.\n", line, methodName);
+ ((PrintWriter) RT.ERR.get())
+ .format("Reflection warning, line: %d - call to %s can't be resolved.\n", line, methodName);
}
}
@@ -1237,7 +1240,8 @@ static class StaticMethodExpr extends MethodExpr{
method = (java.lang.reflect.Method) (methodidx >= 0 ? methods.get(methodidx) : null);
if(method == null && RT.booleanCast(RT.WARN_ON_REFLECTION.get()))
{
- ((PrintWriter)RT.ERR.get()).format("Reflection warning, line: %d - call to %s can't be resolved.\n", line, methodName);
+ ((PrintWriter) RT.ERR.get())
+ .format("Reflection warning, line: %d - call to %s can't be resolved.\n", line, methodName);
}
}
@@ -1328,7 +1332,7 @@ static class StaticMethodExpr extends MethodExpr{
static class UnresolvedVarExpr implements Expr{
public final Symbol symbol;
- public UnresolvedVarExpr(Symbol symbol) {
+ public UnresolvedVarExpr(Symbol symbol){
this.symbol = symbol;
}
@@ -2060,7 +2064,8 @@ public static class NewExpr implements Expr{
this.ctor = ctoridx >= 0 ? (Constructor) ctors.get(ctoridx) : null;
if(ctor == null && RT.booleanCast(RT.WARN_ON_REFLECTION.get()))
{
- ((PrintWriter)RT.ERR.get()).format("Reflection warning, line: %d - call to %s ctor can't be resolved.\n", line, c.getName());
+ ((PrintWriter) RT.ERR.get())
+ .format("Reflection warning, line: %d - call to %s ctor can't be resolved.\n", line, c.getName());
}
}
@@ -2717,7 +2722,7 @@ static class InvokeExpr implements Expr{
// throw new IllegalArgumentException(
// String.format("No more than %d args supported", MAX_POSITIONAL_ARITY));
- return new InvokeExpr((String) SOURCE.get(),(Integer) LINE.get(), tagOf(form), fexpr, args);
+ return new InvokeExpr((String) SOURCE.get(), (Integer) LINE.get(), tagOf(form), fexpr, args);
}
}
@@ -2751,8 +2756,8 @@ static class FnLoaderThunk extends RestFn{
synchronized private IFn loadFn() throws Exception{
if(f == null)
{
- Class fc = fx.getCompiledClass();
- f = (IFn)fc.newInstance();
+ Class fc = fx.getCompiledClass();
+ f = (IFn) fc.newInstance();
v.swapRoot(f);
}
return f;
@@ -2779,20 +2784,62 @@ static public class FnExpr implements Expr{
int line;
PersistentVector constants;
int constantsID;
- public final IPersistentCollection methods() { return methods;}
- public final FnMethod variadicMethod() { return variadicMethod;}
- public final String name() { return name;}
- public final String simpleName() { return simpleName;}
- public final String internalName() { return internalName;}
- public final String thisName() { return thisName;}
- public final Type fntype() { return fntype;}
- public final IPersistentMap closes() { return closes;}
- public final IPersistentMap keywords() { return keywords;}
- public final IPersistentMap vars() { return vars;}
- public final Class compiledClass() { return compiledClass;}
- public final int line() { return line;}
- public final PersistentVector constants() { return constants;}
- public final int constantsID() { return constantsID;}
+
+ public final IPersistentCollection methods(){
+ return methods;
+ }
+
+ public final FnMethod variadicMethod(){
+ return variadicMethod;
+ }
+
+ public final String name(){
+ return name;
+ }
+
+ public final String simpleName(){
+ return simpleName;
+ }
+
+ public final String internalName(){
+ return internalName;
+ }
+
+ public final String thisName(){
+ return thisName;
+ }
+
+ public final Type fntype(){
+ return fntype;
+ }
+
+ public final IPersistentMap closes(){
+ return closes;
+ }
+
+ public final IPersistentMap keywords(){
+ return keywords;
+ }
+
+ public final IPersistentMap vars(){
+ return vars;
+ }
+
+ public final Class compiledClass(){
+ return compiledClass;
+ }
+
+ public final int line(){
+ return line;
+ }
+
+ public final PersistentVector constants(){
+ return constants;
+ }
+
+ public final int constantsID(){
+ return constantsID;
+ }
final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)");
final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)");
@@ -3106,7 +3153,7 @@ static public class FnExpr implements Expr{
cv.visitEnd();
loader = (DynamicClassLoader) LOADER.get();
- bytecode = cw.toByteArray();
+ bytecode = cw.toByteArray();
}
synchronized Class getCompiledClass(){
@@ -3244,14 +3291,38 @@ public static class FnMethod{
int maxLocal = 0;
int line;
PersistentHashSet localsUsedInCatchFinally = PersistentHashSet.EMPTY;
- public final IPersistentMap locals() { return locals;}
- public final PersistentVector reqParms() { return reqParms;}
- public final LocalBinding restParm() { return restParm;}
- public final Expr body() { return body;}
- public final FnExpr fn() { return fn;}
- public final PersistentVector argLocals() { return argLocals;}
- public final int maxLocal() { return maxLocal;}
- public final int line() { return line;}
+
+ public final IPersistentMap locals(){
+ return locals;
+ }
+
+ public final PersistentVector reqParms(){
+ return reqParms;
+ }
+
+ public final LocalBinding restParm(){
+ return restParm;
+ }
+
+ public final Expr body(){
+ return body;
+ }
+
+ public final FnExpr fn(){
+ return fn;
+ }
+
+ public final PersistentVector argLocals(){
+ return argLocals;
+ }
+
+ public final int maxLocal(){
+ return maxLocal;
+ }
+
+ public final int line(){
+ return line;
+ }
public FnMethod(FnExpr fn, FnMethod parent){
this.parent = parent;
@@ -3466,7 +3537,10 @@ public static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{
public static class BodyExpr implements Expr{
PersistentVector exprs;
- public final PersistentVector exprs() { return exprs;}
+
+ public final PersistentVector exprs(){
+ return exprs;
+ }
public BodyExpr(PersistentVector exprs){
this.exprs = exprs;
@@ -3529,8 +3603,14 @@ public static class BodyExpr implements Expr{
public static class BindingInit{
LocalBinding binding;
Expr init;
- public final LocalBinding binding() { return binding;}
- public final Expr init() { return init;}
+
+ public final LocalBinding binding(){
+ return binding;
+ }
+
+ public final Expr init(){
+ return init;
+ }
public BindingInit(LocalBinding binding, Expr init){
this.binding = binding;
@@ -3820,8 +3900,9 @@ private static Expr analyze(C context, Object form, String name) throws Exceptio
static public class CompilerException extends Exception{
public CompilerException(String source, int line, Throwable cause){
- super(errorMsg(source,line,cause.toString()), cause);
+ super(errorMsg(source, line, cause.toString()), cause);
}
+
public String toString(){
return getMessage();
}
@@ -3867,6 +3948,10 @@ static public IFn isInline(Object op, int arity) throws Exception{
return null;
}
+public static boolean namesStaticMember(Symbol sym){
+ return sym.ns != null && namespaceFor(sym) == null;
+}
+
public static Object macroexpand1(Object x) throws Exception{
if(x instanceof ISeq)
{
@@ -3903,17 +3988,14 @@ public static Object macroexpand1(Object x) throws Exception{
Symbol meth = Symbol.intern(sname.substring(1));
return RT.listStar(DOT, RT.second(form), meth, form.rest().rest());
}
- else if(sym.ns != null)
+ else if(namesStaticMember(sym))
{
- if(namespaceFor(sym) == null)
+ Symbol target = Symbol.intern(sym.ns);
+ Class c = HostExpr.maybeClass(target, false);
+ if(c != null)
{
- Symbol target = Symbol.intern(sym.ns);
- Class c = HostExpr.maybeClass(target, false);
- if(c != null)
- {
- Symbol meth = Symbol.intern(sym.name);
- return RT.listStar(DOT, target, meth, form.rest());
- }
+ Symbol meth = Symbol.intern(sym.name);
+ return RT.listStar(DOT, target, meth, form.rest());
}
}
else
@@ -4005,7 +4087,7 @@ public static Object eval(Object form) throws Exception{
catch(Throwable e)
{
if(!(e instanceof CompilerException))
- throw new CompilerException((String)SOURCE.get(), (Integer) LINE.get(),e);
+ throw new CompilerException((String) SOURCE.get(), (Integer) LINE.get(), e);
else
throw (CompilerException) e;
}
@@ -4088,10 +4170,10 @@ static Object resolve(Symbol sym) throws Exception{
}
static private Namespace namespaceFor(Symbol sym){
- return namespaceFor(currentNS(),sym);
+ return namespaceFor(currentNS(), sym);
}
-static private Namespace namespaceFor(Namespace inns,Symbol sym){
+static private Namespace namespaceFor(Namespace inns, Symbol sym){
//note, presumes non-nil sym.ns
// first check against currentNS' aliases...
Symbol nsSym = Symbol.create(sym.ns);
@@ -4108,7 +4190,7 @@ static public Object resolveIn(Namespace n, Symbol sym) throws Exception{
//note - ns-qualified vars must already exist
if(sym.ns != null)
{
- Namespace ns = namespaceFor(n,sym);
+ Namespace ns = namespaceFor(n, sym);
if(ns == null)
throw new Exception("No such namespace: " + sym.ns);
@@ -4132,7 +4214,7 @@ static public Object resolveIn(Namespace n, Symbol sym) throws Exception{
Object o = n.getMapping(sym);
if(o == null)
{
- if( RT.booleanCast(RT.ALLOW_UNRESOLVED_VARS.get()))
+ if(RT.booleanCast(RT.ALLOW_UNRESOLVED_VARS.get()))
{
return sym;
}
@@ -4191,7 +4273,7 @@ static Var lookupVar(Symbol sym, boolean internNew) throws Exception{
var = ns.findInternedVar(name);
}
else if(sym.equals(NS))
- var = RT.NS_VAR;
+ var = RT.NS_VAR;
else if(sym.equals(IN_NS))
var = RT.IN_NS_VAR;
else
@@ -4284,7 +4366,7 @@ public static Object loadFile(String file) throws Exception{
FileInputStream f = new FileInputStream(file);
try
{
- return load(new InputStreamReader(f,RT.UTF8), new File(file).getAbsolutePath(), (new File(file)).getName());
+ return load(new InputStreamReader(f, RT.UTF8), new File(file).getAbsolutePath(), (new File(file)).getName());
}
finally
{
@@ -4323,7 +4405,7 @@ public static Object load(Reader rdr, String sourcePath, String sourceName) thro
}
catch(LispReader.ReaderException e)
{
- throw new CompilerException(sourceName,e.line,e.getCause());
+ throw new CompilerException(sourceName, e.line, e.getCause());
}
finally
{
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java
index d4d03f89..c0cd63ec 100644
--- a/src/jvm/clojure/lang/LispReader.java
+++ b/src/jvm/clojure/lang/LispReader.java
@@ -86,7 +86,7 @@ static
dispatchMacros['"'] = new RegexReader();
dispatchMacros['('] = new FnReader();
dispatchMacros['{'] = new SetReader();
- dispatchMacros['#'] = new EvalReader();
+ dispatchMacros['='] = new EvalReader();
}
static boolean isWhitespace(int ch){
@@ -459,9 +459,12 @@ static class VarReader extends AFn{
public Object invoke(Object reader, Object quote) throws Exception{
PushbackReader r = (PushbackReader) reader;
Object o = read(r, true, null, true);
- Object v = Compiler.maybeResolveIn(Compiler.currentNS(), (Symbol) o);
- if(v instanceof Var)
- return v;
+ if(o instanceof Symbol)
+ {
+ Object v = Compiler.maybeResolveIn(Compiler.currentNS(), (Symbol) o);
+ if(v instanceof Var)
+ return v;
+ }
return RT.list(THE_VAR, o);
}
}
@@ -816,14 +819,68 @@ static class ListReader extends AFn{
}
+static class CtorReader extends AFn{
+ static final Symbol cls = Symbol.create("class");
+
+ public Object invoke(Object reader, Object leftangle) throws Exception{
+ PushbackReader r = (PushbackReader) reader;
+ // #<class classname>
+ // #<classname args*>
+ // #<classname/staticMethod args*>
+ List list = readDelimitedList('>', r, true);
+ if(list.isEmpty())
+ throw new Exception("Must supply 'class', classname or classname/staticMethod");
+ Symbol s = (Symbol) list.get(0);
+ Object[] args = list.subList(1, list.size()).toArray();
+ if(s.equals(cls))
+ {
+ return RT.classForName(args[0].toString());
+ }
+ else if(s.ns != null) //static method
+ {
+ String classname = s.ns;
+ String method = s.name;
+ return Reflector.invokeStaticMethod(classname, method, args);
+ }
+ else
+ {
+ return Reflector.invokeConstructor(RT.classForName(s.name), args);
+ }
+ }
+
+}
+
static class EvalReader extends AFn{
public Object invoke(Object reader, Object eq) throws Exception{
PushbackReader r = (PushbackReader) reader;
-
- Compiler.Expr expr = Compiler.analyze(Compiler.C.EVAL, read(r, true, null, true));
- return expr.eval();
+ Object o = read(r, true, null, true);
+ if(o instanceof Symbol)
+ {
+ return RT.classForName(o.toString());
+ }
+ else if(o instanceof IPersistentList)
+ {
+ Symbol fs = (Symbol) RT.first(o);
+ if(fs.name.endsWith("."))
+ {
+ Object[] args = RT.toArray(RT.rest(o));
+ return Reflector.invokeConstructor(RT.classForName(fs.name.substring(0, fs.name.length() - 1)), args);
+ }
+ if(Compiler.namesStaticMember(fs))
+ {
+ Object[] args = RT.toArray(RT.rest(o));
+ return Reflector.invokeStaticMethod(fs.ns, fs.name, args);
+ }
+ Object v = Compiler.maybeResolveIn(Compiler.currentNS(), fs);
+ if(v instanceof Var)
+ {
+ return ((IFn) v).applyTo(RT.rest(o));
+ }
+ throw new Exception("Can't resolve " + v);
+ }
+ else
+ throw new IllegalArgumentException("Unsupported #= form");
}
-
}
//static class ArgVectorReader extends AFn{
diff --git a/src/jvm/clojure/lang/Repl.java b/src/jvm/clojure/lang/Repl.java
index 1c065dd2..b2549b3c 100644
--- a/src/jvm/clojure/lang/Repl.java
+++ b/src/jvm/clojure/lang/Repl.java
@@ -24,6 +24,7 @@ static final Var in_ns = RT.var("clojure", "in-ns");
static final Var refer = RT.var("clojure", "refer");
static final Var ns = RT.var("clojure", "*ns*");
static final Var warn_on_reflection = RT.var("clojure", "*warn-on-reflection*");
+static final Var print_meta = RT.var("clojure", "*print-meta*");
static final Var star1 = RT.var("clojure", "*1");
static final Var star2 = RT.var("clojure", "*2");
static final Var star3 = RT.var("clojure", "*3");
@@ -41,11 +42,12 @@ public static void main(String[] args) throws Exception{
//must have corresponding popThreadBindings in finally clause
Var.pushThreadBindings(
RT.map(ns, ns.get(),
- warn_on_reflection, warn_on_reflection.get(),
- star1, null,
- star2, null,
- star3, null,
- stare, null));
+ warn_on_reflection, warn_on_reflection.get(),
+ print_meta, print_meta.get(),
+ star1, null,
+ star2, null,
+ star3, null,
+ stare, null));
//create and move into the user namespace
in_ns.invoke(USER);
@@ -59,11 +61,11 @@ public static void main(String[] args) throws Exception{
}
catch(Exception e)
{
- e.printStackTrace((PrintWriter)RT.ERR.get());
+ e.printStackTrace((PrintWriter) RT.ERR.get());
}
//repl IO support
- LineNumberingPushbackReader rdr = new LineNumberingPushbackReader(new InputStreamReader(System.in,RT.UTF8));
+ LineNumberingPushbackReader rdr = new LineNumberingPushbackReader(new InputStreamReader(System.in, RT.UTF8));
OutputStreamWriter w = (OutputStreamWriter) RT.OUT.get();//new OutputStreamWriter(System.out);
Object EOF = new Object();
@@ -95,14 +97,14 @@ public static void main(String[] args) throws Exception{
Throwable c = e;
while(c.getCause() != null)
c = c.getCause();
- ((PrintWriter)RT.ERR.get()).println(e instanceof Compiler.CompilerException ? e : c);
+ ((PrintWriter) RT.ERR.get()).println(e instanceof Compiler.CompilerException ? e : c);
stare.set(e);
}
}
}
catch(Exception e)
{
- e.printStackTrace((PrintWriter)RT.ERR.get());
+ e.printStackTrace((PrintWriter) RT.ERR.get());
}
finally
{