Skip to content

Commit ffd9e78

Browse files
author
Dimitry Gashinsky
committed
Merge branch 'master' of git://github.com/richhickey/clojure
2 parents b8ef94f + 5f96d1c commit ffd9e78

File tree

4 files changed

+84
-26
lines changed

4 files changed

+84
-26
lines changed

pom-template.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<project xmlns="http://maven.apache.org/POM/4.0.0"
33
xmlns:xsi="http//www.w3.org/2001/XMLSchema-instance"
4-
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5+
http://maven.apache.org/maven-v4_0_0.xsd">
56
<modelVersion>4.0.0</modelVersion>
67
<groupId>org.clojure</groupId>
7-
<artifactId>clojure-lang</artifactId>
8-
<name>clojure-lang</name>
8+
<artifactId>clojure</artifactId>
9+
<name>clojure</name>
910
<version>@clojure-version@</version>
1011
<url>http://clojure.org/</url>
1112

src/clj/clojure/core.clj

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,8 +1074,9 @@
10741074
second item in the first form, making a list of it if it is not a
10751075
list already. If there are more forms, inserts the first form as the
10761076
second item in second form, etc."
1077+
([x] x)
10771078
([x form] (if (seq? form)
1078-
`(~(first form) ~x ~@(next form))
1079+
(with-meta `(~(first form) ~x ~@(next form)) (meta form))
10791080
(list form x)))
10801081
([x form & more] `(-> (-> ~x ~form) ~@more)))
10811082

@@ -1085,7 +1086,7 @@
10851086
list already. If there are more forms, inserts the first form as the
10861087
last item in second form, etc."
10871088
([x form] (if (seq? form)
1088-
`(~(first form) ~@(next form) ~x)
1089+
(with-meta `(~(first form) ~@(next form) ~x) (meta form))
10891090
(list form x)))
10901091
([x form & more] `(->> (->> ~x ~form) ~@more)))
10911092

@@ -1253,6 +1254,42 @@
12531254
(finally
12541255
(pop-thread-bindings))))))
12551256

1257+
(defn with-bindings*
1258+
"Takes a map of Var/value pairs. Installs for the given Vars the associated
1259+
values as thread-local bindings. Then calls f with the supplied arguments.
1260+
Pops the installed bindings after f returned. Returns whatever f returns."
1261+
[binding-map f & args]
1262+
(push-thread-bindings binding-map)
1263+
(try
1264+
(apply f args)
1265+
(finally
1266+
(pop-thread-bindings))))
1267+
1268+
(defmacro with-bindings
1269+
"Takes a map of Var/value pairs. Installs for the given Vars the associated
1270+
values as thread-local bindings. The executes body. Pops the installed
1271+
bindings after body was evaluated. Returns the value of body."
1272+
[binding-map & body]
1273+
`(with-bindings* ~binding-map (fn [] ~@body)))
1274+
1275+
(defn bound-fn*
1276+
"Returns a function, which will install the same bindings in effect as in
1277+
the thread at the time bound-fn* was called and then call f with any given
1278+
arguments. This may be used to define a helper function which runs on a
1279+
different thread, but needs the same bindings in place."
1280+
[f]
1281+
(let [bindings (get-thread-bindings)]
1282+
(fn [& args]
1283+
(apply with-bindings* bindings f args))))
1284+
1285+
(defmacro bound-fn
1286+
"Returns a function defined by the given fntail, which will install the
1287+
same bindings in effect as in the thread at the time bound-fn was called.
1288+
This may be used to define a helper function which runs on a different
1289+
thread, but needs the same bindings in place."
1290+
[& fntail]
1291+
`(bound-fn* (fn ~@fntail)))
1292+
12561293
(defn find-var
12571294
"Returns the global var named by the namespace-qualified symbol, or
12581295
nil if no var with that name."

src/clj/clojure/main.clj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
;; Originally contributed by Stephen C. Gilardi
1010

1111
(ns clojure.main
12+
(:refer-clojure :exclude [with-bindings])
1213
(:import (clojure.lang Compiler Compiler$CompilerException
1314
LineNumberingPushbackReader RT)))
1415

src/jvm/clojure/lang/Compiler.java

Lines changed: 40 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -791,24 +791,26 @@ else if(instance != null && instance.hasJavaClass() && instance.getJavaClass() !
791791
if(maybeField) //field
792792
{
793793
Symbol sym = (Symbol) RT.third(form);
794-
if(c != null)
795-
return new StaticFieldExpr(line, c, sym.name);
796-
else
797-
return new InstanceFieldExpr(line, instance, sym.name);
794+
Symbol tag = tagOf(form);
795+
if(c != null) {
796+
return new StaticFieldExpr(line, c, sym.name, tag);
797+
} else
798+
return new InstanceFieldExpr(line, instance, sym.name, tag);
798799
}
799800
else
800801
{
801802
ISeq call = (ISeq) ((RT.third(form) instanceof ISeq) ? RT.third(form) : RT.next(RT.next(form)));
802803
if(!(RT.first(call) instanceof Symbol))
803804
throw new IllegalArgumentException("Malformed member expression");
804805
Symbol sym = (Symbol) RT.first(call);
806+
Symbol tag = tagOf(form);
805807
PersistentVector args = PersistentVector.EMPTY;
806808
for(ISeq s = RT.next(call); s != null; s = s.next())
807809
args = args.cons(analyze(context == C.EVAL ? context : C.EXPRESSION, s.first()));
808810
if(c != null)
809-
return new StaticMethodExpr(source, line, c, sym.name, args);
811+
return new StaticMethodExpr(source, line, tag, c, sym.name, args);
810812
else
811-
return new InstanceMethodExpr(source, line, instance, sym.name, args);
813+
return new InstanceMethodExpr(source, line, tag, instance, sym.name, args);
812814
}
813815
}
814816
}
@@ -901,16 +903,18 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{
901903
public final java.lang.reflect.Field field;
902904
public final String fieldName;
903905
public final int line;
906+
public final Symbol tag;
904907
final static Method invokeNoArgInstanceMember = Method.getMethod("Object invokeNoArgInstanceMember(Object,String)");
905908
final static Method setInstanceFieldMethod = Method.getMethod("Object setInstanceField(Object,String,Object)");
906909

907910

908-
public InstanceFieldExpr(int line, Expr target, String fieldName) throws Exception{
911+
public InstanceFieldExpr(int line, Expr target, String fieldName, Symbol tag) throws Exception{
909912
this.target = target;
910913
this.targetClass = target.hasJavaClass() ? target.getJavaClass() : null;
911914
this.field = targetClass != null ? Reflector.getField(targetClass, fieldName, false) : null;
912915
this.fieldName = fieldName;
913916
this.line = line;
917+
this.tag = tag;
914918
if(field == null && RT.booleanCast(RT.WARN_ON_REFLECTION.deref()))
915919
{
916920
((PrintWriter) RT.ERR.deref())
@@ -960,11 +964,11 @@ public void emit(C context, FnExpr fn, GeneratorAdapter gen){
960964
}
961965

962966
public boolean hasJavaClass() throws Exception{
963-
return field != null;
967+
return field != null || tag != null;
964968
}
965969

966970
public Class getJavaClass() throws Exception{
967-
return field.getType();
971+
return tag != null ? HostExpr.tagToClass(tag) : field.getType();
968972
}
969973

970974
public Object evalAssign(Expr val) throws Exception{
@@ -1000,17 +1004,19 @@ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{
10001004
public final String fieldName;
10011005
public final Class c;
10021006
public final java.lang.reflect.Field field;
1007+
public final Symbol tag;
10031008
// final static Method getStaticFieldMethod = Method.getMethod("Object getStaticField(String,String)");
10041009
// final static Method setStaticFieldMethod = Method.getMethod("Object setStaticField(String,String,Object)");
10051010
final int line;
10061011

1007-
public StaticFieldExpr(int line, Class c, String fieldName) throws Exception{
1012+
public StaticFieldExpr(int line, Class c, String fieldName, Symbol tag) throws Exception{
10081013
//this.className = className;
10091014
this.fieldName = fieldName;
10101015
this.line = line;
10111016
//c = Class.forName(className);
10121017
this.c = c;
10131018
field = c.getField(fieldName);
1019+
this.tag = tag;
10141020
}
10151021

10161022
public Object eval() throws Exception{
@@ -1044,7 +1050,7 @@ public boolean hasJavaClass(){
10441050
public Class getJavaClass() throws Exception{
10451051
//Class c = Class.forName(className);
10461052
//java.lang.reflect.Field field = c.getField(fieldName);
1047-
return field.getType();
1053+
return tag != null ? HostExpr.tagToClass(tag) : field.getType();
10481054
}
10491055

10501056
public Object evalAssign(Expr val) throws Exception{
@@ -1127,19 +1133,21 @@ static class InstanceMethodExpr extends MethodExpr{
11271133
public final IPersistentVector args;
11281134
public final String source;
11291135
public final int line;
1136+
public final Symbol tag;
11301137
public final java.lang.reflect.Method method;
11311138

11321139
final static Method invokeInstanceMethodMethod =
11331140
Method.getMethod("Object invokeInstanceMethod(Object,String,Object[])");
11341141

11351142

1136-
public InstanceMethodExpr(String source, int line, Expr target, String methodName, IPersistentVector args)
1143+
public InstanceMethodExpr(String source, int line, Symbol tag, Expr target, String methodName, IPersistentVector args)
11371144
throws Exception{
11381145
this.source = source;
11391146
this.line = line;
11401147
this.args = args;
11411148
this.methodName = methodName;
11421149
this.target = target;
1150+
this.tag = tag;
11431151
if(target.hasJavaClass() && target.getJavaClass() != null)
11441152
{
11451153
List methods = Reflector.getMethods(target.getJavaClass(), args.count(), methodName, false);
@@ -1269,11 +1277,11 @@ public void emit(C context, FnExpr fn, GeneratorAdapter gen){
12691277
}
12701278

12711279
public boolean hasJavaClass(){
1272-
return method != null;
1280+
return method != null || tag != null;
12731281
}
12741282

12751283
public Class getJavaClass() throws Exception{
1276-
return method.getReturnType();
1284+
return tag != null ? HostExpr.tagToClass(tag) : method.getReturnType();
12771285
}
12781286
}
12791287

@@ -1286,18 +1294,20 @@ static class StaticMethodExpr extends MethodExpr{
12861294
public final String source;
12871295
public final int line;
12881296
public final java.lang.reflect.Method method;
1297+
public final Symbol tag;
12891298
final static Method forNameMethod = Method.getMethod("Class forName(String)");
12901299
final static Method invokeStaticMethodMethod =
12911300
Method.getMethod("Object invokeStaticMethod(Class,String,Object[])");
12921301

12931302

1294-
public StaticMethodExpr(String source, int line, Class c, String methodName, IPersistentVector args)
1303+
public StaticMethodExpr(String source, int line, Symbol tag, Class c, String methodName, IPersistentVector args)
12951304
throws Exception{
12961305
this.c = c;
12971306
this.methodName = methodName;
12981307
this.args = args;
12991308
this.source = source;
13001309
this.line = line;
1310+
this.tag = tag;
13011311

13021312
List methods = Reflector.getMethods(c, args.count(), methodName, true);
13031313
if(methods.isEmpty())
@@ -1402,11 +1412,11 @@ public void emit(C context, FnExpr fn, GeneratorAdapter gen){
14021412
}
14031413

14041414
public boolean hasJavaClass(){
1405-
return method != null;
1415+
return method != null || tag != null;
14061416
}
14071417

14081418
public Class getJavaClass() throws Exception{
1409-
return method.getReturnType();
1419+
return tag != null ? HostExpr.tagToClass(tag) : method.getReturnType();
14101420
}
14111421
}
14121422

@@ -4468,6 +4478,15 @@ public static boolean namesStaticMember(Symbol sym){
44684478
return sym.ns != null && namespaceFor(sym) == null;
44694479
}
44704480

4481+
public static Object preserveTag(ISeq src, Object dst) {
4482+
Symbol tag = tagOf(src);
4483+
if (tag != null && dst instanceof IObj) {
4484+
IPersistentMap meta = RT.meta(dst);
4485+
return ((IObj) dst).withMeta((IPersistentMap) RT.assoc(meta, RT.TAG_KEY, tag));
4486+
}
4487+
return dst;
4488+
}
4489+
44714490
public static Object macroexpand1(Object x) throws Exception{
44724491
if(x instanceof ISeq)
44734492
{
@@ -4507,7 +4526,7 @@ public static Object macroexpand1(Object x) throws Exception{
45074526
{
45084527
target = ((IObj)RT.list(IDENTITY, target)).withMeta(RT.map(RT.TAG_KEY,CLASS));
45094528
}
4510-
return RT.listStar(DOT, target, meth, form.next().next());
4529+
return preserveTag(form, RT.listStar(DOT, target, meth, form.next().next()));
45114530
}
45124531
else if(namesStaticMember(sym))
45134532
{
@@ -4516,7 +4535,7 @@ else if(namesStaticMember(sym))
45164535
if(c != null)
45174536
{
45184537
Symbol meth = Symbol.intern(sym.name);
4519-
return RT.listStar(DOT, target, meth, form.next());
4538+
return preserveTag(form, RT.listStar(DOT, target, meth, form.next()));
45204539
}
45214540
}
45224541
else
@@ -4565,7 +4584,7 @@ private static Expr analyzeSeq(C context, ISeq form, String name) throws Excepti
45654584
throw new IllegalArgumentException("Can't call nil");
45664585
IFn inline = isInline(op, RT.count(RT.next(form)));
45674586
if(inline != null)
4568-
return analyze(context, inline.applyTo(RT.next(form)));
4587+
return analyze(context, preserveTag(form, inline.applyTo(RT.next(form))));
45694588
IParser p;
45704589
if(op.equals(FN))
45714590
return FnExpr.parse(context, form, name);
@@ -4689,7 +4708,7 @@ private static Expr analyzeSymbol(Symbol sym) throws Exception{
46894708
if(c != null)
46904709
{
46914710
if(Reflector.getField(c, sym.name, true) != null)
4692-
return new StaticFieldExpr((Integer) LINE.deref(), c, sym.name);
4711+
return new StaticFieldExpr((Integer) LINE.deref(), c, sym.name, tag);
46934712
throw new Exception("Unable to find static field: " + sym.name + " in " + c);
46944713
}
46954714
}

0 commit comments

Comments
 (0)