summaryrefslogtreecommitdiff
path: root/src/jvm
diff options
context:
space:
mode:
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){
return x + 1;
}
-static public int unchecked_dec(int x){
+static public int unchecked_int_dec(int x){
return x - 1;
}
-static public int unchecked_multiply(int x, int y){
+static public int unchecked_int_multiply(int x, int y){
return x * y;
}
-static public int add(int x, int y){
- int ret = x + y;
- if ((ret ^ x) < 0 && (ret ^ y) < 0)
- return throwIntOverflow();
- return ret;
-}
+//static public int add(int x, int y){
+// int ret = x + y;
+// if ((ret ^ x) < 0 && (ret ^ y) < 0)
+// return throwIntOverflow();
+// return ret;
+//}
-static public int not(int x){
- return ~x;
-}
+//static public int not(int x){
+// return ~x;
+//}
static public long not(long x){
return ~x;
}
-static public int and(int x, int y){
- return x & y;
-}
+//static public int and(int x, int y){
+// return x & y;
+//}
static public long and(long x, long y){