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

@ -0,0 +1,19 @@
## Builtin module
The Builtin module contains functions that can not be coded in ruby.
It is the other side of the parfait coin, part of the runtime.
The functions are organised by their respective classes and get loaded in boot_classes! ,
right at the start. (see register/boot.rb)
These functions return their code, ie a Parfait::CallableMethod with a MethodSource object,
which can then be called by ruby code as if it were a "normal" function.
A normal ruby function is one that is parsed and transformed to code. But not all
functionality can be written in ruby, one of those chicken and egg things.
C uses Assembler in this situation, we use Builtin functions.
Slightly more here : http://ruby-x.org/2014/06/10/more-clarity.html (then still called Kernel)
The Builtin module is scattered into several files, but that is just so the file
doesn't get too long.

View File

@ -0,0 +1,30 @@
module Mom
class Comparison < Macro
attr_reader :operator
def initialize(name , operator)
super(name)
@operator = operator.value
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

View File

@ -0,0 +1,63 @@
module Mom
class Div10 < Macro
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

View File

@ -0,0 +1,17 @@
module Mom
class Div4 < Macro
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

View File

@ -0,0 +1,10 @@
module Mom
class Exit < Macro
def to_risc(compiler)
builder = compiler.builder(compiler.source)
builder.prepare_int_return # makes integer_tmp variable as return
Macro.exit_sequence(builder)
return compiler
end
end
end

View File

@ -0,0 +1,17 @@
module Mom
class GetInternalByte < Macro
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

View File

@ -0,0 +1,13 @@
module Mom
class GetInternalWord < Macro
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

View File

@ -0,0 +1,43 @@
module Mom
# Init "method" is the first thing that happens in the machine
# There is an inital jump to it, but that's it, no setup, no nothing
#
# The method is in quotes, because it is not really a method, it does not return!!
# This is common to all double underscore "methods", but __init also does not
# rely on the message. In fact it's job is to set up the first message
# and to call the main (possibly later _init_ , single undescrore)
#
class Init < Macro
def to_risc(compiler)
builder = compiler.builder(compiler.source)
main = Parfait.object_space.get_method!(:Space, :main)
# Set up the first message, but advance one, so main has somewhere to return to
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
# Set up the call to main, with space as receiver
Mom::MessageSetup.new(main).build_with( builder )
builder.build do
message << message[:next_message]
space? << Parfait.object_space
message[:receiver] << space
end
# set up return address and jump to main
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" , main)
add_code exit_label
end
compiler.reset_regs
Macro.exit_sequence(builder) # exit will use mains return_value as exit_code
return compiler
end
end
end

View File

@ -0,0 +1,67 @@
module Mom
class Macro < Instruction
def to_s
self.class.name.split("::").last
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
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"

View File

@ -0,0 +1,21 @@
module Mom
class MethodMissing < Macro
attr_reader :name
def initialize( source , name )
super(source)
name = name.value if name.is_a?(Vool::SymbolConstant)
raise "No reg #{name.class}" unless name.class == Symbol
@name = name
end
def to_risc(compiler)
builder = compiler.builder(compiler.source_name)
from = Risc::RegisterValue.new(@name , :Word)
to = Risc::RegisterValue.new(:r1 , :Word)
builder.add_code Risc::Transfer.new(self , from , to)
builder.add_code Risc::Syscall.new(self, :died )
return compiler
end
end
end

View File

@ -0,0 +1,3 @@
module Mom
end

View File

@ -0,0 +1,25 @@
module Mom
class IntOperator < Macro
attr_reader :operator
def initialize(name , operator)
super(name)
@operator = operator.value
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

View File

@ -0,0 +1,14 @@
module Mom
class Putstring < Macro
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::Macro.emit_syscall( builder , :putstring )
compiler
end
end
end

View File

@ -0,0 +1,16 @@
module Mom
class SetInternalByte < Macro
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

View File

@ -0,0 +1,15 @@
module Mom
class SetInternalWord < Macro
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