diff --git a/lib/mom/instruction/slot_constant.rb b/lib/mom/instruction/slot_constant.rb index 8762f9a2..715d48b6 100644 --- a/lib/mom/instruction/slot_constant.rb +++ b/lib/mom/instruction/slot_constant.rb @@ -4,7 +4,7 @@ module Mom # the a is an instance variable on the current frame, and the frame is an instance # of the current message, so the effect is something like message.frame.a = 5 # @left: See SlotLoad, an array of symbols - # @right: A Constant from parse, ie an instance of classes in basc_value, like TrueStatement + # @right: A Constant from parse, ie an instance of classes in basc_value, like TrueConstant class SlotConstant < SlotLoad def initialize(left , right) diff --git a/lib/vool/ruby_compiler.rb b/lib/vool/ruby_compiler.rb index 9f8c2f52..09322b4d 100644 --- a/lib/vool/ruby_compiler.rb +++ b/lib/vool/ruby_compiler.rb @@ -38,31 +38,31 @@ module Vool #basic Values def on_self exp - SelfStatement.new + SelfExpression.new end def on_nil expression - NilStatement.new + NilConstant.new end def on_int expression - IntegerStatement.new(expression.children.first) + IntegerConstant.new(expression.children.first) end def on_float expression - FloatStatement.new(expression.children.first) + FloatConstant.new(expression.children.first) end def on_true expression - TrueStatement.new + TrueConstant.new end def on_false expression - FalseStatement.new + FalseConstant.new end def on_str expression - StringStatement.new(expression.children.first) + StringConstant.new(expression.children.first) end alias :on_string :on_str @@ -72,7 +72,7 @@ module Vool alias :on_xstr :on_dstr def on_sym expression - SymbolStatement.new(expression.children.first) + SymbolConstant.new(expression.children.first) end alias :on_string :on_str @@ -151,7 +151,7 @@ module Vool def on_send statement kids = statement.children.dup - receiver = process(kids.shift) || SelfStatement.new + receiver = process(kids.shift) || SelfExpression.new name = kids.shift arguments = process_all(kids) SendStatement.new( name , receiver , arguments ) @@ -167,14 +167,14 @@ module Vool # this is a call to super without args (z = zero arity) def on_zsuper exp - SendStatement.new( nil , SuperStatement.new , nil) + SendStatement.new( nil , SuperExpression.new , nil) end # this is a call to super with args and # same name as current method, which is set later def on_super( statement ) arguments = process_all(statement.children) - SendStatement.new( nil , SuperStatement.new , arguments) + SendStatement.new( nil , SuperExpression.new , arguments) end def on_assignment statement diff --git a/lib/vool/statement.rb b/lib/vool/statement.rb index 7199afce..dd0f8f5d 100644 --- a/lib/vool/statement.rb +++ b/lib/vool/statement.rb @@ -10,6 +10,9 @@ # Also, Vool is a typed tree, not abstract, so there is a base class Statement # and all it's derivation that make up the syntax tree # +# Also Vool has expression and statements and simple syntax. So returns must be explicit +# not everthing is just assignable, ifs can only test simple expressions etc (wip) +# # This allows us to write compilers or passes of the compiler(s) as functions on the # classes. # @@ -22,6 +25,13 @@ module Vool # class Statement + # after creation vool normalizes to ensure valid syntax and simplify + # also throw errors if violation + def normalize + return self + end + + # flatten tree to array def collect(arr) arr << self end @@ -51,6 +61,10 @@ module Vool def set_class( clazz ) end end + + class Expression + end + end @@ -61,7 +75,7 @@ require_relative "statements/class_statement" require_relative "statements/hash_statement" require_relative "statements/if_statement" require_relative "statements/logical_statement" -require_relative "statements/local_statement" +require_relative "statements/local_assignment" require_relative "statements/method_statement" require_relative "statements/return_statement" require_relative "statements/statements" diff --git a/lib/vool/statements/assign_statement.rb b/lib/vool/statements/assign_statement.rb index 2d77a7fa..0311770a 100644 --- a/lib/vool/statements/assign_statement.rb +++ b/lib/vool/statements/assign_statement.rb @@ -5,6 +5,14 @@ module Vool def initialize(name , value ) @name , @value = name , value end + + def normalize() + raise "not named left #{name}" unless @name.is_a?(Named) + raise "unsupported right #{value}" unless @name.is_a?(Named) or + @name.is_a?(SendStatement) or @name.is_a?(Constant) + self + end + def collect(arr) @value.collect(arr) super diff --git a/lib/vool/statements/basic_values.rb b/lib/vool/statements/basic_values.rb index fab8cfd8..9b428c02 100644 --- a/lib/vool/statements/basic_values.rb +++ b/lib/vool/statements/basic_values.rb @@ -4,13 +4,13 @@ module Vool Mom::SlotMove end end - class ConstantStatement < Statement + class Constant < Expression def slot_class Mom::SlotConstant end end - class IntegerStatement < ConstantStatement + class IntegerConstant < Constant attr_reader :value def initialize(value) @value = value @@ -22,7 +22,7 @@ module Vool Parfait.object_space.get_class_by_name(:Integer).instance_type end end - class FloatStatement < ConstantStatement + class FloatConstant < Constant attr_reader :value def initialize(value) @value = value @@ -31,22 +31,22 @@ module Vool true end end - class TrueStatement < ConstantStatement + class TrueConstant < Constant def ct_type Parfait.object_space.get_class_by_name(:True).instance_type end end - class FalseStatement < ConstantStatement + class FalseConstant < Constant def ct_type Parfait.object_space.get_class_by_name(:False).instance_type end end - class NilStatement < ConstantStatement + class NilConstant < Constant def ct_type Parfait.object_space.get_class_by_name(:Nil).instance_type end end - class SelfStatement < Statement + class SelfExpression < Expression attr_reader :clazz def set_class(clazz) @clazz = clazz @@ -58,9 +58,9 @@ module Vool @clazz.instance_type end end - class SuperStatement < Statement + class SuperExpression < Statement end - class StringStatement < ConstantStatement + class StringConstant < Constant attr_reader :value def initialize(value) @value = value @@ -72,7 +72,7 @@ module Vool Parfait.object_space.get_class_by_name(:Word).instance_type end end - class SymbolStatement < StringStatement + class SymbolConstant < StringConstant def ct_type Parfait.object_space.get_class_by_name(:Word).instance_type end diff --git a/lib/vool/statements/hoister.rb b/lib/vool/statements/hoister.rb deleted file mode 100644 index eee5bce3..00000000 --- a/lib/vool/statements/hoister.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Vool - module Hoister - def hoist_condition( method ) - return [@condition] if @condition.is_a?(Vool::Named) - local = method.create_tmp - assign = LocalAssignment.new( local , @condition) - [Vool::LocalVariable.new(local) , assign] - end - end -end diff --git a/lib/vool/statements/if_statement.rb b/lib/vool/statements/if_statement.rb index 74750f16..1484d9af 100644 --- a/lib/vool/statements/if_statement.rb +++ b/lib/vool/statements/if_statement.rb @@ -1,7 +1,7 @@ -require_relative "hoister" +require_relative "normalizer" module Vool class IfStatement < Statement - include Hoister + include Normalizer attr_reader :condition , :if_true , :if_false @@ -12,6 +12,14 @@ module Vool simplify_condition end + def normalize(method) + cond , rest = *normalize_name(@condition) + fals = @if_false ? @if_false.normalize(method) : nil + me = IfStatement.new(cond , @if_true.normalize(method), fals) + return me unless rest + rest << me + end + def to_mom( method ) if_true = @if_true.to_mom( method ) if_false = @if_false ? @if_false.to_mom( method ) : nil diff --git a/lib/vool/statements/local_statement.rb b/lib/vool/statements/local_assignment.rb similarity index 100% rename from lib/vool/statements/local_statement.rb rename to lib/vool/statements/local_assignment.rb diff --git a/lib/vool/statements/normalizer.rb b/lib/vool/statements/normalizer.rb new file mode 100644 index 00000000..b4a5e196 --- /dev/null +++ b/lib/vool/statements/normalizer.rb @@ -0,0 +1,16 @@ +module Vool + module Normalizer + # given a something, determine if it is a Name + # + # Return a Name, and a possible rest that has a hoisted part of the statement + # + # eg if( @var % 5) is not normalized + # but if(tmp_123) is with tmp_123 = @var % 5 hoited above the if + def normalize_name( method ) + return [@condition] if @condition.is_a?(Named) + local = method.create_tmp + assign = LocalAssignment.new( local , @condition) + [LocalVariable.new(local) , assign] + end + end +end diff --git a/lib/vool/statements/send_statement.rb b/lib/vool/statements/send_statement.rb index 6b2310e9..8677f8fa 100644 --- a/lib/vool/statements/send_statement.rb +++ b/lib/vool/statements/send_statement.rb @@ -96,8 +96,8 @@ module Vool [Mom::SlotMove.new([@dynamic, :cached_type] , [:receiver , :type])] end def build_method_cache_update(in_method) - receiver = StringStatement.new(@name) - resolve = SendStatement.new(:resolve_method , receiver , [SelfStatement.new]) + receiver = StringConstant.new(@name) + resolve = SendStatement.new(:resolve_method , receiver , [SelfExpression.new]) move_method = Mom::SlotMove.new([@dynamic, :cached_method] , [:receiver , :return]) resolve.to_mom(in_method) << move_method end diff --git a/lib/vool/statements/variables.rb b/lib/vool/statements/variables.rb index c06c8dcc..39280d4d 100644 --- a/lib/vool/statements/variables.rb +++ b/lib/vool/statements/variables.rb @@ -6,7 +6,7 @@ module Vool end end - class LocalVariable < Statement + class LocalVariable < Expression include Named def to_mom(method) if method.args_type.variable_index(@name) @@ -18,7 +18,7 @@ module Vool end end - class InstanceVariable < Statement + class InstanceVariable < Expression include Named def to_mom(method) Mom::SlotDefinition.new(:message , [ :receiver , @name] ) @@ -29,11 +29,11 @@ module Vool end end - class ClassVariable < Statement + class ClassVariable < Expression include Named end - class ModuleName < Statement + class ModuleName < Expression include Named end end diff --git a/lib/vool/statements/while_statement.rb b/lib/vool/statements/while_statement.rb index 165131bc..0914a286 100644 --- a/lib/vool/statements/while_statement.rb +++ b/lib/vool/statements/while_statement.rb @@ -1,8 +1,8 @@ -require_relative "hoister" +require_relative "normalizer" module Vool class WhileStatement < Statement - include Hoister + include Normalizer attr_reader :condition , :statements def initialize( condition , statements ) @@ -11,6 +11,13 @@ module Vool simplify_condition end + def normalize(method) + cond , rest = *normalize_name(@condition) + me = WhileStatement.new(cond , @statements.normalize(method)) + return me unless rest + rest << me + end + def to_mom( method ) statements = @statements.to_mom( method ) condition , hoisted = hoist_condition( method ) diff --git a/test/vool/statements/test_basic_values.rb b/test/vool/statements/test_basic_values.rb index 5f761fa2..4945ee3c 100644 --- a/test/vool/statements/test_basic_values.rb +++ b/test/vool/statements/test_basic_values.rb @@ -5,31 +5,31 @@ module Vool def test_self lst = RubyCompiler.compile( "self") - assert_equal SelfStatement , lst.class + assert_equal SelfExpression , lst.class end def test_nil lst = RubyCompiler.compile( "nil") - assert_equal NilStatement , lst.class + assert_equal NilConstant , lst.class end def test_false lst = RubyCompiler.compile( "false") - assert_equal FalseStatement , lst.class + assert_equal FalseConstant , lst.class end def test_true lst = RubyCompiler.compile( "true") - assert_equal TrueStatement , lst.class + assert_equal TrueConstant , lst.class end def test_integer lst = RubyCompiler.compile( "123") - assert_equal IntegerStatement , lst.class + assert_equal IntegerConstant , lst.class end def test_string lst = RubyCompiler.compile( "'string'") - assert_equal StringStatement , lst.class , lst.inspect + assert_equal StringConstant , lst.class , lst.inspect end def test_sym lst = RubyCompiler.compile( ":symbol") - assert_equal SymbolStatement , lst.class , lst.inspect + assert_equal SymbolConstant , lst.class , lst.inspect end def test_dstr assert_raises RuntimeError do diff --git a/test/vool/statements/test_class_statement.rb b/test/vool/statements/test_class_statement.rb index fc5c31ea..ed2982bb 100644 --- a/test/vool/statements/test_class_statement.rb +++ b/test/vool/statements/test_class_statement.rb @@ -37,7 +37,7 @@ module Vool def test_compile_two_methods lst = RubyCompiler.compile( in_Test("false; true;") ) assert_equal ScopeStatement , lst.body.class - assert_equal TrueStatement , lst.body.statements[1].class + assert_equal TrueConstant , lst.body.statements[1].class end end diff --git a/test/vool/statements/test_if_statement.rb b/test/vool/statements/test_if_statement.rb index 4aeadbcb..f92c5070 100644 --- a/test/vool/statements/test_if_statement.rb +++ b/test/vool/statements/test_if_statement.rb @@ -16,7 +16,7 @@ module Vool end def test_if_basic_branches lst = RubyCompiler.compile( basic_if ) - assert_equal TrueStatement , lst.if_true.class + assert_equal TrueConstant , lst.if_true.class assert_nil lst.if_false end @@ -29,12 +29,12 @@ module Vool end def test_if_double_cond lst = RubyCompiler.compile( double_if ) - assert_equal FalseStatement , lst.condition.class + assert_equal FalseConstant , lst.condition.class end def test_if_double_branches lst = RubyCompiler.compile( double_if ) - assert_equal TrueStatement , lst.if_true.class - assert_equal FalseStatement, lst.if_false.class + assert_equal TrueConstant , lst.if_true.class + assert_equal FalseConstant, lst.if_false.class end def reverse_if @@ -46,11 +46,11 @@ module Vool end def test_if_reverse_cond lst = RubyCompiler.compile( reverse_if ) - assert_equal FalseStatement , lst.condition.class + assert_equal FalseConstant , lst.condition.class end def test_if_reverse_branches lst = RubyCompiler.compile( reverse_if ) - assert_equal TrueStatement , lst.if_true.class + assert_equal TrueConstant , lst.if_true.class assert_nil lst.if_false end @@ -63,12 +63,12 @@ module Vool end def test_if_reverse_cond lst = RubyCompiler.compile( reverse_unless ) - assert_equal FalseStatement , lst.condition.class + assert_equal FalseConstant , lst.condition.class end def test_if_reverse_branches lst = RubyCompiler.compile( reverse_unless ) assert_nil lst.if_true - assert_equal TrueStatement ,lst.if_false.class + assert_equal TrueConstant ,lst.if_false.class end def ternary @@ -80,12 +80,12 @@ module Vool end def test_if_ternary_cond lst = RubyCompiler.compile( ternary ) - assert_equal FalseStatement , lst.condition.class + assert_equal FalseConstant , lst.condition.class end def test_if_ternary_branches lst = RubyCompiler.compile( ternary ) - assert_equal TrueStatement , lst.if_true.class - assert_equal FalseStatement, lst.if_false.class + assert_equal TrueConstant , lst.if_true.class + assert_equal FalseConstant, lst.if_false.class end end end diff --git a/test/vool/statements/test_send_statement.rb b/test/vool/statements/test_send_statement.rb index 9cc6958f..55144b07 100644 --- a/test/vool/statements/test_send_statement.rb +++ b/test/vool/statements/test_send_statement.rb @@ -13,7 +13,7 @@ module Vool end def test_simple_receiver lst = RubyCompiler.compile( "foo") - assert_equal SelfStatement , lst.receiver.class + assert_equal SelfExpression , lst.receiver.class end def test_simple_args lst = RubyCompiler.compile( "foo") @@ -30,7 +30,7 @@ module Vool end def test_one_arg_receiver lst = RubyCompiler.compile( "bar(1)") - assert_equal SelfStatement , lst.receiver.class + assert_equal SelfExpression , lst.receiver.class end def test_one_arg_args lst = RubyCompiler.compile( "bar(1)") @@ -39,7 +39,7 @@ module Vool def test_super0_receiver lst = RubyCompiler.compile( "super") - assert_equal SuperStatement , lst.receiver.class + assert_equal SuperExpression , lst.receiver.class end def test_super0 lst = RubyCompiler.compile( "super") @@ -48,7 +48,7 @@ module Vool def test_super_receiver lst = RubyCompiler.compile( "super(1)") - assert_equal SuperStatement , lst.receiver.class + assert_equal SuperExpression , lst.receiver.class end def test_super_args lst = RubyCompiler.compile( "super(1)") diff --git a/test/vool/statements/test_while_statement.rb b/test/vool/statements/test_while_statement.rb index 48840ee5..8853bc0c 100644 --- a/test/vool/statements/test_while_statement.rb +++ b/test/vool/statements/test_while_statement.rb @@ -16,7 +16,7 @@ module Vool end def test_while_basic_branches lst = RubyCompiler.compile( basic_while ) - assert_equal TrueStatement , lst.statements.class + assert_equal TrueConstant , lst.statements.class end def reverse_while @@ -28,11 +28,11 @@ module Vool end def test_while_reverse_cond lst = RubyCompiler.compile( reverse_while ) - assert_equal FalseStatement , lst.condition.class + assert_equal FalseConstant , lst.condition.class end def test_while_reverse_branches lst = RubyCompiler.compile( reverse_while ) - assert_equal TrueStatement , lst.statements.class + assert_equal TrueConstant , lst.statements.class end end