From ad316bbe61c6fa3262669df9bcd3ffeb04a52e3f Mon Sep 17 00:00:00 2001 From: Ezra Zygmuntowicz Date: Tue, 23 Nov 2010 21:24:16 -0800 Subject: [PATCH] more tweaks for correctness, added more examples to make sure proper results are being interpreted --- bin/ez-scheme | 2 +- lib/ez-scheme/builtins.rb | 15 ++++++++++----- lib/ez-scheme/environment.rb | 3 ++- lib/ez-scheme/expr.rb | 7 ++++--- lib/ez-scheme/interpreter.rb | 16 ++++++---------- 5 files changed, 23 insertions(+), 20 deletions(-) diff --git a/bin/ez-scheme b/bin/ez-scheme index 5cbe7af..919c491 100755 --- a/bin/ez-scheme +++ b/bin/ez-scheme @@ -2,7 +2,7 @@ require 'ez-scheme/interpreter' if file = ARGV[0] inp = IO.read(file) - interpret_code(inp) + interactive_interpreter(interpret_code(inp)) else interactive_interpreter() end \ No newline at end of file diff --git a/lib/ez-scheme/builtins.rb b/lib/ez-scheme/builtins.rb index 222f71d..820379f 100644 --- a/lib/ez-scheme/builtins.rb +++ b/lib/ez-scheme/builtins.rb @@ -90,7 +90,7 @@ def builtin_eqv(args) # left, right = args[0], args[1] - if left.instance_of(Pair) and right.instance_of(Pair) + if left.instance_of?(Pair) and right.instance_of?(Pair) Boolean.new(left.object_id == right.object_id) else Boolean.new(left == right) @@ -134,16 +134,21 @@ def builtin_or(args) end def make_comparison_operator_builtin(op) - lambda{ |args| + Proc.new{ |args| a = args[0] + res = nil for b in args[1..-1] - if send(op, a.value, b.value) + if a.value.send(op, b.value) a = b else - return Boolean.new(false) + break res = Boolean.new(false) end end - Boolean.new(true) + if res + res + else + Boolean.new(true) + end } end diff --git a/lib/ez-scheme/environment.rb b/lib/ez-scheme/environment.rb index 2cd3d62..027e77c 100644 --- a/lib/ez-scheme/environment.rb +++ b/lib/ez-scheme/environment.rb @@ -30,7 +30,8 @@ def lookup_var(var) elsif ! @parent.nil? return @parent.lookup_var(var) else - raise Unbound.new("unbound variable '#{var}'") + return nil + #raise Unbound.new("unbound variable '#{var}'") end end diff --git a/lib/ez-scheme/expr.rb b/lib/ez-scheme/expr.rb index c187ef7..ea56d82 100644 --- a/lib/ez-scheme/expr.rb +++ b/lib/ez-scheme/expr.rb @@ -111,7 +111,8 @@ def repr_rec(obj) elsif obj.instance_of?(Array) obj.map {|o| repr_rec(o) }.join("\n") else - raise ExprError.new("Unexpected type: #{obj.class}") + obj.class.to_s + #raise ExprError.new("Unexpected type: #{obj.class}") end end @@ -408,8 +409,8 @@ def convert_let_to_application(exp) bindings = let_bindings(exp) while ! bindings.nil? - vars.append(bindings.first.first) - vals.append(bindings.first.second.first) + vars << bindings.first.first + vals << bindings.first.second.first bindings = bindings.second end lambda_expr = make_lambda(make_nested_pairs(*vars), let_body(exp)) diff --git a/lib/ez-scheme/interpreter.rb b/lib/ez-scheme/interpreter.rb index c031177..d17ff40 100644 --- a/lib/ez-scheme/interpreter.rb +++ b/lib/ez-scheme/interpreter.rb @@ -4,7 +4,7 @@ require File.dirname(__FILE__) + '/builtins' require 'pp' -DEBUG = true +DEBUG = ENV['DEBUG'] class Procedure @@ -87,7 +87,6 @@ def _eval(expr, env) elsif is_begin(expr) return _eval_sequence(begin_actions(expr), env) elsif is_application(expr) - puts "eval apply" return _apply(_eval(application_operator(expr), env), _list_of_values(application_operands(expr), env)) else @@ -123,14 +122,10 @@ def _list_of_values(exprs, env) def _apply(proc, args) # Standard Scheme apply (SICP 4.1.1) # - if DEBUG - puts("~~~~ Applying procedure #{proc}") - puts(" with args #{expr_repr(args)}") - end - if proc.instance_of?(BuiltinProcedure) if DEBUG puts("~~~~ Applying builtin procedure: #{proc.name}") + puts(" with args #{expr_repr(args)}") end # The '' builtin gets the current output stream as a custom # argument @@ -138,7 +133,7 @@ def _apply(proc, args) return proc.apply(expand_nested_pairs(args)) elsif proc.instance_of?(Procedure) if DEBUG - puts("~~~~ Applying procedure with args: #{proc.args}") + puts("~~~~ Applying procedure with args: #{expr_repr(proc.args)}") puts(" and body:\n#{expr_repr(proc.body)}") end return _eval_sequence(proc.body, @@ -201,12 +196,13 @@ def interpret_code(code_str, output_stream=nil) for expr in parsed_exprs interp.interpret(expr) end + interp end -def interactive_interpreter() +def interactive_interpreter(interp=nil) # Interactive interpreter - interp = ::SchemeInterpreter.new # by default output_stream is sys.stdout + interp ||= ::SchemeInterpreter.new # by default output_stream is sys.stdout parser = ::SchemeParser.new puts("Type a Scheme expression or 'quit'")