summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-09-22 18:29:04 +0000
committerRich Hickey <richhickey@gmail.com>2007-09-22 18:29:04 +0000
commit6b248387e7631748011afccb65c495b635806d45 (patch)
treeaafeeb77c3290c5d366c69d5631a038675694bbd /src
parentd43857f2e302f4307f2b8b201704b84b5286b567 (diff)
refactoring, commented out test mains
Diffstat (limited to 'src')
-rw-r--r--src/boot.clj8
-rw-r--r--src/jvm/clojure/lang/ArgVector.java97
-rw-r--r--src/jvm/clojure/lang/Compiler.java8
-rw-r--r--src/jvm/clojure/lang/LispReader.java3
-rw-r--r--src/jvm/clojure/lang/LockingTransaction.java4
-rw-r--r--src/jvm/clojure/lang/OldCompiler.java1998
-rw-r--r--src/jvm/clojure/lang/PersistentHashMap.java2
-rw-r--r--src/jvm/clojure/lang/PersistentQueue.java17
-rw-r--r--src/jvm/clojure/lang/PersistentTreeMap.java3
-rw-r--r--src/jvm/clojure/lang/PersistentVector.java3
-rw-r--r--src/jvm/clojure/lang/RT.java14
-rw-r--r--src/jvm/clojure/lang/ThreadLocalData.java93
-rw-r--r--src/jvm/clojure/lang/TransactionalHashMap.java4
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