diff options
author | Rich Hickey <richhickey@gmail.com> | 2007-09-11 12:59:32 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2007-09-11 12:59:32 +0000 |
commit | d4d0a25f1da9d71fe1fd737eb2a59a710ad59413 (patch) | |
tree | a632628378f6b32e3ea711d1d677f0a9649c2373 /src | |
parent | f78d8b3fe57b7eee920a1566f7207708d84a8a3f (diff) |
syntax quoting
Diffstat (limited to 'src')
-rw-r--r-- | src/boot.clj | 120 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 107 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LispReader.java | 17 |
3 files changed, 76 insertions, 168 deletions
diff --git a/src/boot.clj b/src/boot.clj index 49533032..213b70a0 100644 --- a/src/boot.clj +++ b/src/boot.clj @@ -4,30 +4,23 @@ (def defn (fn [name & fdecl] (list 'def name (cons 'fn fdecl)))) -;(def defn (fn [name & fdecl] -; `(def ~name (fn ~@fdecl)))) - (. (the-var defn) (setMacro)) -(def syntax-quote (fn [form] - (. clojure.lang.Compiler (syntaxQuote form)))) - -(. (the-var syntax-quote) (setMacro)) - -(defn contains [coll key] - (. RT (contains coll key))) - -(defn get [coll key] - (. RT (get coll key))) +(defn vector + ([] []) + ([& args] + (. clojure.lang.PersistentVector (create args)))) -(defn assoc [coll key val] - (. RT (assoc coll key val))) +(defn hashmap + ([] {}) + ([& args] + (. clojure.lang.PersistentHashMap (create args)))) -(defn dissoc [coll key] - (. RT (dissoc coll key))) +(defn meta [x] + (. x (meta))) -(defn count [coll] - (. RT (count coll))) +(defn with-meta [x m] + (. x (withMeta m))) (def defmacro (fn [name & args] (list 'do @@ -44,11 +37,6 @@ (def t (. RT T)) -(defn vector - ([] []) - ([& args] - (. clojure.lang.PersistentVector (create args)))) - (defn nil? [x] (if x nil t)) (defn not [x] (nil? x)) @@ -75,31 +63,49 @@ (second clauses) (cons 'cond (rest (rest clauses)))))) -(defmacro and - ([] t) - ([x] x) - ([x & rest] (list 'if x (cons 'and rest)))) - -(defmacro or - ([] nil) - ([x] x) - ([x & rest] - (let [gor (gensym "or__")] - (list 'let (vector gor x) - (list 'if gor gor (cons 'or rest)))))) - (defn spread [arglist] (cond (nil? arglist) nil (nil? (rest arglist)) (first arglist) :else (cons (first arglist) (thisfn (rest arglist))))) - + (defn apply [f & args] (. f (applyTo (spread args)))) (defn list* [& args] (spread args)) +(defmacro delay [& body] + (list '. 'clojure.lang.Delay (list 'new (list* 'fn [] body)))) + +(defmacro lazy-cons [x & body] + (list '. 'clojure.lang.FnSeq (list 'new x (list* 'delay body)))) + +(defn concat + ([] nil) + ([x & xs] + (cond + (nil? xs) x + (nil? x) (recur (first xs) (rest xs)) + :else (lazy-cons (first x) (apply concat (rest x) xs))))) + +;;at this point all the support for syntax-quote exists + +(defmacro and + ([] t) + ([x] x) + ([x & rest] `(if ~x (and ~@rest)))) + +(defmacro or + ([] nil) + ([x] x) + ([x & rest] + (let [gor (gensym "or__")] + `(let [~gor ~x] + (if ~gor ~gor (or ~@rest)))))) + + +;;math stuff (defn + ([] 0) ([x] x) @@ -180,26 +186,23 @@ (defn identity [x] x) -(defmacro locking [x & body] - (let [gsym (gensym)] - (list 'let [gsym x] - (list 'try-finally - (cons 'do (cons (list 'monitor-enter gsym) body)) - (list 'monitor-exit gsym))))) +;;map stuff -(defmacro delay [& body] - (list '. 'clojure.lang.Delay (list 'new (list* 'fn [] body)))) +(defn contains [coll key] + (. RT (contains coll key))) -(defmacro lazy-cons [x & body] - (list '. 'clojure.lang.FnSeq (list 'new x (list* 'delay body)))) +(defn get [coll key] + (. RT (get coll key))) + +(defn assoc [coll key val] + (. RT (assoc coll key val))) + +(defn dissoc [coll key] + (. RT (dissoc coll key))) + +(defn count [coll] + (. RT (count coll))) -(defn concat - ([] nil) - ([x & xs] - (cond - (nil? xs) x - (nil? x) (recur (first xs) (rest xs)) - :else (lazy-cons (first x) (apply concat (rest x) xs))))) (defn andfn [& args] (if (nil? (rest args)) @@ -211,3 +214,10 @@ nil (or (first args) (recur (rest args))))) + +(defmacro locking [x & body] + (let [gsym (gensym)] + `(let [~gsym ~x] + (try-finally + (do (monitor-enter ~gsym) ~@body) + (monitor-exit ~gsym)))))
\ No newline at end of file diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 8be6b813..f0ebf1bc 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -46,7 +46,7 @@ static final Symbol THISFN = Symbol.create("thisfn"); static final Symbol CLASS = Symbol.create("class"); static final Symbol UNQUOTE = Symbol.create("unquote"); static final Symbol UNQUOTE_SPLICING = Symbol.create("unquote-splicing"); -static final Symbol SYNTAX_QUOTE = Symbol.create("clojure", "syntax-quote"); +//static final Symbol SYNTAX_QUOTE = Symbol.create("clojure", "syntax-quote"); static final Symbol LIST = Symbol.create("clojure", "list"); static final Symbol HASHMAP = Symbol.create("clojure", "hashmap"); static final Symbol VECTOR = Symbol.create("clojure", "vector"); @@ -80,8 +80,8 @@ static IPersistentMap specials = RT.map( CLASS, null, UNQUOTE, null, UNQUOTE_SPLICING, null, - SYNTAX_QUOTE, null, - _AMP_, null +// SYNTAX_QUOTE, null, +_AMP_, null ); private static final int MAX_POSITIONAL_ARITY = 20; @@ -182,107 +182,6 @@ static Symbol resolveSymbol(Symbol sym){ return Symbol.intern(currentNS(), sym.name); } - -/* -static public Object syntaxQuote(Object form){ - if(isSpecial(form)) - return RT.list(QUOTE, form); - else if(form instanceof Symbol) - { - Symbol sym = (Symbol) form; - //already qualified or classname? - if(sym.ns != null || sym.name.indexOf('.') > 0) - return RT.list(QUOTE,sqMeta(sym, sym.meta())); - IPersistentMap imports = (IPersistentMap) RT.IMPORTS.get(); - //imported class? - String className = (String) imports.valAt(sym); - if(className != null) - return RT.list(QUOTE, sqMeta(Symbol.intern(null, className), sym.meta())); - //refers? - IPersistentMap refers = (IPersistentMap) RT.REFERS.get(); - Var var = (Var) refers.valAt(sym); - if(var != null) - return RT.list(QUOTE, sqMeta(var.sym, sym.meta())); - - return RT.list(QUOTE, sqMeta(Symbol.intern(currentNS(), sym.name), sym.meta())); - } - else if(form instanceof IPersistentCollection) - { - if(form instanceof IPersistentMap) - { - IPersistentVector keyvals = flattenMap(form); - IObj ret = PersistentHashMap.create((ISeq) syntaxQuote(keyvals.seq())); - if(form instanceof IObj) - return sqMeta(ret, ((IObj) form).meta()); - else - return ret; - } - else if(form instanceof IPersistentVector) - { - IObj ret = PersistentVector.create((ISeq) syntaxQuote(((IPersistentVector) form).seq())); - if(form instanceof IObj) - return sqMeta(ret, ((IObj) form).meta()); - else - return ret; - } - else if(form instanceof ISeq) - { - ISeq seq = RT.seq(form); - if(RT.equal(UNQUOTE, RT.first(seq))) - return RT.second(form); - else if(RT.equal(UNQUOTE_SPLICING, RT.first(seq))) - throw new IllegalStateException("splice not in list"); - else - { - PersistentVector ret = PersistentVector.EMPTY; - ret = sqExpandList(ret, seq); - - if(form instanceof IObj) - return RT.cons(LIST, sqMeta((IObj) ret.seq(), ((IObj) form).meta())); - else - return RT.cons(LIST, ret.seq()); - } - } - else - throw new UnsupportedOperationException("Unknown Collection type"); - } - else if(form instanceof IObj) - return sqMeta((IObj) form, ((IObj) form).meta()); - else - return RT.list(QUOTE, form); -} - - -private static PersistentVector sqExpandList(PersistentVector ret, ISeq seq){ - for(; seq != null; seq = seq.rest()) - { - Object item = seq.first(); - if(item instanceof ISeq && RT.equal(UNQUOTE, RT.first(item))) - ret = ret.cons(RT.second(item)); - else if(item instanceof ISeq && RT.equal(UNQUOTE_SPLICING, RT.first(item))) - { - if(RT.second(item) instanceof ISeq) - ret = sqExpandList(ret, (ISeq) RT.second(item)); - else - throw new IllegalStateException("splicing non-list"); - } - else - ret = ret.cons(syntaxQuote(item)); - } - return ret; -} - -static Object sqMeta(IObj obj, IPersistentMap meta){ - if(meta != null) - { - PersistentVector ret = PersistentVector.EMPTY; - ret = sqExpandList(ret, flattenMap(meta).seq()); - return obj.withMeta(PersistentHashMap.create(ret.seq())); - } - else - return obj; -} - */ static class DefExpr implements Expr{ final Var var; final Expr init; diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java index 1c7b7fbb..33348a9e 100644 --- a/src/jvm/clojure/lang/LispReader.java +++ b/src/jvm/clojure/lang/LispReader.java @@ -20,11 +20,12 @@ import java.math.BigInteger; public class LispReader{
static Symbol QUOTE = Symbol.create(null, "quote");
-static Symbol SYNTAX_QUOTE = Symbol.create(null, "syntax-quote");
+//static Symbol SYNTAX_QUOTE = Symbol.create(null, "syntax-quote");
static Symbol UNQUOTE = Symbol.create(null, "unquote");
static Symbol UNQUOTE_SPLICING = Symbol.create(null, "unquote-splicing");
static Symbol CONCAT = Symbol.create("clojure", "concat");
static Symbol LIST = Symbol.create("clojure", "list");
+static Symbol APPLY = Symbol.create("clojure", "apply");
static Symbol HASHMAP = Symbol.create("clojure", "hashmap");
static Symbol VECTOR = Symbol.create("clojure", "vector");
static Symbol WITH_META = Symbol.create("clojure", "with-meta");
@@ -416,25 +417,22 @@ static class SyntaxQuoteReader extends AFn{ if(form instanceof IPersistentMap)
{
IPersistentVector keyvals = flattenMap(form);
- PersistentVector v = PersistentVector.EMPTY;
- ret = RT.list(HASHMAP, RT.list(CONCAT, sqExpandList(v, keyvals.seq())));
+ ret = RT.list(APPLY, HASHMAP, RT.cons(CONCAT, sqExpandList(keyvals.seq())));
}
else if(form instanceof IPersistentVector)
{
- PersistentVector v = PersistentVector.EMPTY;
- ret = RT.list(VECTOR, RT.list(CONCAT, sqExpandList(v, ((IPersistentVector) form).seq())));
+ ret = RT.list(APPLY, VECTOR, RT.cons(CONCAT, sqExpandList(((IPersistentVector) form).seq())));
}
else if(form instanceof ISeq)
{
ISeq seq = RT.seq(form);
if(RT.equal(UNQUOTE, RT.first(seq)))
- ret = form;
+ return RT.second(seq);
else if(RT.equal(UNQUOTE_SPLICING, RT.first(seq)))
throw new IllegalStateException("splice not in list");
else
{
- PersistentVector v = PersistentVector.EMPTY;
- ret = RT.list(CONCAT, sqExpandList(v, seq));
+ ret = RT.cons(CONCAT, sqExpandList(seq));
}
}
else
@@ -454,7 +452,8 @@ static class SyntaxQuoteReader extends AFn{ return ret;
}
- private static ISeq sqExpandList(PersistentVector ret, ISeq seq) throws Exception{
+ private static ISeq sqExpandList(ISeq seq) throws Exception{
+ PersistentVector ret = PersistentVector.EMPTY;
for(; seq != null; seq = seq.rest())
{
Object item = seq.first();
|