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
remote: git://github.com/salama/salama-arm.git
revision: c278f7eec20e9d62a55394bb7691e976980cbbe9
revision: 3fcf596a028d48ab5fa2f31babafbc5f97a6edab
specs:
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.
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 )

View File

@ -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
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
Sof::Volotile.add(Register::Assembler , [:objects])
Sof::Volotile.add(Assembler , [:objects])
end

View File

@ -1,4 +1,4 @@
module Virtual
module Register
# 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
@ -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

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.
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

View File

@ -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

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
# 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

View File

@ -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

View File

@ -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

View File

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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

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
# 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

View File

@ -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

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 "salama-object-file"
require "virtual"
require "register/register"
require "register"
require "register/builtin/object"
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
class TrueConstant < Constant
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
# 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.
#
# 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.
# (Remember, values are typed)
# 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
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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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|

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"