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 /cs/step2_eval.cs | |
| parent | 53beaa0a6ddd9d8a5fb531f97c44a9c7129d1de7 (diff) | |
| download | mal-b56c49a12dad20c55fbf07775b536c9d656af313.tar.gz mal-b56c49a12dad20c55fbf07775b536c9d656af313.zip | |
C#: add step2_eval.
Diffstat (limited to 'cs/step2_eval.cs')
| -rw-r--r-- | cs/step2_eval.cs | 146 |
1 files changed, 146 insertions, 0 deletions
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; + } + } + } + } +} |
