diff options
author | Rich Hickey <richhickey@gmail.com> | 2007-09-08 19:30:33 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2007-09-08 19:30:33 +0000 |
commit | 638effc5964f882c3bad55aee6018bb3979f58be (patch) | |
tree | 1aa1de4315af0b7b847b41b90fad70ac5f01e4df /src | |
parent | d3ba5541568cd748daae80a9866fa109ded2d520 (diff) |
interim checkin
Diffstat (limited to 'src')
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 125 | ||||
-rw-r--r-- | src/jvm/clojure/lang/PersistentHashMap.java | 23 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 |
3 files changed, 136 insertions, 16 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 6536db16..ad0155c6 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -20,6 +20,7 @@ import org.objectweb.asm.util.CheckClassAdapter; import java.io.*; import java.math.BigInteger; +import java.util.ArrayList; public class Compiler implements Opcodes{ @@ -45,7 +46,8 @@ 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("syntax-quote"); +static final Symbol SYNTAX_QUOTE = Symbol.create("clojure", "syntax-quote"); +static final Symbol LIST = Symbol.create("clojure", "list"); static final Symbol _AMP_ = Symbol.create("&"); @@ -76,8 +78,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; @@ -156,6 +158,112 @@ interface IParser{ Expr parse(C context, Object form) throws Exception; } +static boolean isSpecial(Object sym){ + return specials.contains(sym); +} + +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 sqMeta(sym, sym.meta()); + IPersistentMap imports = (IPersistentMap) RT.IMPORTS.get(); + //imported class? + String className = (String) imports.valAt(sym); + if(className != null) + return sqMeta(Symbol.intern(null, className), sym.meta()); + //refers? + IPersistentMap refers = (IPersistentMap) RT.REFERS.get(); + Var var = (Var) refers.valAt(sym); + if(var != null) + return sqMeta(var.sym, sym.meta()); + + return sqMeta(Symbol.intern(currentNS(), sym.name), sym.meta()); + } + else if(form instanceof IPersistentCollection) + { + if(form instanceof IPersistentMap) + { + IPersistentVector keyvals = PersistentVector.EMPTY; + for(ISeq s = RT.seq(form); s != null; s = s.rest()) + { + IMapEntry e = (IMapEntry) s.first(); + keyvals = (IPersistentVector) keyvals.cons(e.key()); + keyvals = (IPersistentVector) keyvals.cons(e.val()); + } + 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) + { + return obj.withMeta((IPersistentMap) syntaxQuote(meta)); + } + else + return obj; +} + static class DefExpr implements Expr{ final Var var; final Expr init; @@ -1050,6 +1158,7 @@ static class MapExpr implements Expr{ gen.pop(); } + static public Expr parse(C context, IPersistentMap form) throws Exception{ IPersistentVector keyvals = PersistentVector.EMPTY; for(ISeq s = RT.seq(form); s != null; s = s.rest()) @@ -1757,7 +1866,7 @@ private static Expr analyze(C context, Object form) throws Exception{ } private static Expr analyze(C context, Object form, String name) throws Exception{ - //todo symbol macro expansion + //todo symbol macro expansion? if(form == null) return NIL_EXPR; Class fclass = form.getClass(); @@ -1846,8 +1955,8 @@ static Var lookupVar(Symbol sym, boolean internNew) throws Exception{ else { //is it an alias? - IPersistentMap uses = (IPersistentMap) RT.ALIASES.get(); - var = (Var) uses.valAt(sym); + IPersistentMap refers = (IPersistentMap) RT.REFERS.get(); + var = (Var) refers.valAt(sym); if(var == null && sym.ns == null) var = Var.find(Symbol.intern(currentNS(), sym.name)); if(var == null && internNew) @@ -1910,7 +2019,7 @@ public static Object load(InputStream s) throws Exception{ { Var.pushThreadBindings( RT.map(LOADER, new DynamicClassLoader(), - RT.ALIASES, RT.ALIASES.get(), + RT.REFERS, RT.REFERS.get(), RT.IMPORTS, RT.IMPORTS.get(), RT.CURRENT_NS, RT.CURRENT_NS.get() )); @@ -1933,7 +2042,7 @@ public static void main(String[] args){ try { Var.pushThreadBindings( - RT.map(RT.ALIASES, RT.ALIASES.get(), + RT.map(RT.REFERS, RT.REFERS.get(), RT.IMPORTS, RT.IMPORTS.get(), RT.CURRENT_NS, RT.CURRENT_NS.get() )); diff --git a/src/jvm/clojure/lang/PersistentHashMap.java b/src/jvm/clojure/lang/PersistentHashMap.java index 1ff0d481..5727f013 100644 --- a/src/jvm/clojure/lang/PersistentHashMap.java +++ b/src/jvm/clojure/lang/PersistentHashMap.java @@ -38,16 +38,16 @@ final public static PersistentHashMap EMPTY = new PersistentHashMap(0, new Empty /* * @param init {key1,val1,key2,val2,...} */ -public static IPersistentMap create(Object... init){ +public static PersistentHashMap create(Object... init){ IPersistentMap ret = EMPTY; for(int i = 0; i < init.length; i += 2) { ret = ret.assoc(init[i], init[i + 1]); } - return ret; + return (PersistentHashMap) ret; } -public static IPersistentMap create(List init){ +public static PersistentHashMap create(List init){ IPersistentMap ret = EMPTY; for(Iterator i = init.iterator(); i.hasNext();) { @@ -57,19 +57,30 @@ public static IPersistentMap create(List init){ Object val = i.next(); ret = ret.assoc(key, val); } - return ret; + return (PersistentHashMap) ret; +} + +static public PersistentHashMap create(ISeq items){ + IPersistentMap ret = EMPTY; + for(; items != null; items = items.rest().rest()) + { + if(items.rest() == null) + throw new IllegalArgumentException(String.format("No value supplied for key: %s", items.first())); + ret = ret.assoc(items.first(), RT.second(items)); + } + return (PersistentHashMap) ret; } /* * @param init {key1,val1,key2,val2,...} */ -public static IPersistentMap create(IPersistentMap meta, Object... init){ +public static PersistentHashMap create(IPersistentMap meta, Object... init){ IPersistentMap ret = EMPTY.withMeta(meta); for(int i = 0; i < init.length; i += 2) { ret = ret.assoc(init[i], init[i + 1]); } - return ret; + return (PersistentHashMap) ret; } PersistentHashMap(int count, INode root){ diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index ade651e4..0a7acf3e 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -27,9 +27,9 @@ final static public Var CURRENT_MODULE = Var.intern(Symbol.create("clojure", "cu Module.findOrCreateModule("clojure/user")); //string -final static Var CURRENT_NS = Var.intern(Symbol.create("clojure", "*current-namespace*"), "user"); +final static Var CURRENT_NS = Var.intern(Symbol.create("clojure", "*current-namespace*"), "clojure"); //simple-symbol->var -final static Var ALIASES = Var.intern(Symbol.create("clojure", "*aliases*"), PersistentHashMap.EMPTY); +final static Var REFERS = Var.intern(Symbol.create("clojure", "*refers*"), PersistentHashMap.EMPTY); //simple-symbol->fully-qualified-class-name-string final static Var IMPORTS = Var.intern(Symbol.create("clojure", "*imports*"), map(Symbol.create("RT"), "clojure.lang.RT", |