fixed and tightened transformation tests, also by implementing node ==
This commit is contained in:
parent
e04973fc3c
commit
cfcb9ded2f
@ -20,8 +20,10 @@ module Parser
|
|||||||
end
|
end
|
||||||
|
|
||||||
rule(:conditional => simple(:conditional),
|
rule(:conditional => simple(:conditional),
|
||||||
:if_true => {:block => simple(:if_true)},
|
:if_true => {:expressions => sequence(:if_true)},
|
||||||
:if_false => {:block => simple(:if_false)}) { Vm::ConditionalExpression.new(conditional, if_true, if_false) }
|
:if_false => {:expressions => sequence(:if_false)}) do
|
||||||
|
Vm::ConditionalExpression.new(conditional, if_true, if_false)
|
||||||
|
end
|
||||||
|
|
||||||
rule(:parmeter => simple(:parmeter)) { parmeter }
|
rule(:parmeter => simple(:parmeter)) { parmeter }
|
||||||
rule(:parmeter_list => sequence(:parmeter_list)) { parmeter_list }
|
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)
|
# need TWO transform rules, for one/many arguments (see the[] wrapping in the first)
|
||||||
rule(:function_definition => simple(:function_definition),
|
rule(:function_definition => simple(:function_definition),
|
||||||
:parmeter_list => simple(:parmeter),
|
:parmeter_list => simple(:parmeter),
|
||||||
:block => simple(:block)) do
|
:expressions => sequence(:expressions)) do
|
||||||
Vm::FunctionExpression.new(function_definition.name, [parmeter], block)
|
Vm::FunctionExpression.new(function_definition.name, [parmeter], expressions)
|
||||||
end
|
end
|
||||||
|
|
||||||
rule(:function_definition => simple(:function_definition),
|
rule(:function_definition => simple(:function_definition),
|
||||||
:parmeter_list => sequence(:parmeter_list),
|
:parmeter_list => sequence(:parmeter_list),
|
||||||
:block => simple(:block)) do
|
:expressions => sequence(:expressions)) do
|
||||||
Vm::FunctionExpression.new(function_definition.name, parmeter_list, block)
|
Vm::FunctionExpression.new(function_definition.name, parmeter_list, expressions)
|
||||||
end
|
end
|
||||||
|
|
||||||
#shortcut to get the ast tree for a given string
|
#shortcut to get the ast tree for a given string
|
||||||
|
@ -5,6 +5,15 @@ module Vm
|
|||||||
def eval
|
def eval
|
||||||
raise "abstract"
|
raise "abstract"
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
class IntegerExpression < Expression
|
class IntegerExpression < Expression
|
||||||
@ -12,6 +21,9 @@ module Vm
|
|||||||
def initialize val
|
def initialize val
|
||||||
@value = val
|
@value = val
|
||||||
end
|
end
|
||||||
|
def == other
|
||||||
|
compare other , [:value]
|
||||||
|
end
|
||||||
def eval(context, builder)
|
def eval(context, builder)
|
||||||
builder.mov "r0" , value
|
builder.mov "r0" , value
|
||||||
end
|
end
|
||||||
@ -22,11 +34,13 @@ module Vm
|
|||||||
def initialize name
|
def initialize name
|
||||||
@name = name
|
@name = name
|
||||||
end
|
end
|
||||||
|
def == other
|
||||||
|
compare other , [:name]
|
||||||
|
end
|
||||||
def eval(context, builder)
|
def eval(context, builder)
|
||||||
param_names = context[:params] || []
|
param_names = context[:params] || []
|
||||||
position = param_names.index(name)
|
position = param_names.index(name)
|
||||||
raise "Unknown parameter #{name}" unless position
|
raise "Unknown parameter #{name}" unless position
|
||||||
|
|
||||||
builder.iload position
|
builder.iload position
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -36,6 +50,9 @@ module Vm
|
|||||||
def initialize name, args
|
def initialize name, args
|
||||||
@name , @args = name , args
|
@name , @args = name , args
|
||||||
end
|
end
|
||||||
|
def == other
|
||||||
|
compare other , [:name , :args]
|
||||||
|
end
|
||||||
def eval(context, builder)
|
def eval(context, builder)
|
||||||
args.each { |a| a.eval(context, builder) }
|
args.each { |a| a.eval(context, builder) }
|
||||||
types = [builder.int] * (args.length + 1)
|
types = [builder.int] * (args.length + 1)
|
||||||
@ -48,6 +65,9 @@ module Vm
|
|||||||
def initialize cond, if_true, if_false
|
def initialize cond, if_true, if_false
|
||||||
@cond, @if_true, @if_false = cond, if_true, if_false
|
@cond, @if_true, @if_false = cond, if_true, if_false
|
||||||
end
|
end
|
||||||
|
def == other
|
||||||
|
compare other , [:cond, :if_true, :if_false]
|
||||||
|
end
|
||||||
def eval(context, builder)
|
def eval(context, builder)
|
||||||
cond.eval context, builder
|
cond.eval context, builder
|
||||||
|
|
||||||
@ -68,6 +88,9 @@ module Vm
|
|||||||
def initialize name, params, block
|
def initialize name, params, block
|
||||||
@name, @params, @block = name, params, block
|
@name, @params, @block = name, params, block
|
||||||
end
|
end
|
||||||
|
def == other
|
||||||
|
compare other , [:name, :params, :block]
|
||||||
|
end
|
||||||
def eval(context, builder)
|
def eval(context, builder)
|
||||||
param_names = [params].flatten.map(&:name)
|
param_names = [params].flatten.map(&:name)
|
||||||
context[:params] = param_names
|
context[:params] = param_names
|
||||||
|
@ -10,7 +10,7 @@ class TransformTest < MiniTest::Test
|
|||||||
|
|
||||||
def check_equals
|
def check_equals
|
||||||
is = @transform.apply @input
|
is = @transform.apply @input
|
||||||
assert_equal @expected.class , is.class
|
assert_equal @expected , is
|
||||||
end
|
end
|
||||||
def test_number
|
def test_number
|
||||||
@input = {:integer => '42'}
|
@input = {:integer => '42'}
|
||||||
@ -52,13 +52,15 @@ class TransformTest < MiniTest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_conditional
|
def test_conditional
|
||||||
@input = {:conditional => {:integer => '0'},
|
@input = { :conditional => { :integer => "0"},
|
||||||
:if_true => {:block => {:integer => '42'}},
|
:if_true => { :expressions => [ { :integer => "42" } ] } ,
|
||||||
:if_false => {:block => {:integer => '667'}}}
|
:if_false => { :expressions => [ { :integer => "667" } ] } }
|
||||||
@expected = Vm::ConditionalExpression.new \
|
# = {:conditional => {:integer => '0'},
|
||||||
Vm::IntegerExpression.new(0),
|
# :if_true => {:block => {:integer => '42'}},
|
||||||
Vm::IntegerExpression.new(42),
|
# :if_false => {:block => {:integer => '667'}}}
|
||||||
Vm::IntegerExpression.new(667)
|
@expected = Vm::ConditionalExpression.new( Vm::IntegerExpression.new(0),
|
||||||
|
[Vm::IntegerExpression.new(42)],
|
||||||
|
[Vm::IntegerExpression.new(667)])
|
||||||
check_equals
|
check_equals
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -74,10 +76,12 @@ class TransformTest < MiniTest::Test
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_function_definition
|
def test_function_definition
|
||||||
@input = {:function_definition => { :name => "foo"},
|
@input = {:function_definition => {:name => 'foo'},
|
||||||
:parmeter_list => { :parmeter => { :name => "x" }} ,
|
:parmeter_list => {:parmeter => {:name => 'x'}},
|
||||||
:block => { :integer => "5" }}
|
:expressions => [{:integer => '5'}]}
|
||||||
@expected = Vm::FunctionExpression.new('foo', [Vm::NameExpression.new('x')], Vm::IntegerExpression.new(5))
|
@expected = Vm::FunctionExpression.new('foo',
|
||||||
|
[Vm::NameExpression.new('x')],
|
||||||
|
[Vm::IntegerExpression.new(5)])
|
||||||
check_equals
|
check_equals
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user