diff options
author | Rich Hickey <richhickey@gmail.com> | 2010-06-02 12:05:36 -0400 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2010-06-02 12:05:36 -0400 |
commit | c37c15c81a299c617779bff738480b1a2fb45524 (patch) | |
tree | d9218214341b31791a9b720c3705d9494bf7c777 | |
parent | f47b3d6f028e0370c495383731a449092d0ae451 (diff) |
flow primitives through if and let
-rw-r--r-- | src/clj/clojure/core.clj | 20 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 67 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 |
3 files changed, 72 insertions, 19 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index b3f364c6..b44a4965 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -645,8 +645,7 @@ (defn identical? "Tests if 2 arguments are the same object" - {:tag Boolean - :inline (fn [x y] `(. clojure.lang.Util identical ~x ~y)) + {:inline (fn [x y] `(. clojure.lang.Util identical ~x ~y)) :inline-arities #{2} :added "1.0"} ([x y] (clojure.lang.Util/identical x y))) @@ -657,8 +656,7 @@ numbers and collections in a type-independent manner. Clojure's immutable data structures define equals() (and thus =) as a value, not an identity, comparison." - {:tag Boolean - :inline (fn [x y] `(. clojure.lang.Util equiv ~x ~y)) + {:inline (fn [x y] `(. clojure.lang.Util equiv ~x ~y)) :inline-arities #{2} :added "1.0"} ([x] true) @@ -687,7 +685,7 @@ y. Same as Java x.compareTo(y) except it also works for nil, and compares numbers and collections in a type-independent manner. x must implement Comparable" - {:tag Integer + { :inline (fn [x y] `(. clojure.lang.Util compare ~x ~y)) :added "1.0"} [x y] (. clojure.lang.Util (compare x y))) @@ -719,7 +717,7 @@ ;;;;;;;;;;;;;;;;;;; sequence fns ;;;;;;;;;;;;;;;;;;;;;;; (defn zero? "Returns true if num is zero, else false" - {:tag Boolean + { :inline (fn [x] `(. clojure.lang.Numbers (isZero ~x))) :added "1.0"} [x] (. clojure.lang.Numbers (isZero x))) @@ -727,14 +725,14 @@ (defn count "Returns the number of items in the collection. (count nil) returns 0. Also works on strings, arrays, and Java Collections and Maps" - {:tag Integer + { :inline (fn [x] `(. clojure.lang.RT (count ~x))) :added "1.0"} [coll] (clojure.lang.RT/count coll)) (defn int "Coerce to int" - {:tag Integer + { :inline (fn [x] `(. clojure.lang.RT (intCast ~x))) :added "1.0"} [x] (. clojure.lang.RT (intCast x))) @@ -979,14 +977,14 @@ (defn pos? "Returns true if num is greater than zero, else false" - {:tag Boolean + { :inline (fn [x] `(. clojure.lang.Numbers (isPos ~x))) :added "1.0"} [x] (. clojure.lang.Numbers (isPos x))) (defn neg? "Returns true if num is less than zero, else false" - {:tag Boolean + { :inline (fn [x] `(. clojure.lang.Numbers (isNeg ~x))) :added "1.0"} [x] (. clojure.lang.Numbers (isNeg x))) @@ -2698,7 +2696,7 @@ (defn boolean "Coerce to boolean" - {:tag Boolean + { :inline (fn [x] `(. clojure.lang.RT (booleanCast ~x))) :added "1.0"} [x] (clojure.lang.RT/booleanCast x)) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 40acd58d..3aae49f8 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -2191,7 +2191,7 @@ public static class MetaExpr implements Expr{ } } -public static class IfExpr implements Expr{ +public static class IfExpr implements Expr, MaybePrimitiveExpr{ public final Expr testExpr; public final Expr thenExpr; public final Expr elseExpr; @@ -2213,6 +2213,14 @@ public static class IfExpr implements Expr{ } public void emit(C context, ObjExpr objx, GeneratorAdapter gen){ + doEmit(context, objx, gen,false); + } + + public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){ + doEmit(context, objx, gen, true); + } + + public void doEmit(C context, ObjExpr objx, GeneratorAdapter gen, boolean emitUnboxed){ Label nullLabel = gen.newLabel(); Label falseLabel = gen.newLabel(); Label endLabel = gen.newLabel(); @@ -2239,12 +2247,18 @@ public static class IfExpr implements Expr{ { throw new RuntimeException(e); } - thenExpr.emit(context, objx, gen); + if(emitUnboxed) + ((MaybePrimitiveExpr)thenExpr).emitUnboxed(context, objx, gen); + else + thenExpr.emit(context, objx, gen); gen.goTo(endLabel); gen.mark(nullLabel); gen.pop(); gen.mark(falseLabel); - elseExpr.emit(context, objx, gen); + if(emitUnboxed) + ((MaybePrimitiveExpr)elseExpr).emitUnboxed(context, objx, gen); + else + elseExpr.emit(context, objx, gen); gen.mark(endLabel); } @@ -2253,8 +2267,23 @@ public static class IfExpr implements Expr{ && elseExpr.hasJavaClass() && (thenExpr.getJavaClass() == elseExpr.getJavaClass() - || thenExpr.getJavaClass() == null - || elseExpr.getJavaClass() == null); + || (thenExpr.getJavaClass() == null && !elseExpr.getJavaClass().isPrimitive()) + || (elseExpr.getJavaClass() == null && !thenExpr.getJavaClass().isPrimitive())); + } + + public boolean canEmitPrimitive(){ + try + { + return thenExpr instanceof MaybePrimitiveExpr + && elseExpr instanceof MaybePrimitiveExpr + && thenExpr.getJavaClass() == elseExpr.getJavaClass() + && ((MaybePrimitiveExpr)thenExpr).canEmitPrimitive() + && ((MaybePrimitiveExpr)elseExpr).canEmitPrimitive(); + } + catch(Exception e) + { + return false; + } } public Class getJavaClass() throws Exception{ @@ -4838,7 +4867,7 @@ public static class LetFnExpr implements Expr{ } } -public static class LetExpr implements Expr{ +public static class LetExpr implements Expr, MaybePrimitiveExpr{ public final PersistentVector bindingInits; public final Expr body; public final boolean isLoop; @@ -4927,6 +4956,15 @@ public static class LetExpr implements Expr{ } public void emit(C context, ObjExpr objx, GeneratorAdapter gen){ + doEmit(context, objx, gen, false); + } + + public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){ + doEmit(context, objx, gen, true); + } + + + public void doEmit(C context, ObjExpr objx, GeneratorAdapter gen, boolean emitUnboxed){ for(int i = 0; i < bindingInits.count(); i++) { BindingInit bi = (BindingInit) bindingInits.nth(i); @@ -4948,7 +4986,10 @@ public static class LetExpr implements Expr{ try { Var.pushThreadBindings(RT.map(LOOP_LABEL, loopLabel)); - body.emit(context, objx, gen); + if(emitUnboxed) + ((MaybePrimitiveExpr)body).emitUnboxed(context, objx, gen); + else + body.emit(context, objx, gen); } finally { @@ -4956,7 +4997,12 @@ public static class LetExpr implements Expr{ } } else - body.emit(context, objx, gen); + { + if(emitUnboxed) + ((MaybePrimitiveExpr)body).emitUnboxed(context, objx, gen); + else + body.emit(context, objx, gen); + } Label end = gen.mark(); // gen.visitLocalVariable("this", "Ljava/lang/Object;", null, loopLabel, end, 0); for(ISeq bis = bindingInits.seq(); bis != null; bis = bis.next()) @@ -4981,6 +5027,11 @@ public static class LetExpr implements Expr{ public Class getJavaClass() throws Exception{ return body.getJavaClass(); } + + public boolean canEmitPrimitive(){ + return body instanceof MaybePrimitiveExpr && ((MaybePrimitiveExpr)body).canEmitPrimitive(); + } + } public static class RecurExpr implements Expr{ diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index e1016f57..1f78443e 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -894,6 +894,10 @@ static public boolean booleanCast(Object x){ return x != null; } +static public boolean booleanCast(boolean x){ + return x; +} + static public byte byteCast(Object x){ long n = ((Number) x).longValue(); if(n < Byte.MIN_VALUE || n > Byte.MAX_VALUE) |