diff options
author | Rich Hickey <richhickey@gmail.com> | 2007-09-22 18:29:04 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2007-09-22 18:29:04 +0000 |
commit | 6b248387e7631748011afccb65c495b635806d45 (patch) | |
tree | aafeeb77c3290c5d366c69d5631a038675694bbd /src | |
parent | d43857f2e302f4307f2b8b201704b84b5286b567 (diff) |
refactoring, commented out test mains
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.clj | 8 | ||||
-rw-r--r-- | src/jvm/clojure/lang/ArgVector.java | 97 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 8 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 3 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LockingTransaction.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/OldCompiler.java | 1998 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentHashMap.java | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentQueue.java | 17 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentTreeMap.java | 3 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentVector.java | 3 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 14 | ||||
-rw-r--r-- | src/jvm/clojure/lang/ThreadLocalData.java | 93 | ||||
-rw-r--r-- | src/jvm/clojure/lang/TransactionalHashMap.java | 4 |
13 files changed, 38 insertions, 2216 deletions
diff --git a/src/boot.clj b/src/boot.clj index 5210c76b..feb835f2 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -1,3 +1,11 @@ +; Copyright (c) Rich Hickey. All rights reserved. +; The use and distribution terms for this software are covered by the +; Common Public License 1.0 (http://opensource.org/licenses/cpl.php) +; which can be found in the file CPL.TXT at the root of this distribution. +; By using this software in any fashion, you are agreeing to be bound by +; the terms of this license. +; You must not remove this notice, or any other, from this software. + (def list (fn [& args] args)) (def cons (fn [x seq] (. RT (cons x seq)))) (def conj (fn [coll x] (. RT (conj coll x)))) diff --git a/src/jvm/clojure/lang/ArgVector.java b/src/jvm/clojure/lang/ArgVector.java deleted file mode 100644 index 7e18310c..00000000 --- a/src/jvm/clojure/lang/ArgVector.java +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) Rich Hickey. All rights reserved. - * The use and distribution terms for this software are covered by the - * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) - * which can be found in the file CPL.TXT at the root of this distribution. - * By using this software in any fashion, you are agreeing to be bound by - * the terms of this license. - * You must not remove this notice, or any other, from this software. - **/ - -/* rich Aug 19, 2007 */ - -package clojure.lang; - -import java.util.List; - -public class ArgVector extends Obj implements IPersistentVector, IPersistentList{ - -final PersistentVector impl; - -public static final ArgVector EMPTY = new ArgVector(PersistentVector.EMPTY); - -static public ArgVector create(ISeq items){ - return new ArgVector(PersistentVector.create(items)); -} - -static public ArgVector create(List items){ - return new ArgVector(PersistentVector.create(items)); -} - -static public ArgVector create(Object... items){ - return new ArgVector(PersistentVector.create(items)); -} - -private ArgVector(PersistentVector impl){ - this.impl = impl; -} - -private ArgVector(IPersistentMap meta, PersistentVector impl){ - super(meta); - this.impl = impl; -} - -public Obj withMeta(IPersistentMap meta){ - if(meta != this.meta()) - return new ArgVector(meta, impl); - return this; -} - -public int length(){ - return impl.length(); -} - -public Object nth(int i){ - return impl.nth(i); -} - -public IPersistentVector assocN(int i, Object val){ - return new ArgVector(meta(), impl.assocN(i, val)); -} - -public boolean contains(Object key){ - return impl.contains(key); -} - -public IMapEntry entryAt(Object key){ - return impl.entryAt(key); -} - -public Associative assoc(Object key, Object val){ - return new ArgVector(meta(), impl.assoc(key, val)); -} - -public Object valAt(Object key){ - return impl.valAt(key); -} - -public int count(){ - return impl.count(); -} - -public ISeq seq(){ - return impl.seq(); -} - -public IPersistentCollection cons(Object o){ - return new ArgVector(meta(), impl.cons(o)); -} - -public Object peek(){ - return impl.peek(); -} - -public IPersistentList pop(){ - return new ArgVector(meta(), impl.pop()); -} -} diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 9035da7a..5ec414f2 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -1845,9 +1845,9 @@ static class FnExpr implements Expr{ //derived from AFn/RestFn ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); // ClassWriter cw = new ClassWriter(0); - //ClassVisitor cv = cw; + ClassVisitor cv = cw; //ClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), new PrintWriter(System.out)); - ClassVisitor cv = new TraceClassVisitor(cw, new PrintWriter(System.out)); + //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(); String smap = "SMAP\n" + @@ -2681,13 +2681,15 @@ public static void main(String[] args){ { Var.pushThreadBindings( RT.map(LOADER, new DynamicClassLoader())); + w.write("> "); + w.flush(); Object r = LispReader.read(rdr, false, EOF, false); if(r == EOF) break; Object ret = eval(r); RT.print(ret, w); w.write('\n'); - w.flush(); + //w.flush(); } catch(Exception e) { diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java index aba23a7c..9fb0db35 100644 --- a/src/jvm/clojure/lang/LispReader.java +++ b/src/jvm/clojure/lang/LispReader.java @@ -624,6 +624,7 @@ public static List readDelimitedList(char delim, PushbackReader r, boolean isRec return a;
}
+/*
public static void main(String[] args){
LineNumberingPushbackReader r = new LineNumberingPushbackReader(new InputStreamReader(System.in));
OutputStreamWriter w = new OutputStreamWriter(System.out);
@@ -646,7 +647,7 @@ public static void main(String[] args){ e.printStackTrace();
}
}
-
+ */
}
diff --git a/src/jvm/clojure/lang/LockingTransaction.java b/src/jvm/clojure/lang/LockingTransaction.java index 4ccdd8ab..84372f35 100644 --- a/src/jvm/clojure/lang/LockingTransaction.java +++ b/src/jvm/clojure/lang/LockingTransaction.java @@ -348,7 +348,7 @@ Object doCommute(Ref ref, IFn fn) throws Exception{ return ret; } - +/* //for test static CyclicBarrier barrier; static ArrayList<Ref> items; @@ -507,5 +507,5 @@ public static void main(String[] args){ ex.printStackTrace(); } } - +*/ } diff --git a/src/jvm/clojure/lang/OldCompiler.java b/src/jvm/clojure/lang/OldCompiler.java deleted file mode 100644 index 2ae5d2d0..00000000 --- a/src/jvm/clojure/lang/OldCompiler.java +++ /dev/null @@ -1,1998 +0,0 @@ -/** - * Copyright (c) Rich Hickey. All rights reserved. - * The use and distribution terms for this software are covered by the - * Common Public License 1.0 (http://opensource.org/licenses/cpl.php) - * which can be found in the file CPL.TXT at the root of this distribution. - * By using this software in any fashion, you are agreeing to be bound by - * the terms of this license. - * You must not remove this notice, or any other, from this software. - **/ - -/* rich Sep 3, 2006 */ - -package clojure.lang; - -import java.io.StringWriter; -import java.io.InputStreamReader; -import java.io.FileInputStream; -import java.lang.reflect.Field; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; - -public class OldCompiler{ -//* -static Symbol DEF = Symbol.create("def"); -static Symbol FN = Symbol.create("fn"); -static Symbol DO = Symbol.create("do"); -static Symbol IF = Symbol.create("if"); -static Symbol OR = Symbol.create("or"); -static Symbol AND = Symbol.create("and"); -static Symbol LET = Symbol.create("let"); -static Symbol LET_STAR_ = Symbol.create("let*"); -static Symbol LETFN = Symbol.create("letfn"); -static Symbol NOT = Symbol.create("not"); -static Symbol NULL_QM_ = Symbol.create("null?"); - -static Symbol IMPORT = Symbol.create("import"); -static Symbol USE = Symbol.create("use"); -static Symbol _AMP_KEY = Symbol.create("&key"); -static Symbol _AMP_REST = Symbol.create("&rest"); - -static public Var _CRT_OUT = RT.OUT; -static public Var _CRT_MODULE = RT.CURRENT_MODULE; - -static NilExpr NIL_EXPR = new NilExpr(); - -//short-name-string->full-name-string -static public Var IMPORTS = Var.create(); - -//keyword->keywordexpr -static public Var KEYWORDS = Var.create(); - -//var->var -static public Var VARS = Var.create(); - -//symbol->localbinding -static public Var LOCAL_ENV = Var.create(); - - -//FnFrame -static public Var METHOD = Var.create(); - -//module->module -static public Var USES = Var.create(); - - -//ISeq FnExprs -static public Var FNS = Var.create(); - -static public IPersistentMap CHAR_MAP = - new PersistentArrayMap(new Object[]{'-', "_DASH_", - '.', "_DOT_", - ':', "_COLON_", - '+', "_PLUS_", - '>', "_GT_", - '<', "_LT_", - '=', "_EQ_", - '~', "_TILDE_", - '!', "_BANG_", - '@', "_CIRCA_", - '#', "_SHARP_", - '$', "_DOLLARSIGN_", - '%', "_PERCENT_", - '^', "_CARET_", - '&', "_AMPERSAND_", - '*', "_STAR_", - '{', "_LBRACE_", - '}', "_RBRACE_", - '[', "_LBRACK_", - ']', "_RBRACK_", - '/', "_SLASH_", - '\\', "_BSLASH_", - '?', "_QMARK_"}); - -private static final int MAX_POSITIONAL_ARITY = 20; - - -static String compile(String ns, String className, LineNumberingPushbackReader... files) throws Exception{ - StringWriter w = new StringWriter(); - try - { - Var.pushThreadBindings( - RT.map( - _CRT_OUT, w, - KEYWORDS, null, - VARS, null, - METHOD, null, - LOCAL_ENV, null, - FNS, PersistentVector.EMPTY)); - - format("/* Generated by Clojure */~%~%"); - format("package ~A;~%", ns); - format("import clojure.lang.*;~%~%"); - format("public class ~A{~%", className); - - PersistentVector forms = PersistentVector.EMPTY; - for(LineNumberingPushbackReader reader : files) - { - try - { - Var.pushThreadBindings( - RT.map( - IMPORTS, null, - USES, null)); - - Object eof = new Object(); - Object form = null; - - while((form = LispReader.read(reader, false, eof, false)) != eof) - { - form = macroexpand(form); - if(!(form instanceof ISeq)) - throw new Exception("No atoms allowed at top level"); - Object op = RT.first(form); - - //enact import and use at compile-time - if(op == IMPORT) - { - //(import org.package ThisClass ThatClass ...) - //makes entries in IMPORTS for: - //"ThisClass"->"org.package.ThisClass" - //"ThatClass"->"org.package.ThatClass" - IPersistentMap importMap = (IPersistentMap) IMPORTS.get(); - String pkg = RT.second(form).toString(); - for(ISeq classes = RT.rest(RT.rest(form)); classes != null; classes = classes.rest()) - { - String iclassName = classes.first().toString(); - importMap = (IPersistentMap) RT.assoc(importMap, iclassName, pkg + "." + iclassName); - } - IMPORTS.set(importMap); - } - else if(op == USE) - { - //todo implement use - } - else - forms = forms.cons(analyze(C.STATEMENT, form)); - } - } - finally - { - Var.popThreadBindings(); - } - } - //declare static members for keywords, vars - for(ISeq keys = RT.seq(KEYWORDS.get()); keys != null; keys = keys.rest()) - { - KeywordExpr k = (KeywordExpr) ((IMapEntry) keys.first()).val(); - format("static Keyword ~A;~%", k.emitExpressionString()); - } - for(ISeq vars = RT.seq(VARS.get()); vars != null; vars = vars.rest()) - { - Var v = (Var) ((IMapEntry) vars.first()).val(); - format("static DynamicVar ~A;~%", munge(v.toString())); - } - - //todo declare static members for syms, quoted aggregates - - //emit nested static class/method declarations for nested fns - PersistentVector fns = (PersistentVector) FNS.get(); - for(int f = 0; f < fns.count(); f++) - { - FnExpr fn = (FnExpr) fns.nth(f); - fn.emitDeclaration(); - } - - //define the load function - format("public void load() throws Exception{~%"); - //init the keywords and vars - for(ISeq keys = RT.seq(KEYWORDS.get()); keys != null; keys = keys.rest()) - { - KeywordExpr k = (KeywordExpr) ((IMapEntry) keys.first()).val(); - format("~A = (Keyword)Symbol.intern(~S);~%", k.emitExpressionString(), k.sym.name); - } - for(ISeq vars = RT.seq(VARS.get()); vars != null; vars = vars.rest()) - { - Var v = (Var) ((IMapEntry) vars.first()).val(); - //!format("~A = Module.intern(~S,~S);~%", munge(v.toString()), v.module.name, v.name.name); - } - //todo init syms and quoted aggregates - //emit the top level forms - for(int i = 0; i < forms.count(); i++) - { - Expr e = (Expr) forms.nth(i); - e.emitStatement(); - } - //close load function - format("}~%"); - - //close class def - format("}~%"); - } - catch(Exception e) - { - e.printStackTrace(); - } - finally - { - Var.popThreadBindings(); - } - return w.toString(); -} - -static String munge(String name){ - StringBuilder sb = new StringBuilder(); - for(char c : name.toCharArray()) - { - String sub = (String) CHAR_MAP.valAt(c); - if(sub != null) - sb.append(sub); - else - sb.append(c); - } - return sb.toString(); -} - -enum C{ - STATEMENT, EXPRESSION, RETURN, EVAL -} - -interface Expr{ - - void emitReturn() throws Exception; - - void emitStatement() throws Exception; - - void emitExpression() throws Exception; - - String emitExpressionString() throws Exception; - - // may return null if clojure expression with no type hint, or host expression with unknown type - //cannot be used to distinguish host expr vs not - Class getHostType() throws Exception; - - boolean canEmitHostExpr(); - - void emitHostExpr() throws Exception; - -} - -static void format(String str, Object... args) throws Exception{ - RT.format(RT.T, str, args); -} - -static class AnExpr implements Expr{ - - public void emitReturn() throws Exception{ - format("return "); - emitExpression(); - format(";~%"); - } - - public void emitStatement() throws Exception{ - emitExpression(); - format(";~%"); - } - - public void emitExpression() throws Exception{ - throw new UnsupportedOperationException(); - } - - public String emitExpressionString() throws Exception{ - StringWriter w = new StringWriter(); - try - { - Var.pushThreadBindings(RT.map(_CRT_OUT, w)); - emitExpression(); - return w.toString(); - } - finally - { - Var.popThreadBindings(); - } - } - - public Class getHostType() throws Exception{ - return null; - } - - public boolean canEmitHostExpr(){ - return false; - } - - public void emitHostExpr() throws Exception{ - throw new Exception("Can't emit as host expr"); - } - - - public String toString(){ - try - { - return emitExpressionString(); - } - catch(Exception e) - { - //declared exceptions are an incredibly bad idea !!! - throw new RuntimeException(e); - } - } -} - -static abstract class AHostExpr extends AnExpr{ - - public boolean isHostExpr(){ - return false; - } - - public void emitExpression() throws Exception{ - Class hostType = getHostType(); - boolean needsBox = hostType == null - || hostType.isPrimitive() - || hostType == Boolean.class; - if(needsBox) - format("RT.box("); - emitHostExpr(); - if(needsBox) - format(")"); - } - - public boolean canEmitHostExpr(){ - return true; - } - -} - -public static void processForm(Object form) throws Exception{ - if(RT.first(form) == DEF) - { - convert(form); - } - else - throw new UnsupportedOperationException(); -} - -private static void convert(Object form) throws Exception{ - Expr e = analyze(C.STATEMENT, form); -} - -private static Expr analyze(C context, Object form) throws Exception{ - if(form == null) - return NIL_EXPR; - else if(form instanceof Symbol) - return analyzeSymbol((Symbol) form, false); - else if(form instanceof ISeq) - return analyzeSeq(context, (ISeq) form); - else if(form instanceof Num || form instanceof String) - return new LiteralExpr(form); - else if(form instanceof Character) - return new CharExpr((Character) form); - else - throw new UnsupportedOperationException(); -} - -private static Expr analyzeSeq(C context, ISeq form) throws Exception{ - Object op = RT.first(form); - if(op == DEF) - return analyzeDef(context, form); - else if(op == FN) - return analyzeFn(context, form); - else if(op == DO) - return analyzeDo(context, form); - else if(op == IF) - return analyzeIf(context, form); - else if(op == OR) - return analyzeOr(context, form); - else if(op == AND) - return analyzeAnd(context, form); - else if(op == LET) - return analyzeLet(context, form); - else if(op == LET_STAR_) - return analyzeLetStar(context, form); - else if(op == LETFN) - return analyzeLetFn(context, form); - else if(op == NOT || op == NULL_QM_) - return analyzeNot(context, form); - else - { - PersistentVector args = PersistentVector.EMPTY; - for(ISeq s = op instanceof InstanceMemberInvoker ? RT.rrest(form) : RT.rest(form); s != null; s = s.rest()) - args = args.cons(analyze(C.EXPRESSION, macroexpand(s.first()))); - - //if(op instanceof ClassSymbol) - // return new InvokeConstructorExpr((ClassSymbol) op, args); - //else - if(op instanceof StaticMemberInvoker) - return new InvokeStaticMethodExpr((StaticMemberInvoker) op, args); - else if(op instanceof InstanceMemberInvoker) - return analyzeInstanceInvoke((InstanceMemberInvoker) op, - analyze(C.EXPRESSION, macroexpand(RT.second(form))), - args); - - - Expr fexpr = (op instanceof Symbol) ? analyzeSymbol((Symbol) op, true) : analyze(C.EXPRESSION, op); - if(fexpr instanceof FnExpr) - ((FnExpr) fexpr).isCalledDirectly = true; - return new InvokeExpr(fexpr, args); - } -} - -private static Expr analyzeInstanceInvoke(InstanceMemberInvoker sym, Expr target, PersistentVector args) - throws Exception{ - Class targetClass = null; - if(sym.className != null) - targetClass = getTypeNamed(resolveHostClassname(sym.className)); - else if(target.getHostType() != null) - targetClass = target.getHostType(); - else //must make reflection-based call - return new InvokeUntypedInstanceMemberExpr(sym.memberName, target, args); - return new InvokeInstanceMemberExpr(targetClass, sym.memberName, target, args); -} - -static class InvokeExpr extends AnExpr{ - Expr fexpr; - PersistentVector args; - - public InvokeExpr(Expr fexpr, PersistentVector args){ - this.fexpr = fexpr; - this.args = args; - } - - public void emitExpression() throws Exception{ - FnExpr staticMethod = null; - ISeq argseq = RT.seq(args); - if(fexpr instanceof FnExpr && ((FnExpr) fexpr).willBeStaticMethod()) - staticMethod = (FnExpr) fexpr; - else if(fexpr instanceof LocalBindingExpr && ((LocalBindingExpr) fexpr).b.bindsToStaticFn()) - staticMethod = ((LocalBindingExpr) fexpr).b.letfn; - if(staticMethod != null) - { - ISeq closes = RT.keys(staticMethod.closes); - format("~A(~{~A~^, ~}", staticMethod.getName(), closes); - if(closes != null && argseq != null) - format(","); - format("~{~A~^, ~})", argseq); - } - else - { - format("((IFn)~A).invoke(~{~A~^, ~})", fexpr, argseq); - } - } -} - -/* -static class InvokeConstructorExpr extends AHostExpr{ - HostClassExpr fexpr; - PersistentVector args; - - public InvokeConstructorExpr(ClassSymbol fexpr, PersistentVector args) throws Exception{ - this.fexpr = new HostClassExpr(fexpr); - this.args = args; - } - - public Class getHostType() throws Exception{ - return fexpr.type; - } - - public void emitHostExpr() throws Exception{ - Constructor ctor = findSingleConstructor(fexpr.type, args); - - format("(new ~A(", fexpr.resolvedClassName); - if(ctor != null) - emitTypedArgs(ctor.getParameterTypes(), args, ctor.isVarArgs()); - else - emitHostArgs(args); - format("))"); - } -} -*/ - -static class InvokeStaticMethodExpr extends AHostExpr{ - final StaticMemberInvoker sym; - final String resolvedClassName; - final Class type; - PersistentVector args; - final Method method; - final Class returnType; - - public InvokeStaticMethodExpr(StaticMemberInvoker sym, PersistentVector args) throws Exception{ - this.sym = sym; - this.args = args; - this.resolvedClassName = resolveHostClassname(sym.className); - this.type = getTypeNamed(resolvedClassName); - Object sm = findSingleMethod(type, sym.memberName, args, true); - if(sm instanceof Method) - { - method = (Method) sm; - returnType = method.getReturnType(); - } - else if(sm instanceof Class) - { - method = null; - returnType = (Class) sm; - } - else - { - method = null; - returnType = null; - } - } - - public Class getHostType() throws Exception{ - return returnType; - } - - public void emitHostExpr() throws Exception{ - format("~A.~A(", resolvedClassName, sym.memberName); - if(method != null) - emitTypedArgs(method.getParameterTypes(), args, method.isVarArgs()); - else - emitHostArgs(args); - format(")"); - } -} - -static class InvokeUntypedInstanceMemberExpr extends AnExpr{ - final String name; - final Expr target; - PersistentVector args; - - public InvokeUntypedInstanceMemberExpr(String name, Expr target, PersistentVector args) throws Exception{ - this.name = name; - this.args = args; - this.target = target; - } - - public void emitExpression() throws Exception{ - format("Reflector.invokeInstanceMember(~S,~A~{,~A~})", name, target, RT.seq(args)); - } - -} - -static class InvokeInstanceMemberExpr extends AHostExpr{ - final String name; - final Expr target; - PersistentVector args; - final Class targetType; - final Field field; - final Method method; - final Class returnType; - - public InvokeInstanceMemberExpr(Class targetClass, String name, Expr target, PersistentVector args) - throws Exception{ - this.name = name; - this.args = args; - this.target = target; - this.targetType = targetClass; - field = Reflector.getField(targetClass, name, false); - if(field != null) - { - method = null; - returnType = field.getType(); - } - else - { - Object sm = findSingleMethod(targetClass, name, args, false); - if(sm instanceof Method) - { - method = (Method) sm; - returnType = method.getReturnType(); - } - else if(sm instanceof Class) - { - method = null; - returnType = (Class) sm; - } - else - { - method = null; - returnType = null; - } - } - } - - public Class getHostType() throws Exception{ - return returnType; - } - - public void emitHostExpr() throws Exception{ - if(target.canEmitHostExpr()) - target.emitHostExpr(); - else - emitConvert(targetType, target); - if(field != null) - { - format(".~A", name); - } - else - { - format(".~A(", name); - if(method != null) - emitTypedArgs(method.getParameterTypes(), args, method.isVarArgs()); - else - emitHostArgs(args); - format(")"); - } - } - -} - -static void emitHostArgs(PersistentVector args) throws Exception{ - for(int i = 0; i < args.count(); i++) - { - Expr arg = (Expr) args.nth(i); - if(arg.canEmitHostExpr()) - arg.emitHostExpr(); - else if(arg.getHostType() != null) - emitConvert(arg.getHostType(), arg); - else - arg.emitExpression(); - if(i < args.count() - 1) - format(","); - } - -} - -static void emitTypedArgs(Class[] parameterTypes, PersistentVector args, boolean isVariadic) throws Exception{ - for(int i = 0; i < (isVariadic ? parameterTypes.length - 1 : args.count()); i++) - { - Expr arg = (Expr) args.nth(i); - if(arg.canEmitHostExpr()) - arg.emitHostExpr(); - else - emitConvert(parameterTypes[i], arg); - if(i < args.count() - 1) - format(","); - } - - if(isVariadic) - { - Class vtype = parameterTypes[parameterTypes.length - 1].getComponentType(); - for(int i = parameterTypes.length - 1; i < args.count(); i++) - { - Expr arg = (Expr) args.nth(i); - if(arg.canEmitHostExpr()) - arg.emitHostExpr(); - else - emitConvert(vtype, arg); - if(i < args.count() - 1) - format(","); - } - } -} - -static void emitConvert(Class parameterType, Expr arg) throws Exception{ - if(parameterType == Object.class) - arg.emitExpression(); - else if(parameterType == boolean.class || parameterType == Boolean.class) - format("(~A!=null)", arg); - else if(parameterType == int.class || parameterType == Integer.class) - format("((Number)~A).intValue()", arg); - else if(parameterType == double.class || parameterType == Double.class) - format("((Number)~A).doubleValue()", arg); - else if(parameterType == float.class || parameterType == Float.class) - format("((Number)~A).floatValue()", arg); - else if(parameterType == long.class || parameterType == Long.class) - format("((Number)~A).longValue()", arg); - else if(parameterType == short.class || parameterType == Short.class) - format("((Number)~A).shortValue()", arg); - else if(parameterType == byte.class || parameterType == Byte.class) - format("((Number)~A).byteValue()", arg); - else - format("((~A)~A)", parameterType.getName(), arg); -} - -/* -static void emitCast(Class parameterType, Expr arg) throws Exception { - Class hostType = arg.getHostType(); - boolean needsCast = false; - //parameterType != Object.class && (hostType == null || !parameterType.isAssignableFrom(hostType)); - if (needsCast) - format("((~A)", parameterType.getName()); - arg.emitHostExpr(); - if (needsCast) - format(")"); -} -*/ - -/*returns null unless single ctor with matching arity, throws if no ctor can handle arity*/ - -public static Constructor findSingleConstructor(Class c, PersistentVector args) throws Exception{ - Constructor[] allctors = c.getConstructors(); - Constructor found = null; - for(int i = 0; i < allctors.length; i++) - { - Constructor ctor = allctors[i]; - if(ctor.getParameterTypes().length == args.count() - || (ctor.isVarArgs() && ctor.getParameterTypes().length <= args.count())) - { - if(found == null) - found = ctor; - else - return null; //more than one matching - } - } - //verify that at least one ctor can handle arity (requires variadic detection) - if(found == null) - throw new Exception("No constructor that can handle arity"); - return found; -} - -/*returns Method if single method with matching arity, - returns Class of return type if all methods with same arity have same return type - else returns null - throws if no method can handle arity*/ - -public static Object findSingleMethod(Class c, String methodName, PersistentVector args, boolean isStatic) - throws Exception{ - Method[] allmethods = c.getMethods(); - Method found = null; - int foundCount = 0; - boolean returnsMatch = true; - for(int i = 0; i < allmethods.length; i++) - { - Method method = allmethods[i]; - if(Modifier.isStatic(method.getModifiers()) == isStatic - && method.getName().equals(methodName) - && (method.getParameterTypes().length == args.count() - || (method.isVarArgs() && method.getParameterTypes().length <= args.count()))) - { - if(found == null) - { - found = method; - foundCount = 1; - } - else - { - ++foundCount; - if(method.getReturnType() != found.getReturnType()) - returnsMatch = false; - } - } - } - //verify that at least one method can handle arity (requires variadic detection) - if(foundCount == 0) - throw new Exception("No method that can handle arity"); - else if(foundCount == 1) - return found; - else if(returnsMatch) - return found.getReturnType(); - return null; -} - -private static Expr analyzeLet(C context, ISeq form) throws Exception{ - //(let (var val var2 val2 ...) body...) - ISeq bindings = (ISeq) RT.second(form); - //special case (let () expr) ==> expr - if(bindings == null && form.count() < 4) - return analyze(context, macroexpand(RT.third(form))); - ISeq body = RT.rest(RT.rest(form)); - - if(context == C.EXPRESSION) - { - //(let (a b) c) -> ((fn (a) c) b) - PersistentVector parms = PersistentVector.EMPTY; - PersistentVector args = PersistentVector.EMPTY; - for(ISeq bs = bindings; bs != null; bs = RT.rest(RT.rest(bs))) - { - parms = parms.cons(RT.first(bs)); - args = args.cons(RT.second(bs)); - } - return analyze(context, RT.cons(RT.listStar(FN, RT.seq(parms), body), RT.seq(args))); - } - - PersistentVector bindingInits = PersistentVector.EMPTY; - //analyze inits before adding bindings to env - for(ISeq bs = bindings; bs != null; bs = RT.rest(RT.rest(bs))) - { - LocalBinding lb = new LocalBinding(baseSymbol((Symbol) RT.first(bs))); - lb.typeHint = typeHint((Symbol) RT.first(bs)); - bindingInits = bindingInits.cons(new BindingInit(lb, analyze(C.EXPRESSION, RT.second(bs)))); - } - try - { - Var.pushThreadBindings(RT.map(LOCAL_ENV, LOCAL_ENV.get())); - for(int i = 0; i < bindingInits.count(); i++) - { - BindingInit bi = (BindingInit) bindingInits.nth(i); - if(bi.init instanceof FnExpr) - { - bi.binding.letfn = (FnExpr) bi.init; - ((FnExpr) bi.init).binding = bi.binding; - } - registerLocal(bi.binding); - } - return new LetExpr(bindingInits, analyzeBody(context, body)); - } - finally - { - Var.popThreadBindings(); - } - -} - -private static Expr analyzeLetFn(C context, ISeq form) throws Exception{ - //(letfn ((foo [what can occur after fn]) (bar [what can occur after fn])) body ...) - if(context == C.EXPRESSION) - return analyze(context, RT.list(RT.list(FN, null, form))); - try - { - Var.pushThreadBindings(RT.map(LOCAL_ENV, LOCAL_ENV.get())); - ISeq bindings = (ISeq) RT.second(form); - ISeq body = RT.rest(RT.rest(form)); - PersistentVector bindingPairs = PersistentVector.EMPTY; - //add all fn names to env before analyzing bodies - for(ISeq bs = bindings; bs != null; bs = RT.rest(bs)) - { - Object bform = RT.first(bs); - Symbol fsym = (Symbol) RT.first(bform); - LocalBinding lb = new LocalBinding(baseSymbol(fsym)); - lb.typeHint = typeHint(fsym); - registerLocal(lb); - bindingPairs = bindingPairs.cons(PersistentVector.create(lb, RT.cons(FN, RT.rest(bform)))); - } - - PersistentVector bindingInits = PersistentVector.EMPTY; - for(int i = 0; i < bindingPairs.count(); i++) - { - IPersistentVector bpair = (IP |