better, correcter use of return storage

This commit is contained in:
Torsten Ruger 2014-09-14 18:14:57 +03:00
parent b29de4600e
commit 6b85054958
3 changed files with 34 additions and 90 deletions

View File

@ -2,10 +2,18 @@
module Ast
# Constant expressions can by definition be evaluated at compile time.
# But that does not solve their storage, ie they need to be accessible at runtime from _somewhere_
# So we view ConstantExpressions like functions that return the value of the constant.
# In other words, their storage is the return slot as it would be for a method
# The current approach moves the constant into a varaible before using it
# But in the future (in the one that holds great things) we optimize those unneccesay moves away
class IntegerExpression < Expression
# attr_reader :value
def compile method , message
to = Virtual::Return.new(Virtual::Integer)
to = Virtual::NewReturn.new(Virtual::Integer)
method.add_code Virtual::Set.new( to , Virtual::IntegerConstant.new(value))
to
end
@ -13,19 +21,25 @@ module Ast
class TrueExpression
def compile method , message
Virtual::TrueValue.new
to = Virtual::Return.new(Virtual::Reference)
method.add_code Virtual::Set.new( to , Virtual::TrueConstant.new )
to
end
end
class FalseExpression
def compile method , message
Virtual::FalseValue.new
to = Virtual::Return.new(Virtual::Reference)
method.add_code Virtual::Set.new( to , Virtual::FalseConstant.new )
to
end
end
class NilExpression
def compile method , message
Virtual::NilValue.new
to = Virtual::Return.new(Virtual::Reference)
method.add_code Virtual::Set.new( to , Virtual::NilConstant.new )
to
end
end
@ -49,20 +63,22 @@ module Ast
class ModuleName < NameExpression
def compile method , message
to = Virtual::Return.new(Virtual::Reference)
clazz = ::Virtual::BootSpace.space.get_or_create_class name
raise "uups #{clazz}.#{name}" unless clazz
#class qualifier, means call from metaclass
#clazz = clazz.meta_class
clazz
method.add_code Virtual::Set.new( to , clazz )
to
end
end
class StringExpression < Expression
# attr_reader :string
def compile method , message
to = Virtual::Return.new(Virtual::Reference)
value = Virtual::StringConstant.new(string)
::Virtual::BootSpace.space.add_object value
value
Virtual::BootSpace.space.add_object value
method.add_code Virtual::Set.new( to , value )
to
end
end
class AssignmentExpression < Expression
@ -74,32 +90,12 @@ module Ast
raise "oh noo, nil from where #{right.inspect}" unless r
message.compile_set( method , left.name , r )
end
def old_scratch
if operator == "=" # assignment, value based
if(left.is_a? VariableExpression)
left.make_setter
l_val = left.compile(context)
elsif 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)
else
l_val = context.function.new_local.move( into , r_val )
end
context.locals[left.name] = l_val
else
raise "Can only assign variables, not #{left}"
end
return l_val
end
end
end
class VariableExpression < NameExpression
def compile method , message
method.add_code Virtual::InstanceGet.new(name)
Virtual::Return.new( Virtual::Mystery )
Virtual::NewReturn.new( Virtual::Mystery )
end
end
end

View File

@ -10,56 +10,17 @@ module Ast
method.add_code Virtual::Set.new(Virtual::NewName.new(), name)
compiled_args = []
args.each_with_index do |arg , i|
val = arg.compile( method, message) #compile in the running method, ie before passing control
#compile in the running method, ie before passing control
val = arg.compile( method, message)
compiled_args << val
# move the compiled value to it's slot in the new message
# (doing this immediately, not after the loop, so if it's a return it won't get overwritten)
method.add_code Virtual::Set.new(Virtual::NewMessageSlot.new(i ,val.type ) , val )
end
method.add_code Virtual::MessageSend.new(name , me , compiled_args) #and pass control
Virtual::Return.new( method.return_type )
end
def scratch
into = context.function
params = args.collect{ |a| a.compile(context) }
puts "compiling receiver #{receiver} (call #{name})"
if receiver.is_a? ModuleName
clazz = context.object_space.get_or_create_class receiver.name
value_receiver = clazz.meta_class
function = value_receiver.resolve_method name
elsif receiver.is_a?(StringExpression) or receiver.is_a?(IntegerExpression)
#TODO obviously the class is wrong, but you gotta start somewhere
clazz = context.object_space.get_or_create_class :Object
function = clazz.resolve_method name
value_receiver = receiver.compile(context)
elsif receiver.is_a?(NameExpression)
if(receiver.name == :self)
function = context.current_class.resolve_method(name)
value_receiver = Virtual::Integer.new(Virtual::RegisterMachine.instance.receiver_register)
else
value_receiver = receiver.compile(context)
# TODO HACK warning: should determine class dynamically
function = context.current_class.resolve_method(name)
end
elsif receiver.is_a? VariableExpression
value_receiver = receiver.compile(context)
function = context.current_class.resolve_method(name)
else
#This , how does one say nowadays, smells. Smells of unused polymorphism actually
raise "Not sure this is possible, but never good to leave elses open #{receiver} #{receiver.class}"
end
raise "No such method error #{inspect}" if (function.nil?)
raise "No receiver error #{inspect}:#{receiver}" if (value_receiver.nil?)
call = Virtual::CallSite.new( name , value_receiver , params , function)
current_function = context.function
into.push([]) unless current_function.nil?
call.load_args into
call.do_call into
after = into.new_block("#{name}#{@@counter+=1}")
into.current after
into.pop([]) unless current_function.nil?
function.return_type
# the effect of the method is that the NewMessage Return slot will be filled, return it
# (this is what is moved _inside_ above loop for such expressions that are calls (or constants))
Virtual::NewReturn.new( method.return_type )
end
end
end

View File

@ -2,18 +2,6 @@ module Ast
class ModuleExpression < Expression
# attr_reader :name ,:expressions
def compile context
clazz = context.object_space.get_or_create_class name
puts "Created class #{clazz.name.inspect}"
context.current_class = clazz
expressions.each do |expression|
# check if it's a function definition and add
# if not, execute it, but that does means we should be in salama (executable), not ruby. ie throw an error for now
raise "only functions for now #{expression.inspect}" unless expression.is_a? Ast::FunctionExpression
puts "compiling expression #{expression}"
expression_value = expression.compile(context )
#puts "compiled expression #{expression_value.inspect}"
end
return clazz
end
end
@ -22,7 +10,6 @@ module Ast
def compile method , message
clazz = ::Virtual::BootSpace.space.get_or_create_class name
puts "Created class #{clazz.name.inspect}"
# context.current_class = clazz
expressions.each do |expression|
# check if it's a function definition and add
# if not, execute it, but that does means we should be in salama (executable), not ruby. ie throw an error for now