rename and a tiny start
This commit is contained in:
62
lib/virtual/constants.rb
Normal file
62
lib/virtual/constants.rb
Normal 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
|
10
lib/virtual/instruction.rb
Normal file
10
lib/virtual/instruction.rb
Normal 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
51
lib/virtual/integer.rb
Normal 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
8
lib/virtual/mystery.rb
Normal 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
|
33
lib/virtual/object_machine.rb
Normal file
33
lib/virtual/object_machine.rb
Normal 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
30
lib/virtual/reference.rb
Normal 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
36
lib/virtual/word.rb
Normal 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
|
Reference in New Issue
Block a user