fold last of the virtual into register
This commit is contained in:
parent
f658ecf425
commit
dcbd3c7091
@ -1,6 +1,6 @@
|
||||
GIT
|
||||
remote: git://github.com/salama/salama-arm.git
|
||||
revision: c278f7eec20e9d62a55394bb7691e976980cbbe9
|
||||
revision: 3fcf596a028d48ab5fa2f31babafbc5f97a6edab
|
||||
specs:
|
||||
salama-arm (0.3.0)
|
||||
|
||||
|
@ -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.
|
||||
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.
|
||||
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
|
||||
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
|
||||
|
||||
|
@ -106,7 +106,7 @@ module Interpreter
|
||||
|
||||
def object_for reg
|
||||
id = get_register(reg)
|
||||
object = Virtual.machine.objects[id]
|
||||
object = Register.machine.objects[id]
|
||||
object.nil? ? id : object
|
||||
end
|
||||
|
||||
|
@ -24,7 +24,7 @@ module Parfait
|
||||
|
||||
# in a non-booting version this should map to _add_singleton_method
|
||||
# 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
|
||||
# self.functions << function
|
||||
# end
|
||||
|
@ -13,7 +13,7 @@ module Parfait
|
||||
# known local variable names
|
||||
# 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
|
||||
|
@ -2,7 +2,7 @@ module Parfait
|
||||
class Variable < Object
|
||||
|
||||
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.value = 0 if self.type == :Integer and value == nil
|
||||
raise "must give name for variable" unless name
|
||||
|
@ -16,7 +16,7 @@ module Parfait
|
||||
class Word < Object
|
||||
# initialize with length. For now we try to keep all non-parfait (including String) out
|
||||
# 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
|
||||
super()
|
||||
raise "Must init with int, not #{len.class}" unless len.kind_of? Fixnum
|
||||
|
@ -34,10 +34,10 @@ module Phisol
|
||||
end
|
||||
|
||||
# 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
|
||||
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
|
||||
Register.issue_call( @method , method )
|
||||
ret = use_reg( method.source.return_type )
|
||||
|
@ -19,7 +19,7 @@ module Phisol
|
||||
if( r != :self)
|
||||
raise "unimplemented case in function #{r}"
|
||||
else
|
||||
r = Virtual::Self.new()
|
||||
r = Register::Self.new()
|
||||
class_name = method.for_class.name
|
||||
end
|
||||
end
|
||||
@ -34,7 +34,7 @@ module Phisol
|
||||
#TODO check args / type compatibility
|
||||
@method.source.init @method
|
||||
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
|
||||
end
|
||||
@method.source.receiver = r
|
||||
|
20
lib/register.rb
Normal file
20
lib/register.rb
Normal 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"
|
@ -238,5 +238,5 @@ module Register
|
||||
end
|
||||
end
|
||||
|
||||
Sof::Volotile.add(Register::Assembler , [:objects])
|
||||
Sof::Volotile.add(Assembler , [:objects])
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Virtual
|
||||
module Register
|
||||
|
||||
# Think flowcharts: blocks are the boxes. The smallest unit of linear code
|
||||
|
@ -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
|
||||
|
||||
@ -147,19 +147,19 @@ module Virtual
|
||||
# TODO go through the virtual parfait layer and adjust function names to what they really are
|
||||
obj = @space.get_class_by_name(:Object)
|
||||
[: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
|
||||
obj = @space.get_class_by_name(:Kernel)
|
||||
# create __init__ main first, __init__ calls it
|
||||
[: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
|
||||
|
||||
@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)
|
||||
[: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
|
@ -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.
|
||||
|
||||
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.
|
||||
|
||||
A normal ruby function is one that is parsed and transformed to code. But not all functionality can
|
||||
|
@ -5,7 +5,7 @@ module Register
|
||||
module ClassMethods
|
||||
include AST::Sexp
|
||||
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.receiver = :Integer
|
||||
|
||||
@ -15,7 +15,7 @@ module Register
|
||||
|
||||
me = Register.tmp_reg :Integer
|
||||
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 Register.set_slot(plus_function , me , :message , :return_value )
|
||||
return plus_function
|
||||
@ -28,14 +28,14 @@ module Register
|
||||
# As we write before we recurse (save a push) we write the number backwards
|
||||
# arguments: string address , integer
|
||||
# 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.receiver = :Integer
|
||||
# return utoa_function
|
||||
# # str_addr = utoa_function.receiver
|
||||
# # number = utoa_function.args.first
|
||||
# # 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"
|
||||
# # utoa_function.instance_eval do
|
||||
# # add( remainder , remainder , 48)
|
||||
@ -48,7 +48,7 @@ module Register
|
||||
# end
|
||||
|
||||
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.receiver = :Integer
|
||||
return putint_function
|
||||
@ -68,7 +68,7 @@ module Register
|
||||
# add( int , buffer , nil ) # string to write to
|
||||
# mov( moved_int , buffer.length )
|
||||
# end
|
||||
# Virtual::RegisterMachine.instance.write_stdout(putint_function)
|
||||
# RegisterMachine.instance.write_stdout(putint_function)
|
||||
# putint_function
|
||||
end
|
||||
|
||||
@ -77,7 +77,7 @@ module Register
|
||||
# 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
|
||||
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.receiver = :Integer
|
||||
return fibo_function
|
||||
|
@ -6,7 +6,7 @@ module Register
|
||||
# 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
|
||||
def __init__ context
|
||||
function = Virtual::MethodSource.create_method(:Kernel,:Integer,:__init__ , [])
|
||||
function = MethodSource.create_method(:Kernel,:Integer,:__init__ , [])
|
||||
function.source.set_return_type :Integer
|
||||
# no method enter or return (automatically added), remove
|
||||
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)
|
||||
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
|
||||
Register.issue_call( function , Virtual.machine.space.get_main)
|
||||
Register.issue_call( function , Register.machine.space.get_main)
|
||||
emit_syscall( function , :exit )
|
||||
return function
|
||||
end
|
||||
def exit context
|
||||
function = Virtual::MethodSource.create_method(:Kernel,:Integer,:exit , [])
|
||||
function = MethodSource.create_method(:Kernel,:Integer,:exit , [])
|
||||
function.source.set_return_type :Integer
|
||||
return function
|
||||
ret = Virtual::RegisterMachine.instance.exit(function)
|
||||
ret = RegisterMachine.instance.exit(function)
|
||||
function.set_return ret
|
||||
function
|
||||
end
|
||||
def __send context
|
||||
function = Virtual::MethodSource.create_method(:Kernel,:Integer ,:__send , [] )
|
||||
function = MethodSource.create_method(:Kernel,:Integer ,:__send , [] )
|
||||
function.source.set_return_type :Integer
|
||||
return function
|
||||
end
|
||||
|
@ -6,7 +6,7 @@ module Register
|
||||
# main entry point, ie __init__ calls this
|
||||
# defined here as empty, to be redefined
|
||||
def main context
|
||||
function = Virtual::MethodSource.create_method(:Object, :Integer , :main , [])
|
||||
function = MethodSource.create_method(:Object, :Integer , :main , [])
|
||||
return function
|
||||
end
|
||||
|
||||
@ -18,13 +18,13 @@ module Register
|
||||
# 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
|
||||
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
|
||||
# me = get_function.receiver
|
||||
# var_name = get_function.args.first
|
||||
# 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] )
|
||||
# # index = get_function.call( index_function )
|
||||
#
|
||||
@ -39,7 +39,7 @@ module Register
|
||||
end
|
||||
|
||||
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
|
||||
# receiver set_function
|
||||
# me = set_function.receiver
|
||||
|
@ -3,7 +3,7 @@ module Register
|
||||
module Word
|
||||
module ClassMethods
|
||||
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 )
|
||||
Kernel.emit_syscall( function , :putstring )
|
||||
function
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Virtual
|
||||
module Register
|
||||
|
||||
# collect anything that is in the space but and reachable from init
|
||||
module Collector
|
@ -24,8 +24,8 @@ module Register
|
||||
@index = index
|
||||
@register = register
|
||||
raise "not integer #{index}" unless index.is_a? Numeric
|
||||
raise "Not register #{register}" unless Register::RegisterValue.look_like_reg(register)
|
||||
raise "Not register #{array}" unless Register::RegisterValue.look_like_reg(array)
|
||||
raise "Not register #{register}" unless RegisterValue.look_like_reg(register)
|
||||
raise "Not register #{array}" unless RegisterValue.look_like_reg(array)
|
||||
end
|
||||
attr_accessor :array , :index , :register
|
||||
|
||||
|
@ -23,8 +23,8 @@ module Register
|
||||
@array = array
|
||||
@index = index
|
||||
raise "not integer #{index}" unless index.is_a? Numeric
|
||||
raise "Not register #{register}" unless Register::RegisterValue.look_like_reg(register)
|
||||
raise "Not register #{array}" unless Register::RegisterValue.look_like_reg(array)
|
||||
raise "Not register #{register}" unless RegisterValue.look_like_reg(register)
|
||||
raise "Not register #{array}" unless RegisterValue.look_like_reg(array)
|
||||
end
|
||||
attr_accessor :register , :array , :index
|
||||
def to_s
|
||||
|
@ -1,7 +1,7 @@
|
||||
require 'parslet/convenience'
|
||||
require_relative "collector"
|
||||
module Virtual
|
||||
# The Virtual Machine is a object based virtual machine in which ruby is implemented.
|
||||
module Register
|
||||
# The Register Machine is a object based virtual machine in which ruby is implemented.
|
||||
#
|
||||
# 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
|
||||
@ -118,7 +118,7 @@ module Virtual
|
||||
def boot
|
||||
boot_parfait!
|
||||
@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
|
||||
@booted = true
|
||||
self
|
@ -1,6 +1,6 @@
|
||||
require_relative "block"
|
||||
|
||||
module Virtual
|
||||
module Register
|
||||
# the static info of a method (with its compiled code, argument names etc ) is part of the
|
||||
# runtime, ie found in Parfait::Method
|
||||
|
||||
@ -35,17 +35,17 @@ module Virtual
|
||||
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 #{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
|
||||
arguments = []
|
||||
args.each_with_index do | arg , index |
|
||||
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
|
||||
end
|
||||
arguments << arg
|
||||
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
|
||||
end
|
||||
@ -63,11 +63,11 @@ module Virtual
|
||||
@current = enter
|
||||
ret = new_block("return")
|
||||
# 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
|
||||
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)
|
||||
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 = []
|
||||
end
|
||||
attr_reader :blocks , :constants , :return_type
|
||||
@ -75,13 +75,13 @@ module Virtual
|
||||
|
||||
def set_return_type type
|
||||
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
|
||||
end
|
||||
# add an instruction after the current (insertion point)
|
||||
# the added instruction will become the new insertion point
|
||||
def add_code instruction
|
||||
unless instruction.is_a?(Register::Instruction)
|
||||
unless instruction.is_a?(Instruction)
|
||||
raise instruction.to_s
|
||||
end
|
||||
@current.add_code(instruction) #insert after current
|
||||
@ -93,7 +93,7 @@ module Virtual
|
||||
def locals_at l_block
|
||||
used =[]
|
||||
# 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|
|
||||
b.uses.each {|u|
|
||||
(used << u) unless assigned.include?(u)
|
@ -1,4 +1,4 @@
|
||||
module Virtual
|
||||
module Register
|
||||
|
||||
# Remove all functions that are not called
|
||||
# Not called is approximated by the fact that the method name doesn't show up
|
||||
@ -11,7 +11,7 @@ module Virtual
|
||||
@gonners << f
|
||||
end
|
||||
end
|
||||
keep Virtual.machine.space.get_init
|
||||
keep Register.machine.space.get_init
|
||||
remove_remaining
|
||||
end
|
||||
|
||||
@ -25,7 +25,7 @@ module Virtual
|
||||
@gonners.delete function
|
||||
function.source.blocks.each do |block|
|
||||
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
|
@ -4,7 +4,7 @@
|
||||
# To stay sane, we use the same classes that we use later, but "adapt" them to work in ruby
|
||||
# This affects mainly memory layout
|
||||
|
||||
module Virtual
|
||||
module Register
|
||||
def self.new_list array
|
||||
list = Parfait::List.new
|
||||
list.set_length array.length
|
||||
@ -24,7 +24,7 @@ class Symbol
|
||||
true
|
||||
end
|
||||
def get_layout
|
||||
l = Virtual.machine.space.classes[:Word].object_layout
|
||||
l = Register.machine.space.classes[:Word].object_layout
|
||||
#puts "LL #{l.class}"
|
||||
l
|
||||
end
|
||||
@ -42,7 +42,7 @@ class Symbol
|
||||
pos = cache_positions[self]
|
||||
if pos == nil
|
||||
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}"
|
||||
end
|
||||
pos
|
@ -3,7 +3,7 @@
|
||||
module Positioned
|
||||
def position
|
||||
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]}"
|
||||
end
|
||||
@position
|
@ -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.
|
@ -10,7 +10,6 @@ end
|
||||
|
||||
require 'parser/transform'
|
||||
require "salama-object-file"
|
||||
require "virtual"
|
||||
require "register/register"
|
||||
require "register"
|
||||
require "register/builtin/object"
|
||||
require "arm/arm_machine"
|
||||
|
@ -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
|
@ -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.
|
@ -1,6 +1,6 @@
|
||||
module Virtual
|
||||
module Register
|
||||
|
||||
class Constant < ::Virtual::Object
|
||||
class Constant < ::Register::Object
|
||||
end
|
||||
class TrueConstant < Constant
|
||||
end
|
||||
|
@ -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
|
||||
|
||||
# A message contains the sender, return and exceptional return addresses,the arguments,
|
||||
|
@ -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.
|
||||
#
|
||||
# Data in a Block is usefull in the same way data in objects is. Plocks being otherwise just code.
|
||||
|
@ -1,4 +1,4 @@
|
||||
module Virtual
|
||||
module Register
|
||||
# A slot is a slot in an object. It is the storage location for a value.
|
||||
# (Remember, values are typed)
|
||||
# From a memory perspective a slot is an index into an array (the object)
|
||||
|
@ -3,7 +3,7 @@ require 'parslet/convenience'
|
||||
|
||||
Phisol::Compiler.class_eval do
|
||||
def set_main main
|
||||
@clazz = Virtual.machine.space.get_class_by_name :Object
|
||||
@clazz = Register.machine.space.get_class_by_name :Object
|
||||
@method = main
|
||||
end
|
||||
end
|
||||
@ -11,10 +11,10 @@ end
|
||||
module CompilerHelper
|
||||
|
||||
def set_main compiler
|
||||
compiler.set_main Virtual.machine.space.get_main
|
||||
compiler.set_main Register.machine.space.get_main
|
||||
end
|
||||
def check
|
||||
machine = Virtual.machine
|
||||
machine = Register.machine
|
||||
machine.boot unless machine.booted
|
||||
parser = Parser::Salama.new
|
||||
parser = parser.send @root
|
||||
|
@ -1,11 +1,11 @@
|
||||
require_relative "compiler_helper"
|
||||
|
||||
module Virtual
|
||||
module Register
|
||||
class TestCall < MiniTest::Test
|
||||
include CompilerHelper
|
||||
|
||||
def setup
|
||||
Virtual.machine.boot
|
||||
Register.machine.boot
|
||||
@root = :call_site
|
||||
@output = Register::RegisterValue
|
||||
end
|
||||
@ -31,7 +31,7 @@ module Virtual
|
||||
end
|
||||
|
||||
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 )'
|
||||
check
|
||||
end
|
||||
|
@ -1,11 +1,11 @@
|
||||
require_relative "compiler_helper"
|
||||
|
||||
module Virtual
|
||||
module Register
|
||||
class TestFields < MiniTest::Test
|
||||
include CompilerHelper
|
||||
|
||||
def setup
|
||||
Virtual.machine.boot
|
||||
Register.machine.boot
|
||||
end
|
||||
|
||||
def test_field_not_defined
|
||||
@ -17,7 +17,7 @@ HERE
|
||||
end
|
||||
|
||||
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
|
||||
@string_input = <<HERE
|
||||
self.bro
|
||||
@ -27,7 +27,7 @@ HERE
|
||||
end
|
||||
|
||||
def test_local
|
||||
Virtual.machine.space.get_main.ensure_local(:bar , :Integer)
|
||||
Register.machine.space.get_main.ensure_local(:bar , :Integer)
|
||||
@root = :name
|
||||
@string_input = 'bar '
|
||||
@output = Register::RegisterValue
|
||||
@ -35,7 +35,7 @@ HERE
|
||||
end
|
||||
|
||||
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
|
||||
@string_input = 'bar '
|
||||
@output = Register::RegisterValue
|
||||
|
@ -1,11 +1,11 @@
|
||||
require_relative "compiler_helper"
|
||||
|
||||
module Virtual
|
||||
module Register
|
||||
class TestOps < MiniTest::Test
|
||||
include CompilerHelper
|
||||
|
||||
def setup
|
||||
Virtual.machine.boot
|
||||
Register.machine.boot
|
||||
@root = :operator_value
|
||||
@output = Register::RegisterValue
|
||||
end
|
||||
@ -20,24 +20,24 @@ module Virtual
|
||||
end
|
||||
end
|
||||
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'
|
||||
check
|
||||
end
|
||||
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'
|
||||
check
|
||||
end
|
||||
|
||||
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"
|
||||
check
|
||||
end
|
||||
|
||||
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"
|
||||
check
|
||||
end
|
||||
|
@ -13,7 +13,7 @@ module Fragments
|
||||
@stdout = ""
|
||||
end
|
||||
def check
|
||||
machine = Virtual.machine.boot
|
||||
machine = Register.machine.boot
|
||||
machine.parse_and_compile @string_input
|
||||
machine.collect
|
||||
interpreter = Interpreter::Interpreter.new
|
||||
|
@ -16,8 +16,8 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
@expect = [ [SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set,
|
||||
Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
|
||||
@expect = [ [SaveReturn,Register::GetSlot,Register::Set,Register::Set,
|
||||
Register::Set,Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
|
||||
check
|
||||
end
|
||||
|
||||
|
@ -35,7 +35,7 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
@expect = [[SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] ,
|
||||
@expect = [[SaveReturn,Register::GetSlot,Register::Set,Register::Set,RegisterTransfer,FunctionCall] ,
|
||||
[RegisterTransfer,GetSlot,FunctionReturn]]
|
||||
check
|
||||
|
||||
|
@ -11,8 +11,8 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
@expect = [[SaveReturn,Virtual::Set,Register::GetSlot,Virtual::Set,
|
||||
Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn]]
|
||||
@expect = [[SaveReturn,Register::Set,Register::GetSlot,Register::Set,
|
||||
Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn]]
|
||||
check
|
||||
end
|
||||
end
|
||||
|
@ -16,8 +16,8 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
@expect = [ [SaveReturn,Virtual::Set,Register::GetSlot,Virtual::Set,
|
||||
Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
|
||||
@expect = [ [SaveReturn,Register::Set,Register::GetSlot,Register::Set,
|
||||
Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
|
||||
check
|
||||
end
|
||||
end
|
||||
|
@ -27,8 +27,8 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
@expect = [[SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set,
|
||||
Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] , [RegisterTransfer,GetSlot,FunctionReturn]]
|
||||
@expect = [[SaveReturn,Register::GetSlot,Register::Set,Register::Set,
|
||||
Register::Set,Register::Set,RegisterTransfer,FunctionCall] , [RegisterTransfer,GetSlot,FunctionReturn]]
|
||||
check
|
||||
end
|
||||
end
|
||||
|
@ -24,20 +24,20 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
@expect = [ [SaveReturn,Register::GetSlot,Virtual::Set,Virtual::Set,
|
||||
Virtual::Set,Virtual::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
|
||||
@expect = [ [SaveReturn,Register::GetSlot,Register::Set,Register::Set,
|
||||
Register::Set,Register::Set,RegisterTransfer,FunctionCall] ,[RegisterTransfer,GetSlot,FunctionReturn] ]
|
||||
check
|
||||
end
|
||||
|
||||
# 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
|
||||
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)
|
||||
main = @object_space.main
|
||||
main.mov int , 10
|
||||
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)
|
||||
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]
|
||||
|
@ -4,10 +4,10 @@ require_relative '../../helper'
|
||||
module Statements
|
||||
|
||||
def check
|
||||
machine = Virtual.machine
|
||||
machine = Register.machine
|
||||
machine.boot unless machine.booted
|
||||
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_equal @expect.length , produced.blocks.length , "Block length"
|
||||
produced.blocks.each_with_index do |b,i|
|
||||
|
@ -5,7 +5,7 @@ class TestAssignStatement < MiniTest::Test
|
||||
include Statements
|
||||
|
||||
def setup
|
||||
Virtual.machine.boot
|
||||
Register.machine.boot
|
||||
end
|
||||
|
||||
def test_assign_op
|
||||
@ -77,7 +77,7 @@ HERE
|
||||
end
|
||||
|
||||
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
|
||||
class Object
|
||||
int main(int bar)
|
||||
@ -109,7 +109,7 @@ HERE
|
||||
|
||||
def test_arg_get
|
||||
# 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
|
||||
class Object
|
||||
int main(int bar)
|
||||
|
@ -3,7 +3,7 @@ require_relative "../helper"
|
||||
class HelloTest < MiniTest::Test
|
||||
|
||||
def check
|
||||
machine = Virtual.machine.boot
|
||||
machine = Register.machine.boot
|
||||
Parfait::Space.object_space.get_class_by_name(:Integer).remove_instance_method :plus
|
||||
#TODO remove this hack: write proper aliases
|
||||
statements = machine.parse_and_compile @string_input
|
||||
|
@ -19,7 +19,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'test'))
|
||||
|
||||
require 'salama'
|
||||
|
||||
module Virtual
|
||||
module Register
|
||||
# Functions to generate parfait objects
|
||||
def self.new_word( string )
|
||||
string = string.to_s if string.is_a? Symbol
|
||||
|
@ -5,7 +5,7 @@ class AddTest < MiniTest::Test
|
||||
include Ticker
|
||||
|
||||
def setup
|
||||
machine = Virtual.machine.boot
|
||||
machine = Register.machine.boot
|
||||
code = s(:class, :Object,
|
||||
s(:derives, nil),
|
||||
s(:statements,
|
||||
@ -21,7 +21,7 @@ class AddTest < MiniTest::Test
|
||||
Phisol::Compiler.compile( code )
|
||||
machine.collect
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Virtual.machine.init
|
||||
@interpreter.start Register.machine.init
|
||||
end
|
||||
|
||||
def test_branch
|
||||
@ -31,7 +31,7 @@ class AddTest < MiniTest::Test
|
||||
end
|
||||
def test_load
|
||||
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
|
||||
end
|
||||
def test_get
|
||||
|
@ -20,16 +20,16 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
machine = Virtual.machine.boot
|
||||
machine = Register.machine.boot
|
||||
syntax = Parser::Salama.new.parse_with_debug(@string_input)
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
#puts parts.inspect
|
||||
Phisol::Compiler.compile( parts )
|
||||
machine.collect
|
||||
# statements = Virtual.machine.boot.parse_and_compile @string_input
|
||||
# Phisol::Compiler.compile( statements , Virtual.machine.space.get_main )
|
||||
# statements = Register.machine.boot.parse_and_compile @string_input
|
||||
# Phisol::Compiler.compile( statements , Register.machine.space.get_main )
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Virtual.machine.init
|
||||
@interpreter.start Register.machine.init
|
||||
#show_ticks # get output of what is
|
||||
["Branch","LoadConstant","GetSlot","SetSlot","RegisterTransfer",
|
||||
"FunctionCall","SaveReturn","GetSlot","GetSlot","SetSlot",
|
||||
|
@ -48,16 +48,16 @@ class Object
|
||||
end
|
||||
end
|
||||
HERE
|
||||
machine = Virtual.machine.boot
|
||||
machine = Register.machine.boot
|
||||
syntax = Parser::Salama.new.parse_with_debug(@string_input)
|
||||
parts = Parser::Transform.new.apply(syntax)
|
||||
#puts parts.inspect
|
||||
Phisol::Compiler.compile( parts )
|
||||
machine.collect
|
||||
# statements = Virtual.machine.boot.parse_and_compile @string_input
|
||||
# Phisol::Compiler.compile( statements , Virtual.machine.space.get_main )
|
||||
# statements = Register.machine.boot.parse_and_compile @string_input
|
||||
# Phisol::Compiler.compile( statements , Register.machine.space.get_main )
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Virtual.machine.init
|
||||
@interpreter.start Register.machine.init
|
||||
#show_ticks # get output of what is
|
||||
["Branch","LoadConstant","GetSlot","SetSlot","RegisterTransfer",
|
||||
"FunctionCall","SaveReturn","GetSlot","LoadConstant","SetSlot",
|
||||
|
@ -4,7 +4,7 @@ class TestPuts < MiniTest::Test
|
||||
include AST::Sexp
|
||||
include Ticker
|
||||
def setup
|
||||
machine = Virtual.machine.boot
|
||||
machine = Register.machine.boot
|
||||
code = s(:class, :Object,
|
||||
s(:derives, nil),
|
||||
s(:statements,
|
||||
@ -21,7 +21,7 @@ class TestPuts < MiniTest::Test
|
||||
Phisol::Compiler.compile( code )
|
||||
machine.collect
|
||||
@interpreter = Interpreter::Interpreter.new
|
||||
@interpreter.start Virtual.machine.init
|
||||
@interpreter.start Register.machine.init
|
||||
end
|
||||
|
||||
def test_branch
|
||||
@ -31,7 +31,7 @@ class TestPuts < MiniTest::Test
|
||||
end
|
||||
def test_load
|
||||
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
|
||||
end
|
||||
def test_get
|
||||
@ -78,7 +78,7 @@ class TestPuts < MiniTest::Test
|
||||
def test_return
|
||||
done = ticks(24)
|
||||
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}"
|
||||
end
|
||||
|
||||
|
@ -3,7 +3,7 @@ require_relative "../helper"
|
||||
class TestAttributes < MiniTest::Test
|
||||
|
||||
def setup
|
||||
@mess = Virtual.machine.boot.space.first_message
|
||||
@mess = Register.machine.boot.space.first_message
|
||||
@layout = @mess.get_layout
|
||||
end
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
require_relative "../helper"
|
||||
|
||||
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
|
||||
@lookup = ::Parfait::Dictionary.new
|
||||
|
@ -3,7 +3,7 @@ require_relative "../helper"
|
||||
class TestLayout < MiniTest::Test
|
||||
|
||||
def setup
|
||||
@mess = Virtual.machine.boot.space.first_message
|
||||
@mess = Register.machine.boot.space.first_message
|
||||
end
|
||||
|
||||
def test_message_layout
|
||||
@ -46,7 +46,7 @@ class TestLayout < MiniTest::Test
|
||||
end
|
||||
|
||||
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
|
||||
layout = oc.object_layout
|
||||
assert_equal Parfait::Layout , layout.class
|
||||
|
@ -3,14 +3,14 @@ require_relative "../helper"
|
||||
class TestList < MiniTest::Test
|
||||
|
||||
def setup
|
||||
Virtual.machine.boot unless Virtual.machine.booted
|
||||
Register.machine.boot unless Register.machine.booted
|
||||
@list = ::Parfait::List.new
|
||||
end
|
||||
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
|
||||
def test_old_layout_push
|
||||
list = Virtual.machine.space.classes.keys
|
||||
list = Register.machine.space.classes.keys
|
||||
list.push(1)
|
||||
assert_equal Parfait::Layout , list.get_layout.class
|
||||
end
|
||||
@ -26,7 +26,7 @@ class TestList < MiniTest::Test
|
||||
assert_equal 1 , layout.variable_index(:layout)
|
||||
end
|
||||
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)
|
||||
end
|
||||
|
||||
|
@ -3,8 +3,8 @@ require_relative "../helper"
|
||||
class TestMethod < MiniTest::Test
|
||||
|
||||
def setup
|
||||
obj = Virtual.machine.boot.space.get_class_by_name(:Object)
|
||||
args = Virtual.new_list [ Parfait::Variable.new(:Integer , :bar )]
|
||||
obj = Register.machine.boot.space.get_class_by_name(:Object)
|
||||
args = Register.new_list [ Parfait::Variable.new(:Integer , :bar )]
|
||||
@method = ::Parfait::Method.new obj , :foo , args
|
||||
end
|
||||
|
||||
|
@ -3,7 +3,7 @@ require_relative "../helper"
|
||||
class TestSpace < MiniTest::Test
|
||||
|
||||
def setup
|
||||
@machine = Virtual.machine.boot
|
||||
@machine = Register.machine.boot
|
||||
end
|
||||
def classes
|
||||
[:Kernel,:Word,:List,:Message,:Frame,:Layout,:Object,:Class,:Dictionary,:Method , :Integer]
|
||||
|
@ -3,7 +3,7 @@ require_relative "../helper"
|
||||
class TestEmptyWord < MiniTest::Test
|
||||
|
||||
def setup
|
||||
Virtual.machine.boot unless Virtual.machine.booted
|
||||
Register.machine.boot unless Register.machine.booted
|
||||
@word = ::Parfait::Word.new(0)
|
||||
end
|
||||
def test_word_create
|
||||
|
@ -4,19 +4,19 @@ require_relative "../helper"
|
||||
class TestCompat < MiniTest::Test
|
||||
|
||||
def setup
|
||||
Virtual.machine.boot unless Virtual.machine.booted
|
||||
Register.machine.boot unless Register.machine.booted
|
||||
end
|
||||
|
||||
def test_list_create_from_array
|
||||
array = [1,2,3]
|
||||
list = Virtual.new_list(array)
|
||||
list = Register.new_list(array)
|
||||
assert_equal array , list.to_a
|
||||
end
|
||||
|
||||
def test_word_create_from_string
|
||||
string = "something"
|
||||
word = Virtual.new_word(string)
|
||||
assert_equal word , Virtual.new_word(string)
|
||||
word = Register.new_word(string)
|
||||
assert_equal word , Register.new_word(string)
|
||||
assert_equal string , word.to_string
|
||||
end
|
||||
end
|
@ -2,15 +2,15 @@ require_relative "../helper"
|
||||
|
||||
class TestPositioning < MiniTest::Test
|
||||
def setup
|
||||
Virtual.machine.boot unless Virtual.machine.booted
|
||||
Register.machine.boot unless Register.machine.booted
|
||||
end
|
||||
def test_list1
|
||||
list = Virtual.new_list([1])
|
||||
list = Register.new_list([1])
|
||||
list.set_layout( Parfait::Layout.new Object)
|
||||
assert_equal 32 , list.word_length
|
||||
end
|
||||
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)
|
||||
# TODO check why this is 64 and not 32
|
||||
assert_equal 32 , list.word_length
|
@ -4,6 +4,6 @@ require_relative "elf/test_all"
|
||||
|
||||
require_relative "parfait/test_all"
|
||||
|
||||
require_relative "virtual/test_all"
|
||||
require_relative "register/test_all"
|
||||
|
||||
require_relative "interpreter/test_all"
|
||||
|
Loading…
Reference in New Issue
Block a user