aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-04-27 18:28:56 -0500
committerJoel Martin <github@martintribe.org>2014-04-27 18:28:56 -0500
commit72599899e3d3ae1face46a81f01979b040d19c61 (patch)
tree95e163ffacaa7061a1ac90ccd8a1418656ebc5e3 /java
parentd574187895c8519bffd5a0f8b4c1817e00103d91 (diff)
parentcc021efe10380039a13da5300990639203450634 (diff)
downloadmal-72599899e3d3ae1face46a81f01979b040d19c61.tar.gz
mal-72599899e3d3ae1face46a81f01979b040d19c61.zip
Merge branch 'master' into gh-pages
Diffstat (limited to 'java')
-rw-r--r--java/Makefile17
-rw-r--r--java/src/main/java/mal/core.java130
-rw-r--r--java/src/main/java/mal/step0_repl.java2
-rw-r--r--java/src/main/java/mal/step1_read_print.java10
-rw-r--r--java/src/main/java/mal/step2_eval.java58
-rw-r--r--java/src/main/java/mal/step3_env.java44
-rw-r--r--java/src/main/java/mal/step4_if_fn_do.java16
-rw-r--r--java/src/main/java/mal/step5_tco.java22
-rw-r--r--java/src/main/java/mal/step6_file.java56
-rw-r--r--java/src/main/java/mal/step7_quote.java59
-rw-r--r--java/src/main/java/mal/step8_macros.java61
-rw-r--r--java/src/main/java/mal/stepA_more.java81
-rw-r--r--java/src/main/java/mal/types.java3
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; }
}