diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-27 18:28:56 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-27 18:28:56 -0500 |
| commit | 72599899e3d3ae1face46a81f01979b040d19c61 (patch) | |
| tree | 95e163ffacaa7061a1ac90ccd8a1418656ebc5e3 /java | |
| parent | d574187895c8519bffd5a0f8b4c1817e00103d91 (diff) | |
| parent | cc021efe10380039a13da5300990639203450634 (diff) | |
| download | mal-72599899e3d3ae1face46a81f01979b040d19c61.tar.gz mal-72599899e3d3ae1face46a81f01979b040d19c61.zip | |
Merge branch 'master' into gh-pages
Diffstat (limited to 'java')
| -rw-r--r-- | java/Makefile | 17 | ||||
| -rw-r--r-- | java/src/main/java/mal/core.java | 130 | ||||
| -rw-r--r-- | java/src/main/java/mal/step0_repl.java | 2 | ||||
| -rw-r--r-- | java/src/main/java/mal/step1_read_print.java | 10 | ||||
| -rw-r--r-- | java/src/main/java/mal/step2_eval.java | 58 | ||||
| -rw-r--r-- | java/src/main/java/mal/step3_env.java | 44 | ||||
| -rw-r--r-- | java/src/main/java/mal/step4_if_fn_do.java | 16 | ||||
| -rw-r--r-- | java/src/main/java/mal/step5_tco.java | 22 | ||||
| -rw-r--r-- | java/src/main/java/mal/step6_file.java | 56 | ||||
| -rw-r--r-- | java/src/main/java/mal/step7_quote.java | 59 | ||||
| -rw-r--r-- | java/src/main/java/mal/step8_macros.java | 61 | ||||
| -rw-r--r-- | java/src/main/java/mal/stepA_more.java | 81 | ||||
| -rw-r--r-- | java/src/main/java/mal/types.java | 3 |
13 files changed, 279 insertions, 280 deletions
diff --git a/java/Makefile b/java/Makefile index e6312a3..2e168c4 100644 --- a/java/Makefile +++ b/java/Makefile @@ -2,19 +2,16 @@ TESTS = -SOURCES = src/main/java/mal/readline.java src/main/java/mal/types.java \ - src/main/java/mal/reader.java src/main/java/mal/printer.java \ - src/main/java/mal/env.java src/main/java/mal/core.java \ - src/main/java/mal/stepA_more.java +SOURCES_BASE = src/main/java/mal/readline.java src/main/java/mal/types.java \ + src/main/java/mal/reader.java src/main/java/mal/printer.java +SOURCES_LISP = src/main/java/mal/env.java src/main/java/mal/core.java \ + src/main/java/mal/stepA_more.java +SOURCES = $(SOURCES_BASE) $(SOURCES_LISP) #.PHONY: stats tests $(TESTS) .PHONY: stats stats: $(SOURCES) @wc $^ - -#tests: $(TESTS) -# -#$(TESTS): -# @echo "Running $@"; \ -# python $@ || exit 1; \ +stats-lisp: $(SOURCES_LISP) + @wc $^ diff --git a/java/src/main/java/mal/core.java b/java/src/main/java/mal/core.java index 3200c0e..0f1d226 100644 --- a/java/src/main/java/mal/core.java +++ b/java/src/main/java/mal/core.java @@ -7,8 +7,14 @@ import java.util.Map; import java.util.HashMap; import com.google.common.collect.ImmutableMap; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.util.Scanner; +import java.io.File; + import mal.types.*; import mal.printer; +import mal.readline; public class core { // Local references for convenience @@ -84,6 +90,43 @@ public class core { } }; + static MalFunction mal_readline = new MalFunction() { + public MalVal apply(MalList args) throws MalThrowable { + String prompt = ((MalString)args.nth(0)).getValue(); + try { + return new MalString(readline.readline(prompt)); + } catch (IOException e) { + throw new MalException(new MalString(e.getMessage())); + } catch (readline.EOFException e) { + throw new MalException(new MalString(e.getMessage())); + } + } + }; + + static MalFunction read_string = new MalFunction() { + public MalVal apply(MalList args) throws MalThrowable { + try { + return reader.read_str(((MalString)args.nth(0)).getValue()); + } catch (MalContinue c) { + return types.Nil; + } + } + }; + + static MalFunction slurp = new MalFunction() { + public MalVal apply(MalList args) throws MalThrowable { + String fname = ((MalString)args.nth(0)).getValue(); + try { + // Scanner drops final newline, so add it back + return new MalString( + new Scanner(new File(fname)).useDelimiter("\\Z").next() + + "\n"); + } catch (FileNotFoundException e) { + throw new MalError(e.getMessage()); + } + } + }; + // Number functions static MalFunction add = new MalFunction() { @@ -128,6 +171,12 @@ public class core { } }; + static MalFunction time_ms = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return new MalInteger((int)System.currentTimeMillis()); + } + }; + // List functions static MalFunction new_list = new MalFunction() { @@ -162,9 +211,7 @@ public class core { } }; - // - // Hash map operations - // + // HashMap functions static MalFunction new_hash_map = new MalFunction() { public MalVal apply(MalList a) throws MalThrowable { return new MalHashMap(a); @@ -207,13 +254,17 @@ public class core { static MalFunction get = new MalFunction() { public MalVal apply(MalList a) throws MalThrowable { - String key = ((MalString)a.nth(1)).getValue(); - MalHashMap mhm = (MalHashMap)a.nth(0); - HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value; - if (hm.containsKey(key)) { - return hm.get(key); - } else { + if (a.nth(0) == Nil) { return Nil; + } else { + String key = ((MalString)a.nth(1)).getValue(); + MalHashMap mhm = (MalHashMap)a.nth(0); + HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value; + if (hm.containsKey(key)) { + return hm.get(key); + } else { + return Nil; + } } } }; @@ -271,42 +322,22 @@ public class core { static MalFunction cons = new MalFunction() { public MalVal apply(MalList a) throws MalThrowable { - MalList lst = new MalList(); - lst.value.addAll(((MalList)a.nth(1)).value); - lst.value.add(0, a.nth(0)); - return (MalVal) lst; + List<MalVal> lst = new ArrayList<MalVal>(); + lst.add(a.nth(0)); + lst.addAll(((MalList)a.nth(1)).getList()); + return (MalVal)new MalList(lst); } }; static MalFunction concat = new MalFunction() { public MalVal apply(MalList a) throws MalThrowable { if (a.size() == 0) { return new MalList(); } - MalList lst = new MalList(); - lst.value.addAll(((MalList)a.nth(0)).value); + List<MalVal> lst = new ArrayList<MalVal>(); + lst.addAll(((MalList)a.nth(0)).value); for(Integer i=1; i<a.size(); i++) { - lst.value.addAll(((MalList)a.nth(i)).value); + lst.addAll(((MalList)a.nth(i)).value); } - return (MalVal) lst; - } - }; - - static MalFunction conj = new MalFunction() { - public MalVal apply(MalList a) throws MalThrowable { - MalList src_seq = (MalList)a.nth(0), new_seq; - if (a.nth(0) instanceof MalVector) { - new_seq = new MalVector(); - new_seq.value.addAll(src_seq.value); - for(Integer i=1; i<a.size(); i++) { - new_seq.value.add(a.nth(i)); - } - } else { - new_seq = new MalList(); - new_seq.value.addAll(src_seq.value); - for(Integer i=1; i<a.size(); i++) { - new_seq.value.add(0, a.nth(i)); - } - } - return (MalVal) new_seq; + return (MalVal)new MalList(lst); } }; @@ -331,6 +362,26 @@ public class core { } }; + static MalFunction conj = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + MalList src_seq = (MalList)a.nth(0), new_seq; + if (a.nth(0) instanceof MalVector) { + new_seq = new MalVector(); + new_seq.value.addAll(src_seq.value); + for(Integer i=1; i<a.size(); i++) { + new_seq.value.add(a.nth(i)); + } + } else { + new_seq = new MalList(); + new_seq.value.addAll(src_seq.value); + for(Integer i=1; i<a.size(); i++) { + new_seq.value.add(0, a.nth(i)); + } + } + return (MalVal) new_seq; + } + }; + // General list related functions static MalFunction apply = new MalFunction() { public MalVal apply(MalList a) throws MalThrowable { @@ -421,10 +472,14 @@ public class core { .put("true?", true_Q) .put("false?", false_Q) .put("symbol?", symbol_Q) + .put("pr-str", pr_str) .put("str", str) .put("prn", prn) .put("println", println) + .put("readline", mal_readline) + .put("read-string", read_string) + .put("slurp", slurp) .put("<", lt) .put("<=", lte) .put(">", gt) @@ -433,6 +488,7 @@ public class core { .put("-", subtract) .put("*", multiply) .put("/", divide) + .put("time-ms", time_ms) .put("list", new_list) .put("list?", list_Q) diff --git a/java/src/main/java/mal/step0_repl.java b/java/src/main/java/mal/step0_repl.java index 9095aca..060f43e 100644 --- a/java/src/main/java/mal/step0_repl.java +++ b/java/src/main/java/mal/step0_repl.java @@ -20,7 +20,7 @@ public class step0_repl { return exp; } - // REPL + // repl public static String RE(String env, String str) { return EVAL(READ(str), env); } diff --git a/java/src/main/java/mal/step1_read_print.java b/java/src/main/java/mal/step1_read_print.java index 3f7e3fb..e849052 100644 --- a/java/src/main/java/mal/step1_read_print.java +++ b/java/src/main/java/mal/step1_read_print.java @@ -23,7 +23,7 @@ public class step1_read_print { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(String env, String str) throws MalThrowable { return EVAL(READ(str), env); } @@ -49,11 +49,11 @@ public class step1_read_print { System.out.println(PRINT(RE(null, line))); } catch (MalContinue e) { continue; - } catch (MalError e) { - System.out.println("Error: " + e.getMessage()); + } catch (MalThrowable t) { + System.out.println("Error: " + t.getMessage()); continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); continue; } } diff --git a/java/src/main/java/mal/step2_eval.java b/java/src/main/java/mal/step2_eval.java index 3d425db..6de69cd 100644 --- a/java/src/main/java/mal/step2_eval.java +++ b/java/src/main/java/mal/step2_eval.java @@ -72,47 +72,41 @@ public class step2_eval { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(HashMap env, String str) throws MalThrowable { return EVAL(READ(str), env); } - static interface ILambda { - public MalVal apply(MalList args); - } - static class plus implements ILambda { - public MalVal apply(MalList args) { - return ((MalInteger)args.nth(0)).add( - ((MalInteger)args.nth(1))); + static MalFunction add = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).add((MalInteger)a.nth(1)); } - } - static class minus implements ILambda { - public MalVal apply(MalList args) { - return ((MalInteger)args.nth(0)).subtract( - ((MalInteger)args.nth(1))); + }; + static MalFunction subtract = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).subtract((MalInteger)a.nth(1)); } - } - static class multiply implements ILambda { - public MalVal apply(MalList args) { - return ((MalInteger)args.nth(0)).multiply( - ((MalInteger)args.nth(1))); + }; + static MalFunction multiply = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).multiply((MalInteger)a.nth(1)); } - } - static class divide implements ILambda { - public MalVal apply(MalList args) { - return ((MalInteger)args.nth(0)).divide( - ((MalInteger)args.nth(1))); + }; + static MalFunction divide = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).divide((MalInteger)a.nth(1)); } - } + }; + public static void main(String[] args) throws MalThrowable { String prompt = "user> "; HashMap repl_env = new HashMap(); - repl_env.put("+", new plus()); - repl_env.put("-", new minus()); - repl_env.put("*", new multiply()); - repl_env.put("/", new divide()); + repl_env.put("+", add); + repl_env.put("-", subtract); + repl_env.put("*", multiply); + repl_env.put("/", divide); if (args.length > 0 && args[0].equals("--raw")) { readline.mode = readline.Mode.JAVA; @@ -132,11 +126,11 @@ public class step2_eval { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (MalError e) { - System.out.println("Error: " + e.getMessage()); + } catch (MalThrowable t) { + System.out.println("Error: " + t.getMessage()); continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); continue; } } diff --git a/java/src/main/java/mal/step3_env.java b/java/src/main/java/mal/step3_env.java index 690469e..a88dc13 100644 --- a/java/src/main/java/mal/step3_env.java +++ b/java/src/main/java/mal/step3_env.java @@ -11,7 +11,6 @@ import mal.readline; import mal.reader; import mal.printer; import mal.env.Env; -import mal.core; public class step3_env { // read @@ -93,22 +92,41 @@ public class step3_env { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(Env env, String str) throws MalThrowable { return EVAL(READ(str), env); } - public static Env _ref(Env env, String name, MalVal mv) { - return env.set(name, mv); - } + + static MalFunction add = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).add((MalInteger)a.nth(1)); + } + }; + static MalFunction subtract = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).subtract((MalInteger)a.nth(1)); + } + }; + static MalFunction multiply = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).multiply((MalInteger)a.nth(1)); + } + }; + static MalFunction divide = new MalFunction() { + public MalVal apply(MalList a) throws MalThrowable { + return ((MalInteger)a.nth(0)).divide((MalInteger)a.nth(1)); + } + }; + public static void main(String[] args) throws MalThrowable { String prompt = "user> "; Env repl_env = new Env(null); - _ref(repl_env, "+", core.add); - _ref(repl_env, "-", core.subtract); - _ref(repl_env, "*", core.multiply); - _ref(repl_env, "/", core.divide); + repl_env.set("+", add); + repl_env.set("-", subtract); + repl_env.set("*", multiply); + repl_env.set("/", divide); if (args.length > 0 && args[0].equals("--raw")) { readline.mode = readline.Mode.JAVA; @@ -128,11 +146,11 @@ public class step3_env { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (MalError e) { - System.out.println("Error: " + e.getMessage()); + } catch (MalThrowable t) { + System.out.println("Error: " + t.getMessage()); continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); continue; } } diff --git a/java/src/main/java/mal/step4_if_fn_do.java b/java/src/main/java/mal/step4_if_fn_do.java index 4d064cf..ce9043d 100644 --- a/java/src/main/java/mal/step4_if_fn_do.java +++ b/java/src/main/java/mal/step4_if_fn_do.java @@ -118,22 +118,22 @@ public class step4_if_fn_do { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(Env env, String str) throws MalThrowable { return EVAL(READ(str), env); } - public static Env _ref(Env env, String name, MalVal mv) { - return env.set(name, mv); - } public static void main(String[] args) throws MalThrowable { String prompt = "user> "; Env repl_env = new Env(null); + + // core.java: defined using Java for (String key : core.ns.keySet()) { - _ref(repl_env, key, core.ns.get(key)); + repl_env.set(key, core.ns.get(key)); } + // core.mal: defined using the language itself RE(repl_env, "(def! not (fn* (a) (if a false true)))"); if (args.length > 0 && args[0].equals("--raw")) { @@ -154,12 +154,12 @@ public class step4_if_fn_do { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); - continue; } catch (MalThrowable t) { System.out.println("Error: " + t.getMessage()); continue; + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); + continue; } } } diff --git a/java/src/main/java/mal/step5_tco.java b/java/src/main/java/mal/step5_tco.java index 43b93c6..ef56083 100644 --- a/java/src/main/java/mal/step5_tco.java +++ b/java/src/main/java/mal/step5_tco.java @@ -80,7 +80,9 @@ public class step5_tco { val = ((MalList)a1).nth(i+1); let_env.set(key.getName(), EVAL(val, let_env)); } - return EVAL(a2, let_env); + orig_ast = a2; + env = let_env; + break; case "do": eval_ast(ast.slice(1, ast.size()-1), env); orig_ast = ast.nth(ast.size()-1); @@ -115,7 +117,7 @@ public class step5_tco { MalVal fnast = f.getAst(); if (fnast != null) { orig_ast = fnast; - env = new Env(f.getEnv(), f.getParams(), el.slice(1)); + env = f.genEnv(el.slice(1)); } else { return f.apply(el.rest()); } @@ -129,22 +131,22 @@ public class step5_tco { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(Env env, String str) throws MalThrowable { return EVAL(READ(str), env); } - public static Env _ref(Env env, String name, MalVal mv) { - return env.set(name, mv); - } public static void main(String[] args) throws MalThrowable { String prompt = "user> "; Env repl_env = new Env(null); + + // core.java: defined using Java for (String key : core.ns.keySet()) { - _ref(repl_env, key, core.ns.get(key)); + repl_env.set(key, core.ns.get(key)); } + // core.mal: defined using the language itself RE(repl_env, "(def! not (fn* (a) (if a false true)))"); if (args.length > 0 && args[0].equals("--raw")) { @@ -165,12 +167,12 @@ public class step5_tco { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); - continue; } catch (MalThrowable t) { System.out.println("Error: " + t.getMessage()); continue; + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); + continue; } } } diff --git a/java/src/main/java/mal/step6_file.java b/java/src/main/java/mal/step6_file.java index 0a1a99b..56bcdf7 100644 --- a/java/src/main/java/mal/step6_file.java +++ b/java/src/main/java/mal/step6_file.java @@ -1,10 +1,7 @@ package mal; import java.io.IOException; -import java.io.FileNotFoundException; -import java.util.Scanner; -import java.io.File; import java.util.List; import java.util.Map; import java.util.HashMap; @@ -83,7 +80,9 @@ public class step6_file { val = ((MalList)a1).nth(i+1); let_env.set(key.getName(), EVAL(val, let_env)); } - return EVAL(a2, let_env); + orig_ast = a2; + env = let_env; + break; case "do": eval_ast(ast.slice(1, ast.size()-1), env); orig_ast = ast.nth(ast.size()-1); @@ -118,7 +117,7 @@ public class step6_file { MalVal fnast = f.getAst(); if (fnast != null) { orig_ast = fnast; - env = new Env(f.getEnv(), f.getParams(), el.slice(1)); + env = f.genEnv(el.slice(1)); } else { return f.apply(el.rest()); } @@ -132,46 +131,33 @@ public class step6_file { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(Env env, String str) throws MalThrowable { return EVAL(READ(str), env); } - public static Env _ref(Env env, String name, MalVal mv) { - return env.set(name, mv); - } - public static String slurp(String fname) throws MalThrowable { - try { - return new Scanner(new File(fname)) - .useDelimiter("\\Z").next(); - } catch (FileNotFoundException e) { - throw new MalError(e.getMessage()); - } - } public static void main(String[] args) throws MalThrowable { String prompt = "user> "; final Env repl_env = new Env(null); + + // core.java: defined using Java for (String key : core.ns.keySet()) { - _ref(repl_env, key, core.ns.get(key)); + repl_env.set(key, core.ns.get(key)); } - _ref(repl_env, "read-string", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - return reader.read_str(((MalString)args.nth(0)).getValue()); - } - }); - _ref(repl_env, "eval", new MalFunction() { + repl_env.set("eval", new MalFunction() { public MalVal apply(MalList args) throws MalThrowable { return EVAL(args.nth(0), repl_env); } }); - _ref(repl_env, "slurp", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - String fname = ((MalString)args.nth(0)).getValue(); - return new MalString(slurp(fname)); - } - }); + MalList _argv = new MalList(); + for (Integer i=1; i < args.length; i++) { + _argv.conj_BANG(new MalString(args[i])); + } + repl_env.set("*ARGV*", _argv); + + // core.mal: defined using the language itself RE(repl_env, "(def! not (fn* (a) (if a false true)))"); RE(repl_env, "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"); @@ -181,9 +167,7 @@ public class step6_file { fileIdx = 1; } if (args.length > fileIdx) { - for(Integer i=fileIdx; i<args.length; i++) { - RE(repl_env, "(load-file \"" + args[i] + "\")"); - } + RE(repl_env, "(load-file \"" + args[fileIdx] + "\")"); return; } while (true) { @@ -201,12 +185,12 @@ public class step6_file { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); - continue; } catch (MalThrowable t) { System.out.println("Error: " + t.getMessage()); continue; + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); + continue; } } } diff --git a/java/src/main/java/mal/step7_quote.java b/java/src/main/java/mal/step7_quote.java index 7105671..8c3766a 100644 --- a/java/src/main/java/mal/step7_quote.java +++ b/java/src/main/java/mal/step7_quote.java @@ -1,10 +1,7 @@ package mal; import java.io.IOException; -import java.io.FileNotFoundException; -import java.util.Scanner; -import java.io.File; import java.util.List; import java.util.Map; import java.util.HashMap; @@ -110,11 +107,14 @@ public class step7_quote { val = ((MalList)a1).nth(i+1); let_env.set(key.getName(), EVAL(val, let_env)); } - return EVAL(a2, let_env); + orig_ast = a2; + env = let_env; + break; case "quote": return ast.nth(1); case "quasiquote": - return EVAL(quasiquote(ast.nth(1)), env); + orig_ast = quasiquote(ast.nth(1)); + break; case "do": eval_ast(ast.slice(1, ast.size()-1), env); orig_ast = ast.nth(ast.size()-1); @@ -149,7 +149,7 @@ public class step7_quote { MalVal fnast = f.getAst(); if (fnast != null) { orig_ast = fnast; - env = new Env(f.getEnv(), f.getParams(), el.slice(1)); + env = f.genEnv(el.slice(1)); } else { return f.apply(el.rest()); } @@ -163,46 +163,33 @@ public class step7_quote { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(Env env, String str) throws MalThrowable { return EVAL(READ(str), env); } - public static Env _ref(Env env, String name, MalVal mv) { - return env.set(name, mv); - } - public static String slurp(String fname) throws MalThrowable { - try { - return new Scanner(new File(fname)) - .useDelimiter("\\Z").next(); - } catch (FileNotFoundException e) { - throw new MalError(e.getMessage()); - } - } public static void main(String[] args) throws MalThrowable { String prompt = "user> "; final Env repl_env = new Env(null); + + // core.java: defined using Java for (String key : core.ns.keySet()) { - _ref(repl_env, key, core.ns.get(key)); + repl_env.set(key, core.ns.get(key)); } - _ref(repl_env, "read-string", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - return reader.read_str(((MalString)args.nth(0)).getValue()); - } - }); - _ref(repl_env, "eval", new MalFunction() { + repl_env.set("eval", new MalFunction() { public MalVal apply(MalList args) throws MalThrowable { return EVAL(args.nth(0), repl_env); } }); - _ref(repl_env, "slurp", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - String fname = ((MalString)args.nth(0)).getValue(); - return new MalString(slurp(fname)); - } - }); + MalList _argv = new MalList(); + for (Integer i=1; i < args.length; i++) { + _argv.conj_BANG(new MalString(args[i])); + } + repl_env.set("*ARGV*", _argv); + + // core.mal: defined using the language itself RE(repl_env, "(def! not (fn* (a) (if a false true)))"); RE(repl_env, "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"); @@ -212,9 +199,7 @@ public class step7_quote { fileIdx = 1; } if (args.length > fileIdx) { - for(Integer i=fileIdx; i<args.length; i++) { - RE(repl_env, "(load-file \"" + args[i] + "\")"); - } + RE(repl_env, "(load-file \"" + args[fileIdx] + "\")"); return; } while (true) { @@ -232,12 +217,12 @@ public class step7_quote { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); - continue; } catch (MalThrowable t) { System.out.println("Error: " + t.getMessage()); continue; + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); + continue; } } } diff --git a/java/src/main/java/mal/step8_macros.java b/java/src/main/java/mal/step8_macros.java index c834119..4c89356 100644 --- a/java/src/main/java/mal/step8_macros.java +++ b/java/src/main/java/mal/step8_macros.java @@ -1,10 +1,7 @@ package mal; import java.io.IOException; -import java.io.FileNotFoundException; -import java.util.Scanner; -import java.io.File; import java.util.List; import java.util.Map; import java.util.HashMap; @@ -138,11 +135,14 @@ public class step8_macros { val = ((MalList)a1).nth(i+1); let_env.set(key.getName(), EVAL(val, let_env)); } - return EVAL(a2, let_env); + orig_ast = a2; + env = let_env; + break; case "quote": return ast.nth(1); case "quasiquote": - return EVAL(quasiquote(ast.nth(1)), env); + orig_ast = quasiquote(ast.nth(1)); + break; case "defmacro!": a1 = ast.nth(1); a2 = ast.nth(2); @@ -187,7 +187,7 @@ public class step8_macros { MalVal fnast = f.getAst(); if (fnast != null) { orig_ast = fnast; - env = new Env(f.getEnv(), f.getParams(), el.slice(1)); + env = f.genEnv(el.slice(1)); } else { return f.apply(el.rest()); } @@ -201,48 +201,37 @@ public class step8_macros { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(Env env, String str) throws MalThrowable { return EVAL(READ(str), env); } - public static Env _ref(Env env, String name, MalVal mv) { - return env.set(name, mv); - } - public static String slurp(String fname) throws MalThrowable { - try { - return new Scanner(new File(fname)) - .useDelimiter("\\Z").next(); - } catch (FileNotFoundException e) { - throw new MalError(e.getMessage()); - } - } public static void main(String[] args) throws MalThrowable { String prompt = "user> "; final Env repl_env = new Env(null); + + // core.java: defined using Java for (String key : core.ns.keySet()) { - _ref(repl_env, key, core.ns.get(key)); + repl_env.set(key, core.ns.get(key)); } - _ref(repl_env, "read-string", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - return reader.read_str(((MalString)args.nth(0)).getValue()); - } - }); - _ref(repl_env, "eval", new MalFunction() { + repl_env.set("eval", new MalFunction() { public MalVal apply(MalList args) throws MalThrowable { return EVAL(args.nth(0), repl_env); } }); - _ref(repl_env, "slurp", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - String fname = ((MalString)args.nth(0)).getValue(); - return new MalString(slurp(fname)); - } - }); + MalList _argv = new MalList(); + for (Integer i=1; i < args.length; i++) { + _argv.conj_BANG(new MalString(args[i])); + } + repl_env.set("*ARGV*", _argv); + + // core.mal: defined using the language itself RE(repl_env, "(def! not (fn* (a) (if a false true)))"); RE(repl_env, "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"); + RE(repl_env, "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"); + RE(repl_env, "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))"); Integer fileIdx = 0; if (args.length > 0 && args[0].equals("--raw")) { @@ -250,9 +239,7 @@ public class step8_macros { fileIdx = 1; } if (args.length > fileIdx) { - for(Integer i=fileIdx; i<args.length; i++) { - RE(repl_env, "(load-file \"" + args[i] + "\")"); - } + RE(repl_env, "(load-file \"" + args[fileIdx] + "\")"); return; } while (true) { @@ -270,12 +257,12 @@ public class step8_macros { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); - continue; } catch (MalThrowable t) { System.out.println("Error: " + t.getMessage()); continue; + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); + continue; } } } diff --git a/java/src/main/java/mal/stepA_more.java b/java/src/main/java/mal/stepA_more.java index 9f4fb07..7e869e6 100644 --- a/java/src/main/java/mal/stepA_more.java +++ b/java/src/main/java/mal/stepA_more.java @@ -1,10 +1,7 @@ package mal; import java.io.IOException; -import java.io.FileNotFoundException; -import java.util.Scanner; -import java.io.File; import java.io.StringWriter; import java.io.PrintWriter; import java.util.List; @@ -140,11 +137,14 @@ public class stepA_more { val = ((MalList)a1).nth(i+1); let_env.set(key.getName(), EVAL(val, let_env)); } - return EVAL(a2, let_env); + orig_ast = a2; + env = let_env; + break; case "quote": return ast.nth(1); case "quasiquote": - return EVAL(quasiquote(ast.nth(1)), env); + orig_ast = quasiquote(ast.nth(1)); + break; case "defmacro!": a1 = ast.nth(1); a2 = ast.nth(2); @@ -213,7 +213,7 @@ public class stepA_more { MalVal fnast = f.getAst(); if (fnast != null) { orig_ast = fnast; - env = new Env(f.getEnv(), f.getParams(), el.slice(1)); + env = f.genEnv(el.slice(1)); } else { return f.apply(el.rest()); } @@ -227,66 +227,38 @@ public class stepA_more { return printer._pr_str(exp, true); } - // REPL + // repl public static MalVal RE(Env env, String str) throws MalThrowable { return EVAL(READ(str), env); } - public static Env _ref(Env env, String name, MalVal mv) { - return env.set(name, mv); - } - public static String slurp(String fname) throws MalThrowable { - try { - return new Scanner(new File(fname)) - .useDelimiter("\\Z").next(); - } catch (FileNotFoundException e) { - throw new MalError(e.getMessage()); - } - } public static void main(String[] args) throws MalThrowable { String prompt = "user> "; final Env repl_env = new Env(null); + + // core.java: defined using Java for (String key : core.ns.keySet()) { - _ref(repl_env, key, core.ns.get(key)); + repl_env.set(key, core.ns.get(key)); } - _ref(repl_env, "readline", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - String prompt = ((MalString)args.nth(0)).getValue(); - try { - return new MalString(readline.readline(prompt)); - } catch (IOException e) { - throw new MalException(new MalString(e.getMessage())); - } catch (readline.EOFException e) { - throw new MalException(new MalString(e.getMessage())); - } - } - }); - _ref(repl_env, "read-string", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - try { - return reader.read_str(((MalString)args.nth(0)).getValue()); - } catch (MalContinue c) { - return types.Nil; - } - } - }); - _ref(repl_env, "eval", new MalFunction() { + repl_env.set("eval", new MalFunction() { public MalVal apply(MalList args) throws MalThrowable { return EVAL(args.nth(0), repl_env); } }); - _ref(repl_env, "slurp", new MalFunction() { - public MalVal apply(MalList args) throws MalThrowable { - String fname = ((MalString)args.nth(0)).getValue(); - return new MalString(slurp(fname)); - } - }); + MalList _argv = new MalList(); + for (Integer i=1; i < args.length; i++) { + _argv.conj_BANG(new MalString(args[i])); + } + repl_env.set("*ARGV*", _argv); + + // core.mal: defined using the language itself + RE(repl_env, "(def! *host-language* \"java\")"); RE(repl_env, "(def! not (fn* (a) (if a false true)))"); + RE(repl_env, "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"); RE(repl_env, "(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))"); RE(repl_env, "(defmacro! or (fn* (& xs) (if (empty? xs) nil (if (= 1 (count xs)) (first xs) `(let* (or_FIXME ~(first xs)) (if or_FIXME or_FIXME (or ~@(rest xs))))))))"); - RE(repl_env, "(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))"); Integer fileIdx = 0; if (args.length > 0 && args[0].equals("--raw")) { @@ -294,11 +266,12 @@ public class stepA_more { fileIdx = 1; } if (args.length > fileIdx) { - for(Integer i=fileIdx; i<args.length; i++) { - RE(repl_env, "(load-file \"" + args[i] + "\")"); - } + RE(repl_env, "(load-file \"" + args[fileIdx] + "\")"); return; } + + // repl loop + RE(repl_env, "(println (str \"Mal [\" *host-language* \"]\"))"); while (true) { String line; try { @@ -314,15 +287,15 @@ public class stepA_more { System.out.println(PRINT(RE(repl_env, line))); } catch (MalContinue e) { continue; - } catch (reader.ParseError e) { - System.out.println(e.getMessage()); - continue; } catch (MalException e) { System.out.println("Error: " + printer._pr_str(e.getValue(), false)); continue; } catch (MalThrowable t) { System.out.println("Error: " + t.getMessage()); continue; + } catch (Throwable t) { + System.out.println("Uncaught " + t + ": " + t.getMessage()); + continue; } } } diff --git a/java/src/main/java/mal/types.java b/java/src/main/java/mal/types.java index a53c0e9..7ad419a 100644 --- a/java/src/main/java/mal/types.java +++ b/java/src/main/java/mal/types.java @@ -355,6 +355,9 @@ public class types { public MalVal getAst() { return ast; } public Env getEnv() { return env; } public MalList getParams() { return params; } + public Env genEnv(MalList args) { + return new Env(env, params, args); + } public Boolean isMacro() { return macro; } public void setMacro() { macro = true; } } |
