ec1d38f5a6
easier to understand, as indexes map to Binarycode indexes, and can thus later be used to assemble directoy into the code Almost no change in tests (now only multiples of 4 addresses allowed)
115 lines
3.1 KiB
Ruby
115 lines
3.1 KiB
Ruby
module Parfait
|
|
|
|
# A typed method object is a description of the method, it's name etc
|
|
#
|
|
# But the code that the method represents, the binary, is held as an array
|
|
# in these. As Objects are fixed size (this one 16 words), we use linked list
|
|
# and as the last code of each link is a jump to the next link.
|
|
#
|
|
class BinaryCode < Data16
|
|
attr_reader :next
|
|
|
|
def self.type_length
|
|
2 #type + next (could get from space, maybe later)
|
|
end
|
|
def self.byte_offset
|
|
self.type_length * 4 # size of type * word_size (4)
|
|
end
|
|
def self.data_length
|
|
self.memory_size - self.type_length - 1 #one for the jump
|
|
end
|
|
def data_length
|
|
self.class.data_length
|
|
end
|
|
def byte_length
|
|
4*data_length
|
|
end
|
|
|
|
def initialize(total_size)
|
|
super()
|
|
extend_to(total_size )
|
|
(0 ... data_length).each{ |index| set_word(index , 0) }
|
|
set_last(0)
|
|
end
|
|
def extend_to(total_size)
|
|
return if total_size < data_length
|
|
extend_one() unless @next
|
|
@next.extend_to(total_size - data_length)
|
|
end
|
|
|
|
def extend_one()
|
|
@next = BinaryCode.new(1)
|
|
Risc::Position.get(self).trigger_inserted if Risc::Position.set?(self)
|
|
end
|
|
|
|
def ensure_next
|
|
extend_one unless @next
|
|
@next
|
|
end
|
|
|
|
def last_code
|
|
last = self
|
|
last = last.next while(last.next)
|
|
last
|
|
end
|
|
|
|
def each_block( &block )
|
|
block.call( self )
|
|
@next.each_block( &block ) if @next
|
|
end
|
|
|
|
def to_s
|
|
"BinaryCode #{Risc::Position.set?(self) ? Risc::Position.get(self): self.object_id.to_s(16)}"
|
|
end
|
|
|
|
def each_word( all = true)
|
|
index = 0
|
|
while( index < data_length)
|
|
yield get_word(index)
|
|
index += 1
|
|
end
|
|
yield( get_last ) if all
|
|
end
|
|
|
|
def set_word(index , word)
|
|
raise "invalid index #{index}" if index < 0
|
|
if index >= data_length
|
|
#raise "invalid index #{index}" unless @next
|
|
extend_to( index )
|
|
@next.set_word( index - data_length , word)
|
|
else
|
|
set_internal_word(index + BinaryCode.type_length , word)
|
|
end
|
|
end
|
|
def get_last()
|
|
get_internal_word(data_length + BinaryCode.type_length)
|
|
end
|
|
def set_last(word)
|
|
set_internal_word(data_length + BinaryCode.type_length , word)
|
|
end
|
|
def get_word(index)
|
|
raise "invalid index #{index}" if index < 0
|
|
if index >= data_length
|
|
raise "invalid index #{index}" unless @next
|
|
return @next.get_word( index - data_length)
|
|
end
|
|
get_internal_word(index + BinaryCode.type_length)
|
|
end
|
|
def set_char(index , char)
|
|
if index >= byte_length
|
|
#puts "Pass it on #{index} for #{self.object_id}:#{@next.object_id}"
|
|
return @next.set_char( index - byte_length , char )
|
|
end
|
|
word_index = (index - 1) / 4 + 2
|
|
old = get_internal_word( word_index )
|
|
old = old && char << ((index-1)%4)
|
|
set_internal_word(word_index , char)
|
|
end
|
|
def total_byte_length(start = 0 )
|
|
start += self.byte_length
|
|
return start unless self.next
|
|
self.next.total_byte_length(start)
|
|
end
|
|
end
|
|
end
|