diff --git a/lib/ast/basic_expressions.rb b/lib/ast/basic_expressions.rb index 626dc4da..b14771eb 100644 --- a/lib/ast/basic_expressions.rb +++ b/lib/ast/basic_expressions.rb @@ -67,7 +67,7 @@ module Ast def compile frame , method raise "must assign to NameExpression , not #{left}" unless left.instance_of? NameExpression - r = right.compile(frame,method) + r = right.compile(frame , method) frame.compile_set( method , left.name , r ) end end diff --git a/lib/ast/function_expression.rb b/lib/ast/function_expression.rb index 0fd0d3c4..e8d8f15b 100644 --- a/lib/ast/function_expression.rb +++ b/lib/ast/function_expression.rb @@ -2,9 +2,12 @@ module Ast class FunctionExpression < Expression # attr_reader :name, :params, :body , :receiver def compile frame , method - args = params.collect{ |p| p.compile(frame , method )} + args = params.collect do |p| + raise "error, arguemnt must be a identifier, not #{p}" unless p.is_a? NameExpression + Virtual::Argument.new( p.name , Virtual::Mystery.new ) + end r = receiver ? receiver.compile(frame,method) : Virtual::SelfReference.new - method = Virtual::Method.new(name , params , r ) + method = Virtual::Method.new(name , args , r ) frame = frame.new_frame return_type = nil body.each do |ex| diff --git a/lib/ast/if_expression.rb b/lib/ast/if_expression.rb index c8d7fb47..84d6acac 100644 --- a/lib/ast/if_expression.rb +++ b/lib/ast/if_expression.rb @@ -2,7 +2,14 @@ module Ast class IfExpression < Expression # attr_reader :cond, :if_true, :if_false def compile frame , method - Virtual::Reference + is = cond.compile(frame , method) +# is.is_false(frame,method) + last = is + if_true.each do |part| + last = part.compile(frame,method ) + raise part.inspect if last.nil? + end + last end def old f = context.function diff --git a/lib/virtual/frame.rb b/lib/virtual/frame.rb index 46191e39..ba382492 100644 --- a/lib/virtual/frame.rb +++ b/lib/virtual/frame.rb @@ -40,6 +40,7 @@ module Virtual end def compile_set method , name , val + method.set_var(name,val) method.add FrameSet.new(name , val ) method.get_var(name) end diff --git a/lib/virtual/method.rb b/lib/virtual/method.rb index 2f41705b..342a9d1a 100644 --- a/lib/virtual/method.rb +++ b/lib/virtual/method.rb @@ -40,12 +40,29 @@ module Virtual # variables are locals and and arguments # used to determine if a send must be issued def has_var name - var = @args.find {|a| a == name } - var = @locals.find {|a| a == name } unless var - var = @tmps.find {|a| a == name } unless var + name = name.to_sym + var = @args.find {|a| a.name == name } + var = @locals.find {|a| a.name == name } unless var + var = @tmps.find {|a| a.name == name } unless var + var + end + + def set_var name , var + v = has_var name + if( v ) + puts "resetting local #{v}" + else + v = Local.new(name , var) + @locals << v + end + v + end + + def get_var name + var = has_var name + raise "no var #{name} in method #{self.name} , #{@locals} #{@args}" unless var var end - alias :get_var :has_var def get_tmp name = "__tmp__#{@tmps.length}" diff --git a/lib/virtual/value.rb b/lib/virtual/value.rb index 096251a6..5c89b975 100644 --- a/lib/virtual/value.rb +++ b/lib/virtual/value.rb @@ -36,7 +36,7 @@ module Virtual class Variable < Value def initialize name , type - @name = name + @name = name.to_sym @type = type end attr_accessor :name , :type diff --git a/test/virtual/test_methods.rb b/test/virtual/test_methods.rb index 7ebab300..eaf0ea65 100644 --- a/test/virtual/test_methods.rb +++ b/test/virtual/test_methods.rb @@ -9,7 +9,7 @@ def foo(x) 5 end HERE - @output = [Virtual::Method.new(:foo,[Ast::NameExpression.new(:x)],Virtual::SelfReference.new(nil),Virtual::IntegerConstant.new(5),Virtual::MethodEnter.new(nil))] + @output = [Virtual::Method.new(:foo,[Virtual::Argument.new(:x,Virtual::Mystery.new())],Virtual::SelfReference.new(nil),Virtual::IntegerConstant.new(5),Virtual::MethodEnter.new(nil))] check end @@ -19,7 +19,7 @@ def String.length(x) @length end HERE - @output = [Virtual::Method.new(:length,[Ast::NameExpression.new(:x)],Boot::BootClass.new(:String,:Object),Virtual::Return.new( Virtual::Mystery.new()),Virtual::MethodEnter.new(Virtual::ObjectGet.new(:length)))] + @output = [Virtual::Method.new(:length,[Virtual::Argument.new(:x,Virtual::Mystery.new())],Boot::BootClass.new(:String,:Object),Virtual::Return.new(Virtual::Mystery.new()),Virtual::MethodEnter.new(Virtual::ObjectGet.new(:length,nil)))] check end @@ -30,7 +30,7 @@ def foo(x) 2 + 5 end HERE - @output = [Virtual::Method.new(:foo,[Ast::NameExpression.new(:x)],Virtual::SelfReference.new(nil),Virtual::Return.new(Virtual::Mystery),Virtual::MethodEnter.new(Virtual::FrameSet.new(:abba,Virtual::IntegerConstant.new(5),Virtual::LoadSelf.new(Virtual::IntegerConstant.new(2),Virtual::FrameSend.new(:+,[Virtual::IntegerConstant.new(5)],nil)))))] + @output = [Virtual::Method.new(:foo,[Virtual::Argument.new(:x,Virtual::Mystery.new())],Virtual::SelfReference.new(nil),Virtual::Return.new(Virtual::Mystery),Virtual::MethodEnter.new(Virtual::FrameSet.new(:abba,Virtual::IntegerConstant.new(5),Virtual::LoadSelf.new(Virtual::IntegerConstant.new(2),Virtual::FrameSend.new(:+,[Virtual::IntegerConstant.new(5)],nil)))))] check end @@ -44,7 +44,7 @@ HERE check end - def ttest_function_if + def test_function_if @string_input = <