use common list for risc instruction

strange that that was not done before as the code was clearly copied
when extracting it

Fix bug for insertion
This commit is contained in:
Torsten Ruger 2018-03-18 10:36:01 +05:30
parent 9c052c78a7
commit c5ec532616
3 changed files with 29 additions and 60 deletions

View File

@ -11,6 +11,9 @@ module Common
end
# during translation we replace one by one
# TODO avoid this by building a new list
# Make arm instruction not derive from risc (which is weird anyway)
# and include the List into it, translate in same way we go from mom->risc
def replace_next( nekst )
old = @next
@next = nekst
@ -26,9 +29,10 @@ module Common
# set the give instruction as the next, while moving any existing
# instruction along to the given ones's next.
# ie insert into the linked list that the instructions form
# but allowing the instruction to be a list too (ie more than one)
def insert( instruction )
instruction.set_next @next
@next = instruction
instruction.last.set_next @next
@next = instruction.last
end
# return last set instruction. ie follow the linked list until it stops

View File

@ -1,18 +1,26 @@
require "common/list"
module Risc
# the register machine has at least 8 registers, named r0-r5 , :lr and :pc (for historical reasons)
# we can load and store their contents and
# the register machine has at least 8 registers, named r0-r5 , :lr and :pc
# (for historical reasons , r for register, pc for ProgramCounter ie next instruction address
# and lr means LinkRegister, ie the location where to return to when in a function)
#
# We can load and store their contents, move data between them and
# access (get/set) memory at a constant offset from a register
# while the vm works with objects, the register machine has registers,
# but we keep the names for better understanding, r4/5 are temporary/scratch
# there is no direct memory access, only through registers
# constants can/must be loaded into registers before use
# While Mom works with objects, the register machine has registers,
# but we keep the names for better understanding, r2-5 are temporary/scratch
# There is no direct memory access, only through registers
# Constants can/must be loaded into registers before use
# Instructions form a graph.
# Linear instructions form a linked list
# At compile time, Instructions form a linked list (:next attribute is the link)
# At run time Instructions are traversesed as a graph
#
# Branches fan out, Labels collect
# Labels are the only valid branch targets
#
class Instruction
include Common::List
def initialize source , nekst = nil
@source = source
@ -22,55 +30,7 @@ module Risc
end
attr_reader :source
# set the next instruction (also aliased as <<)
# throw an error if that is set, use insert for that use case
# return the instruction, so chaining works as one wants (not backwards)
def set_next nekst
raise "Next already set #{@next}" if @next
@next = nekst
nekst
end
alias :<< :set_next
# during translation we replace one by one
def replace_next nekst
old = @next
@next = nekst
@next.append old.next if old
end
# get the next instruction (without arg given )
# when given an interger, advance along the line that many time and return.
def next( amount = 1)
(amount == 1) ? @next : @next.next(amount-1)
end
# set the give instruction as the next, while moving any existing
# instruction along to the given ones's next.
# ie insert into the linked list that the instructions form
def insert instruction
instruction.last.set_next @next
@next = instruction
end
# return last set instruction. ie follow the linked list until it stops
def last
code = self
code = code.next while( code.next )
return code
end
# set next for the last (see last)
# so append the given code to the linked list at the end
def append code
last.set_next code
end
def length labels = []
ret = 1
ret += self.next.length( labels ) if self.next
ret
end
#TODO check if this is used. Maybe build an each for instructions
def to_arr labels = []
ret = [self.class]
ret += self.next.to_arr(labels) if self.next

View File

@ -36,6 +36,11 @@ module Risc
@instruction.insert @branch
assert_equal @branch, @instruction.last
end
def test_insert_two
@branch << @label
@instruction.insert @branch
assert_equal @label , @instruction.last
end
def test_append_not_empty
@instruction.append @branch
@instruction.append @label