hurra, a first test. looks a lot.... but lets not spoil th efeeling

This commit is contained in:
Torsten Ruger 2014-06-26 18:39:02 +03:00
parent 525f9d45c5
commit 16ceb2a60d
13 changed files with 94 additions and 87 deletions

View File

@ -4,7 +4,7 @@ module Ast
class IntegerExpression < Expression
# attr_reader :value
def compile context
def compile binding
Virtual::IntegerConstant.new value
end
end

View File

@ -2,9 +2,7 @@ module Ast
class ExpressionList < Expression
# attr_reader :expressions
def compile binding
expressions.each do |part|
expr = part.compile( binding )
end
expressions.collect { |part| part.compile( binding ) }
end
end
end

View File

@ -1,16 +1,11 @@
module Vm
module Virtual
# 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
class Constant < ::Virtual::Object
end
# another abstract "marker" class (so we can check for it)
# derived classes are Boot/Meta Clas and StringConstant
# derived classes are Boot/Meta Class and StringConstant
class ObjectConstant < Constant
end
@ -19,11 +14,11 @@ module Vm
@integer = int
end
attr_reader :integer
def value
@integer
def attributes
[:integer]
end
def to_asm
@integer.to_s
def inspect
self.class.name + ".new(#{@integer})"
end
end

View File

@ -1,9 +1,13 @@
module Vm
module Virtual
# 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
#
#
# It is actully the point of the virtual machine layer to express oo functionality in the set of instructions, thus
# defining a minimal set of instructions needed to implement oo.
# This is partly because jumping over this layer and doing in straight in assember was too bi a step
class Instruction
end

View File

@ -1,9 +1,5 @@
module Vm
class Integer < Word
# needs to be here as Word's constructor is private (to make it abstract)
def initialize reg
super
end
class Integer
def less_or_equal block , right
block.cmp( self , right )

View File

@ -56,4 +56,9 @@ module Virtual
end
end
require_relative "list"
require_relative "list"
require_relative "instruction"
require_relative "value"
require_relative "mystery"
require_relative "object"
require_relative "constants"

View File

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

42
lib/virtual/object.rb Normal file
View File

@ -0,0 +1,42 @@
module Virtual
# our machine is made up of objects, some of which are code, some data
#
# during compilation objects are module Virtual objects, but during execution they are not scoped
#
# functions on these classes express their functionality as function objects
class Object
def initialize
@layout = Layout.new([:layout])
end
def attributes
raise "abstract #{self}"
end
def == other
return false unless other.class == self.class
attributes.each do |a|
left = send(a)
right = other.send(a)
return false unless left.class == right.class
return false unless left == right
end
return true
end
end
class Layout < Object
def initialize members
@members = members
end
def attributes
[:members]
end
end
class Class < Object
def initialize name , sup = :Object
@name = name
@super_class = sup
end
end
end

View File

@ -1,26 +1,11 @@
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)
class Reference
def initialize clazz = nil
@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

16
lib/virtual/value.rb Normal file
View File

@ -0,0 +1,16 @@
module Virtual
# the virtual machine is implemented in values. Values have types which are represented as classes, but it is still
# important to make the distinction. Values are immutable, passed by value and machine word sized.
# 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.
class Value
def type
self.class
end
private
def initialize
end
end
end

View File

@ -1,36 +0,0 @@
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

View File

@ -6,7 +6,7 @@ class TestBasic < MiniTest::Test
def test_number
@string_input = '42 '
@output = Ast::IntegerExpression.new(42)
@output = [Virtual::IntegerConstant.new(42)]
check
end

View File

@ -12,9 +12,8 @@ module VirtualHelper
syntax = parser.parse_with_debug(@string_input)
parts = Parser::Transform.new.apply(syntax)
machine = Virtual::Machine.new
puts parts.class.inspect
parts.compile(machine.bindings)
expressions = parts.compile(machine.bindings)
assert_equal @output , expressions
end
end