module Vm # Base class for anything that we can assemble # Derived classes include instructions and constants(data) # The commonality abstracted here is the length and position # and the ability to assemble itself into the stream(io) # All code is position independant once assembled. # But for jumps and calls two passes are neccessary. # The first setting the position, the second assembling class Code def class_for clazz RegisterMachine.instance.class_for(clazz) end # set the position to zero, will have to reset later def initialize @position = 0 end # the position in the stream. Think of it as an address if you want. The difference is small. # Especially since we produce _only_ position independant code # in other words, during assembly the position _must_ be resolved into a pc relative address # and not used as is def position @position end # The containing class (assembler/function) call this to tell the instruction/data where it is in the # stream. During assembly the position is then used to calculate pc relative addresses. def link_at address , context @position = address end # length for this code in bytes def length raise "Not implemented #{inspect}" end # we pass the io (usually string_io) in for the code to assemble itself. def assemble(io) raise "Not implemented #{self.inspect}" end end end