aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-04-10 20:48:26 -0500
committerJoel Martin <github@martintribe.org>2014-04-10 20:48:26 -0500
commit136e5690eec17aa90c35e3fccd8ad6100acd9356 (patch)
treed7928b0a74ec74cc6d007dc47cce24aec7750e09
parentf705f0fce151863091ad77753105f0d15270edec (diff)
downloadmal-136e5690eec17aa90c35e3fccd8ad6100acd9356.tar.gz
mal-136e5690eec17aa90c35e3fccd8ad6100acd9356.zip
Ruby: step2_eval
-rw-r--r--ruby/step2_eval.rb58
1 files changed, 58 insertions, 0 deletions
diff --git a/ruby/step2_eval.rb b/ruby/step2_eval.rb
new file mode 100644
index 0000000..9cbae24
--- /dev/null
+++ b/ruby/step2_eval.rb
@@ -0,0 +1,58 @@
+require "readline"
+require "types"
+require "reader"
+require "printer"
+
+# read
+def READ(str)
+ return read_str(str)
+end
+
+# eval
+def eval_ast(ast, env)
+ return case ast
+ when Symbol
+ raise "'" + ast.to_s + "' not found" if not env.key? ast
+ env[ast]
+ when List
+ List.new ast.map{|a| EVAL(a, env)}
+ when Vector
+ Vector.new ast.map{|a| EVAL(a, env)}
+ else
+ ast
+ end
+end
+
+def EVAL(ast, env)
+ if not ast.is_a? List
+ return eval_ast(ast, env)
+ end
+
+ # apply list
+ el = eval_ast(ast, env)
+ f = el[0]
+ return f[*el.drop(1)]
+end
+
+# print
+def PRINT(exp)
+ return _pr_str(exp, true)
+end
+
+# repl
+repl_env = {}
+REP = lambda {|str| PRINT(EVAL(READ(str), repl_env)) }
+
+repl_env[:+] = lambda {|a,b| a + b}
+repl_env[:-] = lambda {|a,b| a - b}
+repl_env[:*] = lambda {|a,b| a * b}
+repl_env[:/] = lambda {|a,b| a / b}
+
+while line = Readline.readline("user> ", true)
+ begin
+ puts REP[line]
+ rescue Exception => e
+ puts "Error: #{e}"
+ puts "\t#{e.backtrace.join("\n\t")}"
+ end
+end