summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clojure.markdown2
-rw-r--r--src/boot.clj5
-rw-r--r--src/jvm/clojure/lang/LispReader.java35
3 files changed, 35 insertions, 7 deletions
diff --git a/clojure.markdown b/clojure.markdown
index c3280e09..31d3aa54 100644
--- a/clojure.markdown
+++ b/clojure.markdown
@@ -642,7 +642,7 @@ Thus within-thread bindings obey a stack discipline:
</code></pre>
-Bindings created with `binding` cannot be seen by any other thread. Bindings created with `binding` can be assigned to, which provides a means for nested contexts to communicate up the call stack.
+Bindings created with `binding` cannot be seen by any other thread. Bindings created with `binding` can be assigned to, which provides a means for nested contexts to communicate with code above it the call stack.
Functions defined with `defn` are stored in Vars, allowing for the re-definition of functions in a running program. This also enables many of the possibilities of aspect- or context-oriented programming. For instance, you could wrap a function with logging behavior only in certain call contexts or threads.
diff --git a/src/boot.clj b/src/boot.clj
index 0e6873f1..b1dbe2ab 100644
--- a/src/boot.clj
+++ b/src/boot.clj
@@ -109,9 +109,8 @@
([] nil)
([x] x)
([x & rest]
- (let [gor (gensym "or__")]
- `(let [~gor ~x]
- (if ~gor ~gor (or ~@rest))))))
+ `(let [or# ~x]
+ (if or# or# (or ~@rest)))))
;;math stuff
(defn +
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java
index 94789d00..3c6a250e 100644
--- a/src/jvm/clojure/lang/LispReader.java
+++ b/src/jvm/clojure/lang/LispReader.java
@@ -46,6 +46,9 @@ static final Symbol SLASH = Symbol.create("/");
//static Pattern staticMemberPat = Pattern.compile("([a-zA-Z_][\\w\\.]*)\\.([a-zA-Z_]\\w*)");
//static Pattern classNamePat = Pattern.compile("([a-zA-Z_][\\w\\.]*)\\.");
+//symbol->gensymbol
+static Var GENSYM_ENV = Var.create(null);
+
static
{
macros['"'] = new StringReader();
@@ -351,9 +354,18 @@ static class MetaReader extends AFn{
static class SyntaxQuoteReader extends AFn{
public Object invoke(Object reader, Object backquote) throws Exception{
PushbackReader r = (PushbackReader) reader;
- Object form = read(r, true, null, true);
+ try
+ {
+ Var.pushThreadBindings(
+ RT.map(GENSYM_ENV, PersistentHashMap.EMPTY));
- return syntaxQuote(form);
+ Object form = read(r, true, null, true);
+ return syntaxQuote(form);
+ }
+ finally
+ {
+ Var.popThreadBindings();
+ }
}
static Object syntaxQuote(Object form) throws Exception{
@@ -361,7 +373,24 @@ static class SyntaxQuoteReader extends AFn{
if(Compiler.isSpecial(form))
ret = RT.list(Compiler.QUOTE, form);
else if(form instanceof Symbol)
- ret = RT.list(Compiler.QUOTE, Compiler.resolveSymbol((Symbol) form));
+ {
+ Symbol sym = (Symbol) form;
+ if(sym.ns == null && sym.name.endsWith("#"))
+ {
+ IPersistentMap gmap = (IPersistentMap) GENSYM_ENV.get();
+ if(gmap == null)
+ throw new IllegalStateException("Gensym literal not in syntax-quote");
+ Symbol gs = (Symbol) gmap.valAt(sym);
+ if(gs == null)
+ GENSYM_ENV.set(gmap.assoc(sym, gs = Symbol.intern(null,
+ sym.name.substring(0, sym.name.length() - 1)
+ + "_" + RT.nextID())));
+ sym = gs;
+ }
+ else
+ sym = Compiler.resolveSymbol(sym);
+ ret = RT.list(Compiler.QUOTE, sym);
+ }
else if(form instanceof Unquote)
return ((Unquote) form).o;
else if(form instanceof UnquoteSplicing)