diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 202 |
1 files changed, 180 insertions, 22 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 25b04e90..5b6cdaa6 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -12,15 +12,63 @@ package clojure.lang; -import java.util.HashMap; +import java.io.Writer; +import java.io.StringWriter; public class Compiler{ ///* static Symbol DEF = Symbol.intern("def"); static public Var OUT = Module.intern("clojure", "^out"); -static public Var IMPORT_MAP = Module.intern("clojure", "^import-map"); +static public Var MODULE = Module.intern("clojure", "^module"); static NilExpr NIL_EXPR = new NilExpr(); +//short-name-string->full-name-string +static public Var IMPORTS = Module.intern("clojure", "^compiler-imports"); +//keyword->keywordexpr +static public Var KEYWORDS = Module.intern("clojure", "^compiler-keywords"); +//var->varexpr +static public Var VARS = Module.intern("clojure", "^compiler-vars"); +//symbol->localbindingexpr +static public Var LOCALS = Module.intern("clojure", "^compiler-locals"); + +static public IPersistentMap CHAR_MAP = + new PersistentArrayMap('-', "_HY_", + '.', "_DT_", + ':', "_CL_", + '+', "_PL_", + '>', "_GT_", + '<', "_LT_", + '=', "_EQ_", + '~', "_TL_", + '!', "_EP_", + '@', "_AT_", + '#', "_SH_", + '$', "_DS_", + '%', "_PT_", + '^', "_CT_", + '&', "_AM_", + '*', "_ST_", + '{', "_LB_", + '}', "_RB_", + '[', "_LK_", + ']', "_RK_", + '/', "_SL_", + '\\',"_BS_", + '?', "_QM_"); + +static String munge(String name){ + StringBuilder sb = new StringBuilder(); + for(char c : name.toCharArray()) + { + String sub = (String) CHAR_MAP.get(c); + if(sub != null) + sb.append(sub); + else + sb.append(c); + } + return sb.toString(); +} + enum C{STATEMENT,EXPRESSION,RETURN} interface Expr{ @@ -30,6 +78,8 @@ interface Expr{ void emitStatement() throws Exception; void emitExpression() throws Exception; + + String emitExpressionString() throws Exception; } static void format(String str,Object... args) throws Exception { @@ -45,12 +95,25 @@ static class AnExpr implements Expr{ } public void emitStatement() throws Exception{ - //no op + emitExpression(); + format(";~%"); } public void emitExpression() throws Exception{ throw new UnsupportedOperationException(); } + + public String emitExpressionString() throws Exception { + StringWriter w = new StringWriter(); + try{ + OUT.pushThreadBinding(w); + emitExpression(); + return w.toString(); + } + finally{ + OUT.popThreadBinding(); + } + } } public static void processForm(Object form) throws Exception{ @@ -73,32 +136,83 @@ private static Expr analyze(C context, Object form){ return analyzeSymbol((Symbol) form); else if(form instanceof ISeq) return analyzeSeq(context, (ISeq) form); - else if(form instanceof Num || form instanceof String || form instanceof Character) + else if(form instanceof Num || form instanceof String) return new LiteralExpr(form); + else if(form instanceof Character) + return new CharExpr((Character)form); else throw new UnsupportedOperationException(); } private static Expr analyzeSeq(C context, ISeq form) { - return null; + Object op = RT.first(form); + if(op == DEF) + return analyzeDef(context, form); + else + throw new UnsupportedOperationException(); +} + +private static Expr analyzeDef(C context, ISeq form) { + //(def x) or (def x initexpr) + Symbol name = (Symbol) RT.nth(1, form); + Module module = (Module) MODULE.getValue(); + Var var = module.intern(name); + Expr init = analyze(C.EXPRESSION, macroexpand(RT.nth(2, form))); } private static Expr analyzeSymbol(Symbol sym){ - if(sym instanceof HostSymbol) + if(sym instanceof Keyword) + return registerKeyword((Keyword)sym); + else if(sym instanceof HostSymbol) return new HostExpr((HostSymbol)sym); else { int slash = sym.name.indexOf('/'); - String typehint = null; + String typeHint = null; if(slash > 0) { - typehint = sym.name.substring(slash + 1); + typeHint = sym.name.substring(slash + 1); sym = Symbol.intern(sym.name.substring(0, slash)); } - return new SymExpr(sym, typehint); + return new SymExpr(sym, typeHint); } } +static Object macroexpand(Object x){ + return x; //placeholder +} + +private static Expr 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; +} +/* +(defun reference-var (sym) + (let ((b (first (member sym *var-env* :key (lambda (b) + (@ :symbol b)))))) + (labels + ((check-closed (b frame) + (when (and b frame + (not (member b (@ :local-bindings frame)))) ;closed over + (setf (@ :closed? b) t) + (pushnew b (@ :closes frame)) + (check-closed b (@ :parent frame))))) + (check-closed b *frame*)) + b)) + */ + +static String resolveHostClassname(String classname) throws Exception { + if(classname.indexOf('.') != -1) //presume fully qualified if contains . + return classname; + IPersistentMap importMap = (IPersistentMap) IMPORTS.getValue(); + String fullyQualifiedName = (String) RT.get(classname,importMap); + if(fullyQualifiedName == null) + throw new Exception("Can't resolve type name: " + classname); + return fullyQualifiedName; +} static class NilExpr extends AnExpr{ public void emitExpression() throws Exception{ @@ -118,16 +232,19 @@ static class LiteralExpr extends AnExpr{ } } -static String resolveHostClassname(String classname) throws Exception { - if(classname.indexOf('.') != -1) //presume fully qualified if contains . - return classname; - HashMap importMap = (HashMap) IMPORT_MAP.getValue(); - String fullyQualifiedName = (String) importMap.get(classname); - if(fullyQualifiedName == null) - throw new Exception("Can't resolve type name: " + classname); - return fullyQualifiedName; +static class CharExpr extends AnExpr{ + Character val; + + public CharExpr(Character val){ + this.val = val; + } + + public void emitExpression() throws Exception{ + format("'~A'",val); + } } + static class HostExpr extends AnExpr{ HostSymbol sym; @@ -136,21 +253,62 @@ static class HostExpr extends AnExpr{ } public void emitExpression() throws Exception{ - format("%S",sym); + if(sym instanceof ClassSymbol) + format("%A.class", resolveHostClassname(((ClassSymbol) sym).className)); } } static class SymExpr extends AnExpr{ Symbol sym; - String typehint; + String typeHint; + + public SymExpr(Symbol sym, String typeHint){ + this.sym = sym; + this.typeHint = typeHint; + } + + public void emitExpression() throws Exception{ + format("%A", munge(sym.name)); + } +} + +static class KeywordExpr extends AnExpr{ + Symbol sym; - public SymExpr(Symbol sym, String typehint){ + public KeywordExpr(Symbol sym){ this.sym = sym; - this.typehint = typehint; + } + + public void emitExpression() throws Exception { + format("%A", munge(sym.name)); + } +} + +static class LocalBindingExpr extends AnExpr{ + Symbol sym; + String typeHint; + + public LocalBindingExpr(Symbol sym, String typeHint){ + this.sym = sym; + this.typeHint = typeHint; + } + + public void emitExpression() throws Exception{ + format("%A", munge(sym.name)); + } +} + +static class VarExpr extends AnExpr{ + VarExpr var; + Expr init; + + public VarExpr(VarExpr var, Expr init){ + this.var = var; + this.init = init; } public void emitExpression() throws Exception{ - format("%S",sym); + format("%A.bind(%A)", var.emitExpressionString(),init.emitExpressionString()); } } |