finish typing variables

This commit is contained in:
Torsten Ruger 2015-09-27 16:06:48 +03:00
parent 26c6db17b1
commit 252c0ccdca
12 changed files with 81 additions and 40 deletions

View File

@ -2,12 +2,12 @@ module Bosl
Compiler.class_eval do Compiler.class_eval do
def on_class_field expression def on_class_field expression
puts expression.inspect #puts expression.inspect
type , name , value = *expression type , name , value = *expression
for_class = self.method.for_class for_class = self.method.for_class
index = for_class.object_layout.variable_index(name) index = for_class.object_layout.variable_index(name)
raise "class field already defined:#{name} for class #{for_class.name}" if index #raise "class field already defined:#{name} for class #{for_class.name}" if index
puts "Define field #{name} on class #{for_class.name}" puts "Define field #{name} on class #{for_class.name}"
index = for_class.object_layout.add_instance_variable( name ) #TODO need typing index = for_class.object_layout.add_instance_variable( name ) #TODO need typing

View File

@ -2,16 +2,16 @@ module Bosl
Compiler.class_eval do Compiler.class_eval do
def on_field_def expression def on_field_def expression
# puts expression.inspect #puts expression.inspect
type , name , value = *expression type , name , value = *expression
index = method.ensure_local( name ) index = method.ensure_local( name , type )
if value if value
value = process( value ) value = process( value )
end end
Virtual::Return.new( value ) Virtual::Return.new( type , value )
end end
end end
end end

View File

@ -2,12 +2,12 @@ module Bosl
Compiler.class_eval do Compiler.class_eval do
# function attr_reader :name, :params, :body , :receiver # function attr_reader :name, :params, :body , :receiver
def on_function expression def on_function expression
# puts expression.inspect #puts expression.inspect
return_type , name , parameters, kids , receiver = *expression return_type , name , parameters, kids , receiver = *expression
name = name.to_a.first name = name.to_a.first
args = parameters.to_a.collect do |p| args = parameters.to_a.collect do |p|
raise "error, argument must be a identifier, not #{p}" unless p.type == :parameter raise "error, argument must be a identifier, not #{p}" unless p.type == :parameter
Parfait::Variable.new( p.first , p[1]) Parfait::Variable.new( *p)
end end
if receiver if receiver

View File

@ -13,8 +13,12 @@ module Bosl
if( index = method.has_arg(name)) if( index = method.has_arg(name))
method.source.add_code Virtual::Set.new( Virtual::ArgSlot.new(index,:int ) , ret) method.source.add_code Virtual::Set.new( Virtual::ArgSlot.new(index,:int ) , ret)
else # or a local so it is in the frame else # or a local so it is in the frame
index = method.ensure_local( name ) index = method.has_local( name )
if(index)
method.source.add_code Virtual::Set.new(Virtual::FrameSlot.new(index,:int ) , ret ) method.source.add_code Virtual::Set.new(Virtual::FrameSlot.new(index,:int ) , ret )
else
raise "must define variable #{name} before using it"
end
end end
return ret return ret
end end

View File

@ -10,8 +10,17 @@ module Bosl
name , value = *expression name , value = *expression
name = name.to_a.first name = name.to_a.first
v = process(value) v = process(value)
index = method.ensure_local( name ) index = method.has_local( name )
if(index)
method.source.add_code Virtual::Set.new(Virtual::FrameSlot.new(:int,index ) , v ) method.source.add_code Virtual::Set.new(Virtual::FrameSlot.new(:int,index ) , v )
else
index = method.has_arg( name )
if(index)
method.source.add_code Virtual::Set.new(Virtual::ArgSlot.new(:int,index ) , v )
else
raise "must define variable #{name} before using it in #{@method.inspect}"
end
end
end end
end end

View File

@ -34,46 +34,48 @@ module Parfait
attributes [:name , :arguments , :for_class , :code , :locals ] attributes [:name , :arguments , :for_class , :code , :locals ]
# determine whether this method has a variable by the given name
# variables are locals and and arguments
# used to determine if a send must be issued
# return index of the name into the message if so
def has_var name
raise "has_var #{name}.#{name.class}" unless name.is_a? Symbol
index = has_arg(name)
return index if index
has_local(name)
end
# determine whether this method has an argument by the name # determine whether this method has an argument by the name
def has_arg name def has_arg name
raise "has_arg #{name}.#{name.class}" unless name.is_a? Symbol raise "has_arg #{name}.#{name.class}" unless name.is_a? Symbol
self.arguments.index_of name max = self.arguments.get_length
counter = 1
while( counter <= max )
if( self.arguments.get(counter).name == name)
return counter
end
counter = counter + 1
end
return nil
end end
# determine if method has a local variable or tmp (anonymous local) by given name # determine if method has a local variable or tmp (anonymous local) by given name
def has_local name def has_local name
raise "has_local #{name}.#{name.class}" unless name.is_a? Symbol raise "has_local #{name}.#{name.class}" unless name.is_a? Symbol
index = self.locals.index_of(name) max = self.locals.get_length
index counter = 1
while( counter <= max )
if( self.locals.get(counter).name == name)
return counter
end
counter = counter + 1
end
return nil
end end
def ensure_local name def ensure_local name , type
index = has_local name index = has_local name
return index if index return index if index
self.locals.push name var = Variable.new( type , name)
self.locals.push var
self.locals.get_length self.locals.get_length
end end
def get_var name
var = has_var name
raise "no var #{name} in method #{self.name} , #{self.locals} #{self.arguments}" unless var
var
end
def sof_reference_name def sof_reference_name
self.name self.name
end end
def inspect
"#{self.for_class.name}:#{name}(#{arguments.inspect})"
end
end end
end end

View File

@ -93,6 +93,7 @@ module Virtual
# Objects are data and get assembled after functions # Objects are data and get assembled after functions
def add_object o def add_object o
return false if @objects[o.object_id] return false if @objects[o.object_id]
return if o.is_a? Fixnum
raise "adding non parfait #{o.class}" unless o.is_a? Parfait::Object or o.is_a? Symbol raise "adding non parfait #{o.class}" unless o.is_a? Parfait::Object or o.is_a? Symbol
@objects[o.object_id] = o @objects[o.object_id] = o
true true

View File

@ -34,8 +34,8 @@ class TestBasic < MiniTest::Test
check check
end end
def test_name def test_var
@string_input = 'foo ' @string_input = 'int foo '
@output = "- Virtual::Return(:type => :int)" @output = "- Virtual::Return(:type => :int)"
check check
end end

View File

@ -5,7 +5,7 @@ module Virtual
class TestFoo < MiniTest::Test class TestFoo < MiniTest::Test
include CodeChecker include CodeChecker
def test_foo2 def test_foo3
@string_input = <<HERE @string_input = <<HERE
field int a field int a
int foo(int x) int foo(int x)

View File

@ -6,17 +6,18 @@ class TestRecursinveFibo < MiniTest::Test
def test_recursive_fibo def test_recursive_fibo
@string_input = <<HERE @string_input = <<HERE
int fib_print(int n) int fib_print(int n)
fib = fibonaccir( n ) int fib = fibonaccir( n )
fib.putint() fib.putint()
end end
int fibonaccir( int n ) int fibonaccir( int n )
if( n <= 1 ) if( n <= 1 )
return n return n
else else
int tmp = n - 1 int tmp
a = fibonaccir( tmp ) tmp = n - 1
int a = fibonaccir( tmp )
tmp = n - 2 tmp = n - 2
b = fibonaccir( tmp ) int b = fibonaccir( tmp )
return a + b return a + b
end end
end end

View File

@ -3,3 +3,4 @@ require_relative "test_object"
require_relative "test_list" require_relative "test_list"
require_relative "test_word" require_relative "test_word"
require_relative "test_dictionary" require_relative "test_dictionary"
require_relative "test_method"

View File

@ -0,0 +1,23 @@
require_relative "../helper"
class TestMethod < MiniTest::Test
def setup
obj = Virtual.machine.boot.space.get_class_by_name(:Object)
args = Virtual.new_list [ Parfait::Variable.new(:int , :bar )]
@method = ::Parfait::Method.new obj , :foo , args
end
def test_method_name
assert_equal :foo , @method.name
end
def test_arg1
assert_equal 1 , @method.arguments.get_length
assert_equal Parfait::Variable , @method.arguments.first.class
assert_equal :bar , @method.arguments.first.name
end
def test_has_arg
assert_equal 1 , @method.has_arg(:bar)
end
end