diff options
author | Rich Hickey <richhickey@gmail.com> | 2006-10-03 00:59:14 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2006-10-03 00:59:14 +0000 |
commit | 97230011c3ae6a33d1aac2be5ce78a031b46f189 (patch) | |
tree | c9ea2dd2bd70814367dc3f54eb9eca13093f1943 | |
parent | 3302b103d19483ab301c98f381f03eb3a2ed0107 (diff) |
interim checkin
-rw-r--r-- | src/cli/runtime/RT.cs | 4 | ||||
-rw-r--r-- | src/cli/runtime/RestFn.cs | 2 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 91 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RestFn.java | 2 |
5 files changed, 95 insertions, 8 deletions
diff --git a/src/cli/runtime/RT.cs b/src/cli/runtime/RT.cs index 8f7141d9..431185d6 100644 --- a/src/cli/runtime/RT.cs +++ b/src/cli/runtime/RT.cs @@ -149,6 +149,10 @@ static public Object third(Object x) {
return first(rest(rest(x)));
}
+
+static public Object fourth(Object x) {
+ return first(rest(rest(rest(x))));
+}
static public ISeq rest(Object x)
{
diff --git a/src/cli/runtime/RestFn.cs b/src/cli/runtime/RestFn.cs index 80ae5d40..b83bf057 100644 --- a/src/cli/runtime/RestFn.cs +++ b/src/cli/runtime/RestFn.cs @@ -15,7 +15,7 @@ public abstract class RestFn : AFn { protected int reqArity;
-RestFn(int reqArity) {
+public RestFn(int reqArity) {
this.reqArity = reqArity;
}
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 3f4cd050..d6a14f6d 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -22,6 +22,7 @@ public class Compiler{ static Symbol DEF = Symbol.intern("def"); static Symbol FN = Symbol.intern("fn"); static Symbol DO = Symbol.intern("do"); +static Symbol IF = Symbol.intern("if"); static Symbol IMPORT = Symbol.intern("import"); static Symbol USE = Symbol.intern("use"); static Symbol _AM_KEY = Symbol.intern("&key"); @@ -88,6 +89,7 @@ static String compile(String ns, String className, LineNumberingPushbackReader.. format("/* Generated by Clojure */~%~%"); format("package ~A;~%", ns); + format("import clojure.lang.*;~%~%"); format("public class ~A{~%", className); PersistentArrayList forms = new PersistentArrayList(20); @@ -287,10 +289,30 @@ private static Expr analyzeSeq(C context, ISeq form) throws Exception { return analyzeFn(context, form); else if(op == DO) return analyzeDo(context, form); + else if(op == IF) + return analyzeIf(context, form); else throw new UnsupportedOperationException(); } +private static Expr analyzeIf(C context, ISeq form) throws Exception { + //(if test then) or (if test then else) + if(RT.second(form) == RT.T) //optimize macro-generated (if :t ...) forms + return analyze(context,macroexpand(RT.third(form))); + else if(RT.second(form) == null) + return analyze(context,macroexpand(RT.fourth(form))); + Expr testExpr = analyze(C.EXPRESSION, macroexpand(RT.second(form))); + String compare = "!="; + //lift tests that are not exprs by taking value as test and inverting compare + if(testExpr instanceof NotExpr) + { + testExpr = ((NotExpr)testExpr).expr; + compare = "=="; + } + return new IfExpr(testExpr, compare, analyze(context, macroexpand(RT.third(form))), + analyze(context, macroexpand(RT.fourth(form)))); +} + private static Expr analyzeDo(C context, ISeq form) throws Exception { //(do ...) //(do) == null @@ -299,12 +321,50 @@ private static Expr analyzeDo(C context, ISeq form) throws Exception { else if(RT.rest(RT.rest(form)) == null) //(do x) == x return analyze(context, macroexpand(RT.second(form))); else if(context == C.EXPRESSION) - return analyzeFn(context, RT.cons(FN, RT.cons(null, RT.rest(form)))); + return analyzeFn(context, RT.list(RT.cons(FN, RT.cons(null, RT.rest(form))))); else return analyzeBody(context, RT.rest(form)); } +static class IfExpr extends AnExpr{ + final Expr testExpr; + final String compare; + final Expr thenExpr; + final Expr elseExpr; + + public IfExpr(Expr testExpr, String compare, Expr thenExpr, Expr elseExpr) { + this.testExpr = testExpr; + this.compare = compare; + this.thenExpr = thenExpr; + this.elseExpr = elseExpr; + } + + public void emitReturn() throws Exception { + format("if(~A ~A null)~%", testExpr.emitExpressionString(),compare); + thenExpr.emitReturn(); + format("else~%"); + elseExpr.emitReturn(); + } + + public void emitStatement() throws Exception { + format("if(~A ~A null)~%", testExpr.emitExpressionString(),compare); + thenExpr.emitStatement(); + if(!(elseExpr instanceof NilExpr)) + { + format("~%else~%"); + elseExpr.emitStatement(); + } + } + + public void emitExpression() throws Exception { + format("(~A ~A null?", testExpr.emitExpressionString(),compare); + thenExpr.emitExpression(); + format(":"); + elseExpr.emitExpression(); + format(")"); + } +} private static Expr analyzeBody(C context, ISeq forms) throws Exception { PersistentArrayList exprs = new PersistentArrayList(4); for(;forms != null;forms = forms.rest()) @@ -385,14 +445,14 @@ private static Expr analyzeFn(C context, ISeq form) throws Exception { methods = RT.cons(variadicMethod, methods); fn.methods = methods; - fn.isVariadic = variadicMethod != null; + fn.variadicMethod = variadicMethod; registerFn(fn); return fn; } static class FnExpr extends AnExpr{ IPersistentCollection methods; - boolean isVariadic; + FnMethod variadicMethod; LocalBinding binding; String name = null; boolean isCalledDirectly = false; @@ -439,12 +499,15 @@ static class FnExpr extends AnExpr{ //emit class declaration format("static public class ~A extends ~A{~%", getName(), - isVariadic ? "clojure.lang.RestFn" : "AFn"); + variadicMethod != null ? "clojure.lang.RestFn" : "AFn"); + if(closes != null) { //emit members and ctor if closure format("~{~A ~A;~%~}", closesDecls); format("public ~A (~{~A ~A~^, ~}){~%", getName(), closesDecls); + if(variadicMethod != null) //must call base ctor + format("super(~A);~%", variadicMethod.reqParms.count()); for (ISeq s = RT.seq(closes); s != null; s = s.rest()) { LocalBinding b = (LocalBinding) ((IMapEntry) s.first()).key(); @@ -454,6 +517,13 @@ static class FnExpr extends AnExpr{ } format("}~%"); } + else if(variadicMethod != null) //must create ctor in order to call base ctor + { + format("public ~A (){~%", getName()); + format("super(~A);~%", variadicMethod.reqParms.count()); + format("}~%"); + } + } else { @@ -537,7 +607,7 @@ static class FnExpr extends AnExpr{ } boolean willBeStaticMethod() { - return !isVariadic + return variadicMethod == null && methods.count() == 1 && ( @@ -824,8 +894,17 @@ static class LiteralExpr extends AnExpr{ } public void emitExpression() throws Exception{ - format("%S",val); + format("~S",val); + } +} + +static class NotExpr extends AnExpr{ + final Expr expr; + + public NotExpr(Expr expr){ + this.expr = expr; } + } static class CharExpr extends AnExpr{ diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index ea4f6041..bdc56434 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -142,6 +142,10 @@ static public Object third(Object x) { return first(rest(rest(x))); } +static public Object fourth(Object x) { + return first(rest(rest(rest(x)))); +} + static public ISeq rest(Object x) { if(x == null) return null; diff --git a/src/jvm/clojure/lang/RestFn.java b/src/jvm/clojure/lang/RestFn.java index 57434d25..3beee835 100644 --- a/src/jvm/clojure/lang/RestFn.java +++ b/src/jvm/clojure/lang/RestFn.java @@ -13,7 +13,7 @@ public abstract class RestFn extends AFn { protected int reqArity;
-RestFn(int reqArity) {
+public RestFn(int reqArity) {
this.reqArity = reqArity;
}
|