diff options
-rw-r--r-- | clojure.markdown | 2 | ||||
-rw-r--r-- | src/boot.clj | 5 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 35 |
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)
|