aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-04-02 22:23:37 -0500
committerJoel Martin <github@martintribe.org>2014-04-02 22:23:37 -0500
commitea81a8087bcd7953b083a2be9db447f75e7ebf56 (patch)
tree6cf47a2dbd55d42efc4a901eaabdec952f40ce89 /java
parent1617910ad342a55762f3ddabb975849d843cff85 (diff)
downloadmal-ea81a8087bcd7953b083a2be9db447f75e7ebf56.tar.gz
mal-ea81a8087bcd7953b083a2be9db447f75e7ebf56.zip
All: split types into types, env, printer, core.
- types: low-level mapping to the implementation language. - core: functions on types that are exposed directly to mal. - printer: implementation called by pr-str, str, prn, println. - env: the environment implementation - Also, unindent all TCO while loops so that the diff of step4 and step5 are minimized.
Diffstat (limited to 'java')
-rw-r--r--java/Makefile6
-rw-r--r--java/src/main/java/mal/core.java470
-rw-r--r--java/src/main/java/mal/env.java57
-rw-r--r--java/src/main/java/mal/printer.java50
-rw-r--r--java/src/main/java/mal/step1_read_print.java5
-rw-r--r--java/src/main/java/mal/step2_eval.java20
-rw-r--r--java/src/main/java/mal/step3_env.java27
-rw-r--r--java/src/main/java/mal/step4_if_fn_do.java23
-rw-r--r--java/src/main/java/mal/step5_tco.java27
-rw-r--r--java/src/main/java/mal/step6_file.java25
-rw-r--r--java/src/main/java/mal/step7_quote.java29
-rw-r--r--java/src/main/java/mal/step8_macros.java33
-rw-r--r--java/src/main/java/mal/stepA_more.java35
-rw-r--r--java/src/main/java/mal/types.java654
14 files changed, 768 insertions, 693 deletions
diff --git a/java/Makefile b/java/Makefile
index 8559a05..e6312a3 100644
--- a/java/Makefile
+++ b/java/Makefile
@@ -2,8 +2,10 @@
TESTS =
-SOURCES = src/main/java/mal/types.java src/main/java/mal/readline.java \
- src/main/java/mal/reader.java src/main/java/mal/stepA_more.java
+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
#.PHONY: stats tests $(TESTS)
.PHONY: stats
diff --git a/java/src/main/java/mal/core.java b/java/src/main/java/mal/core.java
new file mode 100644
index 0000000..3200c0e
--- /dev/null
+++ b/java/src/main/java/mal/core.java
@@ -0,0 +1,470 @@
+package mal;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import com.google.common.collect.ImmutableMap;
+
+import mal.types.*;
+import mal.printer;
+
+public class core {
+ // Local references for convenience
+ static MalConstant Nil = mal.types.Nil;
+ static MalConstant True = mal.types.True;
+ static MalConstant False = mal.types.False;
+
+
+ // Errors/Exceptions
+ static MalFunction mal_throw = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ throw new MalException(a.nth(0));
+ }
+ };
+
+
+ // Scalar functions
+ static MalFunction nil_Q = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return args.nth(0) == Nil ? True : False;
+ }
+ };
+
+ static MalFunction true_Q = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return args.nth(0) == True ? True : False;
+ }
+ };
+
+ static MalFunction false_Q = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return args.nth(0) == False ? True : False;
+ }
+ };
+ static MalFunction symbol_Q = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return args.nth(0) instanceof MalSymbol ? True : False;
+ }
+ };
+
+
+ // String functions
+ static MalFunction pr_str = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return new MalString(printer._pr_str_args(args, " ", true));
+ }
+ };
+
+ static MalFunction str = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return new MalString(printer._pr_str_args(args, "", false));
+ }
+ };
+
+ static MalFunction prn = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ System.out.println(printer._pr_str_args(args, " ", true));
+ return Nil;
+ }
+ };
+
+ static MalFunction println = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ System.out.println(printer._pr_str_args(args, " ", false));
+ return Nil;
+ }
+ };
+
+
+ static MalFunction equal_Q = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return types._equal_Q(args.nth(0), args.nth(1)) ? True : False;
+ }
+ };
+
+
+ // Number functions
+ 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));
+ }
+ };
+
+ static MalFunction lt = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return ((MalInteger)a.nth(0)).lt((MalInteger)a.nth(1));
+ }
+ };
+ static MalFunction lte = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return ((MalInteger)a.nth(0)).lte((MalInteger)a.nth(1));
+ }
+ };
+ static MalFunction gt = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return ((MalInteger)a.nth(0)).gt((MalInteger)a.nth(1));
+ }
+ };
+ static MalFunction gte = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return ((MalInteger)a.nth(0)).gte((MalInteger)a.nth(1));
+ }
+ };
+
+
+ // List functions
+ static MalFunction new_list = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return new MalList(a.value);
+ }
+ };
+
+ static public Boolean _list_Q(MalVal mv) {
+ return mv.getClass().equals(MalList.class);
+ }
+ static MalFunction list_Q = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return _list_Q(a.nth(0)) ? True : False;
+ }
+ };
+
+
+ // Vector functions
+ static MalFunction new_vector = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return new MalVector(a.value);
+ }
+ };
+
+ static public Boolean _vector_Q(MalVal mv) {
+ return mv.getClass().equals(MalVector.class);
+ }
+ static MalFunction vector_Q = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return _vector_Q(a.nth(0)) ? True : False;
+ }
+ };
+
+ //
+ // Hash map operations
+ //
+ static MalFunction new_hash_map = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return new MalHashMap(a);
+ }
+ };
+ static MalFunction hash_map_Q = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return a.nth(0) instanceof MalHashMap ? True : False;
+ }
+ };
+
+ static MalFunction contains_Q = 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;
+ return hm.containsKey(key) ? True : False;
+ }
+ };
+
+ static MalFunction assoc = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalHashMap mhm = (MalHashMap)a.nth(0);
+ HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
+ MalHashMap new_mhm = new MalHashMap((Map)hm.clone());
+ new_mhm.assoc_BANG((MalList)a.slice(1));
+ return new_mhm;
+ }
+ };
+
+ static MalFunction dissoc = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalHashMap mhm = (MalHashMap)a.nth(0);
+ HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
+ MalHashMap new_mhm = new MalHashMap((Map)hm.clone());
+ new_mhm.dissoc_BANG((MalList)a.slice(1));
+ return new_mhm;
+ }
+ };
+
+ 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 {
+ return Nil;
+ }
+ }
+ };
+
+ static MalFunction keys = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalHashMap mhm = (MalHashMap)a.nth(0);
+ HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
+ MalList key_lst = new MalList();
+ for (String key : hm.keySet()) {
+ key_lst.conj_BANG(new MalString(key));
+ }
+ return key_lst;
+ }
+ };
+
+ static MalFunction vals = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalHashMap mhm = (MalHashMap)a.nth(0);
+ HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
+ //return new ArrayList<MalVal>(((HashMap<String,MalVal>)hm).values());
+ MalList val_lst = new MalList();
+ for (MalVal val : hm.values()) {
+ val_lst.conj_BANG(val);
+ }
+ return val_lst;
+ }
+ };
+
+
+ // Sequence functions
+ static MalFunction sequential_Q = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return a.nth(0) instanceof MalList ? True : False;
+ }
+ };
+
+ static MalFunction count = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return new MalInteger(((MalList)a.nth(0)).size());
+ }
+ };
+
+ static MalFunction empty_Q = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalVal exp = a.nth(0);
+ if (exp == Nil || (exp instanceof MalList &&
+ ((MalList)exp).size() == 0)) {
+ return True;
+ } else {
+ return False;
+ }
+ }
+ };
+
+ 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;
+ }
+ };
+
+ 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);
+ for(Integer i=1; i<a.size(); i++) {
+ lst.value.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;
+ }
+ };
+
+ static MalFunction first = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalList ml = ((MalList)a.nth(0));
+ return ml.size() > 0 ? ml.nth(0) : Nil;
+ }
+ };
+
+ static MalFunction rest = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalList ml = ((MalList)a.nth(0));
+ return ml.rest();
+ }
+ };
+
+ static MalFunction nth = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ Integer idx = ((MalInteger)a.nth(1)).getValue();
+ return ((MalList)a.nth(0)).nth(idx);
+ }
+ };
+
+ // General list related functions
+ static MalFunction apply = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalFunction f = (MalFunction)a.nth(0);
+ MalList args = a.slice(1,a.size()-1);
+ args.value.addAll( ((MalList)a.nth(a.size()-1)).value);
+ return f.apply(args);
+ }
+ };
+
+ static MalFunction map = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalFunction f = (MalFunction) a.nth(0);
+ MalList src_lst = (MalList) a.nth(1);
+ MalList new_lst = new MalList();
+ for(Integer i=0; i<src_lst.size(); i++) {
+ new_lst.value.add(
+ f.apply(new MalList(src_lst.nth(i))));
+ }
+ return new_lst;
+ }
+ };
+
+
+ // Metadata functions
+
+ static MalFunction meta = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ return args.nth(0).getMeta();
+ }
+ };
+
+ static MalFunction with_meta = new MalFunction() {
+ public MalVal apply(MalList args) throws MalThrowable {
+ MalVal new_mv = ((MalVal)args.nth(0)).copy();
+ new_mv.setMeta(args.nth(1));
+ return new_mv;
+ }
+ };
+
+
+ // Atom functions
+ static MalFunction new_atom = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return new MalAtom(a.nth(0));
+ }
+ };
+
+ static MalFunction atom_Q = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return a.nth(0) instanceof MalAtom ? True : False;
+ }
+ };
+
+ static MalFunction deref = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return ((MalAtom)a.nth(0)).value;
+ }
+ };
+
+ static MalFunction reset_BANG = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ return ((MalAtom)a.nth(0)).value = a.nth(1);
+ }
+ };
+
+ static MalFunction swap_BANG = new MalFunction() {
+ public MalVal apply(MalList a) throws MalThrowable {
+ MalAtom atm = (MalAtom)a.nth(0);
+ MalFunction f = (MalFunction)a.nth(1);
+ MalList new_args = new MalList();
+ new_args.value.addAll(((MalList)a.slice(2)).value);
+ new_args.value.add(0, atm.value);
+ atm.value = f.apply(new_args);
+ return atm.value;
+ }
+ };
+
+
+
+
+
+ // types_ns is namespace of type functions
+ static Map<String, MalVal> ns = ImmutableMap.<String, MalVal>builder()
+ .put("=", equal_Q)
+ .put("throw", mal_throw)
+ .put("nil?", nil_Q)
+ .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("<", lt)
+ .put("<=", lte)
+ .put(">", gt)
+ .put(">=", gte)
+ .put("+", add)
+ .put("-", subtract)
+ .put("*", multiply)
+ .put("/", divide)
+
+ .put("list", new_list)
+ .put("list?", list_Q)
+ .put("vector", new_vector)
+ .put("vector?", vector_Q)
+ .put("hash-map", new_hash_map)
+ .put("map?", hash_map_Q)
+ .put("assoc", assoc)
+ .put("dissoc", dissoc)
+ .put("contains?", contains_Q)
+ .put("get", get)
+ .put("keys", keys)
+ .put("vals", vals)
+
+ .put("sequential?", sequential_Q)
+ .put("cons", cons)
+ .put("concat", concat)
+ .put("nth", nth)
+ .put("first", first)
+ .put("rest", rest)
+ .put("empty?", empty_Q)
+ .put("count", count)
+ .put("conj", conj)
+ .put("apply", apply)
+ .put("map", map)
+
+ .put("with-meta", with_meta)
+ .put("meta", meta)
+ .put("atom", new_atom)
+ .put("atom?", atom_Q)
+ .put("deref", deref)
+ .put("reset!", reset_BANG)
+ .put("swap!", swap_BANG)
+ .build();
+}
diff --git a/java/src/main/java/mal/env.java b/java/src/main/java/mal/env.java
new file mode 100644
index 0000000..8a1913e
--- /dev/null
+++ b/java/src/main/java/mal/env.java
@@ -0,0 +1,57 @@
+package mal;
+
+import java.util.HashMap;
+
+import mal.types.MalThrowable;
+import mal.types.MalException;
+import mal.types.MalVal;
+import mal.types.MalSymbol;
+import mal.types.MalList;
+
+public class env {
+ public static class Env {
+ Env outer = null;
+ HashMap<String,MalVal> data = new HashMap<String,MalVal>();
+
+ public Env(Env outer) {
+ this.outer = outer;
+ }
+ public Env(Env outer, MalList binds, MalList exprs) {
+ this.outer = outer;
+ for (Integer i=0; i<binds.size(); i++) {
+ String sym = ((MalSymbol)binds.nth(i)).getName();
+ if (sym.equals("&")) {
+ data.put(((MalSymbol)binds.nth(i+1)).getName(),
+ exprs.slice(i));
+ break;
+ } else {
+ data.put(sym, exprs.nth(i));
+ }
+ }
+ }
+
+ public Env find(String key) {
+ if (data.containsKey(key)) {
+ return this;
+ } else if (outer != null) {
+ return outer.find(key);
+ } else {
+ return null;
+ }
+ }
+
+ public MalVal get(String key) throws MalThrowable {
+ Env e = find(key);
+ if (e == null) {
+ throw new MalException("'" + key + "' not found");
+ } else {
+ return e.data.get(key);
+ }
+ }
+
+ public Env set(String key, MalVal value) {
+ data.put(key, value);
+ return this;
+ }
+ }
+}
diff --git a/java/src/main/java/mal/printer.java b/java/src/main/java/mal/printer.java
new file mode 100644
index 0000000..73dfca3
--- /dev/null
+++ b/java/src/main/java/mal/printer.java
@@ -0,0 +1,50 @@
+package mal;
+
+import java.util.List;
+import java.util.ArrayList;
+import com.google.common.base.Joiner;
+import java.util.Map;
+import org.apache.commons.lang3.StringEscapeUtils;
+
+import mal.types.MalVal;
+import mal.types.MalList;
+
+public class printer {
+
+ public static String join(List<MalVal> value,
+ String delim, Boolean print_readably) {
+ ArrayList<String> strs = new ArrayList<String>();
+ for (MalVal mv : value) {
+ strs.add(mv.toString(print_readably));
+ }
+ return Joiner.on(delim).join(strs);
+ }
+
+ public static String join(Map<String,MalVal> value,
+ String delim, Boolean print_readably) {
+ ArrayList<String> strs = new ArrayList<String>();
+ for (Map.Entry<String, MalVal> entry : value.entrySet()) {
+ if (print_readably) {
+ strs.add("\"" + entry.getKey().toString() + "\"");
+ } else {
+ strs.add(entry.getKey().toString());
+ }
+ strs.add(entry.getValue().toString(print_readably));
+ }
+ return Joiner.on(" ").join(strs);
+ }
+
+ public static String _pr_str(MalVal mv,
+ Boolean print_readably) {
+ return mv.toString(print_readably);
+ }
+
+ public static String _pr_str_args(MalList args,
+ String sep, Boolean print_readably) {
+ return join(args.getList(), sep, print_readably);
+ }
+
+ public static String escapeString(String value) {
+ return StringEscapeUtils.escapeJson(value);
+ }
+}
diff --git a/java/src/main/java/mal/step1_read_print.java b/java/src/main/java/mal/step1_read_print.java
index 447afc5..3f7e3fb 100644
--- a/java/src/main/java/mal/step1_read_print.java
+++ b/java/src/main/java/mal/step1_read_print.java
@@ -5,6 +5,7 @@ import java.io.IOException;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
public class step1_read_print {
// read
@@ -19,7 +20,7 @@ public class step1_read_print {
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -30,7 +31,7 @@ public class step1_read_print {
public static void main(String[] args) throws MalThrowable {
String prompt = "user> ";
- if (args[0].equals("--raw")) {
+ if (args.length > 0 && args[0].equals("--raw")) {
readline.mode = readline.Mode.JAVA;
}
while (true) {
diff --git a/java/src/main/java/mal/step2_eval.java b/java/src/main/java/mal/step2_eval.java
index e1b30a9..3d425db 100644
--- a/java/src/main/java/mal/step2_eval.java
+++ b/java/src/main/java/mal/step2_eval.java
@@ -9,6 +9,7 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
public class step2_eval {
// read
@@ -23,8 +24,8 @@ public class step2_eval {
return (MalVal)env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -44,8 +45,8 @@ public class step2_eval {
public static MalVal EVAL(MalVal orig_ast, HashMap env) throws MalThrowable {
MalVal a0;
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
@@ -55,17 +56,20 @@ public class step2_eval {
a0 = ast.nth(0);
if (!(a0 instanceof MalSymbol)) {
throw new MalError("attempt to apply on non-symbol '"
- + types._pr_str(a0,true) + "'");
+ + printer._pr_str(a0,true) + "'");
}
- MalVal args = eval_ast(types._rest(ast), env);
+ MalVal args = eval_ast(ast.rest(), env);
MalSymbol fsym = (MalSymbol)a0;
ILambda f = (ILambda)env.get(fsym.getName());
+ if (f == null) {
+ throw new MalError("'" + fsym.getName() + "' not found");
+ }
return f.apply((MalList)args);
}
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -110,7 +114,7 @@ public class step2_eval {
repl_env.put("*", new multiply());
repl_env.put("/", new divide());
- if (args[0].equals("--raw")) {
+ if (args.length > 0 && args[0].equals("--raw")) {
readline.mode = readline.Mode.JAVA;
}
while (true) {
diff --git a/java/src/main/java/mal/step3_env.java b/java/src/main/java/mal/step3_env.java
index 867dba1..690469e 100644
--- a/java/src/main/java/mal/step3_env.java
+++ b/java/src/main/java/mal/step3_env.java
@@ -9,6 +9,9 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
+import mal.env.Env;
+import mal.core;
public class step3_env {
// read
@@ -23,8 +26,8 @@ public class step3_env {
return env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -44,8 +47,8 @@ public class step3_env {
public static MalVal EVAL(MalVal orig_ast, Env env) throws MalThrowable {
MalVal a0, a1,a2, res;
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
@@ -55,7 +58,7 @@ public class step3_env {
a0 = ast.nth(0);
if (!(a0 instanceof MalSymbol)) {
throw new MalError("attempt to apply on non-symbol '"
- + types._pr_str(a0,true) + "'");
+ + printer._pr_str(a0,true) + "'");
}
switch (((MalSymbol)a0).getName()) {
@@ -78,7 +81,7 @@ public class step3_env {
}
return EVAL(a2, let_env);
default:
- MalVal args = eval_ast(types._rest(ast), env);
+ MalVal args = eval_ast(ast.rest(), env);
MalSymbol fsym = (MalSymbol)a0;
ILambda f = (ILambda)env.get(fsym.getName());
return f.apply((MalList)args);
@@ -87,7 +90,7 @@ public class step3_env {
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -102,12 +105,12 @@ public class step3_env {
String prompt = "user> ";
Env repl_env = new Env(null);
- _ref(repl_env, "+", types.add);
- _ref(repl_env, "-", types.subtract);
- _ref(repl_env, "*", types.multiply);
- _ref(repl_env, "/", types.divide);
+ _ref(repl_env, "+", core.add);
+ _ref(repl_env, "-", core.subtract);
+ _ref(repl_env, "*", core.multiply);
+ _ref(repl_env, "/", core.divide);
- if (args[0].equals("--raw")) {
+ if (args.length > 0 && args[0].equals("--raw")) {
readline.mode = readline.Mode.JAVA;
}
while (true) {
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 7501b50..4d064cf 100644
--- a/java/src/main/java/mal/step4_if_fn_do.java
+++ b/java/src/main/java/mal/step4_if_fn_do.java
@@ -9,6 +9,9 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
+import mal.env.Env;
+import mal.core;
public class step4_if_fn_do {
// read
@@ -23,8 +26,8 @@ public class step4_if_fn_do {
return env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -45,8 +48,8 @@ public class step4_if_fn_do {
public static MalVal EVAL(MalVal orig_ast, Env env) throws MalThrowable {
MalVal a0, a1,a2, a3, res;
MalList el;
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
@@ -76,7 +79,7 @@ public class step4_if_fn_do {
}
return EVAL(a2, let_env);
case "do":
- el = (MalList)eval_ast(types._rest(ast), env);
+ el = (MalList)eval_ast(ast.rest(), env);
return el.nth(el.size()-1);
case "if":
a1 = ast.nth(1);
@@ -106,13 +109,13 @@ public class step4_if_fn_do {
default:
el = (MalList)eval_ast(ast, env);
MalFunction f = (MalFunction)el.nth(0);
- return f.apply(types._rest(el));
+ return f.apply(el.rest());
}
}
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -127,13 +130,13 @@ public class step4_if_fn_do {
String prompt = "user> ";
Env repl_env = new Env(null);
- for (String key : types.types_ns.keySet()) {
- _ref(repl_env, key, types.types_ns.get(key));
+ for (String key : core.ns.keySet()) {
+ _ref(repl_env, key, core.ns.get(key));
}
RE(repl_env, "(def! not (fn* (a) (if a false true)))");
- if (args[0].equals("--raw")) {
+ if (args.length > 0 && args[0].equals("--raw")) {
readline.mode = readline.Mode.JAVA;
}
while (true) {
diff --git a/java/src/main/java/mal/step5_tco.java b/java/src/main/java/mal/step5_tco.java
index 41b295b..43b93c6 100644
--- a/java/src/main/java/mal/step5_tco.java
+++ b/java/src/main/java/mal/step5_tco.java
@@ -9,6 +9,9 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
+import mal.env.Env;
+import mal.core;
public class step5_tco {
// read
@@ -23,8 +26,8 @@ public class step5_tco {
return env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -43,20 +46,20 @@ public class step5_tco {
}
public static MalVal EVAL(MalVal orig_ast, Env env) throws MalThrowable {
- MalVal a1,a2, a3, res;
+ MalVal a0, a1,a2, a3, res;
MalList el;
while (true) {
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
// apply list
MalList ast = (MalList)orig_ast;
if (ast.size() == 0) { return ast; }
- MalVal a0 = ast.nth(0);
+ a0 = ast.nth(0);
String a0sym = a0 instanceof MalSymbol ? ((MalSymbol)a0).getName()
: "__<*fn*>__";
switch (a0sym) {
@@ -101,7 +104,7 @@ public class step5_tco {
final MalList a1f = (MalList)ast.nth(1);
final MalVal a2f = ast.nth(2);
final Env cur_env = env;
- return new MalFunction (a2f, (mal.types.Env)env, a1f) {
+ return new MalFunction (a2f, (mal.env.Env)env, a1f) {
public MalVal apply(MalList args) throws MalThrowable {
return EVAL(a2f, new Env(cur_env, a1f, args));
}
@@ -114,7 +117,7 @@ public class step5_tco {
orig_ast = fnast;
env = new Env(f.getEnv(), f.getParams(), el.slice(1));
} else {
- return f.apply(types._rest(el));
+ return f.apply(el.rest());
}
}
@@ -123,7 +126,7 @@ public class step5_tco {
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -138,13 +141,13 @@ public class step5_tco {
String prompt = "user> ";
Env repl_env = new Env(null);
- for (String key : types.types_ns.keySet()) {
- _ref(repl_env, key, types.types_ns.get(key));
+ for (String key : core.ns.keySet()) {
+ _ref(repl_env, key, core.ns.get(key));
}
RE(repl_env, "(def! not (fn* (a) (if a false true)))");
- if (args[0].equals("--raw")) {
+ if (args.length > 0 && args[0].equals("--raw")) {
readline.mode = readline.Mode.JAVA;
}
while (true) {
diff --git a/java/src/main/java/mal/step6_file.java b/java/src/main/java/mal/step6_file.java
index 65d9d38..0a1a99b 100644
--- a/java/src/main/java/mal/step6_file.java
+++ b/java/src/main/java/mal/step6_file.java
@@ -12,6 +12,9 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
+import mal.env.Env;
+import mal.core;
public class step6_file {
// read
@@ -26,8 +29,8 @@ public class step6_file {
return env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -46,20 +49,20 @@ public class step6_file {
}
public static MalVal EVAL(MalVal orig_ast, Env env) throws MalThrowable {
- MalVal a1,a2, a3, res;
+ MalVal a0, a1,a2, a3, res;
MalList el;
while (true) {
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
// apply list
MalList ast = (MalList)orig_ast;
if (ast.size() == 0) { return ast; }
- MalVal a0 = ast.nth(0);
+ a0 = ast.nth(0);
String a0sym = a0 instanceof MalSymbol ? ((MalSymbol)a0).getName()
: "__<*fn*>__";
switch (a0sym) {
@@ -104,7 +107,7 @@ public class step6_file {
final MalList a1f = (MalList)ast.nth(1);
final MalVal a2f = ast.nth(2);
final Env cur_env = env;
- return new MalFunction (a2f, (mal.types.Env)env, a1f) {
+ return new MalFunction (a2f, (mal.env.Env)env, a1f) {
public MalVal apply(MalList args) throws MalThrowable {
return EVAL(a2f, new Env(cur_env, a1f, args));
}
@@ -117,7 +120,7 @@ public class step6_file {
orig_ast = fnast;
env = new Env(f.getEnv(), f.getParams(), el.slice(1));
} else {
- return f.apply(types._rest(el));
+ return f.apply(el.rest());
}
}
@@ -126,7 +129,7 @@ public class step6_file {
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -149,8 +152,8 @@ public class step6_file {
String prompt = "user> ";
final Env repl_env = new Env(null);
- for (String key : types.types_ns.keySet()) {
- _ref(repl_env, key, types.types_ns.get(key));
+ for (String key : core.ns.keySet()) {
+ _ref(repl_env, key, core.ns.get(key));
}
_ref(repl_env, "read-string", new MalFunction() {
public MalVal apply(MalList args) throws MalThrowable {
diff --git a/java/src/main/java/mal/step7_quote.java b/java/src/main/java/mal/step7_quote.java
index 2a09d3e..7105671 100644
--- a/java/src/main/java/mal/step7_quote.java
+++ b/java/src/main/java/mal/step7_quote.java
@@ -12,6 +12,9 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
+import mal.env.Env;
+import mal.core;
public class step7_quote {
// read
@@ -38,12 +41,12 @@ public class step7_quote {
(((MalSymbol)a00).getName() == "splice-unquote")) {
return new MalList(new MalSymbol("concat"),
((MalList)a0).nth(1),
- quasiquote(types._rest((MalList)ast)));
+ quasiquote(((MalList)ast).rest()));
}
}
return new MalList(new MalSymbol("cons"),
quasiquote(a0),
- quasiquote(types._rest((MalList)ast)));
+ quasiquote(((MalList)ast).rest()));
}
}
@@ -53,8 +56,8 @@ public class step7_quote {
return env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -73,20 +76,20 @@ public class step7_quote {
}
public static MalVal EVAL(MalVal orig_ast, Env env) throws MalThrowable {
- MalVal a1,a2, a3, res;
+ MalVal a0, a1,a2, a3, res;
MalList el;
while (true) {
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
// apply list
MalList ast = (MalList)orig_ast;
if (ast.size() == 0) { return ast; }
- MalVal a0 = ast.nth(0);
+ a0 = ast.nth(0);
String a0sym = a0 instanceof MalSymbol ? ((MalSymbol)a0).getName()
: "__<*fn*>__";
switch (a0sym) {
@@ -135,7 +138,7 @@ public class step7_quote {
final MalList a1f = (MalList)ast.nth(1);
final MalVal a2f = ast.nth(2);
final Env cur_env = env;
- return new MalFunction (a2f, (mal.types.Env)env, a1f) {
+ return new MalFunction (a2f, (mal.env.Env)env, a1f) {
public MalVal apply(MalList args) throws MalThrowable {
return EVAL(a2f, new Env(cur_env, a1f, args));
}
@@ -148,7 +151,7 @@ public class step7_quote {
orig_ast = fnast;
env = new Env(f.getEnv(), f.getParams(), el.slice(1));
} else {
- return f.apply(types._rest(el));
+ return f.apply(el.rest());
}
}
@@ -157,7 +160,7 @@ public class step7_quote {
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -180,8 +183,8 @@ public class step7_quote {
String prompt = "user> ";
final Env repl_env = new Env(null);
- for (String key : types.types_ns.keySet()) {
- _ref(repl_env, key, types.types_ns.get(key));
+ for (String key : core.ns.keySet()) {
+ _ref(repl_env, key, core.ns.get(key));
}
_ref(repl_env, "read-string", new MalFunction() {
public MalVal apply(MalList args) throws MalThrowable {
diff --git a/java/src/main/java/mal/step8_macros.java b/java/src/main/java/mal/step8_macros.java
index 47732dd..c834119 100644
--- a/java/src/main/java/mal/step8_macros.java
+++ b/java/src/main/java/mal/step8_macros.java
@@ -12,6 +12,9 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
+import mal.env.Env;
+import mal.core;
public class step8_macros {
// read
@@ -38,12 +41,12 @@ public class step8_macros {
(((MalSymbol)a00).getName() == "splice-unquote")) {
return new MalList(new MalSymbol("concat"),
((MalList)a0).nth(1),
- quasiquote(types._rest((MalList)ast)));
+ quasiquote(((MalList)ast).rest()));
}
}
return new MalList(new MalSymbol("cons"),
quasiquote(a0),
- quasiquote(types._rest((MalList)ast)));
+ quasiquote(((MalList)ast).rest()));
}
}
@@ -68,7 +71,7 @@ public class step8_macros {
while (is_macro_call(ast, env)) {
MalSymbol a0 = (MalSymbol)((MalList)ast).nth(0);
MalFunction mac = (MalFunction) env.get(a0.getName());
- ast = mac.apply(types._rest((MalList)ast));
+ ast = mac.apply(((MalList)ast).rest());
}
return ast;
}
@@ -79,8 +82,8 @@ public class step8_macros {
return env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -99,22 +102,22 @@ public class step8_macros {
}
public static MalVal EVAL(MalVal orig_ast, Env env) throws MalThrowable {
- MalVal a1,a2, a3, res;
+ MalVal a0, a1,a2, a3, res;
MalList el;
while (true) {
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
// apply list
MalVal expanded = macroexpand(orig_ast, env);
- if (!types._list_Q(expanded)) { return expanded; }
+ if (!expanded.list_Q()) { return expanded; }
MalList ast = (MalList) expanded;
if (ast.size() == 0) { return ast; }
- MalVal a0 = ast.nth(0);
+ a0 = ast.nth(0);
String a0sym = a0 instanceof MalSymbol ? ((MalSymbol)a0).getName()
: "__<*fn*>__";
switch (a0sym) {
@@ -173,7 +176,7 @@ public class step8_macros {
final MalList a1f = (MalList)ast.nth(1);
final MalVal a2f = ast.nth(2);
final Env cur_env = env;
- return new MalFunction (a2f, (mal.types.Env)env, a1f) {
+ return new MalFunction (a2f, (mal.env.Env)env, a1f) {
public MalVal apply(MalList args) throws MalThrowable {
return EVAL(a2f, new Env(cur_env, a1f, args));
}
@@ -186,7 +189,7 @@ public class step8_macros {
orig_ast = fnast;
env = new Env(f.getEnv(), f.getParams(), el.slice(1));
} else {
- return f.apply(types._rest(el));
+ return f.apply(el.rest());
}
}
@@ -195,7 +198,7 @@ public class step8_macros {
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -218,8 +221,8 @@ public class step8_macros {
String prompt = "user> ";
final Env repl_env = new Env(null);
- for (String key : types.types_ns.keySet()) {
- _ref(repl_env, key, types.types_ns.get(key));
+ for (String key : core.ns.keySet()) {
+ _ref(repl_env, key, core.ns.get(key));
}
_ref(repl_env, "read-string", new MalFunction() {
public MalVal apply(MalList args) throws MalThrowable {
diff --git a/java/src/main/java/mal/stepA_more.java b/java/src/main/java/mal/stepA_more.java
index d3bb161..9f4fb07 100644
--- a/java/src/main/java/mal/stepA_more.java
+++ b/java/src/main/java/mal/stepA_more.java
@@ -14,6 +14,9 @@ import java.util.Iterator;
import mal.types.*;
import mal.readline;
import mal.reader;
+import mal.printer;
+import mal.env.Env;
+import mal.core;
public class stepA_more {
// read
@@ -40,12 +43,12 @@ public class stepA_more {
(((MalSymbol)a00).getName() == "splice-unquote")) {
return new MalList(new MalSymbol("concat"),
((MalList)a0).nth(1),
- quasiquote(types._rest((MalList)ast)));
+ quasiquote(((MalList)ast).rest()));
}
}
return new MalList(new MalSymbol("cons"),
quasiquote(a0),
- quasiquote(types._rest((MalList)ast)));
+ quasiquote(((MalList)ast).rest()));
}
}
@@ -70,7 +73,7 @@ public class stepA_more {
while (is_macro_call(ast, env)) {
MalSymbol a0 = (MalSymbol)((MalList)ast).nth(0);
MalFunction mac = (MalFunction) env.get(a0.getName());
- ast = mac.apply(types._rest((MalList)ast));
+ ast = mac.apply(((MalList)ast).rest());
}
return ast;
}
@@ -81,8 +84,8 @@ public class stepA_more {
return env.get(sym.getName());
} else if (ast instanceof MalList) {
MalList old_lst = (MalList)ast;
- MalList new_lst = types._list_Q(ast) ? new MalList()
- : (MalList)new MalVector();
+ MalList new_lst = ast.list_Q() ? new MalList()
+ : (MalList)new MalVector();
for (MalVal mv : (List<MalVal>)old_lst.value) {
new_lst.conj_BANG(EVAL(mv, env));
}
@@ -101,22 +104,22 @@ public class stepA_more {
}
public static MalVal EVAL(MalVal orig_ast, Env env) throws MalThrowable {
- MalVal a1,a2, a3, res;
+ MalVal a0, a1,a2, a3, res;
MalList el;
while (true) {
- //System.out.println("EVAL: " + types._pr_str(orig_ast, true));
- if (!(types._list_Q(orig_ast))) {
+ //System.out.println("EVAL: " + printer._pr_str(orig_ast, true));
+ if (!orig_ast.list_Q()) {
return eval_ast(orig_ast, env);
}
// apply list
MalVal expanded = macroexpand(orig_ast, env);
- if (!types._list_Q(expanded)) { return expanded; }
+ if (!expanded.list_Q()) { return expanded; }
MalList ast = (MalList) expanded;
if (ast.size() == 0) { return ast; }
- MalVal a0 = ast.nth(0);
+ a0 = ast.nth(0);
String a0sym = a0 instanceof MalSymbol ? ((MalSymbol)a0).getName()
: "__<*fn*>__";
switch (a0sym) {
@@ -199,7 +202,7 @@ public class stepA_more {
final MalList a1f = (MalList)ast.nth(1);
final MalVal a2f = ast.nth(2);
final Env cur_env = env;
- return new MalFunction (a2f, (mal.types.Env)env, a1f) {
+ return new MalFunction (a2f, (mal.env.Env)env, a1f) {
public MalVal apply(MalList args) throws MalThrowable {
return EVAL(a2f, new Env(cur_env, a1f, args));
}
@@ -212,7 +215,7 @@ public class stepA_more {
orig_ast = fnast;
env = new Env(f.getEnv(), f.getParams(), el.slice(1));
} else {
- return f.apply(types._rest(el));
+ return f.apply(el.rest());
}
}
@@ -221,7 +224,7 @@ public class stepA_more {
// print
public static String PRINT(MalVal exp) {
- return types._pr_str(exp, true);
+ return printer._pr_str(exp, true);
}
// REPL
@@ -244,8 +247,8 @@ public class stepA_more {
String prompt = "user> ";
final Env repl_env = new Env(null);
- for (String key : types.types_ns.keySet()) {
- _ref(repl_env, key, types.types_ns.get(key));
+ for (String key : core.ns.keySet()) {
+ _ref(repl_env, key, core.ns.get(key));
}
_ref(repl_env, "readline", new MalFunction() {
public MalVal apply(MalList args) throws MalThrowable {
@@ -315,7 +318,7 @@ public class stepA_more {
System.out.println(e.getMessage());
continue;
} catch (MalException e) {
- System.out.println("Error: " + types._pr_str(e.getValue(), false));
+ System.out.println("Error: " + printer._pr_str(e.getValue(), false));
continue;
} catch (MalThrowable t) {
System.out.println("Error: " + t.getMessage());
diff --git a/java/src/main/java/mal/types.java b/java/src/main/java/mal/types.java
index 8a4910b..a53c0e9 100644
--- a/java/src/main/java/mal/types.java
+++ b/java/src/main/java/mal/types.java
@@ -2,12 +2,12 @@ package mal;
import java.util.List;
import java.util.ArrayList;
-import com.google.common.base.Joiner;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
-import com.google.common.collect.ImmutableMap;
-import org.apache.commons.lang3.StringEscapeUtils;
+
+import mal.printer;
+import mal.env.Env;
public class types {
//
@@ -34,6 +34,41 @@ public class types {
public MalVal getValue() { return value; }
}
+ //
+ // General functions
+ //
+
+ public static Boolean _equal_Q(MalVal a, MalVal b) {
+ Class ota = a.getClass(), otb = b.getClass();
+ if (!((ota == otb) ||
+ (a instanceof MalList && b instanceof MalList))) {
+ return false;
+ } else {
+ if (a instanceof MalInteger) {
+ return ((MalInteger)a).getValue() ==
+ ((MalInteger)b).getValue();
+ } else if (a instanceof MalSymbol) {
+ return ((MalSymbol)a).getName().equals(
+ ((MalSymbol)b).getName());
+ } else if (a instanceof MalString) {
+ return ((MalString)a).getValue().equals(
+ ((MalString)b).getValue());
+ } else if (a instanceof MalList) {
+ if (((MalList)a).size() != ((MalList)b).size()) {
+ return false;
+ }
+ for (Integer i=0; i<((MalList)a).size(); i++) {
+ if (! _equal_Q(((MalList)a).nth(i),
+ ((MalList)b).nth(i))) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return a == b;
+ }
+ }
+ }
//
// Mal boxed types
@@ -48,6 +83,7 @@ public class types {
}
public MalVal getMeta() { return meta; }
public void setMeta(MalVal m) { meta = m; }
+ public Boolean list_Q() { return false; }
}
public static class MalConstant extends MalVal {
String value;
@@ -56,9 +92,9 @@ public class types {
public String toString() { return value; }
}
- static MalConstant Nil = new MalConstant("nil");
- static MalConstant True = new MalConstant("true");
- static MalConstant False = new MalConstant("false");
+ public static MalConstant Nil = new MalConstant("nil");
+ public static MalConstant True = new MalConstant("true");
+ public static MalConstant False = new MalConstant("false");
public static class MalInteger extends MalVal {
Integer value;
@@ -117,7 +153,7 @@ public class types {
}
public String toString(Boolean print_readably) {
if (print_readably) {
- return "\"" + StringEscapeUtils.escapeJson(value) + "\"";
+ return "\"" + printer.escapeString(value) + "\"";
} else {
return value;
}
@@ -141,19 +177,15 @@ public class types {
return new_ml;
}
- String _join(String delim, Boolean print_readably) {
- ArrayList<String> strs = new ArrayList<String>();
- for (MalVal mv : (List<MalVal>)value) {
- strs.add(mv.toString(print_readably));
- }
- return Joiner.on(delim).join(strs);
- }
@Override public String toString() {
- return start + _join(" ", true) + end;
+ return start + printer.join(value, " ", true) + end;
}
public String toString(Boolean print_readably) {
- return start + _join(" ", print_readably) + end;
+ return start + printer.join(value, " ", print_readably) + end;
}
+
+ public List getList() { return value; }
+ public Boolean list_Q() { return true; }
public MalList conj_BANG(MalVal... mvs) {
for (MalVal mv : mvs) {
@@ -169,6 +201,14 @@ public class types {
public MalVal nth(Integer idx) {
return (MalVal)value.get(idx);
}
+ public MalList rest () {
+ if (size() > 0) {
+ return new MalList(value.subList(1, value.size()));
+ } else {
+ return new MalList();
+ }
+ }
+
public MalList slice(Integer start, Integer end) {
return new MalList(value.subList(start, end));
@@ -197,6 +237,8 @@ public class types {
return new_mv;
}
+ public Boolean list_Q() { return false; }
+
public MalVector slice(Integer start, Integer end) {
return new MalVector(value.subList(start, end));
}
@@ -223,24 +265,11 @@ public class types {
return new_hm;
}
- String _join(Boolean print_readably) {
- ArrayList<String> strs = new ArrayList<String>();
- for (Map.Entry<String, MalVal> entry :
- ((Map<String,MalVal>)value).entrySet()) {
- if (print_readably) {
- strs.add("\"" + entry.getKey().toString() + "\"");
- } else {
- strs.add(entry.getKey().toString());
- }
- strs.add(entry.getValue().toString(print_readably));
- }
- return Joiner.on(" ").join(strs);
- }
@Override public String toString() {
- return "{" + _join(true) + "}";
+ return "{" + printer.join(value, " ", true) + "}";
}
public String toString(Boolean print_readably) {
- return "{" + _join(print_readably) + "}";
+ return "{" + printer.join(value, " ", print_readably) + "}";
}
public Set _entries() {
@@ -280,10 +309,10 @@ public class types {
public MalAtom(MalVal value) { this.value = value; }
public MalAtom copy() throws MalThrowable { return new MalAtom(value); }
@Override public String toString() {
- return "(atom " + _pr_str(value, true) + ")";
+ return "(atom " + printer._pr_str(value, true) + ")";
}
public String toString(Boolean print_readably) {
- return "(atom " + _pr_str(value, print_readably) + ")";
+ return "(atom " + printer._pr_str(value, print_readably) + ")";
}
}
@@ -329,563 +358,4 @@ public class types {
public Boolean isMacro() { return macro; }
public void setMacro() { macro = true; }
}
-
-
- //
- // General functions
- //
- public static String _pr_str(MalVal mv, Boolean print_readably) {
- return mv.toString(print_readably);
- }
-
- public static String _pr_str_args(MalList args, String sep, Boolean print_readably) {
- return args._join(sep, print_readably);
- }
-
- static MalFunction pr_str = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return new MalString(_pr_str_args(args, " ", true));
- }
- };
-
- static MalFunction str = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return new MalString(_pr_str_args(args, "", false));
- }
- };
-
- static MalFunction prn = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- System.out.println(_pr_str_args(args, " ", true));
- return Nil;
- }
- };
-
- static MalFunction println = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- System.out.println(_pr_str_args(args, " ", false));
- return Nil;
- }
- };
-
-
- static MalFunction meta = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return args.nth(0).getMeta();
- }
- };
-
- static MalFunction with_meta = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- MalVal new_mv = ((MalVal)args.nth(0)).copy();
- new_mv.setMeta(args.nth(1));
- return new_mv;
- }
- };
-
-
- public static Boolean _equal_Q(MalVal a, MalVal b) {
- Class ota = a.getClass(), otb = b.getClass();
- if (!((ota == otb) ||
- (a instanceof MalList && b instanceof MalList))) {
- return false;
- } else {
- if (a instanceof MalInteger) {
- return ((MalInteger)a).getValue() ==
- ((MalInteger)b).getValue();
- } else if (a instanceof MalSymbol) {
- return ((MalSymbol)a).getName().equals(
- ((MalSymbol)b).getName());
- } else if (a instanceof MalString) {
- return ((MalString)a).getValue().equals(
- ((MalString)b).getValue());
- } else if (a instanceof MalList) {
- if (((MalList)a).size() != ((MalList)b).size()) {
- return false;
- }
- for (Integer i=0; i<((MalList)a).size(); i++) {
- if (! _equal_Q(((MalList)a).nth(i),
- ((MalList)b).nth(i))) {
- return false;
- }
- }
- return true;
- } else {
- return a == b;
- }
- }
- }
-
- static MalFunction equal_Q = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return _equal_Q(args.nth(0), args.nth(1)) ? True : False;
- }
- };
-
-
- //
- // Constants operations
- //
- static MalFunction symbol_Q = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return args.nth(0) instanceof MalSymbol ? True : False;
- }
- };
-
- static MalFunction nil_Q = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return args.nth(0) == Nil ? True : False;
- }
- };
-
- static MalFunction true_Q = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return args.nth(0) == True ? True : False;
- }
- };
-
- static MalFunction false_Q = new MalFunction() {
- public MalVal apply(MalList args) throws MalThrowable {
- return args.nth(0) == False ? True : False;
- }
- };
-
-
- //
- // Number operations
- //
- 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));
- }
- };
-
- static MalFunction lt = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return ((MalInteger)a.nth(0)).lt((MalInteger)a.nth(1));
- }
- };
- static MalFunction lte = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return ((MalInteger)a.nth(0)).lte((MalInteger)a.nth(1));
- }
- };
- static MalFunction gt = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return ((MalInteger)a.nth(0)).gt((MalInteger)a.nth(1));
- }
- };
- static MalFunction gte = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return ((MalInteger)a.nth(0)).gte((MalInteger)a.nth(1));
- }
- };
-
- //
- // Errors/Exceptions
- //
- static MalFunction mal_throw = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- throw new MalException(a.nth(0));
- }
- };
-
- //
- // List operations
- //
- static MalFunction new_list = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return new MalList(a.value);
- }
- };
-
- static public Boolean _list_Q(MalVal mv) {
- return mv.getClass().equals(MalList.class);
- }
- static MalFunction list_Q = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return _list_Q(a.nth(0)) ? True : False;
- }
- };
-
- //
- // Vector operations
- //
- static MalFunction new_vector = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return new MalVector(a.value);
- }
- };
-
- static public Boolean _vector_Q(MalVal mv) {
- return mv.getClass().equals(MalVector.class);
- }
- static MalFunction vector_Q = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return _vector_Q(a.nth(0)) ? True : False;
- }
- };
-
- //
- // Hash map operations
- //
- static MalFunction new_hash_map = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return new MalHashMap(a);
- }
- };
-
- static MalFunction hash_map_Q = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return a.nth(0) instanceof MalHashMap ? True : False;
- }
- };
-
- static MalFunction contains_Q = 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;
- return hm.containsKey(key) ? True : False;
- }
- };
-
- static MalFunction assoc = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalHashMap mhm = (MalHashMap)a.nth(0);
- HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
- MalHashMap new_mhm = new MalHashMap((Map)hm.clone());
- new_mhm.assoc_BANG((MalList)a.slice(1));
- return new_mhm;
- }
- };
-
- static MalFunction dissoc = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalHashMap mhm = (MalHashMap)a.nth(0);
- HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
- MalHashMap new_mhm = new MalHashMap((Map)hm.clone());
- new_mhm.dissoc_BANG((MalList)a.slice(1));
- return new_mhm;
- }
- };
-
- 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 {
- return Nil;
- }
- }
- };
-
- static MalFunction keys = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalHashMap mhm = (MalHashMap)a.nth(0);
- HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
- MalList key_lst = new MalList();
- for (String key : hm.keySet()) {
- key_lst.conj_BANG(new MalString(key));
- }
- return key_lst;
- }
- };
-
- static MalFunction vals = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalHashMap mhm = (MalHashMap)a.nth(0);
- HashMap<String,MalVal> hm = (HashMap<String,MalVal>)mhm.value;
- //return new ArrayList<MalVal>(((HashMap<String,MalVal>)hm).values());
- MalList val_lst = new MalList();
- for (MalVal val : hm.values()) {
- val_lst.conj_BANG(val);
- }
- return val_lst;
- }
- };
-
-
- //
- // Atoms
- //
- static MalFunction new_atom = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return new MalAtom(a.nth(0));
- }
- };
-
- static MalFunction atom_Q = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return a.nth(0) instanceof MalAtom ? True : False;
- }
- };
-
- static MalFunction deref = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return ((MalAtom)a.nth(0)).value;
- }
- };
-
- static MalFunction reset_BANG = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return ((MalAtom)a.nth(0)).value = a.nth(1);
- }
- };
-
- static MalFunction swap_BANG = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalAtom atm = (MalAtom)a.nth(0);
- MalFunction f = (MalFunction)a.nth(1);
- MalList new_args = new MalList();
- new_args.value.addAll(((MalList)a.slice(2)).value);
- new_args.value.add(0, atm.value);
- atm.value = f.apply(new_args);
- return atm.value;
- }
- };
-
-
-
-
- //
- // Sequence operations
- //
- static MalFunction sequential_Q = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return a.nth(0) instanceof MalList ? True : False;
- }
- };
-
- static MalFunction count = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- return new MalInteger(((MalList)a.nth(0)).size());
- }
- };
-
- static MalFunction empty_Q = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalVal exp = a.nth(0);
- if (exp == Nil || (exp instanceof MalList &&
- ((MalList)exp).size() == 0)) {
- return True;
- } else {
- return False;
- }
- }
- };
-
- 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;
- }
- };
-
- 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);
- for(Integer i=1; i<a.size(); i++) {
- lst.value.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;
- }
- };
-
- static MalFunction first = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalList ml = ((MalList)a.nth(0));
- return ml.size() > 0 ? ml.nth(0) : Nil;
- }
- };
-
- static MalList _rest (MalList ml) {
- if (ml.size() > 0) {
- return new MalList(ml.value.subList(1, ml.value.size()));
- } else {
- return new MalList();
- }
- }
-
- static MalFunction rest = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalList ml = ((MalList)a.nth(0));
- return _rest(ml);
- }
- };
-
- static MalFunction nth = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- Integer idx = ((MalInteger)a.nth(1)).getValue();
- return ((MalList)a.nth(0)).nth(idx);
- }
- };
-
- // General list related functions
- static MalFunction apply = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalFunction f = (MalFunction)a.nth(0);
- MalList args = a.slice(1,a.size()-1);
- args.value.addAll( ((MalList)a.nth(a.size()-1)).value);
- return f.apply(args);
- }
- };
-
- static MalFunction map = new MalFunction() {
- public MalVal apply(MalList a) throws MalThrowable {
- MalFunction f = (MalFunction) a.nth(0);
- MalList src_lst = (MalList) a.nth(1);
- MalList new_lst = new MalList();
- for(Integer i=0; i<src_lst.size(); i++) {
- new_lst.value.add(
- f.apply(new MalList(src_lst.nth(i))));
- }
- return new_lst;
- }
- };
-
-
-
- //
- // Env implementation
- //
- public static class Env {
- Env outer = null;
- HashMap<String,MalVal> data = new HashMap<String,MalVal>();
-
- public Env(Env outer) {
- this.outer = outer;
- }
- public Env(Env outer, MalList binds, MalList exprs) {
- this.outer = outer;
- for (Integer i=0; i<binds.size(); i++) {
- String sym = ((MalSymbol)binds.nth(i)).getName();
- if (sym.equals("&")) {
- data.put(((MalSymbol)binds.nth(i+1)).getName(),
- exprs.slice(i));
- break;
- } else {
- data.put(sym, exprs.nth(i));
- }
- }
- }
-
- public Env find(String key) {
- if (data.containsKey(key)) {
- return this;
- } else if (outer != null) {
- return outer.find(key);
- } else {
- return null;
- }
- }
-
- public MalVal get(String key) throws MalThrowable {
- Env e = find(key);
- if (e == null) {
- throw new MalException("'" + key + "' not found");
- } else {
- return e.data.get(key);
- }
- }
-
- public Env set(String key, MalVal value) {
- data.put(key, value);
- return this;
- }
- }
-
- // types_ns is namespace of type functions
- static Map<String, MalVal> types_ns = ImmutableMap.<String, MalVal>builder()
- .put("pr-str", pr_str)
- .put("str", str)
- .put("prn", prn)
- .put("println", println)
- .put("meta", meta)
- .put("with-meta", with_meta)
- .put("=", equal_Q)
- .put("symbol?", symbol_Q)
- .put("nil?", nil_Q)
- .put("true?", true_Q)
- .put("false?", false_Q)
- .put("<", lt)
- .put("<=", lte)
- .put(">", gt)
- .put(">=", gte)
- .put("+", add)
- .put("-", subtract)
- .put("*", multiply)
- .put("/", divide)
- .put("throw", mal_throw)
- .put("list", new_list)
- .put("list?", list_Q)
- .put("vector", new_vector)
- .put("vector?", vector_Q)
- .put("hash-map", new_hash_map)
- .put("map?", hash_map_Q)
- .put("assoc", assoc)
- .put("dissoc", dissoc)
- .put("contains?", contains_Q)
- .put("get", get)
- .put("keys", keys)
- .put("vals", vals)
- .put("atom", new_atom)
- .put("atom?", atom_Q)
- .put("deref", deref)
- .put("reset!", reset_BANG)
- .put("swap!", swap_BANG)
- .put("sequential?", sequential_Q)
- .put("cons", cons)
- .put("concat", concat)
- .put("conj", conj)
- .put("first", first)
- .put("rest", rest)
- .put("nth", nth)
- .put("count", count)
- .put("empty?", empty_Q)
- .put("apply", apply)
- .put("map", map)
- .build();
}