b980def84e
Also make the machine the singleton and space hang off it Many repercussions, not all fixed in this commit
72 lines
2.6 KiB
Ruby
72 lines
2.6 KiB
Ruby
module Virtual
|
|
module Compiler
|
|
# function attr_reader :name, :params, :body , :receiver
|
|
def self.compile_function expression, method
|
|
args = expression.params.collect do |p|
|
|
raise "error, argument must be a identifier, not #{p}" unless p.is_a? Ast::NameExpression
|
|
p.name
|
|
end
|
|
r = expression.receiver ? Compiler.compile(expression.receiver, method ) : Self.new()
|
|
new_method = CompiledMethod.new(expression.name , args , r )
|
|
new_method.class_name = r.is_a?(BootClass) ? r.name : method.class_name
|
|
clazz = Space.space.get_or_create_class(new_method.class_name)
|
|
clazz.add_instance_method new_method
|
|
|
|
#frame = frame.new_frame
|
|
return_type = nil
|
|
expression.body.each do |ex|
|
|
return_type = Compiler.compile(ex,new_method )
|
|
raise return_type.inspect if return_type.is_a? Instruction
|
|
end
|
|
new_method.return_type = return_type
|
|
new_method
|
|
end
|
|
def scratch
|
|
args = []
|
|
locals = {}
|
|
expression.params.each_with_index do |param , index|
|
|
arg = param.name
|
|
register = RegisterReference.new(RegisterMachine.instance.receiver_register).next_reg_use(index + 1)
|
|
arg_value = Integer.new(register)
|
|
locals[arg] = arg_value
|
|
args << arg_value
|
|
end
|
|
# class depends on receiver
|
|
me = Integer.new( RegisterMachine.instance.receiver_register )
|
|
if expression.receiver.nil?
|
|
clazz = context.current_class
|
|
else
|
|
c = context.object_space.get_or_create_class expression.receiver.name.to_sym
|
|
clazz = c.meta_class
|
|
end
|
|
|
|
function = Function.new(name , me , args )
|
|
clazz.add_code_function function
|
|
|
|
parent_locals = context.locals
|
|
parent_function = context.function
|
|
context.locals = locals
|
|
context.function = function
|
|
|
|
last_compiled = nil
|
|
expression.body.each do |b|
|
|
puts "compiling in function #{b}"
|
|
last_compiled = b.compile(context)
|
|
raise "alarm #{last_compiled} \n #{b}" unless last_compiled.is_a? Word
|
|
end
|
|
|
|
return_reg = Integer.new(RegisterMachine.instance.return_register)
|
|
if last_compiled.is_a?(IntegerConstant) or last_compiled.is_a?(ObjectConstant)
|
|
return_reg.load function , last_compiled if last_compiled.register_symbol != return_reg.register_symbol
|
|
else
|
|
return_reg.move( function, last_compiled ) if last_compiled.register_symbol != return_reg.register_symbol
|
|
end
|
|
function.set_return return_reg
|
|
|
|
context.locals = parent_locals
|
|
context.function = parent_function
|
|
function
|
|
end
|
|
end
|
|
end
|