adding receiver and a register abstraction
This commit is contained in:
parent
c59f22f11f
commit
6433a394e7
@ -7,19 +7,21 @@ module Ast
|
|||||||
locals = {}
|
locals = {}
|
||||||
params.each_with_index do |param , index|
|
params.each_with_index do |param , index|
|
||||||
arg = param.name
|
arg = param.name
|
||||||
arg_value = Vm::Integer.new(index+1)
|
arg_value = Vm::Integer.new(index+2)
|
||||||
locals[arg] = arg_value
|
locals[arg] = arg_value
|
||||||
args << arg_value
|
args << arg_value
|
||||||
end
|
end
|
||||||
# class depends on receiver
|
# class depends on receiver
|
||||||
if receiver.nil?
|
if receiver.nil?
|
||||||
clazz = context.current_class
|
clazz = context.current_class
|
||||||
|
me = Vm::Integer.new( Vm::Function::RECEIVER_REG )
|
||||||
else
|
else
|
||||||
c = context.object_space.get_or_create_class receiver.name.to_sym
|
c = context.object_space.get_or_create_class receiver.name.to_sym
|
||||||
clazz = c.meta_class
|
clazz = c.meta_class
|
||||||
|
raise "get the constant loaded to 1"
|
||||||
end
|
end
|
||||||
|
|
||||||
function = Vm::Function.new(name , args )
|
function = Vm::Function.new(name , me , args )
|
||||||
clazz.add_function function
|
clazz.add_function function
|
||||||
|
|
||||||
parent_locals = context.locals
|
parent_locals = context.locals
|
||||||
|
@ -6,7 +6,7 @@ module Boot
|
|||||||
# set/get instance variable use it.
|
# set/get instance variable use it.
|
||||||
# This is just a placeholder, as we code this in ruby, but the instance methods need the definition before.
|
# This is just a placeholder, as we code this in ruby, but the instance methods need the definition before.
|
||||||
def index_of context , name = Vm::Integer
|
def index_of context , name = Vm::Integer
|
||||||
index_function = Vm::Function.new(:index_of , [Vm::Integer] , Vm::Integer )
|
index_function = Vm::Function.new(:index_of , Vm::Integer , [Vm::Integer] , Vm::Integer )
|
||||||
return index_function
|
return index_function
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ module Boot
|
|||||||
# end
|
# end
|
||||||
# The at_index is just "below" the api, somehting we need but don't want to expose, so we can't code the above in ruby
|
# The at_index is just "below" the api, somehting we need but don't want to expose, so we can't code the above in ruby
|
||||||
def _get_instance_variable context , name = Vm::Integer
|
def _get_instance_variable context , name = Vm::Integer
|
||||||
get_function = Vm::Function.new(:_get_instance_variable , [Vm::Integer , Vm::Integer ] , Vm::Integer )
|
get_function = Vm::Function.new(:_get_instance_variable , Vm::Integer , [ Vm::Integer ] , Vm::Integer )
|
||||||
me = get_function.args[0]
|
me = get_function.args[0]
|
||||||
var_name = get_function.args[1]
|
var_name = get_function.args[1]
|
||||||
return_to = get_function.return_type
|
return_to = get_function.return_type
|
||||||
|
@ -2,11 +2,11 @@ module Boot
|
|||||||
class String
|
class String
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
def get context , index = Vm::Integer
|
def get context , index = Vm::Integer
|
||||||
get_function = Vm::Function.new(:get , [Vm::Integer, Vm::Integer] , Vm::Integer )
|
get_function = Vm::Function.new(:get , Vm::Integer , [ Vm::Integer] , Vm::Integer )
|
||||||
return get_function
|
return get_function
|
||||||
end
|
end
|
||||||
def set context , index = Vm::Integer , char = Vm::Integer
|
def set context , index = Vm::Integer , char = Vm::Integer
|
||||||
set_function = Vm::Function.new(:set , [Vm::Integer, Vm::Integer, Vm::Integer] , Vm::Integer )
|
set_function = Vm::Function.new(:set , Vm::Integer ,[Vm::Integer, Vm::Integer] , Vm::Integer )
|
||||||
return set_function
|
return set_function
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -32,8 +32,8 @@ module Core
|
|||||||
function
|
function
|
||||||
end
|
end
|
||||||
|
|
||||||
def putint context , arg = Vm::Integer
|
def putint context
|
||||||
putint_function = Vm::Function.new(:putint , [arg] , arg )
|
putint_function = Vm::Function.new(:putint , Vm::Integer , [] , Vm::Integer )
|
||||||
buffer = Vm::StringConstant.new(" ") # create a buffer
|
buffer = Vm::StringConstant.new(" ") # create a buffer
|
||||||
context.object_space.add_object buffer # and save it (function local variable: a no no)
|
context.object_space.add_object buffer # and save it (function local variable: a no no)
|
||||||
int = putint_function.args.first
|
int = putint_function.args.first
|
||||||
@ -59,7 +59,7 @@ module Core
|
|||||||
# As we write before we recurse (save a push) we write the number backwards
|
# As we write before we recurse (save a push) we write the number backwards
|
||||||
# arguments: string address , integer
|
# arguments: string address , integer
|
||||||
def utoa context
|
def utoa context
|
||||||
utoa_function = Vm::Function.new(:utoa , [Vm::Integer , Vm::Integer ] , Vm::Integer )
|
utoa_function = Vm::Function.new(:utoa , Vm::Integer , [ Vm::Integer ] , Vm::Integer )
|
||||||
str_addr = utoa_function.args[0]
|
str_addr = utoa_function.args[0]
|
||||||
number = utoa_function.args[1]
|
number = utoa_function.args[1]
|
||||||
remainder = utoa_function.new_local
|
remainder = utoa_function.new_local
|
||||||
@ -79,7 +79,7 @@ module Core
|
|||||||
# a hand coded version of the fibonachi numbers
|
# a hand coded version of the fibonachi numbers
|
||||||
# not my hand off course, found in the net from a basic introduction
|
# not my hand off course, found in the net from a basic introduction
|
||||||
def fibo context
|
def fibo context
|
||||||
fibo_function = Vm::Function.new(:fibo , [Vm::Integer] , Vm::Integer )
|
fibo_function = Vm::Function.new(:fibo , Vm::Integer , [] , Vm::Integer )
|
||||||
result = Vm::Integer.new(7)
|
result = Vm::Integer.new(7)
|
||||||
int = fibo_function.args[0]
|
int = fibo_function.args[0]
|
||||||
count = fibo_function.new_local
|
count = fibo_function.new_local
|
||||||
|
@ -27,16 +27,27 @@ module Vm
|
|||||||
|
|
||||||
class Function < Code
|
class Function < Code
|
||||||
|
|
||||||
def initialize(name , args = [] , return_type = nil)
|
TYPE_REG = 0
|
||||||
|
RECEIVER_REG = 1
|
||||||
|
RETURN_REG = 7
|
||||||
|
|
||||||
|
def initialize(name , receiver = Vm::Integer , args = [] , return_type = Vm::Integer)
|
||||||
super()
|
super()
|
||||||
@name = name.to_sym
|
@name = name.to_sym
|
||||||
|
if receiver.is_a?(Value)
|
||||||
|
@receiver = receiver
|
||||||
|
raise "arg in non std register #{arg.inspect}" unless RECEIVER_REG == receiver.register
|
||||||
|
else
|
||||||
|
@receiver = receiver.new(RECEIVER_REG)
|
||||||
|
end
|
||||||
|
|
||||||
@args = Array.new(args.length)
|
@args = Array.new(args.length)
|
||||||
args.each_with_index do |arg , i|
|
args.each_with_index do |arg , i|
|
||||||
if arg.is_a?(Value)
|
if arg.is_a?(Value)
|
||||||
@args[i] = arg
|
@args[i] = arg
|
||||||
raise "arg in non std register #{arg.inspect}" unless (i+1) == arg.register
|
raise "arg in non std register #{arg.inspect}" unless (i+1+RECEIVER_REG) == arg.register
|
||||||
else
|
else
|
||||||
@args[i] = arg.new(i+1)
|
@args[i] = arg.new(i+1+RECEIVER_REG)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
set_return return_type
|
set_return return_type
|
||||||
@ -48,14 +59,14 @@ module Vm
|
|||||||
@blocks = []
|
@blocks = []
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :args , :entry , :exit , :body , :name , :return_type
|
attr_reader :args , :entry , :exit , :body , :name , :return_type , :revceiver
|
||||||
|
|
||||||
def set_return type_or_value
|
def set_return type_or_value
|
||||||
@return_type = type_or_value || Vm::Integer
|
@return_type = type_or_value || Vm::Integer
|
||||||
if @return_type.is_a?(Value)
|
if @return_type.is_a?(Value)
|
||||||
raise "return in non std register #{@return_type.inspect}" unless 7 == @return_type.register
|
raise "return in non std register #{@return_type.inspect}" unless RETURN_REG == @return_type.register
|
||||||
else
|
else
|
||||||
@return_type = @return_type.new(7)
|
@return_type = @return_type.new(RETURN_REG)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
def arity
|
def arity
|
||||||
@ -63,13 +74,14 @@ module Vm
|
|||||||
end
|
end
|
||||||
|
|
||||||
def new_local type = Vm::Integer
|
def new_local type = Vm::Integer
|
||||||
register = args.length + @locals.length
|
register = args.length + 1 + @locals.length # one for the receiver implicit arg
|
||||||
l = type.new(register + 1) # one for the type register 0, TODO add type as arg0 implicitly
|
l = type.new(register + 1) # one for the type register 0, TODO add type as arg0 implicitly
|
||||||
puts "new local #{l.register}"
|
puts "new local #{l.register}"
|
||||||
# raise "Register overflow in function #{name}" if l.register > 6
|
# raise "Register overflow in function #{name}" if l.register > 6
|
||||||
@locals << l
|
@locals << l
|
||||||
l
|
l
|
||||||
end
|
end
|
||||||
|
#BUG - must save receiver
|
||||||
|
|
||||||
def save_locals context , into
|
def save_locals context , into
|
||||||
save = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
save = args.collect{|a| a.register } + @locals.collect{|l| l.register}
|
||||||
|
@ -48,21 +48,40 @@ module Vm
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# This is what it is when we don't know what it is.
|
# RegisterUSe is _not_ the name for a register, "only" for a certain use of it.
|
||||||
# Must be promoted to A Word-Value to to anything
|
# In a way it is like a variable name, a storage location. The location is a register off course,
|
||||||
|
# but which register can be changed, and _all_ instructions sharing the RegisterUse then use that register
|
||||||
|
# In other words a simple level of indirection, or change from value to reference sematics.
|
||||||
|
class RegisterUse
|
||||||
|
attr_accessor :register
|
||||||
|
def initialize r
|
||||||
|
@register = r
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# This is what it is when we don't know what it is. #TODO, better if it were explicitly a different type, not the base
|
||||||
|
# Must be promoted to A Word-Value to to anything makes is_a chaecking easier
|
||||||
# remembering that our oo machine is typed, no overloading or stuff
|
# remembering that our oo machine is typed, no overloading or stuff
|
||||||
class Word < Value
|
class Word < Value
|
||||||
|
|
||||||
attr_accessor :register
|
attr_accessor :used_register
|
||||||
|
|
||||||
|
def register
|
||||||
|
@used_register.register
|
||||||
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
self.class.name + "(r#{register})"
|
self.class.name + "(r#{used_register.register})"
|
||||||
end
|
end
|
||||||
def to_s
|
def to_s
|
||||||
inspect
|
inspect
|
||||||
end
|
end
|
||||||
def initialize reg
|
def initialize reg
|
||||||
@register = reg
|
if reg.is_a? Fixnum
|
||||||
|
@used_register = RegisterUse.new(reg)
|
||||||
|
else
|
||||||
|
@used_register = reg
|
||||||
|
end
|
||||||
raise inspect if reg == nil
|
raise inspect if reg == nil
|
||||||
end
|
end
|
||||||
def length
|
def length
|
||||||
|
Loading…
Reference in New Issue
Block a user