Change Mom to SlotMachine

rather large commit, but essentially a simple rename
Rationale in docs and blogs
This commit is contained in:
2019-10-03 20:55:41 +03:00
parent fd8a3e9cc5
commit c43436f35a
170 changed files with 481 additions and 480 deletions

View File

@ -13,7 +13,7 @@ module Arm
@source = source
@next = nekst
return unless source
raise "Source must be string or Instruction, not #{source.class}" unless source.is_a?(String) or source.is_a?(Mom::Instruction)
raise "Source must be string or Instruction, not #{source.class}" unless source.is_a?(String) or source.is_a?(SlotMachine::Instruction)
end
attr_reader :source

View File

@ -38,8 +38,8 @@ module Parfait
callable_method = self_type.get_method(@name)
#puts "Using #{name} for #{self_type.object_class.name}.#{self_type.hash}" unless callable_method
raise "Callable not found #{@name}" unless callable_method
compiler = Mom::MethodCompiler.new( callable_method )
head = @source.to_mom( compiler )
compiler = SlotMachine::MethodCompiler.new( callable_method )
head = @source.to_slot( compiler )
compiler.add_code(head)
compiler
end

View File

@ -7,9 +7,9 @@ module Risc
attr_reader :block , :risc_instructions , :constants , :in_method
def initialize( block , in_method , mom_label)
def initialize( block , in_method , slot_label)
@in_method = in_method
super(block , mom_label)
super(block , slot_label)
end
def source_name

View File

@ -204,18 +204,18 @@ module Risc
# - setting up the next message
# - moving receiver (factory) and arguments (none)
# - issuing the call
# These steps shadow the MomInstructions MessageSetup, ArgumentTransfer and SimpleCall
# These steps shadow the SlotMachineInstructions MessageSetup, ArgumentTransfer and SimpleCall
def call_get_more
factory = Parfait.object_space.get_factory_for( :Integer )
calling = factory.get_type.get_method( :get_more )
calling = Parfait.object_space.get_method!(:Space,:main) #until we actually parse Factory
raise "no main defined" unless calling
Mom::MessageSetup.new( calling ).build_with( self )
SlotMachine::MessageSetup.new( calling ).build_with( self )
self.build do
factory_reg! << factory
message[:receiver] << factory_reg
end
Mom::SimpleCall.new(calling).to_risc(compiler)
SlotMachine::SimpleCall.new(calling).to_risc(compiler)
end
end

View File

@ -14,12 +14,12 @@ module Risc
# Must pass the callable (method/block)
# Also start instuction, usually a label is mandatory
def initialize( callable , mom_label)
def initialize( callable , slot_label)
raise "No method" unless callable
@callable = callable
@regs = []
@constants = []
@current = @risc_instructions = mom_label.risc_label(self)
@current = @risc_instructions = slot_label.risc_label(self)
reset_regs
end
attr_reader :risc_instructions , :constants , :callable , :current

View File

@ -8,7 +8,7 @@ module Risc
#
# We can load and store their contents, move data between them and
# access (get/set) memory at a constant offset from a register
# While Mom works with objects, the register machine has registers,
# While SlotMachine works with objects, the register machine has registers,
# but we keep the names for better understanding, r2-5 are temporary/scratch
# There is no direct memory access, only through registers
# Constants can/must be loaded into registers before use
@ -27,7 +27,7 @@ module Risc
@next = nekst
return unless source
raise "Source must be string or Instruction, not #{source.class}" unless source.is_a?(String) or
source.is_a?(Mom::Instruction) or source.is_a?(Parfait::Callable)
source.is_a?(SlotMachine::Instruction) or source.is_a?(Parfait::Callable)
end
attr_reader :source

View File

@ -9,7 +9,7 @@ module Risc
super(source)
@register = register
@constant = constant
raise "Not Constant #{constant}" if constant.is_a?(Mom::SlotDefinition)
raise "Not Constant #{constant}" if constant.is_a?(SlotMachine::SlotDefinition)
raise "Not register #{register}" unless RegisterValue.look_like_reg(register)
end
attr_accessor :register , :constant

View File

@ -7,8 +7,8 @@ module Risc
# Methods starts with a Label, both in risc and mom.
# Pass in the callable(method) and the mom label that the method starts with
def initialize( method , mom_label)
super(method , mom_label)
def initialize( method , slot_label)
super(method , slot_label)
end
def source_name

View File

@ -24,7 +24,7 @@ module Ruby
#
# The next step is then to go to the vool level, which is
# simpler, and then finally to compile
# to the next level down, MOM (Minimal Object Machine)
# to the next level down, SlotMachine (Minimal Object Machine)
class RubyCompiler < AST::Processor
include AST::Sexp

View File

@ -3,7 +3,7 @@ require "rx-file"
require_relative "util"
require_relative "elf/object_writer"
require_relative "risc"
require_relative "mom/mom"
require_relative "slot_machine/slot_machine"
require_relative "arm/arm_machine"
require_relative "arm/arm_platform"
require_relative "vool/statement"

View File

@ -35,7 +35,7 @@ module RubyX
end
# The highest level function creates binary code for the given ruby code
# for the given platform (see Platform). Binary code means that vool/mom/risc
# for the given platform (see Platform). Binary code means that vool/slot_machine/risc
# are created and then assembled into BinaryCode objects.
# (no executable is generated, only the binary code and objects needed for a binary)
#
@ -67,11 +67,11 @@ module RubyX
# Transform the incoming ruby source (string) to mom
#
# The vool is stored using ruby_to_vool,the to_mom is called
# Return Mom Statement
def ruby_to_mom(ruby)
# The vool is stored using ruby_to_vool,the to_slot is called
# Return SlotMachine Statement
def ruby_to_slot(ruby)
ruby_to_vool(ruby)
to_mom
to_slot
end
# Process previously stored vool source to binary.
@ -97,14 +97,14 @@ module RubyX
# Process previously stored vool source to risc.
# return a Risc::RiscCollection , a collection of MethodCompilers
def to_risc()
mom = to_mom
mom = to_slot
mom.to_risc()
end
# return mom for the previously stored vool source.
def to_mom
def to_slot
@vool.to_parfait
@vool.to_mom(nil)
@vool.to_slot(nil)
end
# ruby_to_vool compiles the ruby to ast, and then to vool

View File

@ -1,4 +1,4 @@
# MOM , Minimal Object Machine
# SlotMachine , Minimal Object Machine
This layer sits between the language layer (vool) and the risc machine layer.
It is meant to make the transition (between vool and risc) easier to understand.
@ -9,7 +9,7 @@ that everything in computing can be fixed by another layer :-)
## Recap
A little recap of why the transition was too steep will naturally reveal the design of MOM.
A little recap of why the transition was too steep will naturally reveal the design of SlotMachine.
### Structure
@ -34,7 +34,7 @@ used (stacks are messy, not oo)
The *essential* step from vool to risc, is the one from a language to a machine. From statements
that hang in the air, to an instruction set.
So to put a layer in the middle of those two, MOM will be:
So to put a layer in the middle of those two, SlotMachine will be:
### Linked list

View File

@ -1,12 +1,12 @@
module Mom
# The Compiler/Collection for the Mom level is a collection of Mom level Method
module SlotMachine
# The Compiler/Collection for the SlotMachine level is a collection of SlotMachine level Method
# compilers These will transform to Risc MethodCompilers on the way down.
#
# As RubyCompiler pools source at the vool level, when several classes are compiled
# from vool to mom, several MomCompilers get instantiated. They must be merged before
# from vool to mom, several SlotMachineCompilers get instantiated. They must be merged before
# proceeding with translate. Thus we have a append method.
#
class MomCollection
class SlotCollection
attr_reader :method_compilers
# Initialize with an array of risc MethodCompilers
@ -19,8 +19,8 @@ module Mom
def init_compilers
return if @init_compilers
@init_compilers = true
add_compiler MomCollection.create_init_compiler
add_compiler MomCollection.create_mm_compiler
add_compiler SlotCollection.create_init_compiler
add_compiler SlotCollection.create_mm_compiler
self
end
@ -40,7 +40,7 @@ module Mom
self
end
# Append another MomCompilers method_compilers to this one.
# Append another SlotMachineCompilers method_compilers to this one.
def append(collection)
@method_compilers.add_method_compiler( collection.method_compilers)
self

View File

@ -7,12 +7,13 @@
#
# ### Instruction based
#
# So a machine rather than a language. No control structures, but compare and jump instructions.
# No send or call, just objects and jump.
# Machine capabilities (instructions) for basic operations. Use of macros for higher level.
# So a machine rather than a language. No control structures, but compare and jump
# instructions. No send or dynamic call, just objects and jump.
# Machine capabilities (instructions) for basic operations.
# Use of macros for higher level.
require_relative "instruction.rb"
require_relative "mom_collection"
require_relative "slot_collection"
require_relative "callable_compiler"
require_relative "method_compiler"
require_relative "block_compiler"

View File

@ -12,7 +12,7 @@ Possibly later other languages can compile to this level and use rx-file as code
Vool is a layer with concrete syntax tree, just like the ruby layer above.
Vool is just simplified, without fluff, see below.
The next layer down is the Mom, Minimal object Machine, which uses an instruction list.
The next layer down is the SlotMachine, Minimal object Machine, which uses an instruction list.
The nodes of the syntax tree are all the things one would expect from a language,
if statements and the like. There is no context yet, and actual objects,
@ -33,4 +33,4 @@ existence of until, which really means if not. Other examples, some more impactf
The compilation process ends up creating (parfait) objects to represent
things like classes, types and constants. This is done in this layer,
on the way down to MOM (ie not during init)
on the way down to SlotMachine (ie not during init)

View File

@ -30,13 +30,13 @@ module Vool
# When the right hand side is a CallStatement, it must be compiled, before the assign
# is executed
#
# Derived classes do not implement to_mom, only slot_position
def to_mom(compiler)
to = Mom::SlotDefinition.new(:message , self.slot_position(compiler))
from = @value.to_slot(compiler)
assign = Mom::SlotLoad.new(self,to,from)
# Derived classes do not implement to_slot, only slot_position
def to_slot(compiler)
to = SlotMachine::SlotDefinition.new(:message , self.slot_position(compiler))
from = @value.to_slot_definition(compiler)
assign = SlotMachine::SlotLoad.new(self,to,from)
return assign unless @value.is_a?(CallStatement)
@value.to_mom(compiler) << assign
@value.to_slot(compiler) << assign
end
end
end

View File

@ -9,8 +9,8 @@ module Vool
def initialize(value)
@value = value
end
def to_slot(_)
return Mom::SlotDefinition.new(Mom::IntegerConstant.new(@value) , [])
def to_slot_definition(_)
return SlotMachine::SlotDefinition.new(SlotMachine::IntegerConstant.new(@value) , [])
end
def ct_type
Parfait.object_space.get_type_by_class_name(:Integer)
@ -37,8 +37,8 @@ module Vool
def ct_type
Parfait.object_space.get_type_by_class_name(:True)
end
def to_slot(_)
return Mom::SlotDefinition.new(Parfait.object_space.true_object , [])
def to_slot_definition(_)
return SlotMachine::SlotDefinition.new(Parfait.object_space.true_object , [])
end
def to_s(depth = 0)
"true"
@ -49,8 +49,8 @@ module Vool
def ct_type
Parfait.object_space.get_type_by_class_name(:False)
end
def to_slot(_)
return Mom::SlotDefinition.new(Parfait.object_space.false_object , [])
def to_slot_definition(_)
return SlotMachine::SlotDefinition.new(Parfait.object_space.false_object , [])
end
def to_s(depth = 0)
"false"
@ -61,8 +61,8 @@ module Vool
def ct_type
Parfait.object_space.get_type_by_class_name(:Nil)
end
def to_slot(_)
return Mom::SlotDefinition.new(Parfait.object_space.nil_object , [])
def to_slot_definition(_)
return SlotMachine::SlotDefinition.new(Parfait.object_space.nil_object , [])
end
def to_s(depth = 0)
"nil"
@ -75,9 +75,9 @@ module Vool
def initialize(type = nil)
@my_type = type
end
def to_slot(compiler)
def to_slot_definition(compiler)
@my_type = compiler.receiver_type
Mom::SlotDefinition.new(:message , [:receiver])
SlotMachine::SlotDefinition.new(:message , [:receiver])
end
def ct_type
@my_type
@ -91,8 +91,8 @@ module Vool
def initialize(value)
@value = value
end
def to_slot(_)
return Mom::SlotDefinition.new(Mom::StringConstant.new(@value),[])
def to_slot_definition(_)
return SlotMachine::SlotDefinition.new(SlotMachine::StringConstant.new(@value),[])
end
def ct_type
Parfait.object_space.get_type_by_class_name(:Word)

View File

@ -10,8 +10,8 @@ module Vool
# When used as right hand side, this tells what data to move to get the result into
# a varaible. It is (off course) the return value of the message
def to_slot(_)
Mom::SlotDefinition.new(:message ,[ :return_value])
def to_slot_definition(_)
SlotMachine::SlotDefinition.new(:message ,[ :return_value])
end
def to_s(depth = 0)

View File

@ -42,21 +42,21 @@ module Vool
# Other statements are not yet allowed (baring in mind that attribute
# accessors are transformed to methods in the ruby layer )
#
# As there is no class equivalnet in code, a MomCollection is returned,
# which is just a list of Mom::MethodCompilers
# As there is no class equivalnet in code, a SlotCollection is returned,
# which is just a list of SlotMachine::MethodCompilers
# The compilers help to transform the code further, into Risc next
def to_mom( _ )
def to_slot( _ )
method_compilers = body.statements.collect do |node|
case node
when MethodExpression
node.to_mom(@clazz)
node.to_slot(@clazz)
when ClassMethodExpression
node.to_mom(@clazz.single_class)
node.to_slot(@clazz.single_class)
else
raise "Only methods for now #{node.class}:#{node}"
end
end
Mom::MomCollection.new(method_compilers)
SlotMachine::SlotCollection.new(method_compilers)
end
# goes through the code looking for instance variables and their assignments.

View File

@ -17,7 +17,7 @@ module Vool
vool_m
end
def to_mom(clazz)
def to_slot(clazz)
raise "not singleton #{clazz.class}" unless clazz.class == Parfait::SingletonClass
raise( "no class in #{self}") unless clazz
method = clazz.get_instance_method(name )

View File

@ -10,29 +10,29 @@ module Vool
@if_false = if_false
end
def to_mom( compiler )
true_label = Mom::Label.new( self , "true_label_#{object_id.to_s(16)}")
false_label = Mom::Label.new( self , "false_label_#{object_id.to_s(16)}")
merge_label = Mom::Label.new( self , "merge_label_#{object_id.to_s(16)}")
def to_slot( compiler )
true_label = SlotMachine::Label.new( self , "true_label_#{object_id.to_s(16)}")
false_label = SlotMachine::Label.new( self , "false_label_#{object_id.to_s(16)}")
merge_label = SlotMachine::Label.new( self , "merge_label_#{object_id.to_s(16)}")
if @condition.is_a?(CallStatement)
head = @condition.to_mom(compiler)
head = @condition.to_slot(compiler)
head << check_slot(compiler , false_label)
else
head = check_slot(compiler , false_label)
end
head << true_label
head << if_true.to_mom(compiler) if @if_true
head << Mom::Jump.new(merge_label) if @if_false
head << if_true.to_slot(compiler) if @if_true
head << SlotMachine::Jump.new(merge_label) if @if_false
head << false_label
head << if_false.to_mom(compiler) if @if_false
head << if_false.to_slot(compiler) if @if_false
head << merge_label if @if_false
head
end
# create the slot lazily, so to_mom gets called first
# create the slot lazily, so to_slot gets called first
def check_slot(compiler , false_label)
Mom::TruthCheck.new(@condition.to_slot(compiler) , false_label)
SlotMachine::TruthCheck.new(@condition.to_slot_definition(compiler) , false_label)
end
def each(&block)

View File

@ -11,19 +11,19 @@ module Vool
# because of normalization (of send), slot_definition is called first,
# to assign the block to a variable.
#
# This means we do the compiler here (rather than to_mom, which is in
# This means we do the compiler here (rather than to_slot, which is in
# fact never called)
def to_slot(compiler)
def to_slot_definition(compiler)
compile(compiler) unless @parfait_block
return Mom::SlotDefinition.new(Mom::LambdaConstant.new(parfait_block(compiler)) , [])
return SlotMachine::SlotDefinition.new(SlotMachine::LambdaConstant.new(parfait_block(compiler)) , [])
end
# create a block, a compiler for it, comile the bock and add the compiler(code)
# to the method compiler for further processing
def compile( compiler )
parfait_block = self.parfait_block(compiler)
block_compiler = Mom::BlockCompiler.new( parfait_block , compiler.get_method )
head = body.to_mom( block_compiler )
block_compiler = SlotMachine::BlockCompiler.new( parfait_block , compiler.get_method )
head = body.to_slot( block_compiler )
block_compiler.add_code(head)
compiler.add_method_compiler(block_compiler)
nil

View File

@ -6,16 +6,16 @@ module Vool
super(name , SelfExpression.new , arguments)
end
def to_mom(compiler)
def to_slot(compiler)
parts = name.to_s.split("_")
class_name = "Mom::#{parts.collect{|s| s.capitalize}.join}"
class_name = "SlotMachine::#{parts.collect{|s| s.capitalize}.join}"
eval(class_name).new( self , *arguments)
end
# When used as right hand side, this tells what data to move to get the result into
# a varaible. It is (off course) the return value of the message
def to_slot(_)
Mom::SlotDefinition.new(:message ,[ :return_value])
def to_slot_definition(_)
SlotMachine::SlotDefinition.new(:message ,[ :return_value])
end
def to_s(depth = 0)

View File

@ -22,8 +22,8 @@ module Vool
vool_m
end
# Creates the Mom::MethodCompiler that will do the next step
def to_mom(clazz)
# Creates the SlotMachine::MethodCompiler that will do the next step
def to_slot(clazz)
raise( "no class in #{self}") unless clazz
method = clazz.get_instance_method(@name)
raise( "no method in #{@name} in #{clazz.name}") unless method

View File

@ -16,14 +16,14 @@ module Vool
# To return form a method in mom instructions we only need to do two things:
# - store the given return value, this is a SlotMove
# - activate return sequence (reinstantiate old message and jump to return address)
def to_mom( compiler )
def to_slot( compiler )
if @return_value.is_a?(CallStatement)
ret = @return_value.to_mom(compiler)
ret = @return_value.to_slot(compiler)
ret << slot_load(compiler)
else
ret = slot_load(compiler)
end
ret << Mom::ReturnJump.new(self , compiler.return_label )
ret << SlotMachine::ReturnJump.new(self , compiler.return_label )
end
def to_s(depth = 0)
@ -31,8 +31,8 @@ module Vool
end
def slot_load(compiler)
Mom::SlotLoad.new( self , [:message , :return_value] ,
@return_value.to_slot(compiler) )
SlotMachine::SlotLoad.new( self , [:message , :return_value] ,
@return_value.to_slot_definition(compiler) )
end
end
end

View File

@ -28,7 +28,7 @@ module Vool
# lazy init this, to keep the dependency (which goes to parfait and booting) at bay
def dynamic_call
@dynamic ||= Mom::DynamicCall.new()
@dynamic ||= SlotMachine::DynamicCall.new()
end
# A Send breaks down to 2 steps:
@ -40,7 +40,7 @@ module Vool
# So we check, and if find, add the source (vool_method) to the class and start
# compiling the vool for the receiver_type
#
def to_mom( compiler )
def to_slot( compiler )
@receiver = SelfExpression.new(compiler.receiver_type) if @receiver.is_a?(SelfExpression)
if(@receiver.ct_type)
method = @receiver.ct_type.get_method(@name)
@ -66,18 +66,18 @@ module Vool
end
def message_setup(compiler,called_method)
setup = Mom::MessageSetup.new( called_method )
mom_receive = @receiver.to_slot(compiler)
setup = SlotMachine::MessageSetup.new( called_method )
mom_receive = @receiver.to_slot_definition(compiler)
arg_target = [:message , :next_message ]
args = []
@arguments.each_with_index do |arg , index| # +1 because of type
args << Mom::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slot(compiler))
args << SlotMachine::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slot_definition(compiler))
end
setup << Mom::ArgumentTransfer.new(self, mom_receive , args )
setup << SlotMachine::ArgumentTransfer.new(self, mom_receive , args )
end
def simple_call(compiler, called_method)
message_setup(compiler,called_method) << Mom::SimpleCall.new(called_method)
message_setup(compiler,called_method) << SlotMachine::SimpleCall.new(called_method)
end
# this breaks cleanly into two parts:
@ -91,10 +91,10 @@ module Vool
# if not, change and find method for the type (simple_call to resolve_method)
# conceptually easy in ruby, but we have to compile that "easy" ruby
def cache_check(compiler)
ok = Mom::Label.new(self,"cache_ok_#{self.object_id}")
ok = SlotMachine::Label.new(self,"cache_ok_#{self.object_id}")
check = build_condition(ok, compiler) # if cached_type != current_type
check << Mom::SlotLoad.new(self,[dynamic_call.cache_entry, :cached_type] , receiver_type_definition(compiler))
check << Mom::ResolveMethod.new(self, @name , dynamic_call.cache_entry )
check << SlotMachine::SlotLoad.new(self,[dynamic_call.cache_entry, :cached_type] , receiver_type_definition(compiler))
check << SlotMachine::ResolveMethod.new(self, @name , dynamic_call.cache_entry )
check << ok
end
@ -111,14 +111,14 @@ module Vool
private
def receiver_type_definition(compiler)
defi = @receiver.to_slot(compiler)
defi = @receiver.to_slot_definition(compiler)
defi.slots << :type
defi
end
def build_condition(ok_label, compiler)
cached_type = Mom::SlotDefinition.new(dynamic_call.cache_entry , [:cached_type])
cached_type = SlotMachine::SlotDefinition.new(dynamic_call.cache_entry , [:cached_type])
current_type = receiver_type_definition(compiler)
Mom::NotSameCheck.new(cached_type , current_type, ok_label)
SlotMachine::NotSameCheck.new(cached_type , current_type, ok_label)
end
end
end

View File

@ -11,12 +11,12 @@
# data. Statements represent code whereas Expressions resolve to data.
# (in ruby there are no pure statements, everthing resolves to data)
#
# Vool resolves to Mom in the next step down. But it also the place where we create
# Vool resolves to SlotMachine in the next step down. But it also the place where we create
# Parfait representations for the main oo players, ie classes and methods.
# The protocol is thus two stage:
# - first to_parfait with implicit side-effects of creating parfait objects that
# are added to the Parfait object_space
# - second to_mom , which will return a mom version of the statement. This may be code
# - second to_slot , which will return a mom version of the statement. This may be code
# or a compiler (for methods), or compiler collection (for classes)
#
module Vool
@ -43,7 +43,7 @@ module Vool
#
# The argument given most often is a compiler
# The default implementation (this) is to raise an error
def to_mom( _ )
def to_slot( _ )
raise "Not implemented for #{self}"
end

View File

@ -61,17 +61,17 @@ module Vool
def to_parfait
@statements.collect{|s| s.to_parfait}
end
# to_mom all the statements. Append subsequent ones to the first, and return the
# to_slot all the statements. Append subsequent ones to the first, and return the
# first.
#
# For ClassStatements this creates and returns a MomCompiler
# For ClassStatements this creates and returns a SlotMachineCompiler
#
def to_mom( compiler )
def to_slot( compiler )
raise "Empty list ? #{statements.length}" if empty?
stats = @statements.dup
first = stats.shift.to_mom(compiler)
first = stats.shift.to_slot(compiler)
while( nekst = stats.shift )
next_mom = nekst.to_mom(compiler)
next_mom = nekst.to_slot(compiler)
first.append next_mom
end
first

View File

@ -10,9 +10,9 @@ module Vool
class LocalVariable < Expression
include Named
def to_slot(compiler)
def to_slot_definition(compiler)
slot_def = compiler.slot_type_for(@name)
Mom::SlotDefinition.new(:message , slot_def)
SlotMachine::SlotDefinition.new(:message , slot_def)
end
def to_s(depth = 0)
name.to_s
@ -24,8 +24,8 @@ module Vool
class InstanceVariable < Expression
include Named
def to_slot(_)
Mom::SlotDefinition.new(:message , [ :receiver , @name] )
def to_slot_definition(_)
SlotMachine::SlotDefinition.new(:message , [ :receiver , @name] )
end
# used to collect type information
def add_ivar( array )
@ -51,8 +51,8 @@ module Vool
def ct_type
get_named_class.single_class.instance_type
end
def to_slot(_)
return Mom::SlotDefinition.new( get_named_class, [])
def to_slot_definition(_)
return SlotMachine::SlotDefinition.new( get_named_class, [])
end
def get_named_class
Parfait.object_space.get_class_by_name(self.name)

View File

@ -9,15 +9,15 @@ module Vool
@body = body
end
def to_mom( compiler )
merge_label = Mom::Label.new(self, "merge_label_#{object_id.to_s(16)}")
cond_label = Mom::Label.new(self, "cond_label_#{object_id.to_s(16)}")
def to_slot( compiler )
merge_label = SlotMachine::Label.new(self, "merge_label_#{object_id.to_s(16)}")
cond_label = SlotMachine::Label.new(self, "cond_label_#{object_id.to_s(16)}")
codes = cond_label
codes << @hoisted.to_mom(compiler) if @hoisted
codes << @condition.to_mom(compiler) if @condition.is_a?(SendStatement)
codes << Mom::TruthCheck.new(condition.to_slot(compiler) , merge_label)
codes << @body.to_mom(compiler)
codes << Mom::Jump.new(cond_label)
codes << @hoisted.to_slot(compiler) if @hoisted
codes << @condition.to_slot(compiler) if @condition.is_a?(SendStatement)
codes << SlotMachine::TruthCheck.new(condition.to_slot_definition(compiler) , merge_label)
codes << @body.to_slot(compiler)
codes << SlotMachine::Jump.new(cond_label)
codes << merge_label
end

View File

@ -5,7 +5,7 @@ module Vool
#
# On the ruby side, normalisation works pretty much the same too.
#
# On the way down to Mom, small differences become abvious, as the block that is
# On the way down to SlotMachine, small differences become abvious, as the block that is
# yielded to is an argument. Whereas in a send it is either statically known
# or resolved and cached. Here it is dynamic, but sort of known dynamic.
# All we do before calling it is check that it is the right type.
@ -14,8 +14,8 @@ module Vool
# A Yield breaks down to 2 steps:
# - Setting up the next message, with receiver, arguments, and (importantly) return address
# - a SimpleCall,
def to_mom( compiler )
@parfait_block = @block.to_mom(compiler) if @block
def to_slot( compiler )
@parfait_block = @block.to_slot(compiler) if @block
@receiver = SelfExpression.new(compiler.receiver_type) if @receiver.is_a?(SelfExpression)
yield_call(compiler)
end
@ -33,10 +33,10 @@ module Vool
# this needs run-time variable resolution, which is just not done.
# we brace ourselves with the check, and exit (later raise) if . . .
def method_check(compiler)
ok_label = Mom::Label.new(self,"method_ok_#{self.object_id}")
compile_method = Mom::SlotDefinition.new( compiler.get_method , [])
runtime_method = Mom::SlotDefinition.new( :message , [ :method] )
check = Mom::NotSameCheck.new(compile_method , runtime_method, ok_label)
ok_label = SlotMachine::Label.new(self,"method_ok_#{self.object_id}")
compile_method = SlotMachine::SlotDefinition.new( compiler.get_method , [])
runtime_method = SlotMachine::SlotDefinition.new( :message , [ :method] )
check = SlotMachine::NotSameCheck.new(compile_method , runtime_method, ok_label)
# TODO? Maybe create mom instructions for this
#builder = compiler.builder("yield")
#Risc::Macro.exit_sequence(builder)
@ -48,15 +48,15 @@ module Vool
# we do a message setup, arg transfer and the a arg_yield (which is similar to dynamic_call)
def yield_arg_block(compiler)
arg_index = compiler.get_method.arguments_type.get_length - 1
setup = Mom::MessageSetup.new( arg_index )
mom_receive = @receiver.to_slot(compiler)
setup = SlotMachine::MessageSetup.new( arg_index )
mom_receive = @receiver.to_slot_definition(compiler)
arg_target = [:message , :next_message ]
args = []
@arguments.each_with_index do |arg , index| # +1 because of type
args << Mom::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slot(compiler))
args << SlotMachine::SlotLoad.new(self, arg_target + ["arg#{index+1}".to_sym] , arg.to_slot_definition(compiler))
end
setup << Mom::ArgumentTransfer.new( self , mom_receive , args )
setup << Mom::BlockYield.new( self , arg_index )
setup << SlotMachine::ArgumentTransfer.new( self , mom_receive , args )
setup << SlotMachine::BlockYield.new( self , arg_index )
end
end