better, correcter use of return storage
This commit is contained in:
parent
b29de4600e
commit
6b85054958
@ -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
|
@ -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
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user