From 0a14cffefbfce698ac64b35dfe656db0ca2820fe Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sat, 7 Jun 2014 23:22:32 +0300 Subject: [PATCH] fixing fragment tests, most done --- Gemfile.lock | 2 +- lib/ast/basic_expressions.rb | 14 ++++++++++++-- lib/ast/call_site_expression.rb | 28 ++++++++++------------------ lib/ast/function_expression.rb | 2 ++ lib/ast/operator_expressions.rb | 2 +- lib/ast/while_expression.rb | 1 + lib/core/kernel.rb | 4 ++-- lib/vm/function.rb | 2 +- lib/vm/instruction.rb | 1 - lib/vm/values.rb | 6 +++--- test/fragments/helper.rb | 7 +++---- test/fragments/test_foo.rb | 2 +- test/fragments/test_functions.rb | 10 +++++++--- test/fragments/test_hello.rb | 2 +- test/fragments/test_putint.rb | 3 +-- test/fragments/test_while_fibo.rb | 5 +++-- 16 files changed, 49 insertions(+), 42 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 22984bf4..b5dad01d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,7 +7,7 @@ GIT GIT remote: https://github.com/ruby-in-ruby/crystal-reader.git - revision: b25d5ab99250965883d3a71163961ea75431778f + revision: 06d4ab2fe5af054df6c3a247528b1088e78e24c9 specs: crystal-reader (0.1.0) diff --git a/lib/ast/basic_expressions.rb b/lib/ast/basic_expressions.rb index 812b5f1f..ee341450 100644 --- a/lib/ast/basic_expressions.rb +++ b/lib/ast/basic_expressions.rb @@ -12,14 +12,24 @@ module Ast class NameExpression < Expression # attr_reader :name - # compiling a variable resolves it. - # if it wasn't defined, nli is returned + # compiling a variable resolves it. if it wasn't defined, raise an exception def compile context , into + raise "Undefined variable #{name}, defined locals #{context.locals.keys.join('-')}" unless context.locals.has_key?(name) context.locals[name] end end class ModuleName < NameExpression + + def compile context , into + clazz = context.object_space.get_or_create_class name + raise "uups #{clazz}.#{name}" unless clazz + #class qualifier, means call from metaclass + clazz = clazz.meta_class + value = clazz + puts "CLAZZ #{value}" + function = clazz.get_or_create_function(name) + end end class StringExpression < Expression diff --git a/lib/ast/call_site_expression.rb b/lib/ast/call_site_expression.rb index 67a44b38..f64f5bd0 100644 --- a/lib/ast/call_site_expression.rb +++ b/lib/ast/call_site_expression.rb @@ -7,28 +7,20 @@ module Ast def compile context , into params = args.collect{ |a| a.compile(context, into) } - if receiver.name == :self + if receiver.is_a?(NameExpression) and (receiver.name == :self) function = context.current_class.get_or_create_function(name) - value = Vm::Integer.new(Vm::Function::RECEIVER_REG) - elsif receiver.is_a? ModuleName - c_name = receiver.name - clazz = context.object_space.get_or_create_class c_name - raise "uups #{clazz}.#{c_name}" unless clazz - #class qualifier, means call from metaclass - clazz = clazz.meta_class - value = clazz - puts "CLAZZ #{value}" - function = clazz.get_or_create_function(name) - elsif receiver.is_a? VariableExpression - raise "not implemented instance var:#{receiver}" + value_receiver = Vm::Integer.new(Vm::Function::RECEIVER_REG) else - # should be case switch for basic tyes and dynamic dispatch for objects reference - value = context.locals[receiver.name] - raise "no value" unless value + value_receiver = receiver.compile(context , into) function = context.current_class.get_or_create_function(name) end - raise "No such method error #{clazz.to_s}:#{name}" if function == nil - call = Vm::CallSite.new( name , value , params , function) + # this lot below should go, since the compile should handle all + if receiver.is_a? VariableExpression + raise "not implemented instance var:#{receiver}" + end + raise "No such method error #{3.to_s}:#{name}" if (function.nil?) + raise "No receiver error #{inspect}:#{value_receiver}:#{name}" if (value_receiver.nil?) + call = Vm::CallSite.new( name , value_receiver , params , function) current_function = context.function current_function.save_locals(context , into) if current_function call.load_args into diff --git a/lib/ast/function_expression.rb b/lib/ast/function_expression.rb index 837892f1..300e02f4 100644 --- a/lib/ast/function_expression.rb +++ b/lib/ast/function_expression.rb @@ -25,7 +25,9 @@ module Ast parent_locals = context.locals parent_function = context.function + puts "Locals #{locals.keys.join('-')}, #{locals.object_id}" context.locals = locals + puts "Locals #{context.locals.keys.join('-')}, #{context.locals.object_id}" context.function = function into = function.body diff --git a/lib/ast/operator_expressions.rb b/lib/ast/operator_expressions.rb index 54a09c83..e153d374 100644 --- a/lib/ast/operator_expressions.rb +++ b/lib/ast/operator_expressions.rb @@ -7,6 +7,7 @@ module Ast #puts "compiled right #{r_val.inspect}" if operator == "=" # assignment, value based raise "Can only assign variables, not #{left}" unless left.is_a?(NameExpression) + puts context.inspect unless context.locals l_val = context.locals[left.name] if( l_val ) #variable existed, move data there l_val = l_val.move( into , r_val) @@ -18,7 +19,6 @@ module Ast end l_val = left.compile(context , into) - case operator when ">" code = l_val.greater_than into , r_val diff --git a/lib/ast/while_expression.rb b/lib/ast/while_expression.rb index d372907a..80d61853 100644 --- a/lib/ast/while_expression.rb +++ b/lib/ast/while_expression.rb @@ -5,6 +5,7 @@ module Ast while_block = into.new_block "#{into.name}_while" ret = while_block.new_block "#{into.name}_return" puts "compiling while condition #{condition}" + puts "Locals #{context.locals.keys.join('-')}, #{context.locals.object_id}" cond_val = condition.compile(context , while_block) while_block.b ret , condition_code: cond_val.not_operator last = nil diff --git a/lib/core/kernel.rb b/lib/core/kernel.rb index c0d55c4f..f993eb8b 100644 --- a/lib/core/kernel.rb +++ b/lib/core/kernel.rb @@ -23,8 +23,8 @@ module Core #TODO this is in the wrong place. It is a function that returns a function object # while all other methods add their code into some block. --> kernel - def putstring context , string = Vm::Integer , length = Vm::Integer - function = Vm::Function.new(:putstring , [string , length ] , string) + def putstring context + function = Vm::Function.new(:putstring , Vm::Integer , [] ) block = function.body # should be another level of indirection, ie write(io,str) ret = Vm::RegisterMachine.instance.write_stdout(block) diff --git a/lib/vm/function.rb b/lib/vm/function.rb index 96787322..b2deaf16 100644 --- a/lib/vm/function.rb +++ b/lib/vm/function.rb @@ -45,7 +45,7 @@ module Vm args.each_with_index do |arg , i| if arg.is_a?(Value) @args[i] = arg - raise "arg in non std register #{arg.inspect}" unless RECEIVER_REG == arg.used_register.next_reg(i - 1) + raise "arg #{i}in non std register #{arg.inspect}" unless RECEIVER_REG == arg.used_register.next_reg(-1-i) else @args[i] = arg.new(RegisterUse.new(RECEIVER_REG).next_reg(i + 1)) end diff --git a/lib/vm/instruction.rb b/lib/vm/instruction.rb index 7b5e390e..e2f188f0 100644 --- a/lib/vm/instruction.rb +++ b/lib/vm/instruction.rb @@ -1,5 +1,4 @@ require_relative "code" -require "support/hash_attributes" module Vm # Because the idea of what one instruction does, does not always map one to one to real machine diff --git a/lib/vm/values.rb b/lib/vm/values.rb index 0f318347..0ac3f998 100644 --- a/lib/vm/values.rb +++ b/lib/vm/values.rb @@ -122,9 +122,6 @@ module Vm def less_than block , right RegisterMachine.instance.integer_less_than block , self , right end - def equals block , right - RegisterMachine.instance.integer_equals block , self , right - end def == other code = class_for(CompareInstruction).new(self , other , opcode: :cmp) end @@ -146,6 +143,9 @@ module Vm def left_shift block , first , right RegisterMachine.instance.integer_left_shift block , self , first , right end + def equals block , right + RegisterMachine.instance.integer_equals block , self , right + end def load block , right if(right.is_a? IntegerConstant) diff --git a/test/fragments/helper.rb b/test/fragments/helper.rb index 844ee55a..7488880d 100644 --- a/test/fragments/helper.rb +++ b/test/fragments/helper.rb @@ -23,11 +23,10 @@ module Fragments # file is a list of expressions, all but the last must be a function # and the last is wrapped as a main parts.each_with_index do |part,index| - if index == (parts.length - 1) - expr = part.compile( @object_space.context , @object_space.main ) - else + if part.is_a? Ast::FunctionExpression expr = part.compile( @object_space.context , nil ) - raise "should be function definition for now, not #{part.inspect}#{expr.inspect}" unless expr.is_a? Vm::Function + else + expr = part.compile( @object_space.context , @object_space.main ) end end end diff --git a/test/fragments/test_foo.rb b/test/fragments/test_foo.rb index c94c4ddb..a04ce48e 100644 --- a/test/fragments/test_foo.rb +++ b/test/fragments/test_foo.rb @@ -8,7 +8,7 @@ class TestFoo < MiniTest::Test def foo(x) a = 5 end -foo( 3 ) +3.foo( 4 ) HERE @should = [0x0,0x40,0x2d,0xe9,0x5,0x20,0xa0,0xe3,0x2,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x5,0x20,0xa0,0xe3,0x2,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8] @output = "" diff --git a/test/fragments/test_functions.rb b/test/fragments/test_functions.rb index 15877083..9114bcbe 100644 --- a/test/fragments/test_functions.rb +++ b/test/fragments/test_functions.rb @@ -20,9 +20,13 @@ def minus(a,b) a = plus(a,t) end end - -tim = times(7,6) -tim.putint() + +def t_seven() + tim = times(7,6) + tim.putint() +end + +t_seven() HERE @should = [0x0,0x40,0x2d,0xe9,0x2,0x30,0x41,0xe0,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8,0x0,0x40,0x2d,0xe9,0x2,0x30,0x41,0xe0,0x3,0x70,0xa0,0xe1,0x0,0x80,0xbd,0xe8] @output = " 42 " diff --git a/test/fragments/test_hello.rb b/test/fragments/test_hello.rb index a0ad3d73..78491085 100644 --- a/test/fragments/test_hello.rb +++ b/test/fragments/test_hello.rb @@ -5,7 +5,7 @@ class TestHello < MiniTest::Test def test_hello @string_input = <