summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2006-10-03 00:59:14 +0000
committerRich Hickey <richhickey@gmail.com>2006-10-03 00:59:14 +0000
commit97230011c3ae6a33d1aac2be5ce78a031b46f189 (patch)
treec9ea2dd2bd70814367dc3f54eb9eca13093f1943
parent3302b103d19483ab301c98f381f03eb3a2ed0107 (diff)
interim checkin
-rw-r--r--src/cli/runtime/RT.cs4
-rw-r--r--src/cli/runtime/RestFn.cs2
-rw-r--r--src/jvm/clojure/lang/Compiler.java91
-rw-r--r--src/jvm/clojure/lang/RT.java4
-rw-r--r--src/jvm/clojure/lang/RestFn.java2
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;
}