diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index 62e9b990..1ecd9664 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -20,6 +20,11 @@ module Arm left end + def integer_minus block , left , right + block.add_code sub(:left => left , :right => right ) + left + end + def integer_load block , left , right reg = "r#{left.register}".to_sym block.add_code mov( :left => reg , :right => right ) @@ -35,7 +40,7 @@ module Arm def function_call into , call raise "Not CallSite #{call.inspect}" unless call.is_a? Vm::CallSite raise "Not linked #{call.inspect}" unless call.function - into.add_code bl( :left => call.function ) + into.add_code call( :left => call.function ) call.function.return_type end diff --git a/lib/ast/function_expression.rb b/lib/ast/function_expression.rb index 913a9809..d103b2bf 100644 --- a/lib/ast/function_expression.rb +++ b/lib/ast/function_expression.rb @@ -1,20 +1,20 @@ module Ast class FunctionExpression < Expression - attr_reader :name, :params, :block - def initialize name, params, block - @name, @params, @block = name.to_sym, params, block + attr_reader :name, :params, :body + def initialize name, params, body + @name, @params, @body = name.to_sym, params, body end def attributes - [:name, :params, :block] + [:name, :params, :body] end def inspect self.class.name + ".new(" + name.inspect + ", ["+ params.collect{|m| m.inspect }.join( ",") +"] , [" + - block.collect{|m| m.inspect }.join( ",") +"] )" + body.collect{|m| m.inspect }.join( ",") +"] )" end def to_s - "def #{name}( " + params.join(",") + ") \n" + block.join("\n") + "end\n" + "def #{name}( " + params.join(",") + ") \n" + body.join("\n") + "end\n" end def compile context , into raise "function does not compile into anything #{self}" if into @@ -35,11 +35,11 @@ module Ast context.function = function into = function.body - block.each do |b| + body.each do |b| compiled = b.compile(context , into) function.return_type = compiled - raise "alarm " unless compiled.is_a? Vm::Word - puts compiled.inspect + puts "compiled in function #{compiled.inspect}" + raise "alarm #{compiled} \n #{b}" unless compiled.is_a? Vm::Word end context.locals = parent_locals context.function = parent_function diff --git a/lib/ast/operator_expressions.rb b/lib/ast/operator_expressions.rb index 85c1041e..973a0099 100644 --- a/lib/ast/operator_expressions.rb +++ b/lib/ast/operator_expressions.rb @@ -16,18 +16,25 @@ module Ast "#{left} #{operator} #{right}" end def compile context , into - puts "compile #{to_s}" + puts "compile operator #{to_s}" r_val = right.compile(context , into) - if operator == "=" # assignemnt + if operator == "=" # assignment, value based raise "Can only assign variables, not #{left}" unless left.is_a?(NameExpression) - if r_val.is_a? Vm::IntegerConstant - puts context.attributes.keys.join(" ") - next_register = context.function.next_register - r_val = Vm::Integer.new(next_register).load( into , r_val ) + l_val = context.locals[left.name] + if( l_val ) #variable existed, move data there + l_val = l_val.move( into , r_val) + else + if r_val.is_a? Vm::IntegerConstant + next_register = context.function.next_register + l_val = Vm::Integer.new(next_register).load( into , r_val ) + else + l_val = r_val + end end - context.locals[left.name] = r_val - return r_val + context.locals[left.name] = l_val + return l_val end + l_val = left.compile(context , into) case operator @@ -35,6 +42,8 @@ module Ast code = l_val.less_or_equal into , r_val when "+" code = l_val.plus into , r_val + when "-" + code = l_val.minus into , r_val else raise "unimplemented operator #{operator} #{self}" end diff --git a/lib/ast/while_expression.rb b/lib/ast/while_expression.rb index 5b0039a2..f2c0b069 100644 --- a/lib/ast/while_expression.rb +++ b/lib/ast/while_expression.rb @@ -16,10 +16,12 @@ module Ast def compile context , into cond_val = condition.compile(context , into) #set up branches for bodies + last = nil body.each do |part| - part.compile(context , into ) + last = part.compile(context , into ) + puts "compiled in while #{last.inspect}" end - return cond_val + return last end end diff --git a/lib/vm/call_site.rb b/lib/vm/call_site.rb index ecf9d92f..6c9958ec 100644 --- a/lib/vm/call_site.rb +++ b/lib/vm/call_site.rb @@ -13,13 +13,17 @@ module Vm def load_args into args.each_with_index do |arg , index| - puts "load " + arg.inspect - arg.load( into , index ) + if arg.is_a? IntegerConstant + Vm::Integer.new(index).load into , arg + else + raise "no #{arg.inspect}" if arg.register != index + #arg.load( into , index ) + end end end def do_call into - into.add_code CMachine.instance.function_call into , self + CMachine.instance.function_call into , self end end end diff --git a/lib/vm/values.rb b/lib/vm/values.rb index 4aea4970..4a4ae3f1 100644 --- a/lib/vm/values.rb +++ b/lib/vm/values.rb @@ -66,6 +66,9 @@ module Vm def plus block , right CMachine.instance.integer_plus block , self , right end + def minus block , right + CMachine.instance.integer_minus block , self , right + end def load block , right CMachine.instance.integer_load block , self , right