diff --git a/lib/mom/callable_compiler.rb b/lib/mom/callable_compiler.rb index fbad0df2..bdfb0553 100644 --- a/lib/mom/callable_compiler.rb +++ b/lib/mom/callable_compiler.rb @@ -28,12 +28,6 @@ module Mom end end - # Only for init, as init has no return - def _reset_for_init - @mom_instructions = Label.new(source_name, source_name) - @current = @mom_instructions - end - # add a constant (which get created during compilation and need to be linked) def add_constant(const) raise "Must be Parfait #{const}" unless const.is_a?(Parfait::Object) diff --git a/lib/mom/instruction/resolve_method.rb b/lib/mom/instruction/resolve_method.rb index d33b0b80..92f9c4ea 100644 --- a/lib/mom/instruction/resolve_method.rb +++ b/lib/mom/instruction/resolve_method.rb @@ -65,7 +65,7 @@ module Mom # temporary, need to raise really. factory! << Parfait.object_space.get_factory_for(:Integer) integer_tmp! << factory[:reserve] - Mom::Builtin.emit_syscall( builder , :died ) #uses integer_tmp + Mom::Macro.emit_syscall( builder , :died ) #uses integer_tmp add_code ok_label cache_entry[:cached_method] << callable_method diff --git a/lib/mom/macro.rb b/lib/mom/macro.rb deleted file mode 100644 index 5e57c272..00000000 --- a/lib/mom/macro.rb +++ /dev/null @@ -1,77 +0,0 @@ -module Mom - module Builtin - module CompileHelper - - def compiler_for( clazz_name , method_name , arguments , locals = {}) - frame = Parfait::NamedList.type_for( locals ) - args = Parfait::NamedList.type_for( arguments ) - Mom::MethodCompiler.compiler_for_class(clazz_name , method_name , args, frame ) - end - end - end - class Macro < Instruction - end -end - -require_relative "macro/space" -require_relative "macro/integer" -require_relative "macro/object" -require_relative "macro/word" - -module Mom - module Builtin - # classes have booted, now create a minimal set of functions - # minimal means only that which can not be coded in ruby - # Methods are grabbed from respective modules by sending the method name. - # This should return the implementation of the method (ie a method compiler), - # not actually try to implement it(as that's impossible in ruby) - # - # We create an empty main for init to jump to, if no code is compiled, that just returns - # See Builtin directory readme and module - def self.boot_functions( options = nil) - space = Parfait.object_space - space_type = space.get_class.instance_type - - if @compilers and options == nil - if(space_type.methods.nil?) - @compilers << compiler_for( space_type , Space , :main) - end - return @compilers - end - # TODO go through the virtual parfait layer and adjust function names - # to what they really are - @compilers = [] - - obj_type = space.get_type_by_class_name(:Object) - [ :__init__ , :exit , :_method_missing, :get_internal_word , - :set_internal_word ].each do |f| - @compilers << compiler_for( obj_type , Object , f) - end - - word_type = space.get_type_by_class_name(:Word) - [:putstring , :get_internal_byte , :set_internal_byte ].each do |f| - @compilers << compiler_for( word_type , Word , f) - end - - int_type = space.get_type_by_class_name(:Integer) - Risc.operators.each do |op| - @compilers << operator_compiler( int_type , op) - end - [ :div4, :<,:<= , :>=, :> , :div10 ].each do |f| #div4 is just a forward declaration - @compilers << compiler_for( int_type , Integer , f) - end - return @compilers - end - - def self.compiler_for( type , mod , name) - compiler = mod.send(name , nil) - compiler.add_method_to(type) - compiler - end - def self.operator_compiler(int_type , op) - compiler = Integer.operator_method(op) - compiler.add_method_to(int_type) - compiler - end - end -end diff --git a/lib/mom/macro/comparison.rb b/lib/mom/macro/comparison.rb index 1d05d554..70e33619 100644 --- a/lib/mom/macro/comparison.rb +++ b/lib/mom/macro/comparison.rb @@ -1,34 +1,4 @@ module Mom - module Builtin - class Comparison < ::Mom::Instruction - attr_reader :operator - def initialize(name , operator) - super(name) - @operator = operator - end - def to_risc(compiler) - builder = compiler.builder(compiler.source) - operator = @operator # make accessible in block - builder.build do - integer! << message[:receiver] - integer.reduce_int - integer_reg! << message[:arg1] #"other" - integer_reg.reduce_int - swap_names(:integer , :integer_reg) if(operator.to_s.start_with?('<') ) - integer.op :- , integer_reg - if_minus false_label - if_zero( false_label ) if operator.to_s.length == 1 - object! << Parfait.object_space.true_object - branch merge_label - add_code false_label - object << Parfait.object_space.false_object - add_code merge_label - message[:return_value] << object - end - return compiler - end - end - end class Comparison < Macro attr_reader :operator def initialize(name , operator) diff --git a/lib/mom/macro/div10.rb b/lib/mom/macro/div10.rb index 532d04a8..cde977eb 100644 --- a/lib/mom/macro/div10.rb +++ b/lib/mom/macro/div10.rb @@ -1,67 +1,4 @@ module Mom - module Builtin - class Div10 < ::Mom::Instruction - def to_risc(compiler) - s = "div_10 " - builder = compiler.builder(compiler.source) - integer_tmp = builder.allocate_int - builder.build do - integer_self! << message[:receiver] - integer_self.reduce_int - integer_1! << integer_self - integer_reg! << integer_self - - integer_const! << 1 - integer_1.op :>> , integer_const - - integer_const << 2 - integer_reg.op :>> , integer_const - integer_reg.op :+ , integer_1 - - integer_const << 4 - integer_1 << integer_reg - integer_reg.op :>> , integer_1 - - integer_reg.op :+ , integer_1 - - integer_const << 8 - integer_1 << integer_reg - integer_1.op :>> , integer_const - - integer_reg.op :+ , integer_1 - - integer_const << 16 - integer_1 << integer_reg - integer_1.op :>> , integer_const - - integer_reg.op :+ , integer_1 - - integer_const << 3 - integer_reg.op :>> , integer_const - - integer_const << 10 - integer_1 << integer_reg - integer_1.op :* , integer_const - - integer_self.op :- , integer_1 - integer_1 << integer_self - - integer_const << 6 - integer_1.op :+ , integer_const - - integer_const << 4 - integer_1.op :>> , integer_const - - integer_reg.op :+ , integer_1 - - integer_tmp[Parfait::Integer.integer_index] << integer_reg - message[:return_value] << integer_tmp - - end - return compiler - end - end - end class Div10 < Macro def to_risc(compiler) s = "div_10 " diff --git a/lib/mom/macro/div4.rb b/lib/mom/macro/div4.rb index 87de235a..6b1c5ccd 100644 --- a/lib/mom/macro/div4.rb +++ b/lib/mom/macro/div4.rb @@ -1,21 +1,4 @@ module Mom - module Builtin - class Div4 < ::Mom::Instruction - def to_risc(compiler) - builder = compiler.builder(compiler.source) - integer_tmp = builder.allocate_int - builder.build do - integer_self! << message[:receiver] - integer_self.reduce_int - integer_1! << 2 - integer_self.op :>> , integer_1 - integer_tmp[Parfait::Integer.integer_index] << integer_self - message[:return_value] << integer_tmp - end - return compiler - end - end - end class Div4 < Macro def to_risc(compiler) builder = compiler.builder(compiler.source) diff --git a/lib/mom/macro/exit.rb b/lib/mom/macro/exit.rb index e626283e..e9816b62 100644 --- a/lib/mom/macro/exit.rb +++ b/lib/mom/macro/exit.rb @@ -1,14 +1,4 @@ module Mom - module Builtin - class Exit < ::Mom::Instruction - def to_risc(compiler) - builder = compiler.builder(compiler.source) - builder.prepare_int_return # makes integer_tmp variable as return - Builtin.exit_sequence(builder) - return compiler - end - end - end class Exit < Macro def to_risc(compiler) builder = compiler.builder(compiler.source) diff --git a/lib/mom/macro/get_internal_byte.rb b/lib/mom/macro/get_internal_byte.rb index 5727be93..deaf8fd6 100644 --- a/lib/mom/macro/get_internal_byte.rb +++ b/lib/mom/macro/get_internal_byte.rb @@ -1,21 +1,4 @@ module Mom - module Builtin - class GetInternalByte < ::Mom::Instruction - def to_risc(compiler) - builder = compiler.builder(compiler.source) - integer_tmp = builder.allocate_int - builder.build do - object! << message[:receiver] - integer! << message[:arg1] #"at" - integer.reduce_int - object <= object[integer] - integer_tmp[Parfait::Integer.integer_index] << object - message[:return_value] << integer_tmp - end - return compiler - end - end - end class GetInternalByte < Macro def to_risc(compiler) builder = compiler.builder(compiler.source) diff --git a/lib/mom/macro/get_internal_word.rb b/lib/mom/macro/get_internal_word.rb index 1211902d..331b76dd 100644 --- a/lib/mom/macro/get_internal_word.rb +++ b/lib/mom/macro/get_internal_word.rb @@ -1,17 +1,4 @@ module Mom - module Builtin - class GetInternalWord < ::Mom::Instruction - def to_risc(compiler) - compiler.builder(compiler.source).build do - object! << message[:receiver] - integer! << message[:arg1] #"at" is at index 0 - integer.reduce_int - object << object[integer] - message[:return_value] << object - end - end - end - end class GetInternalWord < Macro def to_risc(compiler) compiler.builder(compiler.source).build do diff --git a/lib/mom/macro/init.rb b/lib/mom/macro/init.rb index c81dd212..2606a37e 100644 --- a/lib/mom/macro/init.rb +++ b/lib/mom/macro/init.rb @@ -1,37 +1,4 @@ module Mom - module Builtin - class Init < ::Mom::Instruction - def to_risc(compiler) - builder = compiler.builder(compiler.source) - builder.build do - factory! << Parfait.object_space.get_factory_for(:Message) - message << factory[:next_object] - next_message! << message[:next_message] - factory[:next_object] << next_message - end - builder.reset_names - Mom::MessageSetup.new(Parfait.object_space.get_main).build_with( builder ) - - builder.build do - message << message[:next_message] - space? << Parfait.object_space - message[:receiver] << space - end - - exit_label = Risc.label(compiler.source , "#{compiler.receiver_type.object_class.name}.#{compiler.source.name}" ) - ret_tmp = compiler.use_reg(:Label).set_builder(builder) - builder.build do - ret_tmp << exit_label - message[:return_address] << ret_tmp - add_code Risc.function_call( "__init__ issue call" , Parfait.object_space.get_main) - add_code exit_label - end - compiler.reset_regs - Builtin.exit_sequence(builder) - return compiler - end - end - end class Init < Macro def to_risc(compiler) builder = compiler.builder(compiler.source) @@ -59,7 +26,7 @@ module Mom add_code exit_label end compiler.reset_regs - Builtin.exit_sequence(builder) + Macro.exit_sequence(builder) return compiler end end diff --git a/lib/mom/macro/integer.rb b/lib/mom/macro/integer.rb deleted file mode 100644 index 01e7f06c..00000000 --- a/lib/mom/macro/integer.rb +++ /dev/null @@ -1,85 +0,0 @@ -require_relative "div4" -require_relative "div10" -require_relative "operator" -require_relative "comparison" - -module Mom - module Builtin - # integer related kernel functions - # all these functions (return the function they implement) assume interger input - # Also the returned integer object has to be passed in to avoid having to allocate it. - # - # This means the methods will have to be renamed at some point and wrapped - module Integer - module ClassMethods - include CompileHelper - - # div by 4, ie shift right by 2 - # Mostly created for testing at this point, as it is short - # return new int with result - def div4(context) - compiler = compiler_for(:Integer,:div4 ,{}) - compiler.add_code Div4.new("div4") - return compiler - end - - # implemented by the comparison - def >( context ) - comparison( :> ) - end - # implemented by the comparison - def <( context ) - comparison( :< ) - end - # implemented by the comparison - def <=( context ) - comparison( :<= ) - end - # implemented by the comparison - def >=( context ) - comparison( :>= ) - end - - # all (four) comparison operation are quite similar and implemented here - # - reduce the ints (assume int as input) - # - subtract the fixnums - # - check for minus ( < and > ) - # - also check for zero (<= and >=) - # - load true or false object into return, depending on check - # - return - def comparison( operator ) - compiler = compiler_for(:Integer, operator ,{other: :Integer }) - compiler.add_code Comparison.new("comparison" , operator) - return compiler - end - - # implemented all known binary operators that map straight to machine codes - # this function (similar to comparison): - # - unpacks the intergers to fixnum - # - applies the operator (at a risc level) - # - gets a new integer and stores the result - # - returns the new int - def operator_method( op_sym ) - compiler = compiler_for(:Integer, op_sym ,{other: :Integer }) - compiler.add_code Operator.new( "op:#{op_sym}" , op_sym) - return compiler - end - - # as the name suggests, this devides the integer (self) by ten - # - # This version is lifted from some arm assembler tricks and is _much_ - # faster than the general div versions. I think it was about three - # times less instructions. Useful for itos - # - # In fact it is possible to generate specific div function for any given - # integer and some are even more faster (as eg div4). - def div10( context ) - compiler = compiler_for(:Integer,:div10 ,{}) - compiler.add_code Div10.new("div10") - return compiler - end - end - extend ClassMethods - end - end -end diff --git a/lib/mom/macro/macro.rb b/lib/mom/macro/macro.rb new file mode 100644 index 00000000..77c6e682 --- /dev/null +++ b/lib/mom/macro/macro.rb @@ -0,0 +1,63 @@ +module Mom + class Macro < Instruction + + # emit the syscall with given name + # there is a Syscall instruction, but the message has to be saved and restored + def self.emit_syscall( builder , name ) + save_message( builder ) + builder.add_code Risc::Syscall.new("emit_syscall(#{name})", name ) + restore_message(builder) + return unless (@clazz and @method) + builder.add_code Risc.label( "#{@clazz.name}.#{@message.name}" , "return_syscall" ) + end + + # a sort of inline version of exit method. + # Used by exit and __init__ (so it doesn't have to call it) + # Assumes int return value and extracts the fixnum for process exit code + def self.exit_sequence(builder) + save_message( builder ) + builder.build do + message << message[:return_value] + message.reduce_int + add_code Risc::Syscall.new("emit_syscall(exit)", :exit ) + end + end + + # save the current message, as the syscall destroys all context + # + # This relies on linux to save and restore all registers + # + def self.save_message(builder) + r8 = Risc::RegisterValue.new( :r8 , :Message).set_builder(builder) + builder.build {r8 << message} + end + + # restore the message that we save in r8 + # before th restore, the syscall return, a fixnum, is saved + # The caller of this method is assumed to caal prepare_int_return + # so that the return value already has an integer instance + # This instance is filled with os return value + def self.restore_message(builder) + r8 = Risc::RegisterValue.new( :r8 , :Message) + builder.build do + integer_reg! << message + message << r8 + integer_2! << message[:return_value] + integer_2[Parfait::Integer.integer_index] << integer_reg + end + end + end +end + +require_relative "comparison" +require_relative "exit" +require_relative "init" +require_relative "putstring" +require_relative "set_internal_word" +require_relative "div10" +require_relative "get_internal_byte" +require_relative "method_missing" +require_relative "div4" +require_relative "get_internal_word" +require_relative "operator" +require_relative "set_internal_byte" diff --git a/lib/mom/macro/method_missing.rb b/lib/mom/macro/method_missing.rb index 50a75b92..e116750a 100644 --- a/lib/mom/macro/method_missing.rb +++ b/lib/mom/macro/method_missing.rb @@ -1,14 +1,4 @@ module Mom - module Builtin - class MethodMissing < ::Mom::Instruction - def to_risc(compiler) - builder = compiler.builder(compiler.source) - builder.prepare_int_return # makes integer_tmp variable as return - Builtin.emit_syscall( builder , :exit ) - return compiler - end - end - end class MethodMissing < Macro def to_risc(compiler) builder = compiler.builder(compiler.source) diff --git a/lib/mom/macro/object.rb b/lib/mom/macro/object.rb index e7420b0a..fea4c03d 100644 --- a/lib/mom/macro/object.rb +++ b/lib/mom/macro/object.rb @@ -1,107 +1,3 @@ -require_relative "get_internal_word" -require_relative "set_internal_word" -require_relative "method_missing" -require_relative "init" -require_relative "exit" module Mom - module Builtin - class Object - module ClassMethods - include CompileHelper - - # self[index] basically. Index is the first arg - # return is stored in return_value - def get_internal_word( context ) - compiler = compiler_for(:Object , :get_internal_word ,{at: :Integer}) - compiler.add_code GetInternalWord.new("get_internal_word") - return compiler - end - # self[index] = val basically. Index is the first arg , value the second - # return the value passed in - def set_internal_word( context ) - compiler = compiler_for(:Object , :set_internal_word , {at: :Integer, value: :Object} ) - compiler.add_code SetInternalWord.new("set_internal_word") - return compiler - end - - # every object needs a method missing. - # Even if it's just this one, sys_exit (later raise) - def _method_missing( context ) - compiler = compiler_for(:Object,:method_missing ,{}) - compiler.add_code MethodMissing.new("missing") - return compiler - end - - # this is the really really first place the machine starts (apart from the jump here) - # it isn't really a function, ie it is jumped to (not called), exits and may not return - # so it is responsible for initial setup: - # - load fist message, set up Space as receiver - # - call main, ie set up message for that etc - # - exit (exit_sequence) which passes a machine int out to c - def __init__( context ) - compiler = compiler_for(:Object,:__init__ ,{}) - compiler._reset_for_init # no return, just for init - compiler.add_code Init.new("missing") - return compiler - end - - # the exit function - # mainly calls exit_sequence - def exit( context ) - compiler = compiler_for(:Object,:exit ,{}) - compiler.add_code Exit.new("exit") - return compiler - end - - end - extend ClassMethods - end - - # emit the syscall with given name - # there is a Syscall instruction, but the message has to be saved and restored - def self.emit_syscall( builder , name ) - save_message( builder ) - builder.add_code Risc::Syscall.new("emit_syscall(#{name})", name ) - restore_message(builder) - return unless (@clazz and @method) - builder.add_code Risc.label( "#{@clazz.name}.#{@message.name}" , "return_syscall" ) - end - - # a sort of inline version of exit method. - # Used by exit and __init__ (so it doesn't have to call it) - # Assumes int return value and extracts the fixnum for process exit code - def self.exit_sequence(builder) - save_message( builder ) - builder.build do - message << message[:return_value] - message.reduce_int - add_code Risc::Syscall.new("emit_syscall(exit)", :exit ) - end - end - - # save the current message, as the syscall destroys all context - # - # This relies on linux to save and restore all registers - # - def self.save_message(builder) - r8 = Risc::RegisterValue.new( :r8 , :Message).set_builder(builder) - builder.build {r8 << message} - end - - # restore the message that we save in r8 - # before th restore, the syscall return, a fixnum, is saved - # The caller of this method is assumed to caal prepare_int_return - # so that the return value already has an integer instance - # This instance is filled with os return value - def self.restore_message(builder) - r8 = Risc::RegisterValue.new( :r8 , :Message) - builder.build do - integer_reg! << message - message << r8 - integer_2! << message[:return_value] - integer_2[Parfait::Integer.integer_index] << integer_reg - end - end - end end diff --git a/lib/mom/macro/operator.rb b/lib/mom/macro/operator.rb index e4ee137f..1c7d58f7 100644 --- a/lib/mom/macro/operator.rb +++ b/lib/mom/macro/operator.rb @@ -1,29 +1,4 @@ module Mom - module Builtin - class Operator < Instruction - attr_reader :operator - def initialize(name , operator) - super(name) - @operator = operator - end - - def to_risc(compiler) - builder = compiler.builder(compiler.source) - integer_tmp = builder.allocate_int - operator = @operator # make accessible in block - builder.build do - integer! << message[:receiver] - integer.reduce_int - integer_reg! << message[:arg1] #"other" - integer_reg.reduce_int - integer.op operator , integer_reg - integer_tmp[Parfait::Integer.integer_index] << integer - message[:return_value] << integer_tmp - end - return compiler - end - end - end class IntOperator < Macro attr_reader :operator def initialize(name , operator) diff --git a/lib/mom/macro/putstring.rb b/lib/mom/macro/putstring.rb index c0f3d2d7..636ce67a 100644 --- a/lib/mom/macro/putstring.rb +++ b/lib/mom/macro/putstring.rb @@ -1,18 +1,4 @@ module Mom - module Builtin - class Putstring < ::Mom::Instruction - def to_risc(compiler) - builder = compiler.builder(compiler.source) - builder.prepare_int_return # makes integer_tmp variable as return - builder.build do - word! << message[:receiver] - integer! << word[Parfait::Word.get_length_index] - end - Mom::Builtin.emit_syscall( builder , :putstring ) - compiler - end - end - end class Putstring < Macro def to_risc(compiler) builder = compiler.builder(compiler.source) diff --git a/lib/mom/macro/set_internal_byte.rb b/lib/mom/macro/set_internal_byte.rb index aa265fcf..ab4f3d70 100644 --- a/lib/mom/macro/set_internal_byte.rb +++ b/lib/mom/macro/set_internal_byte.rb @@ -1,20 +1,4 @@ module Mom - module Builtin - class SetInternalByte < ::Mom::Instruction - def to_risc(compiler) - compiler.builder(compiler.source).build do - word! << message[:receiver] - integer_reg! << message[:arg2] #VALUE - message[:return_value] << integer_reg - integer! << message[:arg1] #"index" - integer.reduce_int - integer_reg.reduce_int - word[integer] <= integer_reg - end - return compiler - end - end - end class SetInternalByte < Macro def to_risc(compiler) compiler.builder(compiler.source).build do diff --git a/lib/mom/macro/set_internal_word.rb b/lib/mom/macro/set_internal_word.rb index 6c6d7561..4cbbb498 100644 --- a/lib/mom/macro/set_internal_word.rb +++ b/lib/mom/macro/set_internal_word.rb @@ -1,19 +1,4 @@ module Mom - module Builtin - class SetInternalWord < ::Mom::Instruction - def to_risc(compiler) - compiler.builder(compiler.source).build do - object! << message[:receiver] - integer! << message[:arg1] # "index" - object_reg! << message[:arg2]#"value" - integer.reduce_int - object[integer] << object_reg - message[:return_value] << object_reg - end - return compiler - end - end - end class SetInternalWord < Macro def to_risc(compiler) compiler.builder(compiler.source).build do diff --git a/lib/mom/macro/space.rb b/lib/mom/macro/space.rb deleted file mode 100644 index 61999513..00000000 --- a/lib/mom/macro/space.rb +++ /dev/null @@ -1,18 +0,0 @@ -module Mom - module Builtin - class Space - module ClassMethods - include CompileHelper - - # main entry point, ie __init__ calls this - # defined here as empty, to be redefined - def main(context) - compiler = compiler_for(:Space , :main ,{args: :Integer}) - return compiler - end - - end - extend ClassMethods - end - end -end diff --git a/lib/mom/macro/word.rb b/lib/mom/macro/word.rb deleted file mode 100644 index 945933d5..00000000 --- a/lib/mom/macro/word.rb +++ /dev/null @@ -1,43 +0,0 @@ -require_relative "get_internal_byte" -require_relative "set_internal_byte" -require_relative "putstring" - -module Mom - module Builtin - module Word - module ClassMethods - include CompileHelper - - # wrapper for the syscall - # io/file currently hardcoded to stdout - # set up registers for syscall, ie - # - pointer in r1 - # - length in r2 - # - emit_syscall (which does the return of an integer, see there) - def putstring( context) - compiler = compiler_for(:Word , :putstring ,{}) - compiler.add_code Putstring.new("putstring") - return compiler - end - # self[index] basically. Index is the first arg > 0 - # return a word sized new int, in return_value - # - # Note: no index (or type) checking. Method should be internal and check before. - # Which means the returned integer could be passed in, instead of allocated. - def get_internal_byte( context) - compiler = compiler_for(:Word , :get_internal_byte , {at: :Integer}) - compiler.add_code GetInternalByte.new("get_internal_byte") - return compiler - end - # self[index] = val basically. Index is the first arg ( >0 , unchecked), - # value the second, which is also returned - def set_internal_byte( context ) - compiler = compiler_for(:Word, :set_internal_byte , {at: :Integer , value: :Integer} ) - compiler.add_code SetInternalByte.new("set_internal_byte") - return compiler - end - end - extend ClassMethods - end - end -end diff --git a/lib/mom/method_compiler.rb b/lib/mom/method_compiler.rb index bb103cff..bc8f5a15 100644 --- a/lib/mom/method_compiler.rb +++ b/lib/mom/method_compiler.rb @@ -87,5 +87,12 @@ module Mom ret end + # Only for init, as init has no return + # kind of private + def _reset_for_init + @mom_instructions = Label.new(source_name, source_name) + @current = @mom_instructions + end + end end diff --git a/lib/mom/mom.rb b/lib/mom/mom.rb index 926c7ba4..a39fcc61 100644 --- a/lib/mom/mom.rb +++ b/lib/mom/mom.rb @@ -11,16 +11,9 @@ # No send or call, just objects and jump. # Machine capabilities (instructions) for basic operations. Use of macros for higher level. -module Mom - # boot bubiltin function (subject to change) - def self.boot!(options = {}) - Builtin.boot_functions(options) - end -end - require_relative "instruction.rb" require_relative "mom_collection" require_relative "callable_compiler" require_relative "method_compiler" require_relative "block_compiler" -require_relative "macro" +require_relative "macro/macro" diff --git a/lib/mom/mom_collection.rb b/lib/mom/mom_collection.rb index 5b432aa5..991a7955 100644 --- a/lib/mom/mom_collection.rb +++ b/lib/mom/mom_collection.rb @@ -14,16 +14,15 @@ module Mom @method_compilers = compilers end - # lazily instantiate the compilers for boot functions - # (in the hope of only booting the functions once) - def boot_compilers - @boot_compilers ||= Mom::Builtin.boot_functions + # lazily instantiate the compiler for init function + def init_compiler + @init_compilers ||= create_init_compiler end # Return all compilers, namely the MethodCompilers passed in, plus the # boot_function's compilers (boot_compilers) def compilers - @method_compilers + boot_compilers + @method_compilers << init_compiler end # Append another MomCompilers method_compilers to this one. @@ -42,5 +41,23 @@ module Mom Risc::RiscCollection.new(riscs) end + # this is the really really first place the machine starts (apart from the jump here) + # it isn't really a function, ie it is jumped to (not called), exits and may not return + # so it is responsible for initial setup: + # - load fist message, set up Space as receiver + # - call main, ie set up message for that etc + # - exit (exit_sequence) which passes a machine int out to c + def create_init_compiler + compiler = self.class.compiler_for(:Object,:__init__ ,{}) + compiler._reset_for_init # no return, just for init + compiler.add_code Init.new("missing") + return compiler + end + def self.compiler_for( clazz_name , method_name , arguments , locals = {}) + frame = Parfait::NamedList.type_for( locals ) + args = Parfait::NamedList.type_for( arguments ) + MethodCompiler.compiler_for_class(clazz_name , method_name , args, frame ) + end + end end diff --git a/lib/rubyx/rubyx_compiler.rb b/lib/rubyx/rubyx_compiler.rb index 3b3e4a4a..6c88aa9b 100644 --- a/lib/rubyx/rubyx_compiler.rb +++ b/lib/rubyx/rubyx_compiler.rb @@ -31,7 +31,6 @@ module RubyX def initialize(options) @options = options Parfait.boot!(options[:parfait] || {}) - Mom.boot!(options[:mom] || {}) Risc.boot!(options[:risc] || {}) end