summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2010-06-02 12:05:36 -0400
committerRich Hickey <richhickey@gmail.com>2010-06-02 12:05:36 -0400
commitc37c15c81a299c617779bff738480b1a2fb45524 (patch)
treed9218214341b31791a9b720c3705d9494bf7c777
parentf47b3d6f028e0370c495383731a449092d0ae451 (diff)
flow primitives through if and let
-rw-r--r--src/clj/clojure/core.clj20
-rw-r--r--src/jvm/clojure/lang/Compiler.java67
-rw-r--r--src/jvm/clojure/lang/RT.java4
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)