diff options
author | Rich Hickey <richhickey@gmail.com> | 2006-09-26 20:24:16 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2006-09-26 20:24:16 +0000 |
commit | 2212ddd3122b6f0799b4ed73e77aeeea7c19c34c (patch) | |
tree | e27e56585826a7717e3310410cf1f15df4970beb | |
parent | bbabe65cbbbba066e2df174d7b7bea9b5739b8a5 (diff) |
interim checkin
-rw-r--r-- | src/cli/runtime/Module.cs | 9 | ||||
-rw-r--r-- | src/cli/runtime/RT.cs | 7 | ||||
-rw-r--r-- | src/cli/runtime/Var.cs | 3 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 154 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Module.java | 6 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 5 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Var.java | 1 |
7 files changed, 157 insertions, 28 deletions
diff --git a/src/cli/runtime/Module.cs b/src/cli/runtime/Module.cs index e2c091fe..3e396783 100644 --- a/src/cli/runtime/Module.cs +++ b/src/cli/runtime/Module.cs @@ -52,7 +52,14 @@ static public Module findOrCreate(String name) return ns; } }
-
+
+public Var find(Symbol sym){
+ lock(vars)
+ {
+ return (Var) vars[sym];
+ }
+}
+
static public Var intern(String ns, String name)
{
return findOrCreate(ns).intern(Symbol.intern(name));
diff --git a/src/cli/runtime/RT.cs b/src/cli/runtime/RT.cs index bb0c3886..7a932f78 100644 --- a/src/cli/runtime/RT.cs +++ b/src/cli/runtime/RT.cs @@ -13,6 +13,7 @@ using System;
using System.Collections;
using System.IO;
+using System.Threading;
namespace clojure.lang
{
@@ -27,6 +28,12 @@ public class RT static public readonly Object[] chars;
+ static int id = 1;
+ static public int nextID()
+ {
+ return Interlocked.Increment(ref id);
+ }
+
static RT(){
chars = new Object[256];
for(int i=0;i<chars.Length;i++)
diff --git a/src/cli/runtime/Var.cs b/src/cli/runtime/Var.cs index 626c4f48..d2fae255 100644 --- a/src/cli/runtime/Var.cs +++ b/src/cli/runtime/Var.cs @@ -15,7 +15,8 @@ namespace clojure.lang {
public class Var : AFn
{
-public readonly Symbol name;
public Module module;
public Binding binding;
IPersistentMap threadBindings = PersistentArrayMap.EMPTY;
int tcount = 0;
internal Var(Symbol sym, Module ns)
{
if(sym.GetType() != typeof(Symbol))
throw new ArgumentException("Only simple symbols can be var names");
this.module = ns;
this.name = sym;
}
override public String ToString()
{
if(module == null)
return "#:" + name;
return module.name + ":" + name;
}
public Var bind(Object val)
{
lock(this){
if(binding == null)
+public readonly Symbol name;
public Module module;
public Binding binding;
+public bool hidden = false;
IPersistentMap threadBindings = PersistentArrayMap.EMPTY;
int tcount = 0;
internal Var(Symbol sym, Module ns)
{
if(sym.GetType() != typeof(Symbol))
throw new ArgumentException("Only simple symbols can be var names");
this.module = ns;
this.name = sym;
}
override public String ToString()
{
if(module == null)
return "#:" + name;
return module.name + ":" + name;
}
public Var bind(Object val)
{
lock(this){
if(binding == null)
binding = new Binding(val);
else
binding.val = val;
return this;
}
}
public Object getValue()
{
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 5b6cdaa6..c7fc1cff 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -12,7 +12,6 @@ package clojure.lang; -import java.io.Writer; import java.io.StringWriter; public class Compiler{ @@ -26,10 +25,14 @@ static NilExpr NIL_EXPR = new NilExpr(); static public Var IMPORTS = Module.intern("clojure", "^compiler-imports"); //keyword->keywordexpr static public Var KEYWORDS = Module.intern("clojure", "^compiler-keywords"); -//var->varexpr +//var->var static public Var VARS = Module.intern("clojure", "^compiler-vars"); -//symbol->localbindingexpr -static public Var LOCALS = Module.intern("clojure", "^compiler-locals"); +//symbol->localbinding +static public Var LOCAL_ENV = Module.intern("clojure", "^compiler-local-env"); +//FnFrame +static public Var FRAME = Module.intern("clojure", "^compiler-frame"); +//module->module +static public Var USES = Module.intern("clojure", "^compiler-uses"); static public IPersistentMap CHAR_MAP = new PersistentArrayMap('-', "_HY_", @@ -129,7 +132,7 @@ private static void convert(Object form) throws Exception{ Expr e = analyze(C.STATEMENT, form); } -private static Expr analyze(C context, Object form){ +private static Expr analyze(C context, Object form) throws Exception { if(form == null) return NIL_EXPR; else if(form instanceof Symbol) @@ -144,7 +147,7 @@ private static Expr analyze(C context, Object form){ throw new UnsupportedOperationException(); } -private static Expr analyzeSeq(C context, ISeq form) { +private static Expr analyzeSeq(C context, ISeq form) throws Exception { Object op = RT.first(form); if(op == DEF) return analyzeDef(context, form); @@ -152,15 +155,41 @@ private static Expr analyzeSeq(C context, ISeq form) { throw new UnsupportedOperationException(); } -private static Expr analyzeDef(C context, ISeq form) { +private static Expr analyzeDef(C context, ISeq form) throws Exception { //(def x) or (def x initexpr) - Symbol name = (Symbol) RT.nth(1, form); + Symbol sym = (Symbol) RT.nth(1, form); Module module = (Module) MODULE.getValue(); - Var var = module.intern(name); + Var var = module.intern(baseSymbol(sym)); + registerVar(var); + VarExpr ve = new VarExpr(var, typeHint(sym)); Expr init = analyze(C.EXPRESSION, macroexpand(RT.nth(2, form))); + return new DefExpr(ve, init); } -private static Expr analyzeSymbol(Symbol sym){ +static Symbol baseSymbol(Symbol sym) { + String base = baseName(sym); + + if(base == sym.name) //no typeHint + return sym; + + return Symbol.intern(base); +} + +static String baseName(Symbol sym){ + int slash = sym.name.indexOf('/'); + if(slash > 0) + return sym.name.substring(0, slash); + return sym.name; +} + +static String typeHint(Symbol sym){ + int slash = sym.name.indexOf('/'); + if(slash > 0) + return sym.name.substring(slash + 1); + return null; +} + +private static Expr analyzeSymbol(Symbol sym) throws Exception { if(sym instanceof Keyword) return registerKeyword((Keyword)sym); else if(sym instanceof HostSymbol) @@ -174,21 +203,63 @@ private static Expr analyzeSymbol(Symbol sym){ typeHint = sym.name.substring(slash + 1); sym = Symbol.intern(sym.name.substring(0, slash)); } - return new SymExpr(sym, typeHint); + LocalBinding b = referenceLocal(sym); + if(b != null) + return new LocalBindingExpr(b, typeHint); + Var v = lookupVar(sym); + if(v != null) + return new VarExpr(v, typeHint); + throw new Exception("Unable to resolve symbol: " + sym.name + " in this context"); } } +static Var lookupVar(Symbol sym){ + Module module = (Module) MODULE.getValue(); + Var v = module.find(sym); + if(v != null) + return v; + for(ISeq seq = RT.seq(USES.getValue());seq != null;seq = RT.rest(seq)) + { + module = (Module) ((MapEntry)RT.first(seq)).key(); + v = module.find(sym); + if(v != null && !v.hidden) + return v; + } + return null; +} + static Object macroexpand(Object x){ return x; //placeholder } -private static Expr registerKeyword(Keyword keyword) { +private static KeywordExpr registerKeyword(Keyword keyword) { IPersistentMap keywordsMap = (IPersistentMap) KEYWORDS.getValue(); KeywordExpr ke = (KeywordExpr) RT.get(keyword,keywordsMap); if(ke == null) KEYWORDS.setValue(RT.assoc(keyword, ke = new KeywordExpr(keyword),keywordsMap)); return ke; } + +private static void registerVar(Var var) { + IPersistentMap varsMap = (IPersistentMap) VARS.getValue(); + if(RT.get(var,varsMap) == null) + VARS.setValue(RT.assoc(var, var, varsMap)); +} + +static void closeOver(LocalBinding b,FnFrame frame){ + if(b != null && frame != null && RT.get(b,frame.locals) == null) + { + b.closed = true; + frame.closes = (IPersistentMap)RT.assoc(b, b, frame.closes); + closeOver(b,frame.parent); + } +} + +static LocalBinding referenceLocal(Symbol sym) { + LocalBinding b = (LocalBinding) RT.get(sym, LOCAL_ENV.getValue()); + closeOver(b,(FnFrame) FRAME.getValue()); + return b; +} /* (defun reference-var (sym) (let ((b (first (member sym *var-env* :key (lambda (b) @@ -214,6 +285,13 @@ static String resolveHostClassname(String classname) throws Exception { return fullyQualifiedName; } +static class FnFrame{ + FnFrame parent = null; + IPersistentMap locals = null; + IPersistentMap closes = null; + +} + static class NilExpr extends AnExpr{ public void emitExpression() throws Exception{ format("null"); @@ -221,7 +299,7 @@ static class NilExpr extends AnExpr{ } static class LiteralExpr extends AnExpr{ - Object val; + final Object val; public LiteralExpr(Object val){ this.val = val; @@ -233,7 +311,7 @@ static class LiteralExpr extends AnExpr{ } static class CharExpr extends AnExpr{ - Character val; + final Character val; public CharExpr(Character val){ this.val = val; @@ -246,7 +324,7 @@ static class CharExpr extends AnExpr{ static class HostExpr extends AnExpr{ - HostSymbol sym; + final HostSymbol sym; public HostExpr(HostSymbol sym){ this.sym = sym; @@ -257,7 +335,7 @@ static class HostExpr extends AnExpr{ format("%A.class", resolveHostClassname(((ClassSymbol) sym).className)); } } - +/* static class SymExpr extends AnExpr{ Symbol sym; String typeHint; @@ -271,9 +349,9 @@ static class SymExpr extends AnExpr{ format("%A", munge(sym.name)); } } - +*/ static class KeywordExpr extends AnExpr{ - Symbol sym; + final Symbol sym; public KeywordExpr(Symbol sym){ this.sym = sym; @@ -284,25 +362,49 @@ static class KeywordExpr extends AnExpr{ } } -static class LocalBindingExpr extends AnExpr{ - Symbol sym; - String typeHint; +static class LocalBinding{ + final Symbol sym; + boolean closed = false; + final int id = RT.nextID(); - public LocalBindingExpr(Symbol sym, String typeHint){ + public LocalBinding(Symbol sym) { this.sym = sym; + } +} + +static class LocalBindingExpr extends AnExpr{ + final LocalBinding b; + final String typeHint; + + public LocalBindingExpr(LocalBinding b, String typeHint){ + this.b = b; this.typeHint = typeHint; } public void emitExpression() throws Exception{ - format("%A", munge(sym.name)); + format("%A", munge(b.sym.name)); } } static class VarExpr extends AnExpr{ - VarExpr var; - Expr init; + final Var var; + final String typeHint; + + public VarExpr(Var var, String typeHint){ + this.var = var; + this.typeHint = typeHint; + } + + public void emitExpression() throws Exception{ + format("%A", munge(var.toString())); + } +} + +static class DefExpr extends AnExpr{ + final VarExpr var; + final Expr init; - public VarExpr(VarExpr var, Expr init){ + public DefExpr(VarExpr var, Expr init){ this.var = var; this.init = init; } diff --git a/src/jvm/clojure/lang/Module.java b/src/jvm/clojure/lang/Module.java index 80ae6f58..3f839e8d 100644 --- a/src/jvm/clojure/lang/Module.java +++ b/src/jvm/clojure/lang/Module.java @@ -55,6 +55,12 @@ static public Var intern(String ns,String name) return findOrCreate(ns).intern(Symbol.intern(name)); } +public Var find(Symbol sym){ + synchronized(vars) + { + return (Var) vars.get(sym); + } +} public Var intern(Symbol sym) { diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index be94d654..faacff57 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -13,6 +13,7 @@ package clojure.lang; import java.util.Iterator; +import java.util.concurrent.atomic.AtomicInteger; import java.io.*; public class RT{ @@ -21,6 +22,7 @@ public class RT{ static public Var OUT = Module.intern("clojure","^out"); static public final Object[] EMPTY_ARRAY = new Object[]{}; static public final Character[] chars; + static AtomicInteger id = new AtomicInteger(1); static { chars = new Character[256]; @@ -28,6 +30,9 @@ public class RT{ chars[i] = new Character((char)i); } + static public int nextID(){ + return id.getAndIncrement(); + } static public boolean equal(Object k1,Object k2){ return k1 == k2 || diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java index 7576fbb1..8fa87cb7 100644 --- a/src/jvm/clojure/lang/Var.java +++ b/src/jvm/clojure/lang/Var.java @@ -21,6 +21,7 @@ public class Var extends AFn { public final Symbol name; public Module module; public Binding binding; +public boolean hidden = false; AtomicInteger tcount = new AtomicInteger(0); AtomicReference<IPersistentMap> threadBindings = new AtomicReference(PersistentArrayMap.EMPTY); |