rename and a tiny start

This commit is contained in:
Torsten Ruger
2014-06-25 15:20:46 +03:00
parent e41bb8027d
commit fe337fad79
9 changed files with 22 additions and 9 deletions

62
lib/virtual/constants.rb Normal file
View File

@ -0,0 +1,62 @@
module Vm
# constants are the stuff that you embedd in the program as numbers or strings.
# Another way to think about them is as Operands, they have no seperate "identity"
# and usually end up embedded in the instructions. ie your basic foo + 4 will encode
# the 4 in the instruction opcode. The 4 is not accessible anywhere else.
# When it should be usable in other forms, the constant must become a Value first
class Constant < Code
end
# another abstract "marker" class (so we can check for it)
# derived classes are Boot/Meta Clas and StringConstant
class ObjectConstant < Constant
end
class IntegerConstant < Constant
def initialize int
@integer = int
end
attr_reader :integer
def value
@integer
end
def to_asm
@integer.to_s
end
end
# The name really says it all.
# The only interesting thing is storage.
# Currently string are stored "inline" , ie in the code segment.
# Mainly because that works an i aint no elf expert.
class StringConstant < ObjectConstant
attr_reader :string
# currently aligned to 4 (ie padded with 0) and off course 0 at the end
def initialize str
str = str.to_s if str.is_a? Symbol
length = str.length
# rounding up to the next 4 (always adding one for zero pad)
pad = ((length / 4 ) + 1 ) * 4 - length
raise "#{pad} #{self}" unless pad >= 1
@string = str + " " * pad
end
def result= value
class_for(MoveInstruction).new(value , self , :opcode => :mov)
end
# the strings length plus padding
def length
string.length
end
# just writing the string
def assemble(io)
io << string
end
end
end

View File

@ -0,0 +1,10 @@
module Vm
# Instruction is an abstract for all the code of the object-machine. Derived classe make up the actual functionality
# of the machine.
# All functions on the machine are captured as instances of instructions
#
class Instruction
end
end

51
lib/virtual/integer.rb Normal file
View File

@ -0,0 +1,51 @@
module Vm
class Integer < Word
# needs to be here as Word's constructor is private (to make it abstract)
def initialize reg
super
end
def less_or_equal block , right
block.cmp( self , right )
Vm::BranchCondition.new :le
end
def greater_or_equal block , right
block.cmp( self , right )
Vm::BranchCondition.new :ge
end
def greater_than block , right
block.cmp( self , right )
Vm::BranchCondition.new :gt
end
def less_than block , right
block.cmp( self , right )
Vm::BranchCondition.new :lt
end
def plus block , first , right
block.add( self , left , right )
self
end
def minus block , left , right
block.sub( self , left , right )
self
end
def left_shift block , left , right
block.mov( self , left , shift_lsr: right )
self
end
def equals block , right
block.cmp( self , right )
Vm::BranchCondition.new :eq
end
def is_true? function
function.cmp( self , 0 )
Vm::BranchCondition.new :ne
end
def move block , right
block.mov( self , right )
self
end
end
end

8
lib/virtual/mystery.rb Normal file
View File

@ -0,0 +1,8 @@
module Vm
class Mystery < Word
# needs to be here as Word's constructor is private (to make it abstract)
def initilize reg
super
end
end
end

View File

@ -0,0 +1,33 @@
module Vm
# The ObjectMachine is the object-oriented 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 the opposite from
# ruby, which has several loops, many redundant if forms and the like.
# - realistic means it is easy to implement on a 32 bit machine (arm) and possibly 64 bit. Memory access, a stack,
# some registers of same size are the underlying hardware. (not ie byte machine)
# - low level means it's basic instructions are realively easily implemented in a register machine. ie send is not
# a an instruction but a function.
#
# A better name may be Value-based machine. Ie all "objects" are values, all passing is value based.
# The illusion of objects is created by a value called object-reference.
#
# So the memory model of the machine allows for indexed access into and "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.
#
# The ast is transformed to object-machine objects, some of which represent code, some data.
#
# The next step transforms to the register machine layer, which is what actually executes.
#
# More concretely, an object machine is a sort of oo turing machine, it has a current instruction, executes the
# instructions, fetches the next one and so on.
# Off course the instructions are not soo simple, but in oo terms quite so.
#
# The machine has a no register, but local variables, a scope at each point in time.
# Scope changes with calls and blocks, but is saved at each level. In terms of lower level implementation this means
# that the the model is such that what is a variable in ruby, never ends up being just on the cpu stack.
#
class ObjectMachine
end
end

30
lib/virtual/reference.rb Normal file
View File

@ -0,0 +1,30 @@
module Vm
class Reference < Word
# needs to be here as Word's constructor is private (to make it abstract)
def initialize reg , clazz = nil
super(reg)
@clazz = clazz
end
attr_accessor :clazz
def load block , right
if(right.is_a? IntegerConstant)
block.mov( self , right ) #move the value
elsif right.is_a? StringConstant
block.add( self , right , nil) #move the address, by "adding" to pc, ie pc relative
block.mov( Integer.new(self.register.next_reg_use) , right.length ) #and the length HACK TODO
elsif right.is_a?(Boot::BootClass) or right.is_a?(Boot::MetaClass)
block.add( self , right , nil) #move the address, by "adding" to pc, ie pc relative
else
raise "unknown #{right.inspect}"
end
self
end
def at_index block , left , right
block.ldr( self , left , right )
self
end
end
end

36
lib/virtual/word.rb Normal file
View File

@ -0,0 +1,36 @@
module Vm
# Word is an abstract base class for the obvious values, ie those that fit into a register
# Marked as abstract by private constructor
#
# Integer and (Object) References are the main derived classes, but float will come and ...
# The Mystery Value has unknown type and has only casting methods. So it must be cast to be useful.
# Types are stored at runtime when needed in TYPE_REGISTER (r1 on arm), which is mostly before calls,
# so that the called function can do casts / branching correctly
class Word < Value
attr_accessor :register
def register_symbol
@register.symbol
end
def inspect
"#{self.class.name} (#{register_symbol})"
end
def to_s
inspect
end
def length
4
end
# aka to string
def to_asm
"#{register_symbol}"
end
private
def initialize reg
if reg.is_a? RegisterReference
@register = reg
else
@register = RegisterReference.new(reg)
end
end
end
end