summaryrefslogtreecommitdiff
path: root/src/jvm/clojure
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-01-06 17:13:59 +0000
committerRich Hickey <richhickey@gmail.com>2008-01-06 17:13:59 +0000
commitebe40313d671a1cbc9930e58b550a68d1da3c075 (patch)
tree17b15c201f8b3bf2be00e8cf02c812a44a5b0b76 /src/jvm/clojure
parent433fc199d68217c4d048eaeac81d7ff9f6928c7e (diff)
first cut of true/false support
Diffstat (limited to 'src/jvm/clojure')
-rw-r--r--src/jvm/clojure/lang/Compiler.java96
-rw-r--r--src/jvm/clojure/lang/LispReader.java9
-rw-r--r--src/jvm/clojure/lang/Num.java10
-rw-r--r--src/jvm/clojure/lang/RT.java24
-rw-r--r--src/jvm/clojure/lang/Reflector.java12
5 files changed, 113 insertions, 38 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 7b825b76..dd3fe7e1 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -117,6 +117,7 @@ private static final Type RT_TYPE = Type.getType(RT.class);
final static Type CLASS_TYPE = Type.getType(Class.class);
final static Type REFLECTOR_TYPE = Type.getType(Reflector.class);
final static Type THROWABLE_TYPE = Type.getType(Throwable.class);
+final static Type BOOLEAN_OBJECT_TYPE = Type.getType(Boolean.class);
private static final Type[][] ARG_TYPES;
private static final Type[] EXCEPTION_TYPES = {Type.getType(Exception.class)};
@@ -561,10 +562,11 @@ static abstract class HostExpr implements Expr{
Label falseLabel = gen.newLabel();
Label endLabel = gen.newLabel();
gen.ifZCmp(GeneratorAdapter.EQ, falseLabel);
- gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "TRUE", BOOLEAN_OBJECT_TYPE);
gen.goTo(endLabel);
gen.mark(falseLabel);
- NIL_EXPR.emit(C.EXPRESSION, fn, gen);
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
+// NIL_EXPR.emit(C.EXPRESSION, fn, gen);
gen.mark(endLabel);
}
else if(returnType == void.class)
@@ -1134,8 +1136,41 @@ static class NilExpr extends LiteralExpr{
}
}
-static NilExpr NIL_EXPR = new NilExpr();
+final static NilExpr NIL_EXPR = new NilExpr();
+
+static class BooleanExpr extends LiteralExpr{
+ final boolean val;
+
+
+ public BooleanExpr(boolean val){
+ this.val = val;
+ }
+
+ Object val(){
+ return val ? RT.T : RT.F;
+ }
+
+ public void emit(C context, FnExpr fn, GeneratorAdapter gen){
+ if(context != C.STATEMENT)
+ {
+ if(val)
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "TRUE", BOOLEAN_OBJECT_TYPE);
+ else
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
+ }
+ }
+
+ public boolean hasJavaClass(){
+ return true;
+ }
+
+ public Class getJavaClass() throws Exception{
+ return Boolean.class;
+ }
+}
+final static BooleanExpr TRUE_EXPR = new BooleanExpr(true);
+final static BooleanExpr FALSE_EXPR = new BooleanExpr(false);
static class NumExpr extends LiteralExpr{
final Num num;
@@ -1711,7 +1746,7 @@ static class NewExpr implements Expr{
}
-static class IdenticalExpr extends UntypedExpr{
+static class IdenticalExpr implements Expr{
final Expr expr1;
final Expr expr2;
@@ -1721,9 +1756,17 @@ static class IdenticalExpr extends UntypedExpr{
this.expr2 = expr2;
}
+ public boolean hasJavaClass(){
+ return true;
+ }
+
+ public Class getJavaClass(){
+ return Boolean.class;
+ }
+
public Object eval() throws Exception{
return expr1.eval() == expr2.eval() ?
- RT.T : null;
+ RT.T : RT.F;
}
public void emit(C context, FnExpr fn, GeneratorAdapter gen){
@@ -1734,10 +1777,12 @@ static class IdenticalExpr extends UntypedExpr{
expr1.emit(C.EXPRESSION, fn, gen);
expr2.emit(C.EXPRESSION, fn, gen);
gen.visitJumpInsn(IF_ACMPNE, not);
- gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "TRUE", BOOLEAN_OBJECT_TYPE);
+// gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
gen.goTo(end);
gen.mark(not);
- NIL_EXPR.emit(C.EXPRESSION, fn, gen);
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
+// NIL_EXPR.emit(C.EXPRESSION, fn, gen);
gen.mark(end);
}
}
@@ -1753,7 +1798,7 @@ static class IdenticalExpr extends UntypedExpr{
}
}
-static class InstanceExpr extends UntypedExpr{
+static class InstanceExpr implements Expr{
final Expr expr;
final String className;
@@ -1765,7 +1810,15 @@ static class InstanceExpr extends UntypedExpr{
public Object eval() throws Exception{
return Class.forName(className).isInstance(expr.eval()) ?
- RT.T : null;
+ RT.T : RT.F;
+ }
+
+ public boolean hasJavaClass(){
+ return true;
+ }
+
+ public Class getJavaClass(){
+ return Boolean.class;
}
public void emit(C context, FnExpr fn, GeneratorAdapter gen){
@@ -1776,10 +1829,12 @@ static class InstanceExpr extends UntypedExpr{
expr.emit(C.EXPRESSION, fn, gen);
gen.instanceOf(Type.getObjectType(className.replace('.', '/')));
gen.ifZCmp(GeneratorAdapter.EQ, not);
- gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "TRUE", BOOLEAN_OBJECT_TYPE);
+// gen.getStatic(RT_TYPE, "T", KEYWORD_TYPE);
gen.goTo(end);
gen.mark(not);
- NIL_EXPR.emit(C.EXPRESSION, fn, gen);
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
+// NIL_EXPR.emit(C.EXPRESSION, fn, gen);
gen.mark(end);
}
}
@@ -1850,22 +1905,29 @@ static class IfExpr implements Expr{
}
public Object eval() throws Exception{
- if(testExpr.eval() != null)
+ Object t = testExpr.eval();
+ if(t != null && t != Boolean.FALSE)
return thenExpr.eval();
return elseExpr.eval();
}
public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- Label elseLabel = gen.newLabel();
+ Label nullLabel = gen.newLabel();
+ Label falseLabel = gen.newLabel();
Label endLabel = gen.newLabel();
gen.visitLineNumber(line, gen.mark());
testExpr.emit(C.EXPRESSION, fn, gen);
- gen.ifNull(elseLabel);
+ gen.dup();
+ gen.ifNull(nullLabel);
+ gen.getStatic(BOOLEAN_OBJECT_TYPE, "FALSE", BOOLEAN_OBJECT_TYPE);
+ gen.visitJumpInsn(IF_ACMPEQ, falseLabel);
thenExpr.emit(context, fn, gen);
gen.goTo(endLabel);
- gen.mark(elseLabel);
+ gen.mark(nullLabel);
+ gen.pop();
+ gen.mark(falseLabel);
elseExpr.emit(context, fn, gen);
gen.mark(endLabel);
}
@@ -2910,6 +2972,10 @@ private static Expr analyze(C context, Object form, String name) throws Exceptio
//todo symbol macro expansion?
if(form == null)
return NIL_EXPR;
+ else if(form == Boolean.TRUE)
+ return TRUE_EXPR;
+ else if(form == Boolean.FALSE)
+ return FALSE_EXPR;
Class fclass = form.getClass();
if(fclass == Symbol.class)
return analyzeSymbol((Symbol) form);
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java
index c41ff6fb..52db79c6 100644
--- a/src/jvm/clojure/lang/LispReader.java
+++ b/src/jvm/clojure/lang/LispReader.java
@@ -190,7 +190,14 @@ static private Object interpretToken(String s) throws Exception{
{
return null;
}
-
+ else if(s.equals("true"))
+ {
+ return RT.T;
+ }
+ else if(s.equals("false"))
+ {
+ return RT.F;
+ }
else if(s.equals("/"))
{
return SLASH;
diff --git a/src/jvm/clojure/lang/Num.java b/src/jvm/clojure/lang/Num.java
index 3aa5f3b1..5d8df4f5 100644
--- a/src/jvm/clojure/lang/Num.java
+++ b/src/jvm/clojure/lang/Num.java
@@ -111,11 +111,11 @@ static public Object[] truncate(Object num, Object div){
}
static public Object quotient(Object num, Object div){
- return truncate(num,div)[0];
+ return truncate(num, div)[0];
}
static public Object remainder(Object num, Object div){
- return truncate(num,div)[1];
+ return truncate(num, div)[1];
}
abstract public Object[] truncateDivide(Num rhs);
@@ -188,15 +188,15 @@ static public Num negate(Object x){
}
static public Object negPred(Object x){
- return Num.from(x).minusp() ? RT.T : null;
+ return Num.from(x).minusp() ? RT.T : RT.F;
}
static public Object posPred(Object x){
- return Num.from(x).plusp() ? RT.T : null;
+ return Num.from(x).plusp() ? RT.T : RT.F;
}
static public Object zeroPred(Object x){
- return Num.from(x).zerop() ? RT.T : null;
+ return Num.from(x).zerop() ? RT.T : RT.F;
}
static public Num dec(Object x){
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java
index 05c1557b..3586aab0 100644
--- a/src/jvm/clojure/lang/RT.java
+++ b/src/jvm/clojure/lang/RT.java
@@ -19,7 +19,8 @@ import java.lang.reflect.Array;
public class RT{
-static public Keyword T = Keyword.intern(Symbol.create(null, "t"));
+static final public Boolean T = Boolean.TRUE;//Keyword.intern(Symbol.create(null, "t"));
+static final public Boolean F = Boolean.FALSE;//Keyword.intern(Symbol.create(null, "t"));
final static public Var OUT =
Var.intern(Symbol.create("clojure", "*out*"), new OutputStreamWriter(System.out));
final static public Var IN =
@@ -115,7 +116,7 @@ Symbol.create("Exception"), "java.lang.Exception"
);
-final static Var PRINT_META = Var.intern(Symbol.create("clojure", "*print-meta*"), null);
+final static Var PRINT_META = Var.intern(Symbol.create("clojure", "*print-meta*"), F);
final static Var PRINT_READABLY = Var.intern(Symbol.create("clojure", "*print-readably*"), T);
final static Var IMPORTS = Var.intern(Symbol.create("clojure", "*imports*"), DEFAULT_IMPORTS);
@@ -151,7 +152,7 @@ final static Var REFERS =
new AFn(){
public Object invoke(Object arg1, Object arg2)
throws Exception{
- return arg1 == arg2 ? RT.T : null;
+ return arg1 == arg2 ? RT.T : RT.F;
}
})
));
@@ -162,9 +163,10 @@ static public final Object[] EMPTY_ARRAY = new Object[]{};
//static public final Character[] chars;
static AtomicInteger id = new AtomicInteger(1);
-static{
-OUT.setTag(Symbol.create("java.io.OutputStreamWriter"));
-}
+static
+ {
+ OUT.setTag(Symbol.create("java.io.OutputStreamWriter"));
+ }
//static
// {
// chars = new Character[256];
@@ -339,7 +341,7 @@ static public Associative assoc(Object coll, Object key, Object val){
static public Object contains(Object coll, Object key){
if(coll == null)
return false;
- return ((Associative) coll).containsKey(key) ? T : null;
+ return ((Associative) coll).containsKey(key) ? T : F;
}
static public Object find(Object coll, Object key){
@@ -444,11 +446,11 @@ static public Character box(char x){
}
static public Object box(boolean x){
- return x ? T : null;
+ return x ? T : F;
}
static public Object box(Boolean x){
- return x ? T : null;
+ return x;// ? T : null;
}
static public Num box(byte x){
@@ -681,11 +683,11 @@ static public boolean suppressRead(){
static public void print(Object x, Writer w) throws Exception{
//todo - make extensible
- boolean readably = PRINT_READABLY.get() != null;
+ boolean readably = booleanCast(PRINT_READABLY.get());
if(x instanceof Obj)
{
Obj o = (Obj) x;
- if(RT.count(o.meta()) > 0 && readably && PRINT_META.get() != null)
+ if(RT.count(o.meta()) > 0 && readably && booleanCast(PRINT_META.get()))
{
IPersistentMap meta = o.meta();
w.write("#^");
diff --git a/src/jvm/clojure/lang/Reflector.java b/src/jvm/clojure/lang/Reflector.java
index 2192ce1f..867f3590 100644
--- a/src/jvm/clojure/lang/Reflector.java
+++ b/src/jvm/clojure/lang/Reflector.java
@@ -65,7 +65,7 @@ static Object invokeMatchingMethod(String methodName, List methods, Object targe
}
if(m == null)
throw new IllegalArgumentException("No matching method found: " + methodName);
- return prepRet(m.getReturnType(),m.invoke(target, boxedArgs));
+ return prepRet(m.getReturnType(), m.invoke(target, boxedArgs));
}
public static Method getAsMethodOfPublicBase(Class c, Method m){
@@ -149,7 +149,7 @@ public static Object getStaticField(String className, String fieldName) throws E
Field f = getField(c, fieldName, true);
if(f != null)
{
- return prepRet(f.getType(),f.get(null));
+ return prepRet(f.getType(), f.get(null));
}
throw new IllegalArgumentException("No matching field found");
}
@@ -170,7 +170,7 @@ public static Object getInstanceField(Object target, String fieldName) throws Ex
Field f = getField(c, fieldName, false);
if(f != null)
{
- return prepRet(f.getType(),f.get(target));
+ return prepRet(f.getType(), f.get(target));
}
throw new IllegalArgumentException("No matching field found");
}
@@ -192,7 +192,7 @@ public static Object invokeInstanceMember(Object target, String name) throws Exc
Field f = getField(c, name, false);
if(f != null) //field get
{
- return prepRet(f.getType(),f.get(target));
+ return prepRet(f.getType(), f.get(target));
}
return invokeInstanceMethod(target, name, RT.EMPTY_ARRAY);
}
@@ -323,8 +323,8 @@ static boolean isCongruent(Class[] params, Object[] args){
}
static Object prepRet(Class c, Object x){
- if(c == boolean.class)
- return ((Boolean) x).booleanValue() ? RT.T : null;
+// if(c == boolean.class)
+// return ((Boolean) x).booleanValue() ? RT.T : null;
return x;
}
}