fold last of the virtual into register

This commit is contained in:
Torsten Ruger 2015-10-22 18:16:29 +03:00
parent f658ecf425
commit dcbd3c7091
67 changed files with 161 additions and 227 deletions

View File

@ -1,6 +1,6 @@
GIT GIT
remote: git://github.com/salama/salama-arm.git remote: git://github.com/salama/salama-arm.git
revision: c278f7eec20e9d62a55394bb7691e976980cbbe9 revision: 3fcf596a028d48ab5fa2f31babafbc5f97a6edab
specs: specs:
salama-arm (0.3.0) salama-arm (0.3.0)

View File

@ -80,13 +80,13 @@ it's main purpose is to have an oo system language to compile to.
I spent some time on the parse testing framework, so it is safe to fiddle and add. I spent some time on the parse testing framework, so it is safe to fiddle and add.
In fact it is very modular and easy to add to. In fact it is very modular and easy to add to.
### Virtual: Compile the Ast ### Register: Compile the Ast
Since we now have an Abstact syntax tree, it needs to be compiled to a virtual machine Instruction format. Since we now have an Abstact syntax tree, it needs to be compiled to a virtual machine Instruction format.
For the parsed subset that's almost done. For the parsed subset that's almost done.
It took me a while to come up with a decent but simple machine model. I had tried to map straight to hardware It took me a while to come up with a decent but simple machine model. I had tried to map straight to hardware
but failed. The current Virtual directory represent a machine with basic oo features. but failed. The current Register directory represent a machine with basic oo features.
### Parfait - the runtime ### Parfait - the runtime

View File

@ -106,7 +106,7 @@ module Interpreter
def object_for reg def object_for reg
id = get_register(reg) id = get_register(reg)
object = Virtual.machine.objects[id] object = Register.machine.objects[id]
object.nil? ? id : object object.nil? ? id : object
end end

View File

@ -24,7 +24,7 @@ module Parfait
# in a non-booting version this should map to _add_singleton_method # in a non-booting version this should map to _add_singleton_method
# def add_function function # def add_function function
# raise "not a function #{function}" unless function.is_a? Virtual::Function # raise "not a function #{function}" unless function.is_a? Register::Function
# raise "syserr " unless function.name.is_a? Symbol # raise "syserr " unless function.name.is_a? Symbol
# self.functions << function # self.functions << function
# end # end

View File

@ -13,7 +13,7 @@ module Parfait
# known local variable names # known local variable names
# executable code # executable code
# ps, the compiler injects its own info, see Virtual::MethodSource # ps, the compiler injects its own info, see Register::MethodSource
class Method < Object class Method < Object

View File

@ -2,7 +2,7 @@ module Parfait
class Variable < Object class Variable < Object
def initialize type , name , value = nil def initialize type , name , value = nil
raise "not type #{type}" unless Virtual.machine.space.get_class_by_name(type) raise "not type #{type}" unless Register.machine.space.get_class_by_name(type)
self.type , self.name , self.value = type , name , value self.type , self.name , self.value = type , name , value
self.value = 0 if self.type == :Integer and value == nil self.value = 0 if self.type == :Integer and value == nil
raise "must give name for variable" unless name raise "must give name for variable" unless name

View File

@ -16,7 +16,7 @@ module Parfait
class Word < Object class Word < Object
# initialize with length. For now we try to keep all non-parfait (including String) out # initialize with length. For now we try to keep all non-parfait (including String) out
# String will contain spaces for non-zero length # String will contain spaces for non-zero length
# Virtual provides methods to create Parfait objects from ruby # Register provides methods to create Parfait objects from ruby
def initialize len def initialize len
super() super()
raise "Must init with int, not #{len.class}" unless len.kind_of? Fixnum raise "Must init with int, not #{len.class}" unless len.kind_of? Fixnum

View File

@ -34,10 +34,10 @@ module Phisol
end end
# now we have to resolve the method name (+ receiver) into a callable method # now we have to resolve the method name (+ receiver) into a callable method
clazz = Virtual.machine.space.get_class_by_name(me.type) clazz = Register.machine.space.get_class_by_name(me.type)
raise "No such class #{me.type}" unless clazz raise "No such class #{me.type}" unless clazz
method = clazz.get_instance_method(name) method = clazz.get_instance_method(name)
#puts Virtual.machine.space.get_class_by_name(:Integer).method_names.to_a #puts Register.machine.space.get_class_by_name(:Integer).method_names.to_a
raise "Method not implemented #{me.type}.#{name}" unless method raise "Method not implemented #{me.type}.#{name}" unless method
Register.issue_call( @method , method ) Register.issue_call( @method , method )
ret = use_reg( method.source.return_type ) ret = use_reg( method.source.return_type )

View File

@ -19,7 +19,7 @@ module Phisol
if( r != :self) if( r != :self)
raise "unimplemented case in function #{r}" raise "unimplemented case in function #{r}"
else else
r = Virtual::Self.new() r = Register::Self.new()
class_name = method.for_class.name class_name = method.for_class.name
end end
end end
@ -34,7 +34,7 @@ module Phisol
#TODO check args / type compatibility #TODO check args / type compatibility
@method.source.init @method @method.source.init @method
else else
@method = Virtual::MethodSource.create_method(class_name, return_type, name , args ) @method = Register::MethodSource.create_method(class_name, return_type, name , args )
@method.for_class.add_instance_method @method @method.for_class.add_instance_method @method
end end
@method.source.receiver = r @method.source.receiver = r

20
lib/register.rb Normal file
View File

@ -0,0 +1,20 @@
require "parfait"
require "register/machine"
#if we are in the ruby run-time / generating an executable
require "register/positioned"
require "register/padding"
require "register/parfait_adapter"
require "phisol/compiler"
require "register/method_source"
class Fixnum
def fits_u8?
self >= 0 and self <= 255
end
end
require "register/instruction"
require "register/register_value"
require "register/assembler"

View File

@ -238,5 +238,5 @@ module Register
end end
end end
Sof::Volotile.add(Register::Assembler , [:objects]) Sof::Volotile.add(Assembler , [:objects])
end end

View File

@ -1,4 +1,4 @@
module Virtual module Register
# Think flowcharts: blocks are the boxes. The smallest unit of linear code # Think flowcharts: blocks are the boxes. The smallest unit of linear code

View File

@ -1,4 +1,4 @@
module Virtual module Register
# Booting is a complicated, so it is extracted into this file, even it has only one entry point # Booting is a complicated, so it is extracted into this file, even it has only one entry point
@ -147,19 +147,19 @@ module Virtual
# TODO go through the virtual parfait layer and adjust function names to what they really are # TODO go through the virtual parfait layer and adjust function names to what they really are
obj = @space.get_class_by_name(:Object) obj = @space.get_class_by_name(:Object)
[:main , :_get_instance_variable , :_set_instance_variable].each do |f| [:main , :_get_instance_variable , :_set_instance_variable].each do |f|
obj.add_instance_method Register::Builtin::Object.send(f , nil) obj.add_instance_method Builtin::Object.send(f , nil)
end end
obj = @space.get_class_by_name(:Kernel) obj = @space.get_class_by_name(:Kernel)
# create __init__ main first, __init__ calls it # create __init__ main first, __init__ calls it
[:exit,:__send , :__init__ ].each do |f| [:exit,:__send , :__init__ ].each do |f|
obj.add_instance_method Register::Builtin::Kernel.send(f , nil) obj.add_instance_method Builtin::Kernel.send(f , nil)
end end
@space.get_class_by_name(:Word).add_instance_method Register::Builtin::Word.send(:putstring , nil) @space.get_class_by_name(:Word).add_instance_method Builtin::Word.send(:putstring , nil)
obj = @space.get_class_by_name(:Integer) obj = @space.get_class_by_name(:Integer)
[:putint,:fibo , :plus].each do |f| [:putint,:fibo , :plus].each do |f|
obj.add_instance_method Register::Builtin::Integer.send(f , nil) obj.add_instance_method Builtin::Integer.send(f , nil)
end end
end end
end end

View File

@ -4,9 +4,9 @@ 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. It is the other side of the parfait coin, part of the runtime.
The functions are organized by their respective class and get loaded in boot_classes! , The functions are organized by their respective class and get loaded in boot_classes! ,
right at the start. (see virtual/boot.rb) right at the start. (see register/boot.rb)
These functions return their code, ie a Parfait::Method with a Virtual::MethodSource object, These functions return their code, ie a Parfait::Method with a MethodSource object,
which can then be called by ruby code as if it were a "normal" function. 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 A normal ruby function is one that is parsed and transformed to code. But not all functionality can

View File

@ -5,7 +5,7 @@ module Register
module ClassMethods module ClassMethods
include AST::Sexp include AST::Sexp
def plus c def plus c
plus_function = Virtual::MethodSource.create_method(:Integer,:Integer,:plus , [:Integer] ) plus_function = MethodSource.create_method(:Integer,:Integer,:plus , [:Integer] )
plus_function.source.set_return_type :Integer plus_function.source.set_return_type :Integer
plus_function.source.receiver = :Integer plus_function.source.receiver = :Integer
@ -15,7 +15,7 @@ module Register
me = Register.tmp_reg :Integer me = Register.tmp_reg :Integer
plus_function.source.add_code Register.get_slot(plus_function , :message , :receiver , me ) plus_function.source.add_code Register.get_slot(plus_function , :message , :receiver , me )
add = Register::OperatorInstruction.new( plus_function, :add , me , tmp ) add = OperatorInstruction.new( plus_function, :add , me , tmp )
plus_function.source.add_code add plus_function.source.add_code add
plus_function.source.add_code Register.set_slot(plus_function , me , :message , :return_value ) plus_function.source.add_code Register.set_slot(plus_function , me , :message , :return_value )
return plus_function return plus_function
@ -28,14 +28,14 @@ module Register
# As we write before we recurse (save a push) we write the number backwards # As we write before we recurse (save a push) we write the number backwards
# arguments: string address , integer # arguments: string address , integer
# def utoa context # def utoa context
# utoa_function = Virtual::MethodSource.create_method(:Integer ,:utoa , [ :Integer ] ) # utoa_function = MethodSource.create_method(:Integer ,:utoa , [ :Integer ] )
# function.source.return_type = :Integer # function.source.return_type = :Integer
# function.source.receiver = :Integer # function.source.receiver = :Integer
# return utoa_function # return utoa_function
# # str_addr = utoa_function.receiver # # str_addr = utoa_function.receiver
# # number = utoa_function.args.first # # number = utoa_function.args.first
# # remainder = utoa_function.new_local # # remainder = utoa_function.new_local
# # Virtual::RegisterMachine.instance.div10( utoa_function , number , remainder ) # # RegisterMachine.instance.div10( utoa_function , number , remainder )
# # # make char out of digit (by using ascii encoding) 48 == "0" # # # make char out of digit (by using ascii encoding) 48 == "0"
# # utoa_function.instance_eval do # # utoa_function.instance_eval do
# # add( remainder , remainder , 48) # # add( remainder , remainder , 48)
@ -48,7 +48,7 @@ module Register
# end # end
def putint context def putint context
putint_function = Virtual::MethodSource.create_method(:Integer,:Integer,:putint , [] ) putint_function = MethodSource.create_method(:Integer,:Integer,:putint , [] )
putint_function.source.set_return_type :Integer putint_function.source.set_return_type :Integer
putint_function.source.receiver = :Integer putint_function.source.receiver = :Integer
return putint_function return putint_function
@ -68,7 +68,7 @@ module Register
# add( int , buffer , nil ) # string to write to # add( int , buffer , nil ) # string to write to
# mov( moved_int , buffer.length ) # mov( moved_int , buffer.length )
# end # end
# Virtual::RegisterMachine.instance.write_stdout(putint_function) # RegisterMachine.instance.write_stdout(putint_function)
# putint_function # putint_function
end end
@ -77,7 +77,7 @@ module Register
# a hand coded version of the fibonachi numbers # a hand coded version of the fibonachi numbers
# not my hand off course, found in the net http://www.peter-cockerell.net/aalp/html/ch-5.html # not my hand off course, found in the net http://www.peter-cockerell.net/aalp/html/ch-5.html
def fibo context def fibo context
fibo_function = Virtual::MethodSource.create_method(:Integer,:Integer,:fibo , [] ) fibo_function = MethodSource.create_method(:Integer,:Integer,:fibo , [] )
fibo_function.source.set_return_type :Integer fibo_function.source.set_return_type :Integer
fibo_function.source.receiver = :Integer fibo_function.source.receiver = :Integer
return fibo_function return fibo_function

View File

@ -6,7 +6,7 @@ module Register
# it isn't really a function, ie it is jumped to (not called), exits and may not return # 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 # so it is responsible for initial setup
def __init__ context def __init__ context
function = Virtual::MethodSource.create_method(:Kernel,:Integer,:__init__ , []) function = MethodSource.create_method(:Kernel,:Integer,:__init__ , [])
function.source.set_return_type :Integer function.source.set_return_type :Integer
# no method enter or return (automatically added), remove # no method enter or return (automatically added), remove
function.source.blocks.first.codes.pop # no Method enter function.source.blocks.first.codes.pop # no Method enter
@ -21,20 +21,20 @@ module Register
# And store the space as the new self (so the call can move it back as self) # And store the space as the new self (so the call can move it back as self)
function.source.add_code Register.set_slot( function, space_reg , :new_message , :receiver) function.source.add_code Register.set_slot( function, space_reg , :new_message , :receiver)
# now we are set up to issue a call to the main # now we are set up to issue a call to the main
Register.issue_call( function , Virtual.machine.space.get_main) Register.issue_call( function , Register.machine.space.get_main)
emit_syscall( function , :exit ) emit_syscall( function , :exit )
return function return function
end end
def exit context def exit context
function = Virtual::MethodSource.create_method(:Kernel,:Integer,:exit , []) function = MethodSource.create_method(:Kernel,:Integer,:exit , [])
function.source.set_return_type :Integer function.source.set_return_type :Integer
return function return function
ret = Virtual::RegisterMachine.instance.exit(function) ret = RegisterMachine.instance.exit(function)
function.set_return ret function.set_return ret
function function
end end
def __send context def __send context
function = Virtual::MethodSource.create_method(:Kernel,:Integer ,:__send , [] ) function = MethodSource.create_method(:Kernel,:Integer ,:__send , [] )
function.source.set_return_type :Integer function.source.set_return_type :Integer
return function return function
end end

View File

@ -6,7 +6,7 @@ module Register
# main entry point, ie __init__ calls this # main entry point, ie __init__ calls this
# defined here as empty, to be redefined # defined here as empty, to be redefined
def main context def main context
function = Virtual::MethodSource.create_method(:Object, :Integer , :main , []) function = MethodSource.create_method(:Object, :Integer , :main , [])
return function return function
end end
@ -18,13 +18,13 @@ module Register
# The at_index is just "below" the api, something we need but don't want to expose, # The at_index is just "below" the api, something we need but don't want to expose,
# so we can't code the above in ruby # so we can't code the above in ruby
def _get_instance_variable context , name = :Integer def _get_instance_variable context , name = :Integer
get_function = Virtual::MethodSource.create_method(:Object,:Integer, :_get_instance_variable , [ ] ) get_function = MethodSource.create_method(:Object,:Integer, :_get_instance_variable , [ ] )
return get_function return get_function
# me = get_function.receiver # me = get_function.receiver
# var_name = get_function.args.first # var_name = get_function.args.first
# return_to = get_function.return_type # return_to = get_function.return_type
# #
# index_function = ::Virtual.machine.space.get_class_by_name(:Object).resolve_method(:index_of) # index_function = ::Register.machine.space.get_class_by_name(:Object).resolve_method(:index_of)
# # get_function.push( [me] ) # # get_function.push( [me] )
# # index = get_function.call( index_function ) # # index = get_function.call( index_function )
# #
@ -39,7 +39,7 @@ module Register
end end
def _set_instance_variable(context , name = :Integer , value = :Integer ) def _set_instance_variable(context , name = :Integer , value = :Integer )
set_function = Virtual::MethodSource.create_method(:Object,:Integer,:_set_instance_variable ,[] ) set_function = MethodSource.create_method(:Object,:Integer,:_set_instance_variable ,[] )
return set_function return set_function
# receiver set_function # receiver set_function
# me = set_function.receiver # me = set_function.receiver

View File

@ -3,7 +3,7 @@ module Register
module Word module Word
module ClassMethods module ClassMethods
def putstring context def putstring context
function = Virtual::MethodSource.create_method(:Word,:Integer , :putstring , [] ) function = MethodSource.create_method(:Word,:Integer , :putstring , [] )
function.source.add_code Register.get_slot( function , :message , :receiver , :new_message ) function.source.add_code Register.get_slot( function , :message , :receiver , :new_message )
Kernel.emit_syscall( function , :putstring ) Kernel.emit_syscall( function , :putstring )
function function

View File

@ -1,4 +1,4 @@
module Virtual module Register
# collect anything that is in the space but and reachable from init # collect anything that is in the space but and reachable from init
module Collector module Collector

View File

@ -24,8 +24,8 @@ module Register
@index = index @index = index
@register = register @register = register
raise "not integer #{index}" unless index.is_a? Numeric raise "not integer #{index}" unless index.is_a? Numeric
raise "Not register #{register}" unless Register::RegisterValue.look_like_reg(register) raise "Not register #{register}" unless RegisterValue.look_like_reg(register)
raise "Not register #{array}" unless Register::RegisterValue.look_like_reg(array) raise "Not register #{array}" unless RegisterValue.look_like_reg(array)
end end
attr_accessor :array , :index , :register attr_accessor :array , :index , :register

View File

@ -23,8 +23,8 @@ module Register
@array = array @array = array
@index = index @index = index
raise "not integer #{index}" unless index.is_a? Numeric raise "not integer #{index}" unless index.is_a? Numeric
raise "Not register #{register}" unless Register::RegisterValue.look_like_reg(register) raise "Not register #{register}" unless RegisterValue.look_like_reg(register)
raise "Not register #{array}" unless Register::RegisterValue.look_like_reg(array) raise "Not register #{array}" unless RegisterValue.look_like_reg(array)
end end
attr_accessor :register , :array , :index attr_accessor :register , :array , :index
def to_s def to_s

View File

@ -1,7 +1,7 @@
require 'parslet/convenience' require 'parslet/convenience'
require_relative "collector" require_relative "collector"
module Virtual module Register
# The Virtual Machine is a object based virtual machine in which ruby is implemented. # The Register Machine is a object based virtual machine in which ruby is implemented.
# #
# It is minimal and realistic and low level # It is minimal and realistic and low level
# - minimal means that if one thing can be implemented by another, it is left out. This is quite # - minimal means that if one thing can be implemented by another, it is left out. This is quite
@ -118,7 +118,7 @@ module Virtual
def boot def boot
boot_parfait! boot_parfait!
@init = Block.new("init", :__init__ ) @init = Block.new("init", :__init__ )
branch = Register::Branch.new( "__init__" , self.space.get_init.source.blocks.first ) branch = Branch.new( "__init__" , self.space.get_init.source.blocks.first )
@init.add_code branch @init.add_code branch
@booted = true @booted = true
self self

View File

@ -1,6 +1,6 @@
require_relative "block" require_relative "block"
module Virtual module Register
# the static info of a method (with its compiled code, argument names etc ) is part of the # the static info of a method (with its compiled code, argument names etc ) is part of the
# runtime, ie found in Parfait::Method # runtime, ie found in Parfait::Method
@ -35,17 +35,17 @@ module Virtual
def self.create_method( class_name , return_type , method_name , args) def self.create_method( class_name , return_type , method_name , args)
raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol raise "create_method #{class_name}.#{class_name.class}" unless class_name.is_a? Symbol
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
clazz = Virtual.machine.space.get_class_by_name class_name clazz = Register.machine.space.get_class_by_name class_name
raise "No such class #{class_name}" unless clazz raise "No such class #{class_name}" unless clazz
arguments = [] arguments = []
args.each_with_index do | arg , index | args.each_with_index do | arg , index |
unless arg.is_a? Parfait::Variable unless arg.is_a? Parfait::Variable
raise "not type #{arg}:#{arg.class}" unless Virtual.machine.space.get_class_by_name arg raise "not type #{arg}:#{arg.class}" unless Register.machine.space.get_class_by_name arg
arg = Parfait::Variable.new arg , "arg#{index}".to_sym arg = Parfait::Variable.new arg , "arg#{index}".to_sym
end end
arguments << arg arguments << arg
end end
method = clazz.create_instance_method( method_name , Virtual.new_list(arguments)) method = clazz.create_instance_method( method_name , Register.new_list(arguments))
method.source = MethodSource.new(method , return_type) method.source = MethodSource.new(method , return_type)
method method
end end
@ -63,11 +63,11 @@ module Virtual
@current = enter @current = enter
ret = new_block("return") ret = new_block("return")
# move the current message to new_message # move the current message to new_message
ret.add_code Register::RegisterTransfer.new(self, Register.message_reg , Register.new_message_reg ) ret.add_code RegisterTransfer.new(self, Register.message_reg , Register.new_message_reg )
# and restore the message from saved value in new_message # and restore the message from saved value in new_message
ret.add_code Register.get_slot(self,:new_message , :caller , :message ) ret.add_code Register.get_slot(self,:new_message , :caller , :message )
#load the return address into pc, affecting return. (other cpus have commands for this, but not arm) #load the return address into pc, affecting return. (other cpus have commands for this, but not arm)
ret.add_code Register::FunctionReturn.new( self , Register.new_message_reg , Register.resolve_index(:message , :return_address) ) ret.add_code FunctionReturn.new( self , Register.new_message_reg , Register.resolve_index(:message , :return_address) )
@constants = [] @constants = []
end end
attr_reader :blocks , :constants , :return_type attr_reader :blocks , :constants , :return_type
@ -75,13 +75,13 @@ module Virtual
def set_return_type type def set_return_type type
return if type.nil? return if type.nil?
raise "not type #{type}" unless Virtual.machine.space.get_class_by_name type raise "not type #{type}" unless Register.machine.space.get_class_by_name type
@return_type = type @return_type = type
end end
# add an instruction after the current (insertion point) # add an instruction after the current (insertion point)
# the added instruction will become the new insertion point # the added instruction will become the new insertion point
def add_code instruction def add_code instruction
unless instruction.is_a?(Register::Instruction) unless instruction.is_a?(Instruction)
raise instruction.to_s raise instruction.to_s
end end
@current.add_code(instruction) #insert after current @current.add_code(instruction) #insert after current
@ -93,7 +93,7 @@ module Virtual
def locals_at l_block def locals_at l_block
used =[] used =[]
# call assigns the return register, but as it is in l_block, it is not asked. # call assigns the return register, but as it is in l_block, it is not asked.
assigned = [ Register::RegisterValue.new(Virtual::RegisterMachine.instance.return_register) ] assigned = [ RegisterValue.new(RegisterMachine.instance.return_register) ]
l_block.reachable.each do |b| l_block.reachable.each do |b|
b.uses.each {|u| b.uses.each {|u|
(used << u) unless assigned.include?(u) (used << u) unless assigned.include?(u)

View File

@ -1,4 +1,4 @@
module Virtual module Register
# Remove all functions that are not called # Remove all functions that are not called
# Not called is approximated by the fact that the method name doesn't show up # Not called is approximated by the fact that the method name doesn't show up
@ -11,7 +11,7 @@ module Virtual
@gonners << f @gonners << f
end end
end end
keep Virtual.machine.space.get_init keep Register.machine.space.get_init
remove_remaining remove_remaining
end end
@ -25,7 +25,7 @@ module Virtual
@gonners.delete function @gonners.delete function
function.source.blocks.each do |block| function.source.blocks.each do |block|
block.codes.each do |code| block.codes.each do |code|
keep code.method if code.is_a? Register::FunctionCall keep code.method if code.is_a? FunctionCall
end end
end end
end end

View File

@ -4,7 +4,7 @@
# To stay sane, we use the same classes that we use later, but "adapt" them to work in ruby # To stay sane, we use the same classes that we use later, but "adapt" them to work in ruby
# This affects mainly memory layout # This affects mainly memory layout
module Virtual module Register
def self.new_list array def self.new_list array
list = Parfait::List.new list = Parfait::List.new
list.set_length array.length list.set_length array.length
@ -24,7 +24,7 @@ class Symbol
true true
end end
def get_layout def get_layout
l = Virtual.machine.space.classes[:Word].object_layout l = Register.machine.space.classes[:Word].object_layout
#puts "LL #{l.class}" #puts "LL #{l.class}"
l l
end end
@ -42,7 +42,7 @@ class Symbol
pos = cache_positions[self] pos = cache_positions[self]
if pos == nil if pos == nil
str = "position accessed but not set, " str = "position accessed but not set, "
str += "Machine has object=#{Virtual.machine.objects.has_key?(self.object_id)} " str += "Machine has object=#{Register.machine.objects.has_key?(self.object_id)} "
raise str + " for Symbol:#{self}" raise str + " for Symbol:#{self}"
end end
pos pos

View File

@ -3,7 +3,7 @@
module Positioned module Positioned
def position def position
if @position.nil? if @position.nil?
str = "IN machine #{Virtual.machine.objects.has_key?(self.object_id)}, at #{self.object_id.to_s(16)}\n" str = "IN machine #{Register.machine.objects.has_key?(self.object_id)}, at #{self.object_id.to_s(16)}\n"
raise str + "position not set for #{self.class} len #{word_length} for #{self.inspect[0...100]}" raise str + "position not set for #{self.class} len #{word_length} for #{self.inspect[0...100]}"
end end
@position @position

View File

@ -1,7 +0,0 @@
require_relative "instruction"
require_relative "register_value"
require_relative "assembler"
# So the memory model of the machine allows for indexed access into an "object" .
# A fixed number of objects exist (ie garbage collection is reclaming, not destroying and
# recreating) although there may be a way to increase that number.

View File

@ -10,7 +10,6 @@ end
require 'parser/transform' require 'parser/transform'
require "salama-object-file" require "salama-object-file"
require "virtual" require "register"
require "register/register"
require "register/builtin/object" require "register/builtin/object"
require "arm/arm_machine" require "arm/arm_machine"

View File

@ -1,16 +0,0 @@
require "parfait"
require "virtual/machine"
#if we are in the ruby run-time / generating an executable
require "virtual/positioned"
require "virtual/padding"
require "virtual/parfait_adapter"
require "phisol/compiler"
require "virtual/method_source"
class Fixnum
def fits_u8?
self >= 0 and self <= 255
end
end

View File

@ -1,62 +0,0 @@
### Virtual OO Machine
This is really an OV (object value) not object oriented machine.
Integers and References are Values. We make them look like objects, sure, but they are not.
Symbols have similar properties and those are:
- equality means identity
- no change over lifetime
It's like with Atoms: they used to be the smallest possible physical unit. Now we have electrons,
proton and neutrons. And so objects are made up of Values (not objects), integers, floats ,
references and possibly more.
Values have type in the same way objects have a class. We keep track of the type of a value at runtime,
also in an similar way that objects have their classes at runtime.
### Layers
*Ast* instances get created by the [salama-reader](https://github.com/salama/salama-reader) gem from
source. Here we add compile functions to ast classes and compile the AST layer into
Virtual::Objects and Parfait::Values
The main objects are Space (lots of objects), Parfait::Class ,
Method and MethodSource (with Blocks and Instruction).
**Virtual** Instructions get further transformed into **register** instructions.
This is done by an abstractly defined Register Machine with basic Intructions.
A concrete implementation (like Arm) derives and creates derived Instructions.
The transformation is implemented as **passes** to make it easier to understand what is going on.
Also this makes it easier to add functionality and optimisations from external (to the gem) sources.
The final transformation assigns Positions to all boot objects (Linker) and assembles them into a
binary representation. The data- part is then a representation of classes in the **parfait** runtime.
And the instrucions make up the funtions.
### Accessible Objects
Object oriented systems have data hiding. So we have access to the inner state of only four objects:
- Self
- Message (arguments, method name, self)
- Frame (local and tmp variables)
- NewMessage ( to build the next message sent)
A single instructions (Set) allows movement of data between these.
There are compare, branch and call intructions too.
### Micro
The micro-kernel idea is well stated by: If you can leave it out, do.
As such we are aiming for integer and reference (type) support, and a minimal class system
(object/class/aray/hash/string). It is possible to add types to the system in a similar way as we add classes,
and also implement very machine dependent functionality which nevertheless is fully wrapped as OO.
**Parfait** is that part of the runtime that can be coded in ruby.
It is parsed, like any other code and always included in the resulting binary.
**Builtin** is the part of the runtime that can not be coded in ruby (but is still needed).
This is coded by construction MethodSource in code and necessarily machine dependant.

View File

@ -1,6 +1,6 @@
module Virtual module Register
class Constant < ::Virtual::Object class Constant < ::Register::Object
end end
class TrueConstant < Constant class TrueConstant < Constant
end end

View File

@ -1,4 +1,4 @@
module Virtual module Register
# So when an object calls a method, or sends a message, this is what it sends: a Message # So when an object calls a method, or sends a message, this is what it sends: a Message
# A message contains the sender, return and exceptional return addresses,the arguments, # A message contains the sender, return and exceptional return addresses,the arguments,

View File

@ -1,4 +1,4 @@
module Virtual module Register
# Plock (Proc-Block) is mostly a Block but also somewhat Proc-ish: A Block that carries data. # Plock (Proc-Block) is mostly a Block but also somewhat Proc-ish: A Block that carries data.
# #
# Data in a Block is usefull in the same way data in objects is. Plocks being otherwise just code. # Data in a Block is usefull in the same way data in objects is. Plocks being otherwise just code.

View File

@ -1,4 +1,4 @@
module Virtual module Register
# A slot is a slot in an object. It is the storage location for a value. # A slot is a slot in an object. It is the storage location for a value.
# (Remember, values are typed) # (Remember, values are typed)
# From a memory perspective a slot is an index into an array (the object) # From a memory perspective a slot is an index into an array (the object)

View File

@ -3,7 +3,7 @@ require 'parslet/convenience'
Phisol::Compiler.class_eval do Phisol::Compiler.class_eval do
def set_main main def set_main main
@clazz = Virtual.machine.space.get_class_by_name :Object @clazz = Register.machine.space.get_class_by_name :Object
@method = main @method = main
end end
end end
@ -11,10 +11,10 @@ end
module CompilerHelper module CompilerHelper
def set_main compiler def set_main compiler
compiler.set_main Virtual.machine.space.get_main compiler.set_main Register.machine.space.get_main
end end
def check def check
machine = Virtual.machine machine = Register.machine
machine.boot unless machine.booted machine.boot unless machine.booted
parser = Parser::Salama.new parser = Parser::Salama.new
parser = parser.send @root parser = parser.send @root

View File

@ -1,11 +1,11 @@
require_relative "compiler_helper" require_relative "compiler_helper"
module Virtual module Register
class TestCall < MiniTest::Test class TestCall < MiniTest::Test
include CompilerHelper include CompilerHelper
def setup def setup
Virtual.machine.boot Register.machine.boot
@root = :call_site @root = :call_site
@output = Register::RegisterValue @output = Register::RegisterValue
end end
@ -31,7 +31,7 @@ module Virtual
end end
def test_call_main_op def test_call_main_op
Virtual.machine.space.get_main.ensure_local(:bar , :Integer) Register.machine.space.get_main.ensure_local(:bar , :Integer)
@string_input = 'main( bar )' @string_input = 'main( bar )'
check check
end end

View File

@ -1,11 +1,11 @@
require_relative "compiler_helper" require_relative "compiler_helper"
module Virtual module Register
class TestFields < MiniTest::Test class TestFields < MiniTest::Test
include CompilerHelper include CompilerHelper
def setup def setup
Virtual.machine.boot Register.machine.boot
end end
def test_field_not_defined def test_field_not_defined
@ -17,7 +17,7 @@ HERE
end end
def test_field def test_field
Virtual.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro) Register.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro)
@root = :field_access @root = :field_access
@string_input = <<HERE @string_input = <<HERE
self.bro self.bro
@ -27,7 +27,7 @@ HERE
end end
def test_local def test_local
Virtual.machine.space.get_main.ensure_local(:bar , :Integer) Register.machine.space.get_main.ensure_local(:bar , :Integer)
@root = :name @root = :name
@string_input = 'bar ' @string_input = 'bar '
@output = Register::RegisterValue @output = Register::RegisterValue
@ -35,7 +35,7 @@ HERE
end end
def test_args def test_args
Virtual.machine.space.get_main.arguments.push Parfait::Variable.new(:Integer , :bar) Register.machine.space.get_main.arguments.push Parfait::Variable.new(:Integer , :bar)
@root = :name @root = :name
@string_input = 'bar ' @string_input = 'bar '
@output = Register::RegisterValue @output = Register::RegisterValue

View File

@ -1,11 +1,11 @@
require_relative "compiler_helper" require_relative "compiler_helper"
module Virtual module Register
class TestOps < MiniTest::Test class TestOps < MiniTest::Test
include CompilerHelper include CompilerHelper
def setup def setup
Virtual.machine.boot Register.machine.boot
@root = :operator_value @root = :operator_value
@output = Register::RegisterValue @output = Register::RegisterValue
end end
@ -20,24 +20,24 @@ module Virtual
end end
end end
def test_local_int def test_local_int
Virtual.machine.space.get_main.ensure_local(:bar , :Integer) Register.machine.space.get_main.ensure_local(:bar , :Integer)
@string_input = 'bar + 3' @string_input = 'bar + 3'
check check
end end
def test_int_local def test_int_local
Virtual.machine.space.get_main.ensure_local(:bar , :Integer) Register.machine.space.get_main.ensure_local(:bar , :Integer)
@string_input = '3 + bar' @string_input = '3 + bar'
check check
end end
def test_field_int def test_field_int
Virtual.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro) Register.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro)
@string_input = "self.bro + 3" @string_input = "self.bro + 3"
check check
end end
def test_int_field def test_int_field
Virtual.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro) Register.machine.space.get_class_by_name(:Object).object_layout.add_instance_variable(:bro)
@string_input = "3 + self.bro" @string_input = "3 + self.bro"
check check
end end

View File

@ -13,7 +13,7 @@ module Fragments
@stdout = "" @stdout = ""
end end
def check def check
machine = Virtual.machine.boot machine = Register.machine.boot
machine.parse_and_compile @string_input machine.parse_and_compile @string_input
machine.collect machine.collect
interpreter = Interpreter::Interpreter.new interpreter = Interpreter::Interpreter.new

View File

@ -16,8 +16,8 @@ class Object
end end
end end
HERE HERE
@expect = [ [SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set, @expect = [ [SaveReturn,Register::GetSlot,Register::Set,Register::Set,
Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ] Register::Set,Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
check check
end end

View File

@ -35,7 +35,7 @@ class Object
end end
end end
HERE HERE
@expect = [[SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] , @expect = [[SaveReturn,Register::GetSlot,Register::Set,Register::Set,RegisterTransfer,FunctionCall] ,
[RegisterTransfer,GetSlot,FunctionReturn]] [RegisterTransfer,GetSlot,FunctionReturn]]
check check

View File

@ -11,8 +11,8 @@ class Object
end end
end end
HERE HERE
@expect = [[SaveReturn,Virtual::Set,Register::GetSlot,Virtual::Set, @expect = [[SaveReturn,Register::Set,Register::GetSlot,Register::Set,
Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn]] Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn]]
check check
end end
end end

View File

@ -16,8 +16,8 @@ class Object
end end
end end
HERE HERE
@expect = [ [SaveReturn,Virtual::Set,Register::GetSlot,Virtual::Set, @expect = [ [SaveReturn,Register::Set,Register::GetSlot,Register::Set,
Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ] Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
check check
end end
end end

View File

@ -27,8 +27,8 @@ class Object
end end
end end
HERE HERE
@expect = [[SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set, @expect = [[SaveReturn,Register::GetSlot,Register::Set,Register::Set,
Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] , [RegisterTransfer,GetSlot,FunctionReturn]] Register::Set,Register::Set,RegisterTransfer,FunctionCall] , [RegisterTransfer,GetSlot,FunctionReturn]]
check check
end end
end end

View File

@ -24,20 +24,20 @@ class Object
end end
end end
HERE HERE
@expect = [ [SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set, @expect = [ [SaveReturn,Register::GetSlot,Register::Set,Register::Set,
Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ] Register::Set,Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
check check
end end
# a hand coded version of the fibonachi numbers (moved to kernel to be able to call it) # a hand coded version of the fibonachi numbers (moved to kernel to be able to call it)
# not my hand off course, found in the net from a basic introduction # not my hand off course, found in the net from a basic introduction
def ttest_kernel_fibo def ttest_kernel_fibo
int = Register::Integer.new(Virtual::RegisterMachine.instance.receiver_register) int = Register::Integer.new(Register::RegisterMachine.instance.receiver_register)
fibo = @object_space.get_class_by_name(:Object).resolve_method(:fibo) fibo = @object_space.get_class_by_name(:Object).resolve_method(:fibo)
main = @object_space.main main = @object_space.main
main.mov int , 10 main.mov int , 10
main.call( fibo ) main.call( fibo )
main.mov( Virtual::RegisterMachine.instance.receiver_register , Virtual::RegisterMachine.instance.return_register ) main.mov( Register::RegisterMachine.instance.receiver_register , Register::RegisterMachine.instance.return_register )
putint = @object_space.get_class_by_name(:Object).resolve_method(:putint) putint = @object_space.get_class_by_name(:Object).resolve_method(:putint)
main.call( putint ) main.call( putint )
@should = [0x0,0x40,0x2d,0xe9,0x1,0x0,0x52,0xe3,0x2,0x0,0xa0,0xd1,0x7,0x0,0x0,0xda,0x1,0x30,0xa0,0xe3,0x0,0x40,0xa0,0xe3,0x4,0x30,0x83,0xe0,0x4,0x40,0x43,0xe0,0x1,0x20,0x42,0xe2,0x1,0x0,0x52,0xe3,0xfa,0xff,0xff,0x1a,0x3,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8] @should = [0x0,0x40,0x2d,0xe9,0x1,0x0,0x52,0xe3,0x2,0x0,0xa0,0xd1,0x7,0x0,0x0,0xda,0x1,0x30,0xa0,0xe3,0x0,0x40,0xa0,0xe3,0x4,0x30,0x83,0xe0,0x4,0x40,0x43,0xe0,0x1,0x20,0x42,0xe2,0x1,0x0,0x52,0xe3,0xfa,0xff,0xff,0x1a,0x3,0x0,0xa0,0xe1,0x0,0x80,0xbd,0xe8]

View File

@ -4,10 +4,10 @@ require_relative '../../helper'
module Statements module Statements
def check def check
machine = Virtual.machine machine = Register.machine
machine.boot unless machine.booted machine.boot unless machine.booted
machine.parse_and_compile @string_input machine.parse_and_compile @string_input
produced = Virtual.machine.space.get_main.source produced = Register.machine.space.get_main.source
assert @expect , "No output given" assert @expect , "No output given"
assert_equal @expect.length , produced.blocks.length , "Block length" assert_equal @expect.length , produced.blocks.length , "Block length"
produced.blocks.each_with_index do |b,i| produced.blocks.each_with_index do |b,i|

View File

@ -5,7 +5,7 @@ class TestAssignStatement < MiniTest::Test
include Statements include Statements
def setup def setup
Virtual.machine.boot Register.machine.boot
end end
def test_assign_op def test_assign_op
@ -77,7 +77,7 @@ HERE
end end
def test_assign_arg def test_assign_arg
Virtual.machine.space.get_main.arguments.push Parfait::Variable.new(:Integer , :bar) Register.machine.space.get_main.arguments.push Parfait::Variable.new(:Integer , :bar)
@string_input = <<HERE @string_input = <<HERE
class Object class Object
int main(int bar) int main(int bar)
@ -109,7 +109,7 @@ HERE
def test_arg_get def test_arg_get
# have to define bar externally, just because redefining main. Otherwise that would be automatic # have to define bar externally, just because redefining main. Otherwise that would be automatic
Virtual.machine.space.get_main.arguments.push Parfait::Variable.new(:Integer , :bar) Register.machine.space.get_main.arguments.push Parfait::Variable.new(:Integer , :bar)
@string_input = <<HERE @string_input = <<HERE
class Object class Object
int main(int bar) int main(int bar)

View File

@ -3,7 +3,7 @@ require_relative "../helper"
class HelloTest < MiniTest::Test class HelloTest < MiniTest::Test
def check def check
machine = Virtual.machine.boot machine = Register.machine.boot
Parfait::Space.object_space.get_class_by_name(:Integer).remove_instance_method :plus Parfait::Space.object_space.get_class_by_name(:Integer).remove_instance_method :plus
#TODO remove this hack: write proper aliases #TODO remove this hack: write proper aliases
statements = machine.parse_and_compile @string_input statements = machine.parse_and_compile @string_input

View File

@ -19,7 +19,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
require 'salama' require 'salama'
module Virtual module Register
# Functions to generate parfait objects # Functions to generate parfait objects
def self.new_word( string ) def self.new_word( string )
string = string.to_s if string.is_a? Symbol string = string.to_s if string.is_a? Symbol

View File

@ -5,7 +5,7 @@ class AddTest < MiniTest::Test
include Ticker include Ticker
def setup def setup
machine = Virtual.machine.boot machine = Register.machine.boot
code = s(:class, :Object, code = s(:class, :Object,
s(:derives, nil), s(:derives, nil),
s(:statements, s(:statements,
@ -21,7 +21,7 @@ class AddTest < MiniTest::Test
Phisol::Compiler.compile( code ) Phisol::Compiler.compile( code )
machine.collect machine.collect
@interpreter = Interpreter::Interpreter.new @interpreter = Interpreter::Interpreter.new
@interpreter.start Virtual.machine.init @interpreter.start Register.machine.init
end end
def test_branch def test_branch
@ -31,7 +31,7 @@ class AddTest < MiniTest::Test
end end
def test_load def test_load
assert_equal Register::LoadConstant , ticks(2).class assert_equal Register::LoadConstant , ticks(2).class
assert_equal Parfait::Space , Virtual.machine.objects[ @interpreter.get_register(:r2)].class assert_equal Parfait::Space , Register.machine.objects[ @interpreter.get_register(:r2)].class
assert_equal :r2, @interpreter.instruction.array.symbol assert_equal :r2, @interpreter.instruction.array.symbol
end end
def test_get def test_get

View File

@ -20,16 +20,16 @@ class Object
end end
end end
HERE HERE
machine = Virtual.machine.boot machine = Register.machine.boot
syntax = Parser::Salama.new.parse_with_debug(@string_input) syntax = Parser::Salama.new.parse_with_debug(@string_input)
parts = Parser::Transform.new.apply(syntax) parts = Parser::Transform.new.apply(syntax)
#puts parts.inspect #puts parts.inspect
Phisol::Compiler.compile( parts ) Phisol::Compiler.compile( parts )
machine.collect machine.collect
# statements = Virtual.machine.boot.parse_and_compile @string_input # statements = Register.machine.boot.parse_and_compile @string_input
# Phisol::Compiler.compile( statements , Virtual.machine.space.get_main ) # Phisol::Compiler.compile( statements , Register.machine.space.get_main )
@interpreter = Interpreter::Interpreter.new @interpreter = Interpreter::Interpreter.new
@interpreter.start Virtual.machine.init @interpreter.start Register.machine.init
#show_ticks # get output of what is #show_ticks # get output of what is
["Branch","LoadConstant","GetSlot","SetSlot","RegisterTransfer", ["Branch","LoadConstant","GetSlot","SetSlot","RegisterTransfer",
"FunctionCall","SaveReturn","GetSlot","GetSlot","SetSlot", "FunctionCall","SaveReturn","GetSlot","GetSlot","SetSlot",

View File

@ -48,16 +48,16 @@ class Object
end end
end end
HERE HERE
machine = Virtual.machine.boot machine = Register.machine.boot
syntax = Parser::Salama.new.parse_with_debug(@string_input) syntax = Parser::Salama.new.parse_with_debug(@string_input)
parts = Parser::Transform.new.apply(syntax) parts = Parser::Transform.new.apply(syntax)
#puts parts.inspect #puts parts.inspect
Phisol::Compiler.compile( parts ) Phisol::Compiler.compile( parts )
machine.collect machine.collect
# statements = Virtual.machine.boot.parse_and_compile @string_input # statements = Register.machine.boot.parse_and_compile @string_input
# Phisol::Compiler.compile( statements , Virtual.machine.space.get_main ) # Phisol::Compiler.compile( statements , Register.machine.space.get_main )
@interpreter = Interpreter::Interpreter.new @interpreter = Interpreter::Interpreter.new
@interpreter.start Virtual.machine.init @interpreter.start Register.machine.init
#show_ticks # get output of what is #show_ticks # get output of what is
["Branch","LoadConstant","GetSlot","SetSlot","RegisterTransfer", ["Branch","LoadConstant","GetSlot","SetSlot","RegisterTransfer",
"FunctionCall","SaveReturn","GetSlot","LoadConstant","SetSlot", "FunctionCall","SaveReturn","GetSlot","LoadConstant","SetSlot",

View File

@ -4,7 +4,7 @@ class TestPuts < MiniTest::Test
include AST::Sexp include AST::Sexp
include Ticker include Ticker
def setup def setup
machine = Virtual.machine.boot machine = Register.machine.boot
code = s(:class, :Object, code = s(:class, :Object,
s(:derives, nil), s(:derives, nil),
s(:statements, s(:statements,
@ -21,7 +21,7 @@ class TestPuts < MiniTest::Test
Phisol::Compiler.compile( code ) Phisol::Compiler.compile( code )
machine.collect machine.collect
@interpreter = Interpreter::Interpreter.new @interpreter = Interpreter::Interpreter.new
@interpreter.start Virtual.machine.init @interpreter.start Register.machine.init
end end
def test_branch def test_branch
@ -31,7 +31,7 @@ class TestPuts < MiniTest::Test
end end
def test_load def test_load
assert_equal Register::LoadConstant , ticks(2).class assert_equal Register::LoadConstant , ticks(2).class
assert_equal Parfait::Space , Virtual.machine.objects[ @interpreter.get_register(:r2)].class assert_equal Parfait::Space , Register.machine.objects[ @interpreter.get_register(:r2)].class
assert_equal :r2, @interpreter.instruction.array.symbol assert_equal :r2, @interpreter.instruction.array.symbol
end end
def test_get def test_get
@ -78,7 +78,7 @@ class TestPuts < MiniTest::Test
def test_return def test_return
done = ticks(24) done = ticks(24)
assert_equal Register::FunctionReturn , done.class assert_equal Register::FunctionReturn , done.class
assert @interpreter.block.is_a?(Virtual::Block) assert @interpreter.block.is_a?(Register::Block)
assert @interpreter.instruction.is_a?(Register::Instruction) , "not instruction #{@interpreter.instruction}" assert @interpreter.instruction.is_a?(Register::Instruction) , "not instruction #{@interpreter.instruction}"
end end

View File

@ -3,7 +3,7 @@ require_relative "../helper"
class TestAttributes < MiniTest::Test class TestAttributes < MiniTest::Test
def setup def setup
@mess = Virtual.machine.boot.space.first_message @mess = Register.machine.boot.space.first_message
@layout = @mess.get_layout @layout = @mess.get_layout
end end

View File

@ -1,7 +1,7 @@
require_relative "../helper" require_relative "../helper"
class TestDictionary < MiniTest::Test class TestDictionary < MiniTest::Test
Virtual.machine.boot #have to book, otherwise layouts etc not set Register.machine.boot #have to book, otherwise layouts etc not set
def setup def setup
@lookup = ::Parfait::Dictionary.new @lookup = ::Parfait::Dictionary.new

View File

@ -3,7 +3,7 @@ require_relative "../helper"
class TestLayout < MiniTest::Test class TestLayout < MiniTest::Test
def setup def setup
@mess = Virtual.machine.boot.space.first_message @mess = Register.machine.boot.space.first_message
end end
def test_message_layout def test_message_layout
@ -46,7 +46,7 @@ class TestLayout < MiniTest::Test
end end
def test_class_layout def test_class_layout
oc = Virtual.machine.boot.space.get_class_by_name( :Object ) oc = Register.machine.boot.space.get_class_by_name( :Object )
assert_equal Parfait::Class , oc.class assert_equal Parfait::Class , oc.class
layout = oc.object_layout layout = oc.object_layout
assert_equal Parfait::Layout , layout.class assert_equal Parfait::Layout , layout.class

View File

@ -3,14 +3,14 @@ require_relative "../helper"
class TestList < MiniTest::Test class TestList < MiniTest::Test
def setup def setup
Virtual.machine.boot unless Virtual.machine.booted Register.machine.boot unless Register.machine.booted
@list = ::Parfait::List.new @list = ::Parfait::List.new
end end
def test_old_layout def test_old_layout
assert_equal Parfait::Layout , Virtual.machine.space.classes.keys.get_layout.class assert_equal Parfait::Layout , Register.machine.space.classes.keys.get_layout.class
end end
def test_old_layout_push def test_old_layout_push
list = Virtual.machine.space.classes.keys list = Register.machine.space.classes.keys
list.push(1) list.push(1)
assert_equal Parfait::Layout , list.get_layout.class assert_equal Parfait::Layout , list.get_layout.class
end end
@ -26,7 +26,7 @@ class TestList < MiniTest::Test
assert_equal 1 , layout.variable_index(:layout) assert_equal 1 , layout.variable_index(:layout)
end end
def notest_layout_is_first_old def notest_layout_is_first_old
layout = Virtual.machine.space.classes.keys.get_layout layout = Register.machine.space.classes.keys.get_layout
assert_equal 1 , layout.variable_index(:layout) assert_equal 1 , layout.variable_index(:layout)
end end

View File

@ -3,8 +3,8 @@ require_relative "../helper"
class TestMethod < MiniTest::Test class TestMethod < MiniTest::Test
def setup def setup
obj = Virtual.machine.boot.space.get_class_by_name(:Object) obj = Register.machine.boot.space.get_class_by_name(:Object)
args = Virtual.new_list [ Parfait::Variable.new(:Integer , :bar )] args = Register.new_list [ Parfait::Variable.new(:Integer , :bar )]
@method = ::Parfait::Method.new obj , :foo , args @method = ::Parfait::Method.new obj , :foo , args
end end

View File

@ -3,7 +3,7 @@ require_relative "../helper"
class TestSpace < MiniTest::Test class TestSpace < MiniTest::Test
def setup def setup
@machine = Virtual.machine.boot @machine = Register.machine.boot
end end
def classes def classes
[:Kernel,:Word,:List,:Message,:Frame,:Layout,:Object,:Class,:Dictionary,:Method , :Integer] [:Kernel,:Word,:List,:Message,:Frame,:Layout,:Object,:Class,:Dictionary,:Method , :Integer]

View File

@ -3,7 +3,7 @@ require_relative "../helper"
class TestEmptyWord < MiniTest::Test class TestEmptyWord < MiniTest::Test
def setup def setup
Virtual.machine.boot unless Virtual.machine.booted Register.machine.boot unless Register.machine.booted
@word = ::Parfait::Word.new(0) @word = ::Parfait::Word.new(0)
end end
def test_word_create def test_word_create

View File

@ -4,19 +4,19 @@ require_relative "../helper"
class TestCompat < MiniTest::Test class TestCompat < MiniTest::Test
def setup def setup
Virtual.machine.boot unless Virtual.machine.booted Register.machine.boot unless Register.machine.booted
end end
def test_list_create_from_array def test_list_create_from_array
array = [1,2,3] array = [1,2,3]
list = Virtual.new_list(array) list = Register.new_list(array)
assert_equal array , list.to_a assert_equal array , list.to_a
end end
def test_word_create_from_string def test_word_create_from_string
string = "something" string = "something"
word = Virtual.new_word(string) word = Register.new_word(string)
assert_equal word , Virtual.new_word(string) assert_equal word , Register.new_word(string)
assert_equal string , word.to_string assert_equal string , word.to_string
end end
end end

View File

@ -2,15 +2,15 @@ require_relative "../helper"
class TestPositioning < MiniTest::Test class TestPositioning < MiniTest::Test
def setup def setup
Virtual.machine.boot unless Virtual.machine.booted Register.machine.boot unless Register.machine.booted
end end
def test_list1 def test_list1
list = Virtual.new_list([1]) list = Register.new_list([1])
list.set_layout( Parfait::Layout.new Object) list.set_layout( Parfait::Layout.new Object)
assert_equal 32 , list.word_length assert_equal 32 , list.word_length
end end
def test_list5 def test_list5
list = Virtual.new_list([1,2,3,4,5]) list = Register.new_list([1,2,3,4,5])
list.set_layout( Parfait::Layout.new Object) list.set_layout( Parfait::Layout.new Object)
# TODO check why this is 64 and not 32 # TODO check why this is 64 and not 32
assert_equal 32 , list.word_length assert_equal 32 , list.word_length

View File

@ -4,6 +4,6 @@ require_relative "elf/test_all"
require_relative "parfait/test_all" require_relative "parfait/test_all"
require_relative "virtual/test_all" require_relative "register/test_all"
require_relative "interpreter/test_all" require_relative "interpreter/test_all"