diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-11-29 18:42:17 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-11-29 18:42:17 +0000 |
commit | a4f923670d89fd7f4d72f39ec85ec8f46ea43bdc (patch) | |
tree | 020f7f0b93170b65c7d2a4f33772178a91172875 /src/jvm | |
parent | 09c2d0dd2eff4fbe7962d6f68492d3dc1e07d4ff (diff) |
enhancements to AOT/gen-class
AOT now only produces __init.class by default, load uses that class only
must have at least (:gen-class) ns clause to create named class for ns
gen-class can now be called stand-alone
new options allow for control of mapping to implementing namespace,
name of class, loading of implementing namespace, and method name prefix
(doc ns) and (doc gen-class) and http://clojure.org/compilation for details
Diffstat (limited to 'src/jvm')
-rw-r--r-- | src/jvm/clojure/lang/Compile.java | 14 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 58 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 151 |
3 files changed, 16 insertions, 207 deletions
diff --git a/src/jvm/clojure/lang/Compile.java b/src/jvm/clojure/lang/Compile.java index d31b3569..7dbf6822 100644 --- a/src/jvm/clojure/lang/Compile.java +++ b/src/jvm/clojure/lang/Compile.java @@ -45,18 +45,16 @@ public static void main(String[] args) throws Exception{ { Var.pushThreadBindings(RT.map(compile_path, path)); - out.write("Compiling " + count + " " + - ((count == 1) ? "lib" : "libs") + - " to " + path); - out.flush(); - for(String lib : args) - compile.invoke(Symbol.intern(lib)); - - Var.popThreadBindings(); + { + out.write("Compiling " + lib + " to " + path + "\n"); + out.flush(); + compile.invoke(Symbol.intern(lib)); + } } finally { + Var.popThreadBindings(); try { out.flush(); diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 5d5c7b9e..aee53673 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -4061,6 +4061,8 @@ private static Expr analyzeSeq(C context, ISeq form, String name) throws Excepti return analyze(context, me, name); Object op = RT.first(form); + if(op == null) + throw new IllegalArgumentException("Can't call nil"); IFn inline = isInline(op, RT.count(RT.rest(form))); if(inline != null) return analyze(context, inline.applyTo(RT.rest(form))); @@ -4498,43 +4500,10 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t try { - //use genclass for the stub - String classname = sourcePath.substring(0, sourcePath.lastIndexOf('.')).replace('/', '.'); - Object r = LispReader.read(pushbackReader, false, EOF, false); - Object genclassArgs = null; - if(r instanceof IPersistentList - && (Util.equal(RT.first(r), Symbol.create("ns")) - || Util.equal(RT.first(r), Symbol.create("clojure.core", "ns")))) - { - Keyword gk = Keyword.intern(null, "gen-class"); - Symbol nssym = (Symbol) RT.second(r); - if(!nssym.toString().replace('-','_').equals(classname)) - throw new Exception(String.format("Namespace name must match file, had: %s and %s", - nssym, sourcePath)); - for(ISeq s = RT.rest(RT.rest(r)); s != null; s = s.rest()) - { - Object entry = s.first(); - if(RT.first(entry).equals(gk)) - { - genclassArgs = RT.rest(entry); - break; - } - } - } - - if(genclassArgs == null) - genclassArgs = RT.list(Keyword.intern(null, "main"), RT.T); - - genclassArgs = RT.cons(classname, genclassArgs); - Var genclass = RT.var("clojure.core", "gen-class"); - IPersistentMap gret = (IPersistentMap) genclass.applyTo(RT.seq(genclassArgs)); - writeClassFile(sourcePath.substring(0, sourcePath.lastIndexOf('.')), - (byte[]) RT.get(gret, Keyword.intern(null, "bytecode"))); - //generate loader class FnExpr fn = new FnExpr(null); fn.internalName = sourcePath.replace(File.separator, "/").substring(0, sourcePath.lastIndexOf('.')) - + "__init"; + + RT.LOADER_SUFFIX; fn.fntype = Type.getObjectType(fn.internalName); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); @@ -4549,7 +4518,7 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t cv); gen.visitCode(); - for(; r != EOF; + for(Object r = LispReader.read(pushbackReader, false, EOF, false); r != EOF; r = LispReader.read(pushbackReader, false, EOF, false)) { LINE_AFTER.set(pushbackReader.getLineNumber()); @@ -4606,25 +4575,6 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t clinitgen.returnValue(); clinitgen.endMethod(); - //main -// GeneratorAdapter maingen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, -// Method.getMethod("void main (String[])"), -// null, -// null, -// cv); -// maingen.visitCode(); -// maingen.push(fn.internalName.replace('/', '.')); -// maingen.push("main"); -// maingen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.Var var(String,String)")); -// maingen.loadArgs(); -// maingen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.ISeq seq(Object)")); -// maingen.invokeInterface(IFN_TYPE, new Method("applyTo", OBJECT_TYPE, new Type[]{Type.getType(ISeq.class)})); -// maingen.pop(); -// -// //end of main -// maingen.returnValue(); -// maingen.endMethod(); - //end of class cv.visitEnd(); diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index f6139d1b..aca1bee2 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -34,6 +34,7 @@ public class RT{ static final public Boolean T = Boolean.TRUE;//Keyword.intern(Symbol.create(null, "t")); static final public Boolean F = Boolean.FALSE;//Keyword.intern(Symbol.create(null, "t")); +static final public String LOADER_SUFFIX = "__init"; //simple-symbol->class final static IPersistentMap DEFAULT_IMPORTS = map( @@ -193,9 +194,6 @@ final static public Var USE_CONTEXT_CLASSLOADER = final static Symbol LOAD_FILE = Symbol.create("load-file"); final static Symbol IN_NAMESPACE = Symbol.create("in-ns"); final static Symbol NAMESPACE = Symbol.create("ns"); -//final static Symbol EXPORTS = Symbol.create("*exports*"); -//final static Var EXPORTS_VAR = Var.intern(CLOJURE_NS, EXPORTS, PersistentHashMap.EMPTY); -//final static Symbol EQL_REF = Symbol.create("eql-ref?"); static final Symbol IDENTICAL = Symbol.create("identical?"); final static Var CMD_LINE_ARGS = Var.intern(CLOJURE_NS, Symbol.create("*command-line-args*"), null); //symbol @@ -219,16 +217,6 @@ final static IFn inNamespace = new AFn(){ Symbol nsname = (Symbol) arg1; Namespace ns = Namespace.findOrCreate(nsname); CURRENT_NS.set(ns); -// Var refers = Var.intern(null,Symbol.intern(nsname.name, "*refers*")); -// -// Var imports = Var.intern(null,Symbol.intern(nsname.name, "*imports*"), DEFAULT_IMPORTS, false); -// NS_REFERS.set(refers); -// NS_IMPORTS.set(imports); -// if(!refers.isBound()) -// { -// refers.bindRoot(PersistentHashMap.EMPTY); -// Compiler.eval(list(Symbol.create("clojure.core", "refer"), EXPORTS)); -// } return ns; } }; @@ -243,28 +231,7 @@ public static List<String> processCommandLine(String[] args){ } return arglist; } -//simple-symbol->var -//final static Var REFERS = -// Var.intern(CLOJURE_NS, Symbol.create("*refers*"), -// map( -// IN_NAMESPACE, Var.intern(CLOJURE_NS, IN_NAMESPACE, inNamespace), -// LOAD_FILE, Var.intern(CLOJURE_NS, LOAD_FILE, -// new AFn(){ -// public Object invoke(Object arg1) throws Exception{ -// return Compiler.loadFile((String) arg1); -// } -// }), -// IDENTICAL, Var.intern(CLOJURE_NS, IDENTICAL, -// new AFn(){ -// public Object invoke(Object arg1, Object arg2) -// throws Exception{ -// return arg1 == arg2 ? RT.T : RT.F; -// } -// }) -// )); - -//static Var NS_IMPORTS = Var.intern(CLOJURE_NS,Symbol.create("*ns-imports*"), IMPORTS); -//static Var NS_REFERS = Var.intern(CLOJURE_NS,Symbol.create("*ns-refers*"), REFERS); + static public final Object[] EMPTY_ARRAY = new Object[]{}; static public final Comparator DEFAULT_COMPARATOR = new Comparator(){ public int compare(Object o1, Object o2){ @@ -272,7 +239,6 @@ static public final Comparator DEFAULT_COMPARATOR = new Comparator(){ } }; -//static public final Character[] chars; static AtomicInteger id = new AtomicInteger(1); static final public DynamicClassLoader ROOT_CLASSLOADER = new DynamicClassLoader(); @@ -291,7 +257,8 @@ static AGENT.setTag(Symbol.create("clojure.lang.Agent")); MATH_CONTEXT.setTag(Symbol.create("java.math.MathContext")); //during bootstrap ns same as in-ns - Var.intern(CLOJURE_NS, NAMESPACE, inNamespace); + Var nv = Var.intern(CLOJURE_NS, NAMESPACE, inNamespace); + nv.setMacro(); Var v; v = Var.intern(CLOJURE_NS, IN_NAMESPACE, inNamespace); v.setMeta(map(dockw, "Sets *ns* to the namespace named by the symbol, creating it if needed.", @@ -313,16 +280,6 @@ static }); v.setMeta(map(dockw, "Tests if 2 arguments are the same object", arglistskw, list(vector(Symbol.create("x"), Symbol.create("y"))))); -// try -// { -// InputStream ins = RT.class.getResourceAsStream("/boot.clj"); -// Compiler.load(new InputStreamReader(ins)); -// } -// catch(Exception e) -// { -// throw new IllegalStateException("Error loading boot.clj", e); -// } - try { doInit(); @@ -332,12 +289,6 @@ static throw new RuntimeException(e); } } -//static -// { -// chars = new Character[256]; -// for(int i = 0; i < chars.length; i++) -// chars[i] = new Character((char) i); -// } static public Var var(String ns, String name){ @@ -425,7 +376,7 @@ static public void load(String scriptbase) throws Exception{ } static public void load(String scriptbase, boolean failIfNotFound) throws Exception{ - String classfile = scriptbase + ".class"; + String classfile = scriptbase + LOADER_SUFFIX + ".class"; String cljfile = scriptbase + ".clj"; URL classURL = baseLoader().getResource(classfile); URL cljURL = baseLoader().getResource(cljfile); @@ -439,7 +390,7 @@ static public void load(String scriptbase, boolean failIfNotFound) throws Except Var.pushThreadBindings( RT.map(CURRENT_NS, CURRENT_NS.get(), WARN_ON_REFLECTION, WARN_ON_REFLECTION.get())); - loadClassForName(scriptbase.replace('/','.')); + loadClassForName(scriptbase.replace('/','.') + LOADER_SUFFIX); } finally { @@ -462,23 +413,6 @@ static void doInit() throws Exception{ load("clojure/zip",false); load("clojure/xml",false); load("clojure/set",false); -// try -// { -// Reflector.invokeStaticMethod("clojure.core", "load", EMPTY_ARRAY); -// Reflector.invokeStaticMethod("clojure.zip", "load", EMPTY_ARRAY); -// Reflector.invokeStaticMethod("clojure.xml", "load", EMPTY_ARRAY); -// Reflector.invokeStaticMethod("clojure.set", "load", EMPTY_ARRAY); -// } -// finally -// { -// Var.popThreadBindings(); -// } -// loadResourceScript(RT.class, "clojure/core.clj"); -// loadResourceScript(RT.class, "clojure/proxy.clj", false); -// loadResourceScript(RT.class, "clojure/genclass.clj", false); -// loadResourceScript(RT.class, "clojure/zip.clj", false); -// loadResourceScript(RT.class, "clojure/xml.clj", false); -// loadResourceScript(RT.class, "clojure/set.clj", false); Var.pushThreadBindings( RT.map(CURRENT_NS, CURRENT_NS.get(), @@ -504,38 +438,6 @@ static public int nextID(){ return id.getAndIncrement(); } -//static public Object eq(Object arg1, Object arg2){ -// return (arg1 == arg2) ? Boolean.TRUE : null; -//} -// -//static public Object eql(Object arg1, Object arg2){ -// if(arg1 == arg2) -// return Boolean.TRUE; -// if(arg1 == null || arg2 == null) -// return null; -// if(arg1 instanceof Num -// && arg1.getClass() == arg2.getClass() -// && arg1.equals(arg2)) -// return Boolean.TRUE; -// if(arg1.getClass() == Character.class -// && arg2.getClass() == Character.class -// && arg1.equals(arg2)) -// return Boolean.TRUE; -// return null; -//} - -// static public Object equal(Object arg1, Object arg2) { -// if(arg1 == null) -// return arg2 == null ? Boolean.TRUE : null; -// else if(arg2 == null) -// return null; -// return (eql(arg1,arg2) != null -// || (arg1.getClass() == Cons.class -// && arg2.getClass() == Cons.class -// && equal(((Cons)arg1)._first,((Cons)arg2)._first)!=null -// && equal(((Cons)arg1)._rest,((Cons)arg2)._rest)!=null)) -// ?Boolean.TRUE:null; -// } ////////////// Collections support ///////////////////////////////// @@ -559,10 +461,6 @@ static ISeq seqFrom(Object coll){ return StringSeq.create((String) coll); else if(coll instanceof Map) return seq(((Map) coll).entrySet()); -// else if(coll instanceof Iterator) -// return IteratorSeq.create((Iterator) coll); -// else if(coll instanceof Enumeration) -// return EnumerationSeq.create(((Enumeration) coll)); else throw new IllegalArgumentException("Don't know how to create ISeq from: " + coll.getClass().getSimpleName()); } @@ -680,7 +578,6 @@ static public Object get(Object coll, Object key){ } return null; - //throw new UnsupportedOperationException("get not supported on this type"); } static public Object get(Object coll, Object key, Object notFound){ @@ -709,7 +606,6 @@ static public Object get(Object coll, Object key, Object notFound){ } return notFound; -// throw new UnsupportedOperationException("get not supported on this type"); } static public Associative assoc(Object coll, Object key, Object val){ @@ -736,7 +632,6 @@ static public Object contains(Object coll, Object key){ return n >= 0 && n < count(coll); } return F; - //throw new UnsupportedOperationException("contains not supported on this type"); } static public Object find(Object coll, Object key){ @@ -890,24 +785,6 @@ static public Object assocN(int n, Object val, Object coll){ return null; } -/* -static public Iter iter(Object coll){ - if(coll == null || coll instanceof Iter) - return (Iter) coll; - else if(coll instanceof Iterator) - { - Iterator i = (Iterator) coll; - if(i.hasNext()) - return new IteratorIter(i); - return null; - } - else if(coll instanceof Iterable) - return new IteratorIter(((Iterable) coll).iterator()); - - else - throw new IllegalArgumentException("Don't know how to create Iter from arg"); -} - */ static boolean hasTag(Object o, Object tag){ if(!(o instanceof IObj)) return false; @@ -1357,12 +1234,6 @@ static public void print(Object x, Writer w) throws Exception{ w.write('"'); } } -// else if(x instanceof ArgVector) -// { -// w.write('|'); -// printInnerSeq(seq(x), w); -// w.write('|'); -// } else if(x instanceof IPersistentMap) { w.write('{'); @@ -1400,16 +1271,6 @@ static public void print(Object x, Writer w) throws Exception{ } w.write('}'); } -// else if(x instanceof Map.Entry) -// { -// Map.Entry e = (Map.Entry) x; -// w.write('{'); -// print(e.getKey(),w); -// w.write(' '); -// print(e.getValue(),w); -// -// w.write('}'); -// } else if(x instanceof Character) { char c = ((Character) x).charValue(); |