From 6b85054958b2278a4cb25467a807fecad75b3782 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sun, 14 Sep 2014 18:14:57 +0300 Subject: [PATCH] better, correcter use of return storage --- lib/ast/basic_expressions.rb | 56 +++++++++++++++------------------ lib/ast/call_site_expression.rb | 55 +++++--------------------------- lib/ast/module_expression.rb | 13 -------- 3 files changed, 34 insertions(+), 90 deletions(-) diff --git a/lib/ast/basic_expressions.rb b/lib/ast/basic_expressions.rb index 84b4fee4..834b3990 100644 --- a/lib/ast/basic_expressions.rb +++ b/lib/ast/basic_expressions.rb @@ -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 \ No newline at end of file diff --git a/lib/ast/call_site_expression.rb b/lib/ast/call_site_expression.rb index cffa7f8a..a52e6306 100644 --- a/lib/ast/call_site_expression.rb +++ b/lib/ast/call_site_expression.rb @@ -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 ) + # 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 - - 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 - end - end - + end end \ No newline at end of file diff --git a/lib/ast/module_expression.rb b/lib/ast/module_expression.rb index 9d164b4c..d26d3d9e 100644 --- a/lib/ast/module_expression.rb +++ b/lib/ast/module_expression.rb @@ -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