diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-06 22:38:26 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-06 22:38:26 -0500 |
| commit | b56c49a12dad20c55fbf07775b536c9d656af313 (patch) | |
| tree | 11989cec7ac0bc5ce4cc3b1ea46c9948847cc044 | |
| parent | 53beaa0a6ddd9d8a5fb531f97c44a9c7129d1de7 (diff) | |
| download | mal-b56c49a12dad20c55fbf07775b536c9d656af313.tar.gz mal-b56c49a12dad20c55fbf07775b536c9d656af313.zip | |
C#: add step2_eval.
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | cs/Makefile | 2 | ||||
| -rw-r--r-- | cs/step2_eval.cs | 146 | ||||
| -rw-r--r-- | cs/types.cs | 23 |
4 files changed, 170 insertions, 2 deletions
@@ -19,6 +19,7 @@ c/step9_interop c/stepA_more cs/*.exe cs/*.dll +cs/*.mdb clojure/target clojure/.lein-repl-history java/target/ diff --git a/cs/Makefile b/cs/Makefile index 0028096..7a56e5d 100644 --- a/cs/Makefile +++ b/cs/Makefile @@ -3,7 +3,7 @@ TESTS = SOURCES = readline.cs types.cs reader.cs printer.cs \ - step0_repl.cs step1_read_print.cs + step0_repl.cs step1_read_print.cs step2_eval.cs OTHER_SOURCES = getline.cs ##################### diff --git a/cs/step2_eval.cs b/cs/step2_eval.cs new file mode 100644 index 0000000..fa01901 --- /dev/null +++ b/cs/step2_eval.cs @@ -0,0 +1,146 @@ +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using Mal; +using MalVal = Mal.types.MalVal; +using MalSymbol = Mal.types.MalSymbol; +using MalInteger = Mal.types.MalInteger; +using MalList = Mal.types.MalList; +using MalVector = Mal.types.MalVector; +using MalHashMap = Mal.types.MalHashMap; +using MalFunction = Mal.types.MalFunction; + +namespace Mal { + class step1_repl { + // read + static MalVal READ(string str) { + return reader.read_str(str); + } + + // eval + static MalVal eval_ast(MalVal ast, Dictionary<string, MalVal> env) { + if (ast is MalSymbol) { + MalSymbol sym = (MalSymbol)ast; + return (MalVal)env[sym.getName()]; + } else if (ast is MalList) { + MalList old_lst = (MalList)ast; + MalList new_lst = ast.list_Q() ? new MalList() + : (MalList)new MalVector(); + foreach (MalVal mv in old_lst.getValue()) { + new_lst.conj_BANG(EVAL(mv, env)); + } + return new_lst; + } else if (ast is MalHashMap) { + var new_dict = new Dictionary<string, MalVal>(); + foreach (var entry in ((MalHashMap)ast).getValue()) { + new_dict.Add(entry.Key, EVAL((MalVal)entry.Value, env)); + } + return new MalHashMap(new_dict); + } else { + return ast; + } + } + + + static MalVal EVAL(MalVal orig_ast, Dictionary<string, MalVal> env) { + MalVal a0; + //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; } + a0 = ast.nth(0); + if (!(a0 is MalSymbol)) { + throw new Mal.types.MalError("attempt to apply on non-symbol '" + + Mal.printer._pr_str(a0,true) + "'"); + } + MalVal args = eval_ast(ast.rest(), env); + MalSymbol fsym = (MalSymbol)a0; + var f = (MalFunction)env[fsym.getName()]; + if (f == null) { + throw new Mal.types.MalError("'" + fsym.getName() + "' not found"); + } + return f.apply((MalList)args); + + } + + // print + static string PRINT(MalVal exp) { + return printer._pr_str(exp, true); + } + + // REPL + static MalVal RE(Dictionary<string, MalVal> env, string str) { + return EVAL(READ(str), env); + } + + class plus : MalFunction { + public override MalVal apply(MalList args) { + return ((MalInteger)args.nth(0)).add( + ((MalInteger)args.nth(1))); + } + } + class minus : MalFunction { + public override MalVal apply(MalList args) { + return ((MalInteger)args.nth(0)).subtract( + ((MalInteger)args.nth(1))); + } + } + class multiply : MalFunction { + public override MalVal apply(MalList args) { + return ((MalInteger)args.nth(0)).multiply( + ((MalInteger)args.nth(1))); + } + } + class divide : MalFunction { + public override MalVal apply(MalList args) { + return ((MalInteger)args.nth(0)).divide( + ((MalInteger)args.nth(1))); + } + } + + + static void Main(string[] args) { + string prompt = "user> "; + + var repl_env = new Dictionary<string, MalVal> { + { "+", new plus() }, + { "-", new minus() }, + { "*", new multiply() }, + { "/", new divide() }, + }; + if (args.Length > 0 && args[0] == "--raw") { + Mal.readline.mode = Mal.readline.Mode.Raw; + } + + while (true) { + string line; + try { + line = Mal.readline.Readline(prompt); + if (line == null) { break; } + } catch (IOException e) { + Console.WriteLine("IOException: " + e.Message); + break; + } + try { + Console.WriteLine(PRINT(RE(repl_env, line))); + } catch (Mal.types.MalContinue) { + continue; + } catch (Mal.types.MalError e) { + Console.WriteLine("Error: " + e.Message); + continue; + } catch (Mal.reader.ParseError e) { + Console.WriteLine(e.Message); + continue; + } catch (Exception e) { + Console.WriteLine("Error: " + e.Message); + continue; + } + } + } + } +} diff --git a/cs/types.cs b/cs/types.cs index 1f2e797..7cbbd53 100644 --- a/cs/types.cs +++ b/cs/types.cs @@ -16,7 +16,10 @@ namespace Mal { public abstract class MalVal { // Default is just to call regular toString() - public abstract string ToString(bool print_readably); + public virtual string ToString(bool print_readably) { + return "<unknown>"; + } + public virtual bool list_Q() { return false; } } public class MalConstant : MalVal { @@ -127,6 +130,7 @@ namespace Mal { } public List<MalVal> getValue() { return value; } + public override bool list_Q() { return true; } public override string ToString() { return start + printer.join(value, " ", true) + end; @@ -141,6 +145,16 @@ namespace Mal { } return this; } + + public int size() { return value.Count; } + public MalVal nth(int idx) { return value[idx]; } + public MalVal rest() { + if (size() > 0) { + return new MalList(value.GetRange(1, value.Count-1)); + } else { + return new MalList(); + } + } } public class MalVector : MalList { @@ -164,6 +178,7 @@ namespace Mal { return (MalVector)this.MemberwiseClone(); } + public override bool list_Q() { return false; } } public class MalHashMap : MalVal { @@ -185,6 +200,8 @@ namespace Mal { return (MalHashMap)this.MemberwiseClone(); } + public Dictionary<string, MalVal> getValue() { return value; } + public override string ToString() { return "{" + printer.join(value, " ", true) + "}"; } @@ -206,5 +223,9 @@ namespace Mal { } } + public abstract class MalFunction : MalVal { + public abstract MalVal apply(MalList args); + } + } } |
