2014-04-28 21:08:09 +02:00
|
|
|
module Vm
|
2014-05-02 07:02:25 +02:00
|
|
|
|
|
|
|
# Values represent the information as it is processed. Different subclasses for different types,
|
|
|
|
# each type with different operations.
|
|
|
|
# The oprerations on values is what makes a machine do things.
|
2014-05-03 14:13:44 +02:00
|
|
|
# For compilation, values are moved to the machines registers and the methods (on values) map
|
|
|
|
# to machine instructions
|
2014-05-02 07:02:25 +02:00
|
|
|
|
|
|
|
# Values are immutable! (that's why they are called values)
|
|
|
|
# Operations on values _always_ produce new values (conceptionally)
|
|
|
|
|
2014-05-03 14:13:44 +02:00
|
|
|
# Values are a way to reason about (create/validate) instructions.
|
|
|
|
# In fact a linked lists of values is created by invoking instructions
|
|
|
|
# the linked list goes from value to instruction to value, backwards
|
2014-05-02 07:02:25 +02:00
|
|
|
|
|
|
|
# Word Values are what fits in a register. Derived classes
|
|
|
|
# Float, Reference , Integer(s) must fit the same registers
|
|
|
|
|
2014-04-28 21:08:09 +02:00
|
|
|
class Value
|
2014-05-02 07:02:25 +02:00
|
|
|
def bit_size
|
|
|
|
8 * byte_size
|
|
|
|
end
|
|
|
|
|
|
|
|
def byte_size
|
|
|
|
raise "abstract method called #{self.inspect}"
|
|
|
|
end
|
|
|
|
|
2014-05-03 17:51:47 +02:00
|
|
|
# since we convert ast to values in conversion, value itself is responsible for compiling itself
|
|
|
|
# Compile must return a value, usually used in the next level up
|
|
|
|
def compile(context)
|
|
|
|
raise "abstract method called #{self.inspect}"
|
|
|
|
end
|
2014-05-02 07:02:25 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
class Word < Value
|
2014-05-05 08:35:40 +02:00
|
|
|
def load reg
|
|
|
|
Machine.instance.word_load self , reg
|
|
|
|
end
|
|
|
|
def compile context
|
|
|
|
#nothing to do here
|
2014-05-03 14:13:44 +02:00
|
|
|
end
|
2014-04-28 21:08:09 +02:00
|
|
|
end
|
|
|
|
|
2014-05-02 07:02:25 +02:00
|
|
|
class Unsigned < Word
|
|
|
|
|
2014-05-03 14:13:44 +02:00
|
|
|
def plus unsigned
|
2014-05-03 17:51:47 +02:00
|
|
|
Machine.instance.unsigned_plus self , unsigned
|
2014-05-02 07:02:25 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Signed < Word
|
2014-05-03 14:13:44 +02:00
|
|
|
def plus signed
|
2014-05-03 17:51:47 +02:00
|
|
|
Machine.instance.signed_plus self , signed
|
2014-05-02 07:02:25 +02:00
|
|
|
end
|
|
|
|
end
|
2014-04-28 21:08:09 +02:00
|
|
|
|
2014-05-02 07:02:25 +02:00
|
|
|
class Float < Word
|
2014-04-28 21:08:09 +02:00
|
|
|
end
|
|
|
|
|
2014-05-02 07:02:25 +02:00
|
|
|
class Reference < Word
|
2014-04-28 21:08:09 +02:00
|
|
|
end
|
2014-05-05 08:35:40 +02:00
|
|
|
class StringValue < Value
|
|
|
|
def initialize string
|
|
|
|
@string = string
|
|
|
|
end
|
|
|
|
def at pos
|
|
|
|
@pos = pos
|
|
|
|
end
|
|
|
|
def length
|
|
|
|
@string.length + 3
|
|
|
|
end
|
|
|
|
def compile context
|
|
|
|
#nothing to do here
|
|
|
|
end
|
|
|
|
attr_reader :string
|
|
|
|
end
|
2014-04-28 21:08:09 +02:00
|
|
|
|
|
|
|
class MemoryReference < Reference
|
|
|
|
end
|
2014-05-02 07:02:25 +02:00
|
|
|
|
2014-04-28 21:08:09 +02:00
|
|
|
class ObjectReference < Reference
|
2014-05-03 14:13:44 +02:00
|
|
|
def initialize obj
|
|
|
|
@object = obj
|
|
|
|
end
|
|
|
|
attr_reader :object
|
|
|
|
|
|
|
|
def compile context
|
2014-05-05 08:35:40 +02:00
|
|
|
if object.is_a? StringValue
|
2014-05-03 14:13:44 +02:00
|
|
|
context.program.add_object object
|
|
|
|
else
|
|
|
|
#TODO define object layout more generally and let objects lay themselves out
|
|
|
|
# as it is the program does this (in the objectwriter/stringtable)
|
|
|
|
un.done
|
|
|
|
end
|
|
|
|
end
|
2014-05-02 07:02:25 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
end
|
2014-05-03 14:13:44 +02:00
|
|
|
|
2014-05-05 08:51:16 +02:00
|
|
|
require "ast/conversion"
|