summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-09-08 19:30:33 +0000
committerRich Hickey <richhickey@gmail.com>2007-09-08 19:30:33 +0000
commit638effc5964f882c3bad55aee6018bb3979f58be (patch)
tree1aa1de4315af0b7b847b41b90fad70ac5f01e4df /src
parentd3ba5541568cd748daae80a9866fa109ded2d520 (diff)
interim checkin
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/Compiler.java125
-rw-r--r--src/jvm/clojure/lang/PersistentHashMap.java23
-rw-r--r--src/jvm/clojure/lang/RT.java4
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",