finish typing variables
This commit is contained in:
parent
26c6db17b1
commit
252c0ccdca
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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"
|
||||||
|
23
test/parfait/test_method.rb
Normal file
23
test/parfait/test_method.rb
Normal 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
|
Loading…
Reference in New Issue
Block a user