summaryrefslogtreecommitdiff
path: root/src/jvm
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2010-06-15 23:13:05 -0400
committerRich Hickey <richhickey@gmail.com>2010-06-15 23:13:05 -0400
commit6ab3e4cd672092823a04c944210a23c29142785d (patch)
treef54d634e3fb26e623e21692879f4cd94f261e7fb /src/jvm
parent8fbafa92faacb92a9bd49fa1e9b7e2c8c0747c07 (diff)
Unify numeric semantics around longs, with throw on overflow. Allow numeric literals to be primitive initializers. Canonicalize boxing of integers, if it fits in int, is Integer, else Long, thus primitive coercions can't be used to get particular boxed types, use Long/valueOf etc. Ask for BigIntegers if you want arbitrary precision, new literal number format - append 'N' for BigInteger. BigIntegers do not reduce automatically, are contagious. New particular names for unchecked ops - unchecked-xxx-int or unchecked-xxx-long. You should need far fewer hints for primitive perf, and avoid int casts and any casting of numeric literals, see:
http://gist.github.com/440102
Diffstat (limited to 'src/jvm')
-rw-r--r--src/jvm/clojure/lang/Compiler.java483
-rw-r--r--src/jvm/clojure/lang/LispReader.java2
-rw-r--r--src/jvm/clojure/lang/Numbers.java1258
-rw-r--r--src/jvm/clojure/lang/Reflector.java21
4 files changed, 968 insertions, 796 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 29e8fbbd..9f8c7b5f 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -139,6 +139,7 @@ private static final Type SYMBOL_TYPE = Type.getType(Symbol.class);
private static final Type IFN_TYPE = Type.getType(IFn.class);
private static final Type AFUNCTION_TYPE = Type.getType(AFunction.class);
private static final Type RT_TYPE = Type.getType(RT.class);
+private static final Type NUMBERS_TYPE = Type.getType(Numbers.class);
final static Type CLASS_TYPE = Type.getType(Class.class);
final static Type NS_TYPE = Type.getType(Namespace.class);
final static Type UTIL_TYPE = Type.getType(Util.class);
@@ -726,22 +727,20 @@ static public abstract class HostExpr implements Expr, MaybePrimitiveExpr{
else
{
if(returnType == int.class)
- //gen.invokeStatic(NUM_TYPE, fromIntMethod);
gen.invokeStatic(INTEGER_TYPE, intValueOfMethod);
else if(returnType == float.class)
{
- //gen.visitInsn(F2D);
- gen.invokeStatic(FLOAT_TYPE, floatValueOfMethod);
- //m = floatValueOfMethod;
+ gen.visitInsn(F2D);
+ gen.invokeStatic(DOUBLE_TYPE, doubleValueOfMethod);
}
else if(returnType == double.class)
gen.invokeStatic(DOUBLE_TYPE, doubleValueOfMethod);
- else if(returnType == long.class)
- gen.invokeStatic(LONG_TYPE, longValueOfMethod);
- else if(returnType == byte.class)
- gen.invokeStatic(BYTE_TYPE, byteValueOfMethod);
- else if(returnType == short.class)
- gen.invokeStatic(SHORT_TYPE, shortValueOfMethod);
+ else if(returnType == long.class)
+ gen.invokeStatic(NUMBERS_TYPE, Method.getMethod("Number num(long)"));
+ else if(returnType == byte.class)
+ gen.invokeStatic(BYTE_TYPE, byteValueOfMethod);
+ else if(returnType == short.class)
+ gen.invokeStatic(SHORT_TYPE, shortValueOfMethod);
}
}
}
@@ -1163,9 +1162,35 @@ static abstract class MethodExpr extends HostExpr{
Expr e = (Expr) args.nth(i);
try
{
- if(maybePrimitiveType(e) == parameterTypes[i])
+ final Class primc = maybePrimitiveType(e);
+ if(primc == parameterTypes[i])
{
- ((MaybePrimitiveExpr) e).emitUnboxed(C.EXPRESSION, objx, gen);
+ final MaybePrimitiveExpr pe = (MaybePrimitiveExpr) e;
+ pe.emitUnboxed(C.EXPRESSION, objx, gen);
+ }
+ else if(primc == int.class && parameterTypes[i] == long.class)
+ {
+ final MaybePrimitiveExpr pe = (MaybePrimitiveExpr) e;
+ pe.emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.visitInsn(I2L);
+ }
+ else if(primc == long.class && parameterTypes[i] == int.class)
+ {
+ final MaybePrimitiveExpr pe = (MaybePrimitiveExpr) e;
+ pe.emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.invokeStatic(RT_TYPE, Method.getMethod("int intCast(long)"));
+ }
+ else if(primc == float.class && parameterTypes[i] == double.class)
+ {
+ final MaybePrimitiveExpr pe = (MaybePrimitiveExpr) e;
+ pe.emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.visitInsn(F2D);
+ }
+ else if(primc == double.class && parameterTypes[i] == float.class)
+ {
+ final MaybePrimitiveExpr pe = (MaybePrimitiveExpr) e;
+ pe.emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.visitInsn(D2F);
}
else
{
@@ -1508,6 +1533,66 @@ static class UnresolvedVarExpr implements Expr{
}
}
+static class NumberExpr extends LiteralExpr implements MaybePrimitiveExpr{
+ final Number n;
+ public final int id;
+
+ public NumberExpr(Number n){
+ this.n = n;
+ this.id = registerConstant(n);
+ }
+
+ Object val(){
+ return n;
+ }
+
+ public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
+ if(context != C.STATEMENT)
+ {
+ objx.emitConstant(gen, id);
+// emitUnboxed(context,objx,gen);
+// HostExpr.emitBoxReturn(objx,gen,getJavaClass());
+ }
+ }
+
+ public boolean hasJavaClass() throws Exception{
+ return true;
+ }
+
+ public Class getJavaClass(){
+ if(n instanceof Integer)
+ return long.class;
+ else if(n instanceof Double)
+ return double.class;
+ else if(n instanceof Long)
+ return long.class;
+ else
+ throw new IllegalStateException("Unsupported Number type: " + n.getClass().getName());
+ }
+
+ public boolean canEmitPrimitive(){
+ return true;
+ }
+
+ public void emitUnboxed(C context, ObjExpr objx, GeneratorAdapter gen){
+ if(n instanceof Integer)
+ gen.push(n.longValue());
+ else if(n instanceof Double)
+ gen.push(n.doubleValue());
+ else if(n instanceof Long)
+ gen.push(n.longValue());
+ }
+
+ static public Expr parse(Number form){
+ if(form instanceof Integer
+ || form instanceof Double
+ || form instanceof Long)
+ return new NumberExpr(form);
+ else
+ return new ConstantExpr(form);
+ }
+}
+
static class ConstantExpr extends LiteralExpr{
//stuff quoted vals in classloader at compile time, pull out at runtime
//this won't work for static compilation...
@@ -3938,119 +4023,124 @@ static public class ObjExpr implements Expr{
gen.push(((Integer) value).intValue());
gen.invokeStatic(Type.getType(Integer.class), Method.getMethod("Integer valueOf(int)"));
}
+ else if(value instanceof Long)
+ {
+ gen.push(((Long) value).longValue());
+ gen.invokeStatic(Type.getType(Long.class), Method.getMethod("Long valueOf(long)"));
+ }
else if(value instanceof Double)
{
gen.push(((Double) value).doubleValue());
gen.invokeStatic(Type.getType(Double.class), Method.getMethod("Double valueOf(double)"));
}
- else if(value instanceof Character)
- {
- gen.push(((Character) value).charValue());
- gen.invokeStatic(Type.getType(Character.class), Method.getMethod("Character valueOf(char)"));
- }
- else if(value instanceof Class)
- {
- Class cc = (Class)value;
- if(cc.isPrimitive())
- {
- Type bt;
- if ( cc == boolean.class ) bt = Type.getType(Boolean.class);
- else if ( cc == byte.class ) bt = Type.getType(Byte.class);
- else if ( cc == char.class ) bt = Type.getType(Character.class);
- else if ( cc == double.class ) bt = Type.getType(Double.class);
- else if ( cc == float.class ) bt = Type.getType(Float.class);
- else if ( cc == int.class ) bt = Type.getType(Integer.class);
- else if ( cc == long.class ) bt = Type.getType(Long.class);
- else if ( cc == short.class ) bt = Type.getType(Short.class);
- else throw new RuntimeException(
- "Can't embed unknown primitive in code: " + value);
- gen.getStatic( bt, "TYPE", Type.getType(Class.class) );
- }
- else
- {
- gen.push(destubClassName(cc.getName()));
- gen.invokeStatic(Type.getType(Class.class), Method.getMethod("Class forName(String)"));
- }
- }
- else if(value instanceof Symbol)
- {
- gen.push(((Symbol) value).ns);
- gen.push(((Symbol) value).name);
- gen.invokeStatic(Type.getType(Symbol.class),
- Method.getMethod("clojure.lang.Symbol create(String,String)"));
- }
- else if(value instanceof Keyword)
- {
- emitValue(((Keyword) value).sym, gen);
- gen.invokeStatic(Type.getType(Keyword.class),
- Method.getMethod("clojure.lang.Keyword intern(clojure.lang.Symbol)"));
- }
+ else if(value instanceof Character)
+ {
+ gen.push(((Character) value).charValue());
+ gen.invokeStatic(Type.getType(Character.class), Method.getMethod("Character valueOf(char)"));
+ }
+ else if(value instanceof Class)
+ {
+ Class cc = (Class)value;
+ if(cc.isPrimitive())
+ {
+ Type bt;
+ if ( cc == boolean.class ) bt = Type.getType(Boolean.class);
+ else if ( cc == byte.class ) bt = Type.getType(Byte.class);
+ else if ( cc == char.class ) bt = Type.getType(Character.class);
+ else if ( cc == double.class ) bt = Type.getType(Double.class);
+ else if ( cc == float.class ) bt = Type.getType(Float.class);
+ else if ( cc == int.class ) bt = Type.getType(Integer.class);
+ else if ( cc == long.class ) bt = Type.getType(Long.class);
+ else if ( cc == short.class ) bt = Type.getType(Short.class);
+ else throw new RuntimeException(
+ "Can't embed unknown primitive in code: " + value);
+ gen.getStatic( bt, "TYPE", Type.getType(Class.class) );
+ }
+ else
+ {
+ gen.push(destubClassName(cc.getName()));
+ gen.invokeStatic(Type.getType(Class.class), Method.getMethod("Class forName(String)"));
+ }
+ }
+ else if(value instanceof Symbol)
+ {
+ gen.push(((Symbol) value).ns);
+ gen.push(((Symbol) value).name);
+ gen.invokeStatic(Type.getType(Symbol.class),
+ Method.getMethod("clojure.lang.Symbol create(String,String)"));
+ }
+ else if(value instanceof Keyword)
+ {
+ emitValue(((Keyword) value).sym, gen);
+ gen.invokeStatic(Type.getType(Keyword.class),
+ Method.getMethod("clojure.lang.Keyword intern(clojure.lang.Symbol)"));
+ }
// else if(value instanceof KeywordCallSite)
// {
// emitValue(((KeywordCallSite) value).k.sym, gen);
// gen.invokeStatic(Type.getType(KeywordCallSite.class),
// Method.getMethod("clojure.lang.KeywordCallSite create(clojure.lang.Symbol)"));
// }
- else if(value instanceof Var)
- {
- Var var = (Var) value;
- gen.push(var.ns.name.toString());
- gen.push(var.sym.toString());
- gen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.Var var(String,String)"));
- }
- else if(value instanceof IPersistentMap)
- {
- List entries = new ArrayList();
- for(Map.Entry entry : (Set<Map.Entry>) ((Map) value).entrySet())
- {
- entries.add(entry.getKey());
- entries.add(entry.getValue());
- }
- emitListAsObjectArray(entries, gen);
- gen.invokeStatic(RT_TYPE,
- Method.getMethod("clojure.lang.IPersistentMap map(Object[])"));
- }
- else if(value instanceof IPersistentVector)
- {
- emitListAsObjectArray(value, gen);
- gen.invokeStatic(RT_TYPE, Method.getMethod(
- "clojure.lang.IPersistentVector vector(Object[])"));
- }
- else if(value instanceof ISeq || value instanceof IPersistentList)
- {
- emitListAsObjectArray(value, gen);
- gen.invokeStatic(Type.getType(java.util.Arrays.class),
- Method.getMethod("java.util.List asList(Object[])"));
- gen.invokeStatic(Type.getType(PersistentList.class),
- Method.getMethod(
- "clojure.lang.IPersistentList create(java.util.List)"));
- }
- else
- {
- String cs = null;
- try
- {
- cs = RT.printString(value);
- //System.out.println("WARNING SLOW CODE: " + value.getClass() + " -> " + cs);
- }
- catch(Exception e)
- {
- throw new RuntimeException(
- "Can't embed object in code, maybe print-dup not defined: " +
- value);
- }
- if(cs.length() == 0)
- throw new RuntimeException(
- "Can't embed unreadable object in code: " + value);
-
- if(cs.startsWith("#<"))
- throw new RuntimeException(
- "Can't embed unreadable object in code: " + cs);
-
- gen.push(cs);
- gen.invokeStatic(RT_TYPE, readStringMethod);
- partial = false;
- }
+ else if(value instanceof Var)
+ {
+ Var var = (Var) value;
+ gen.push(var.ns.name.toString());
+ gen.push(var.sym.toString());
+ gen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.Var var(String,String)"));
+ }
+ else if(value instanceof IPersistentMap)
+ {
+ List entries = new ArrayList();
+ for(Map.Entry entry : (Set<Map.Entry>) ((Map) value).entrySet())
+ {
+ entries.add(entry.getKey());
+ entries.add(entry.getValue());
+ }
+ emitListAsObjectArray(entries, gen);
+ gen.invokeStatic(RT_TYPE,
+ Method.getMethod("clojure.lang.IPersistentMap map(Object[])"));
+ }
+ else if(value instanceof IPersistentVector)
+ {
+ emitListAsObjectArray(value, gen);
+ gen.invokeStatic(RT_TYPE, Method.getMethod(
+ "clojure.lang.IPersistentVector vector(Object[])"));
+ }
+ else if(value instanceof ISeq || value instanceof IPersistentList)
+ {
+ emitListAsObjectArray(value, gen);
+ gen.invokeStatic(Type.getType(java.util.Arrays.class),
+ Method.getMethod("java.util.List asList(Object[])"));
+ gen.invokeStatic(Type.getType(PersistentList.class),
+ Method.getMethod(
+ "clojure.lang.IPersistentList create(java.util.List)"));
+ }
+ else
+ {
+ String cs = null;
+ try
+ {
+ cs = RT.printString(value);
+ //System.out.println("WARNING SLOW CODE: " + value.getClass() + " -> " + cs);
+ }
+ catch(Exception e)
+ {
+ throw new RuntimeException(
+ "Can't embed object in code, maybe print-dup not defined: " +
+ value);
+ }
+ if(cs.length() == 0)
+ throw new RuntimeException(
+ "Can't embed unreadable object in code: " + value);
+
+ if(cs.startsWith("#<"))
+ throw new RuntimeException(
+ "Can't embed unreadable object in code: " + cs);
+
+ gen.push(cs);
+ gen.invokeStatic(RT_TYPE, readStringMethod);
+ partial = false;
+ }
if(partial)
{
@@ -4558,26 +4648,8 @@ public static class FnMethod extends ObjMethod{
try
{
Var.pushThreadBindings(RT.map(LOOP_LABEL, loopLabel, METHOD, this));
- MaybePrimitiveExpr be = (MaybePrimitiveExpr) body;
- if(Util.isPrimitive(retClass) && be.canEmitPrimitive())
- {
- if(be.getJavaClass() == retClass)
- be.emitUnboxed(C.RETURN,fn,gen);
- //todo - support the standard widening conversions
- else
- throw new IllegalArgumentException("Mismatched primitive return, expected: "
- + retClass + ", had: " + be.getJavaClass());
- }
- else
- {
- body.emit(C.RETURN, fn, gen);
- if(retClass == void.class)
- {
- gen.pop();
- }
- else
- gen.unbox(getReturnType());
- }
+ emitBody(objx, gen, retClass, body);
+
Label end = gen.mark();
for(ISeq lbs = argLocals.seq(); lbs != null; lbs = lbs.next())
{
@@ -4739,6 +4811,7 @@ abstract public static class ObjMethod{
PersistentHashSet localsUsedInCatchFinally = PersistentHashSet.EMPTY;
protected IPersistentMap methodMeta;
+
public final IPersistentMap locals(){
return locals;
}
@@ -4768,6 +4841,48 @@ abstract public static class ObjMethod{
this.objx = objx;
}
+ static void emitBody(ObjExpr objx, GeneratorAdapter gen, Class retClass, Expr body) throws Exception{
+ MaybePrimitiveExpr be = (MaybePrimitiveExpr) body;
+ if(Util.isPrimitive(retClass) && be.canEmitPrimitive())
+ {
+ Class bc = maybePrimitiveType(be);
+ if(bc == retClass)
+ be.emitUnboxed(C.RETURN, objx, gen);
+ else if(retClass == long.class && bc == int.class)
+ {
+ be.emitUnboxed(C.RETURN, objx, gen);
+ gen.visitInsn(I2L);
+ }
+ else if(retClass == double.class && bc == float.class)
+ {
+ be.emitUnboxed(C.RETURN, objx, gen);
+ gen.visitInsn(F2D);
+ }
+ else if(retClass == int.class && bc == long.class)
+ {
+ be.emitUnboxed(C.RETURN, objx, gen);
+ gen.invokeStatic(RT_TYPE, Method.getMethod("int intCast(long)"));
+ }
+ else if(retClass == float.class && bc == double.class)
+ {
+ be.emitUnboxed(C.RETURN, objx, gen);
+ gen.visitInsn(D2F);
+ }
+ else
+ throw new IllegalArgumentException("Mismatched primitive return, expected: "
+ + retClass + ", had: " + be.getJavaClass());
+ }
+ else
+ {
+ body.emit(C.RETURN, objx, gen);
+ if(retClass == void.class)
+ {
+ gen.pop();
+ }
+ else
+ gen.unbox(Type.getType(retClass));
+ }
+ }
abstract int numParams();
abstract String getMethodName();
abstract Type getReturnType();
@@ -5245,6 +5360,13 @@ public static class LetExpr implements Expr, MaybePrimitiveExpr{
if(sym.getNamespace() != null)
throw new Exception("Can't let qualified name: " + sym);
Expr init = analyze(C.EXPRESSION, bindings.nth(i + 1), sym.name);
+ if(isLoop)
+ {
+ if(maybePrimitiveType(init) == int.class)
+ init = new StaticMethodExpr("", 0, null, RT.class, "longCast", RT.vector(init));
+ else if(maybePrimitiveType(init) == float.class)
+ init = new StaticMethodExpr("", 0, null, RT.class, "doubleCast", RT.vector(init));
+ }
//sequential enhancement of env (like Lisp let*)
LocalBinding lb = registerLocal(sym, tagOf(sym), init,false);
BindingInit bi = new BindingInit(lb, init);
@@ -5389,18 +5511,47 @@ public static class RecurExpr implements Expr{
Class primc = lb.getPrimitiveType();
try
{
- if(!(arg instanceof MaybePrimitiveExpr && arg.hasJavaClass() && arg.getJavaClass() == primc))
- throw new IllegalArgumentException("recur arg for primitive local: " +
+ final Class pc = maybePrimitiveType(arg);
+ if(pc == primc)
+ ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, objx, gen);
+ else if(primc == long.class && pc == int.class)
+ {
+ ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.visitInsn(I2L);
+ }
+ else if(primc == double.class && pc == float.class)
+ {
+ ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.visitInsn(F2D);
+ }
+ else if(primc == int.class && pc == long.class)
+ {
+ ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.invokeStatic(RT_TYPE, Method.getMethod("int intCast(long)"));
+ }
+ else if(primc == float.class && pc == double.class)
+ {
+ ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, objx, gen);
+ gen.visitInsn(D2F);
+ }
+ else
+ {
+ if(RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
+ //throw new IllegalArgumentException
+ RT.errPrintWriter().println
+ ("recur arg for primitive local: " +
lb.name + " must be matching primitive, had: " +
(arg.hasJavaClass() ? arg.getJavaClass().getName():"Object") +
", needed: " +
primc.getName());
+ arg.emit(C.EXPRESSION, objx, gen);
+ HostExpr.emitUnboxArg(objx,gen,primc);
+ }
}
catch(Exception e)
{
throw new RuntimeException(e);
}
- ((MaybePrimitiveExpr) arg).emitUnboxed(C.EXPRESSION, objx, gen);
}
else
{
@@ -5501,28 +5652,28 @@ private static Expr analyze(C context, Object form, String name) throws Exceptio
return analyzeSymbol((Symbol) form);
else if(fclass == Keyword.class)
return registerKeyword((Keyword) form);
-// else if(form instanceof Num)
-// return new NumExpr((Num) form);
+ else if(form instanceof Number)
+ return NumberExpr.parse((Number) form);
else if(fclass == String.class)
return new StringExpr(((String) form).intern());
// else if(fclass == Character.class)
// return new CharExpr((Character) form);
- else if(form instanceof IPersistentCollection && ((IPersistentCollection) form).count() == 0)
- {
- Expr ret = new EmptyExpr(form);
- if(RT.meta(form) != null)
- ret = new MetaExpr(ret, MapExpr
- .parse(context == C.EVAL ? context : C.EXPRESSION, ((IObj) form).meta()));
- return ret;
- }
- else if(form instanceof ISeq)
- return analyzeSeq(context, (ISeq) form, name);
- else if(form instanceof IPersistentVector)
- return VectorExpr.parse(context, (IPersistentVector) form);
- else if(form instanceof IPersistentMap)
- return MapExpr.parse(context, (IPersistentMap) form);
- else if(form instanceof IPersistentSet)
- return SetExpr.parse(context, (IPersistentSet) form);
+ else if(form instanceof IPersistentCollection && ((IPersistentCollection) form).count() == 0)
+ {
+ Expr ret = new EmptyExpr(form);
+ if(RT.meta(form) != null)
+ ret = new MetaExpr(ret, MapExpr
+ .parse(context == C.EVAL ? context : C.EXPRESSION, ((IObj) form).meta()));
+ return ret;
+ }
+ else if(form instanceof ISeq)
+ return analyzeSeq(context, (ISeq) form, name);
+ else if(form instanceof IPersistentVector)
+ return VectorExpr.parse(context, (IPersistentVector) form);
+ else if(form instanceof IPersistentMap)
+ return MapExpr.parse(context, (IPersistentMap) form);
+ else if(form instanceof IPersistentSet)
+ return SetExpr.parse(context, (IPersistentSet) form);
// else
//throw new UnsupportedOperationException();
@@ -7004,27 +7155,7 @@ public static class NewInstanceMethod extends ObjMethod{
try
{
Var.pushThreadBindings(RT.map(LOOP_LABEL, loopLabel, METHOD, this));
- MaybePrimitiveExpr be = (MaybePrimitiveExpr) body;
- if(Util.isPrimitive(retClass) && be.canEmitPrimitive())
- {
- if(be.getJavaClass() == retClass)
- be.emitUnboxed(C.RETURN,obj,gen);
- //todo - support the standard widening conversions
- else
- throw new IllegalArgumentException("Mismatched primitive return, expected: "
- + retClass + ", had: " + be.getJavaClass());
- }
- else
- {
- body.emit(C.RETURN, obj, gen);
- if(retClass == void.class)
- {
- gen.pop();
- }
- else
- gen.unbox(retType);
- }
-
+ emitBody(objx, gen, retClass, body);
Label end = gen.mark();
gen.visitLocalVariable("this", obj.objtype.getDescriptor(), null, loopLabel, end, 0);
for(ISeq lbs = argLocals.seq(); lbs != null; lbs = lbs.next())
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java
index 409ec858..1d95c741 100644
--- a/src/jvm/clojure/lang/LispReader.java
+++ b/src/jvm/clojure/lang/LispReader.java
@@ -330,7 +330,7 @@ private static Object matchNumber(String s){
{
if(m.group(8) != null)
return BigInteger.ZERO;
- return new Long(0);
+ return Numbers.num(0);
}
boolean negate = (m.group(1).equals("-"));
String n;
diff --git a/src/jvm/clojure/lang/Numbers.java b/src/jvm/clojure/lang/Numbers.java
index bdbe1612..722791fd 100644
--- a/src/jvm/clojure/lang/Numbers.java
+++ b/src/jvm/clojure/lang/Numbers.java
@@ -151,7 +151,7 @@ static Number quotient(double n, double d){
double q = n / d;
if(q <= Long.MAX_VALUE && q >= Long.MIN_VALUE)
{
- return (long) q;
+ return box((long) q);
}
else
{ //bigint quotient
@@ -163,12 +163,12 @@ static Number remainder(double n, double d){
double q = n / d;
if(q <= Long.MAX_VALUE && q >= Long.MIN_VALUE)
{
- return (n - ((int) q) * d);
+ return Double.valueOf((n - ((int) q) * d));
}
else
{ //bigint quotient
Number bq = new BigDecimal(q).toBigInteger();
- return (n - bq.doubleValue() * d);
+ return Double.valueOf((n - bq.doubleValue() * d));
}
}
@@ -253,13 +253,32 @@ static public Number rationalize(Number x){
return x;
}
+static Number box(int val){
+ return Integer.valueOf(val);
+}
+
+static Number box(long val){
+ if(val >= Integer.MIN_VALUE && val <= Integer.MAX_VALUE)
+ return Integer.valueOf((int) val);
+ else
+ return Long.valueOf(val);
+}
+
+static Double box(double val){
+ return Double.valueOf(val);
+}
+
+static Double box(float val){
+ return Double.valueOf((double) val);
+}
+
static public Number reduceBigInteger(BigInteger val){
int bitLength = val.bitLength();
- if(bitLength < 32)
- return val.intValue();
- else
+// if(bitLength < 32)
+// return val.intValue();
+// else
if(bitLength < 64)
- return val.longValue();
+ return box(val.longValue());
else
return val;
}
@@ -269,7 +288,7 @@ static public Number divide(BigInteger n, BigInteger d){
throw new ArithmeticException("Divide by zero");
BigInteger gcd = n.gcd(d);
if(gcd.equals(BigInteger.ZERO))
- return 0;
+ return BigInteger.ZERO;
n = n.divide(gcd);
d = d.divide(gcd);
if(d.equals(BigInteger.ONE))
@@ -329,11 +348,13 @@ static public Number shiftLeft(Object x, Object n){
return bitOps(x).shiftLeft((Number)x, ((Number)n).intValue());
}
-static public int shiftLeft(int x, int n){
+static public int shiftLeftInt(int x, int n){
return x << n;
}
static public long shiftLeft(long x, int n){
+ if(n < 0)
+ return shiftRight(x, -n);
return x << n;
}
@@ -341,7 +362,13 @@ static public Number shiftRight(Object x, Object n){
return bitOps(x).shiftRight((Number)x, ((Number)n).intValue());
}
-static public int shiftRight(int x, int n){
+static public int shiftRightInt(int x, int n){
+ return x >> n;
+}
+
+static public long shiftRight(long x, int n){
+ if(n < 0)
+ return shiftLeft(x, -n);
return x >> n;
}
@@ -383,11 +410,11 @@ final static class LongOps implements Ops{
}
final public Number add(Number x, Number y){
- return Numbers.add(x.longValue(),y.longValue());
+ return box(Numbers.add(x.longValue(),y.longValue()));
}
final public Number multiply(Number x, Number y){
- return Numbers.multiply(x.longValue(),y.longValue());
+ return box(Numbers.multiply(x.longValue(), y.longValue()));
}
static long gcd(long u, long v){
@@ -405,12 +432,12 @@ final static class LongOps implements Ops{
long val = y.longValue();
long gcd = gcd(n, val);
if(gcd == 0)
- return 0;
+ return Integer.valueOf(0);
n = n / gcd;
long d = val / gcd;
if(d == 1)
- return n;
+ return box(n);
if(d < 0)
{
n = -n;
@@ -420,11 +447,11 @@ final static class LongOps implements Ops{
}
public Number quotient(Number x, Number y){
- return x.longValue() / y.longValue();
+ return box(x.longValue() / y.longValue());
}
public Number remainder(Number x, Number y){
- return x.longValue() % y.longValue();
+ return box(x.longValue() % y.longValue());
}
public boolean equiv(Number x, Number y){
@@ -438,17 +465,17 @@ final static class LongOps implements Ops{
//public Number subtract(Number x, Number y);
final public Number negate(Number x){
long val = x.longValue();
- return Numbers.minus(val);
+ return box(Numbers.minus(val));
}
public Number inc(Number x){
long val = x.longValue();
- return Numbers.inc(val);
+ return box(Numbers.inc(val));
}
public Number dec(Number x){
long val = x.longValue();
- return Numbers.dec(val);
+ return box(Numbers.dec(val));
}
}
@@ -490,15 +517,15 @@ final static class DoubleOps implements Ops{
}
final public Number add(Number x, Number y){
- return x.doubleValue() + y.doubleValue();
+ return Double.valueOf(x.doubleValue() + y.doubleValue());
}
final public Number multiply(Number x, Number y){
- return x.doubleValue() * y.doubleValue();
+ return Double.valueOf(x.doubleValue() * y.doubleValue());
}
public Number divide(Number x, Number y){
- return x.doubleValue() / y.doubleValue();
+ return Double.valueOf(x.doubleValue() / y.doubleValue());
}
public Number quotient(Number x, Number y){
@@ -519,15 +546,15 @@ final static class DoubleOps implements Ops{
//public Number subtract(Number x, Number y);
final public Number negate(Number x){
- return -x.doubleValue();
+ return Double.valueOf(-x.doubleValue());
}
public Number inc(Number x){
- return x.doubleValue() + 1;
+ return Double.valueOf(x.doubleValue() + 1);
}
public Number dec(Number x){
- return x.doubleValue() - 1;
+ return Double.valueOf(x.doubleValue() - 1);
}
}
@@ -846,42 +873,42 @@ final static class LongBitOps implements BitOps{
}
public Number not(Number x){
- return ~x.longValue();
+ return box(~x.longValue());
}
public Number and(Number x, Number y){
- return x.longValue() & y.longValue();
+ return box(x.longValue() & y.longValue());
}
public Number or(Number x, Number y){
- return x.longValue() | y.longValue();
+ return box(x.longValue() | y.longValue());
}
public Number xor(Number x, Number y){
- return x.longValue() ^ y.longValue();
+ return box(x.longValue() ^ y.longValue());
}
public Number andNot(Number x, Number y){
- return x.longValue() & ~y.longValue();
+ return box(x.longValue() & ~y.longValue());
}
public Number clearBit(Number x, int n){
if(n < 63)
- return x.longValue() & ~(1L << n);
+ return (box(x.longValue() & ~(1L << n)));
else
return toBigInteger(x).clearBit(n);
}
public Number setBit(Number x, int n){
if(n < 63)
- return x.longValue() | (1L << n);
+ return box(x.longValue() | (1L << n));
else
return toBigInteger(x).setBit(n);
}
public Number flipBit(Number x, int n){
if(n < 63)
- return x.longValue() ^ (1L << n);
+ return box(x.longValue() ^ (1L << n));
else
return toBigInteger(x).flipBit(n);
}
@@ -896,13 +923,13 @@ final static class LongBitOps implements BitOps{
public Number shiftLeft(Number x, int n){
if(n < 0)
return shiftRight(x, -n);
- return Numbers.shiftLeft(x.longValue(),n);
+ return box(Numbers.shiftLeft(x.longValue(), n));
}
public Number shiftRight(Number x, int n){
if(n < 0)
return shiftLeft(x, -n);
- return x.longValue() >> n;
+ return box(x.longValue() >> n);
}
}
@@ -1319,71 +1346,71 @@ static public Number num(Object x){
}
static public Number num(float x){
- return x;
+ return Double.valueOf(x);
}
-static public float add(float x, float y){
- return x + y;
-}
-
-static public float minus(float x, float y){
- return x - y;
-}
+//static public float add(float x, float y){
+// return x + y;
+//}
+//
+//static public float minus(float x, float y){
+// return x - y;
+//}
-static public float minus(float x){
- return -x;
-}
+//static public float minus(float x){
+// return -x;
+//}
-static public float inc(float x){
- return x + 1;
-}
+//static public float inc(float x){
+// return x + 1;
+//}
-static public float dec(float x){
- return x - 1;
-}
+//static public float dec(float x){
+// return x - 1;
+//}
-static public float multiply(float x, float y){
- return x * y;
-}
+//static public float multiply(float x, float y){
+// return x * y;
+//}
-static public float divide(float x, float y){
- return x / y;
-}
+//static public float divide(float x, float y){
+// return x / y;
+//}
-static public boolean equiv(float x, float y){
- return x == y;
-}
+//static public boolean equiv(float x, float y){
+// return x == y;
+//}
-static public boolean lt(float x, float y){
- return x < y;
-}
+//static public boolean lt(float x, float y){
+// return x < y;
+//}
-static public boolean lte(float x, float y){
- return x <= y;
-}
+//static public boolean lte(float x, float y){
+// return x <= y;
+//}
-static public boolean gt(float x, float y){
- return x > y;
-}
+//static public boolean gt(float x, float y){
+// return x > y;
+//}
-static public boolean gte(float x, float y){
- return x >= y;
-}
+//static public boolean gte(float x, float y){
+// return x >= y;
+//}
-static public boolean isPos(float x){
- return x > 0;
-}
+//static public boolean isPos(float x){
+// return x > 0;
+//}
-static public boolean isNeg(float x){
- return x < 0;
-}
+//static public boolean isNeg(float x){
+// return x < 0;
+//}
-static public boolean isZero(float x){
- return x == 0;
-}
+//static public boolean isZero(float x){
+// return x == 0;
+//}
static public Number num(double x){
- return x;
+ return Double.valueOf(x);
}
static public double add(double x, double y){
@@ -1451,168 +1478,168 @@ static int throwIntOverflow(){
}
static public Number num(int x){
- return x;
+ return Integer.valueOf(x);
}
-static public int unchecked_add(int x, int y){
+static public int unchecked_int_add(int x, int y){
return x + y;
}
-static public int unchecked_subtract(int x, int y){
+static public int unchecked_int_subtract(int x, int y){
return x - y;
}
-static public int unchecked_negate(int x){
+static public int unchecked_int_negate(int x){
return -x;
}
-static public int unchecked_inc(int x){
+static public int unchecked_int_inc(int x){