2014-05-05 10:03:43 +02:00
|
|
|
require_relative "code"
|
|
|
|
|
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-05-05 10:03:43 +02:00
|
|
|
# just a base class for data. not sure how this will be usefull (may just have read too much llvm)
|
|
|
|
class Value < Code
|
2014-05-10 09:59:56 +02:00
|
|
|
|
|
|
|
def initialize value
|
|
|
|
@value = value
|
|
|
|
end
|
2014-05-10 14:24:56 +02:00
|
|
|
attr_reader :value
|
|
|
|
|
2014-05-10 09:59:56 +02:00
|
|
|
#naming convention to infer types in kernel functions. Kernel types are basic types, ie see below
|
|
|
|
#
|
|
|
|
def self.type name
|
|
|
|
parts = name.split("_")
|
|
|
|
t = "Basic"
|
|
|
|
if parts[1]
|
|
|
|
t = parts[1]
|
|
|
|
end
|
|
|
|
t
|
|
|
|
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
|
2014-05-10 14:24:56 +02:00
|
|
|
def length
|
|
|
|
4
|
|
|
|
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-06 20:36:28 +02:00
|
|
|
# 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.
|
2014-04-28 21:08:09 +02:00
|
|
|
|
2014-05-06 20:36:28 +02:00
|
|
|
class StringLiteral < Value
|
|
|
|
|
|
|
|
# currently aligned to 4 (ie padded with 0) and off course 0 at the end
|
|
|
|
def initialize(str)
|
2014-05-10 10:03:23 +02:00
|
|
|
super(str)
|
2014-05-06 20:36:28 +02:00
|
|
|
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
|
2014-05-10 10:14:34 +02:00
|
|
|
@value = str + "\x00" * pad
|
2014-05-05 08:35:40 +02:00
|
|
|
end
|
2014-05-10 10:03:23 +02:00
|
|
|
def string
|
|
|
|
@value
|
|
|
|
end
|
2014-05-02 07:02:25 +02:00
|
|
|
|
2014-05-06 20:36:28 +02:00
|
|
|
def load reg_num
|
|
|
|
Machine.instance.string_load self , reg_num
|
|
|
|
end
|
|
|
|
|
|
|
|
# the strings length plus padding
|
|
|
|
def length
|
2014-05-10 10:14:34 +02:00
|
|
|
string.length
|
2014-05-03 14:13:44 +02:00
|
|
|
end
|
|
|
|
|
2014-05-06 20:36:28 +02:00
|
|
|
# just writing the string
|
|
|
|
def assemble(io)
|
2014-05-10 10:14:34 +02:00
|
|
|
io << string
|
2014-05-03 14:13:44 +02:00
|
|
|
end
|
2014-05-02 07:02:25 +02:00
|
|
|
end
|
|
|
|
end
|