From 2a39dfe6d8b5b0f31853d5317fdafb21fa69692a Mon Sep 17 00:00:00 2001 From: Chas Emerick Date: Fri, 1 Feb 2013 13:28:01 -0500 Subject: [PATCH] CLJ-1153: default *read-eval* to false --- src/clj/clojure/core.clj | 6 +-- src/jvm/clojure/lang/Compiler.java | 85 ++++++++++++++++++++++---------- src/jvm/clojure/lang/RT.java | 2 +- test/clojure/test_clojure/evaluation.clj | 4 +- 4 files changed, 65 insertions(+), 32 deletions(-) diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 923b63a..2714fb8 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -5871,11 +5871,11 @@ {:added "1.0"}) (add-doc-and-meta *read-eval* - "When set to logical false, the EvalReader (#=(...)) is disabled in the + "When set to logical true, the EvalReader (#=(...)) is enabled in the read/load in the thread-local binding. - Example: (binding [*read-eval* false] (read-string \"#=(eval (def x 3))\")) + Example: (binding [*read-eval* true] (read-string \"#=(eval (def x 3))\")) - Defaults to true" + Defaults to false" {:added "1.0"}) (defn future? diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 263a1b8..e4e7e92 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -21,6 +21,8 @@ import clojure.asm.commons.Method; import java.io.*; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; +import java.math.BigDecimal; +import java.math.BigInteger; import java.util.*; import java.util.regex.Pattern; @@ -4432,6 +4434,36 @@ static public class ObjExpr implements Expr{ gen.push(((Character) value).charValue()); gen.invokeStatic(Type.getType(Character.class), Method.getMethod("Character valueOf(char)")); } + else if(value instanceof BigInteger) + { + gen.newInstance(Type.getType(BigInteger.class)); + gen.dup(); + gen.push(((BigInteger)value).toString()); + gen.invokeConstructor(Type.getType(BigInteger.class), + Method.getMethod("void (String)")); + } + else if(value instanceof BigDecimal) + { + gen.newInstance(Type.getType(BigDecimal.class)); + gen.dup(); + gen.push(((BigDecimal)value).toString()); + gen.invokeConstructor(Type.getType(BigDecimal.class), + Method.getMethod("void (String)")); + } + else if(value instanceof BigInt) + { + emitValue(((BigInt)value).toBigInteger(), gen); + gen.invokeStatic(Type.getType(BigInt.class), Method.getMethod("clojure.lang.BigInt fromBigInteger(java.math.BigInteger)")); + } + else if(value instanceof Ratio) + { + gen.newInstance(Type.getType(Ratio.class)); + gen.dup(); + emitValue(((Ratio)value).numerator, gen); + emitValue(((Ratio)value).denominator, gen); + gen.invokeConstructor(Type.getType(Ratio.class), + Method.getMethod("void (java.math.BigInteger, java.math.BigInteger)")); + } else if(value instanceof Class) { Class cc = (Class)value; @@ -4558,6 +4590,23 @@ static public class ObjExpr implements Expr{ gen.invokeStatic(Type.getType(Pattern.class), Method.getMethod("java.util.regex.Pattern compile(String)")); } + else if(value instanceof Namespace) + { + gen.push(((Namespace)value).name.ns); + gen.push(((Namespace)value).name.name); + gen.invokeStatic(Type.getType(Symbol.class), + Method.getMethod("clojure.lang.Symbol intern(String,String)")); + gen.invokeStatic(Type.getType(Namespace.class), + Method.getMethod("clojure.lang.Namespace find(clojure.lang.Symbol)")); + } + else if(value instanceof clojure.lang.Fn) + { + // e.g. (eval (list + 1 2 3)) + gen.newInstance(Type.getType(value.getClass())); + gen.dup(); + gen.invokeConstructor(Type.getType(value.getClass()), + new Method("", Type.getConstructorDescriptor(value.getClass().getConstructors()[0]))); + } else { String cs = null; @@ -4569,7 +4618,7 @@ static public class ObjExpr implements Expr{ catch(Exception e) { throw Util.runtimeException( - "Can't embed object in code, maybe print-dup not defined: " + + "Can't embed object in code, maybe print-method not defined: " + value); } if(cs.length() == 0) @@ -4601,20 +4650,11 @@ static public class ObjExpr implements Expr{ void emitConstants(GeneratorAdapter clinitgen){ - try - { - Var.pushThreadBindings(RT.map(RT.PRINT_DUP, RT.T)); - - for(int i = 0; i < constants.count(); i++) - { - emitValue(constants.nth(i), clinitgen); - clinitgen.checkCast(constantType(i)); - clinitgen.putStatic(objtype, constantName(i), constantType(i)); - } - } - finally + for(int i = 0; i < constants.count(); i++) { - Var.popThreadBindings(); + emitValue(constants.nth(i), clinitgen); + clinitgen.checkCast(constantType(i)); + clinitgen.putStatic(objtype, constantName(i), constantType(i)); } } @@ -7240,20 +7280,11 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t null, cv); clinitgen.visitCode(); - try + for(int i = n*INITS_PER; i < objx.constants.count() && i < (n+1)*INITS_PER; i++) { - Var.pushThreadBindings(RT.map(RT.PRINT_DUP, RT.T)); - - for(int i = n*INITS_PER; i < objx.constants.count() && i < (n+1)*INITS_PER; i++) - { - objx.emitValue(objx.constants.nth(i), clinitgen); - clinitgen.checkCast(objx.constantType(i)); - clinitgen.putStatic(objx.objtype, objx.constantName(i), objx.constantType(i)); - } - } - finally - { - Var.popThreadBindings(); + objx.emitValue(objx.constants.nth(i), clinitgen); + clinitgen.checkCast(objx.constantType(i)); + clinitgen.putStatic(objx.objtype, objx.constantName(i), objx.constantType(i)); } clinitgen.returnValue(); clinitgen.endMethod(); diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index cea1bb5..fafa075 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -181,7 +181,7 @@ final static public Var ERR = final static Keyword TAG_KEY = Keyword.intern(null, "tag"); final static Keyword CONST_KEY = Keyword.intern(null, "const"); final static public Var AGENT = Var.intern(CLOJURE_NS, Symbol.intern("*agent*"), null).setDynamic(); -final static public Var READEVAL = Var.intern(CLOJURE_NS, Symbol.intern("*read-eval*"), T).setDynamic(); +final static public Var READEVAL = Var.intern(CLOJURE_NS, Symbol.intern("*read-eval*"), F).setDynamic(); final static public Var DATA_READERS = Var.intern(CLOJURE_NS, Symbol.intern("*data-readers*"), RT.map()).setDynamic(); final static public Var DEFAULT_DATA_READER_FN = Var.intern(CLOJURE_NS, Symbol.intern("*default-data-reader-fn*"), RT.map()).setDynamic(); final static public Var DEFAULT_DATA_READERS = Var.intern(CLOJURE_NS, Symbol.intern("default-data-readers"), RT.map()); diff --git a/test/clojure/test_clojure/evaluation.clj b/test/clojure/test_clojure/evaluation.clj index 62609ee..fb73aed 100644 --- a/test/clojure/test_clojure/evaluation.clj +++ b/test/clojure/test_clojure/evaluation.clj @@ -40,7 +40,9 @@ (is (= (eval '(list + 1 2 3)) (list clojure.core/+ 1 2 3))) (test-that "Non-closure fns are supported as code" (is (= (eval (eval '(list + 1 2 3))) 6))) - (is (= (eval (list '+ 1 2 3)) 6))) + (is (= (eval (list '+ 1 2 3)) 6)) + (test-that "boxed numerics are supported as code" + (is (= 4.5M (eval (list + 1N 2.0M 3/2)))))) ; not using Clojure's RT/classForName since a bug in it could hide a bug in ; eval's resolution -- 1.8.0