diff options
| author | Joel Martin <github@martintribe.org> | 2014-04-10 21:12:17 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2014-04-10 21:12:17 -0500 |
| commit | b5f469de182a3e95b2d968ddccf2e2f9b77a3dc2 (patch) | |
| tree | 04052d317166c09058ebac414e9cfdc7825fa038 | |
| parent | 136e5690eec17aa90c35e3fccd8ad6100acd9356 (diff) | |
| download | mal-b5f469de182a3e95b2d968ddccf2e2f9b77a3dc2.tar.gz mal-b5f469de182a3e95b2d968ddccf2e2f9b77a3dc2.zip | |
Ruby: add step3
| -rw-r--r-- | ruby/env.rb | 28 | ||||
| -rw-r--r-- | ruby/step3_env.rb | 70 |
2 files changed, 98 insertions, 0 deletions
diff --git a/ruby/env.rb b/ruby/env.rb new file mode 100644 index 0000000..dfd5ec9 --- /dev/null +++ b/ruby/env.rb @@ -0,0 +1,28 @@ +class Env + attr_accessor :data + def initialize(outer=nil, binds=[], exprs=[]) + @data = {} + @outer = outer + end + + def find(key) + if @data.key? key + return self + elsif @outer + return @outer.find(key) + else + return nil + end + end + + def set(key, value) + @data[key] = value + return value + end + + def get(key) + env = find(key) + raise "'" + key.to_s + "' not found" if not env + env.data[key] + end +end diff --git a/ruby/step3_env.rb b/ruby/step3_env.rb new file mode 100644 index 0000000..97be81d --- /dev/null +++ b/ruby/step3_env.rb @@ -0,0 +1,70 @@ +require "readline" +require "types" +require "reader" +require "printer" +require "env" + +# read +def READ(str) + return read_str(str) +end + +# eval +def eval_ast(ast, env) + return case ast + when Symbol + env.get(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 + a0,a1,a2,a3 = ast + case a0 + when :"def!" + return env.set(a1, EVAL(a2, env)) + when :"let*" + let_env = Env.new(env) + + a1.each_slice(2) {|a,e| let_env.set(a, EVAL(e, let_env))} + return EVAL(a2, let_env) + else + el = eval_ast(ast, env) + f = el[0] + return f[*el.drop(1)] + end +end + +# print +def PRINT(exp) + return _pr_str(exp, true) +end + +# repl +repl_env = Env.new +REP = lambda {|str| PRINT(EVAL(READ(str), repl_env)) } +_ref = lambda {|k,v| repl_env.set(k, v) } + +_ref[:+, lambda {|a,b| a + b}] +_ref[:-, lambda {|a,b| a - b}] +_ref[:*, lambda {|a,b| a * b}] +_ref[:/, 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 |
