diff --git a/lib/parser/transform.rb b/lib/parser/transform.rb index 18b4c612..39d557dd 100644 --- a/lib/parser/transform.rb +++ b/lib/parser/transform.rb @@ -20,8 +20,10 @@ module Parser end rule(:conditional => simple(:conditional), - :if_true => {:block => simple(:if_true)}, - :if_false => {:block => simple(:if_false)}) { Vm::ConditionalExpression.new(conditional, if_true, if_false) } + :if_true => {:expressions => sequence(:if_true)}, + :if_false => {:expressions => sequence(:if_false)}) do + Vm::ConditionalExpression.new(conditional, if_true, if_false) + end rule(:parmeter => simple(:parmeter)) { parmeter } rule(:parmeter_list => sequence(:parmeter_list)) { parmeter_list } @@ -29,14 +31,14 @@ module Parser # need TWO transform rules, for one/many arguments (see the[] wrapping in the first) rule(:function_definition => simple(:function_definition), :parmeter_list => simple(:parmeter), - :block => simple(:block)) do - Vm::FunctionExpression.new(function_definition.name, [parmeter], block) + :expressions => sequence(:expressions)) do + Vm::FunctionExpression.new(function_definition.name, [parmeter], expressions) end rule(:function_definition => simple(:function_definition), :parmeter_list => sequence(:parmeter_list), - :block => simple(:block)) do - Vm::FunctionExpression.new(function_definition.name, parmeter_list, block) + :expressions => sequence(:expressions)) do + Vm::FunctionExpression.new(function_definition.name, parmeter_list, expressions) end #shortcut to get the ast tree for a given string diff --git a/lib/vm/nodes.rb b/lib/vm/nodes.rb index d7f33da3..8bbdaa41 100644 --- a/lib/vm/nodes.rb +++ b/lib/vm/nodes.rb @@ -5,6 +5,15 @@ module Vm def eval raise "abstract" end + def compare other , attributes + attributes.each do |a| + left = send(a) + right = other.send( a) + return false unless left.class == right.class + return false unless left == right + end + return true + end end class IntegerExpression < Expression @@ -12,6 +21,9 @@ module Vm def initialize val @value = val end + def == other + compare other , [:value] + end def eval(context, builder) builder.mov "r0" , value end @@ -22,11 +34,13 @@ module Vm def initialize name @name = name end + def == other + compare other , [:name] + end def eval(context, builder) param_names = context[:params] || [] position = param_names.index(name) raise "Unknown parameter #{name}" unless position - builder.iload position end end @@ -36,6 +50,9 @@ module Vm def initialize name, args @name , @args = name , args end + def == other + compare other , [:name , :args] + end def eval(context, builder) args.each { |a| a.eval(context, builder) } types = [builder.int] * (args.length + 1) @@ -48,6 +65,9 @@ module Vm def initialize cond, if_true, if_false @cond, @if_true, @if_false = cond, if_true, if_false end + def == other + compare other , [:cond, :if_true, :if_false] + end def eval(context, builder) cond.eval context, builder @@ -68,6 +88,9 @@ module Vm def initialize name, params, block @name, @params, @block = name, params, block end + def == other + compare other , [:name, :params, :block] + end def eval(context, builder) param_names = [params].flatten.map(&:name) context[:params] = param_names diff --git a/test/test_transform.rb b/test/test_transform.rb index 16c5962b..859650f4 100644 --- a/test/test_transform.rb +++ b/test/test_transform.rb @@ -10,7 +10,7 @@ class TransformTest < MiniTest::Test def check_equals is = @transform.apply @input - assert_equal @expected.class , is.class + assert_equal @expected , is end def test_number @input = {:integer => '42'} @@ -52,13 +52,15 @@ class TransformTest < MiniTest::Test end def test_conditional - @input = {:conditional => {:integer => '0'}, - :if_true => {:block => {:integer => '42'}}, - :if_false => {:block => {:integer => '667'}}} - @expected = Vm::ConditionalExpression.new \ - Vm::IntegerExpression.new(0), - Vm::IntegerExpression.new(42), - Vm::IntegerExpression.new(667) + @input = { :conditional => { :integer => "0"}, + :if_true => { :expressions => [ { :integer => "42" } ] } , + :if_false => { :expressions => [ { :integer => "667" } ] } } + # = {:conditional => {:integer => '0'}, + # :if_true => {:block => {:integer => '42'}}, + # :if_false => {:block => {:integer => '667'}}} + @expected = Vm::ConditionalExpression.new( Vm::IntegerExpression.new(0), + [Vm::IntegerExpression.new(42)], + [Vm::IntegerExpression.new(667)]) check_equals end @@ -74,10 +76,12 @@ class TransformTest < MiniTest::Test end def test_function_definition - @input = {:function_definition => { :name => "foo"}, - :parmeter_list => { :parmeter => { :name => "x" }} , - :block => { :integer => "5" }} - @expected = Vm::FunctionExpression.new('foo', [Vm::NameExpression.new('x')], Vm::IntegerExpression.new(5)) + @input = {:function_definition => {:name => 'foo'}, + :parmeter_list => {:parmeter => {:name => 'x'}}, + :expressions => [{:integer => '5'}]} + @expected = Vm::FunctionExpression.new('foo', + [Vm::NameExpression.new('x')], + [Vm::IntegerExpression.new(5)]) check_equals end end