rubyx/test/support/risc_interpreter.rb
Torsten Ruger ce79617875 fix the exit sequence
was returning wrong register (1, not 0)
also saving the message for test, which changes order as the return value destroys the message
2018-06-19 19:52:06 +03:00

123 lines
3.2 KiB
Ruby

require "util/eventable"
require "risc/interpreter"
require_relative "compiling"
module Risc
module Ticker
include CompilerHelper
def setup
Risc.machine.boot
Vool::VoolCompiler.ruby_to_binary( @string_input , :interpreter)
@interpreter = Interpreter.new
@interpreter.start_machine
end
alias :do_setup :setup
# check the given array of instructions is what the interpreter actually does
# possible second argument ignores the given amount, usually up until main
def check_chain( should , start_at = 0 )
ticks( start_at ) if start_at > 0
should.each_with_index do |name , index|
got = ticks(1)
assert_equal got.class ,name , "Wrong class for #{index + 1 - start_at}, expect #{name} , got #{got}"
end
end
# check the main only, ignoring the __init instructions
def check_main_chain( should )
check_chain( should , main_at)
end
# how many instruction up until the main starts, ie
# ticks(main_at) will be the label for main
def main_at
26
end
def get_return
assert_equal Parfait::Message , @interpreter.get_register(:r8).class
@interpreter.get_register(:r0)
end
# do as many as given ticks in the main, ie main_at more
def main_ticks(num)
ticks( main_at + num)
end
# do a certain number of steps in the interpreter and return the last executed instruction
def ticks( num )
last = nil
num.times do
last = @interpreter.instruction
@interpreter.tick
end
return last
end
# collect the classes of all executed istructions
def all_classes(max = 300)
classes = []
tick = 1
begin
while true and (classes.length < max)
cl = ticks(1).class
tick += 1
classes << cl
break if cl == NilClass
end
rescue => e
puts "Error at tick #{tick}"
puts e
puts e.backtrace
end
classes
end
# do the setup, compile and run the input (a main) to the end
def run_main_return(input)
run_main("return #{input}")
end
# get the return from the message (not exit code)
# exit code must be int
def get_message_return
@interpreter.get_register(:r8).return_value
end
def run_main(input)
@string_input = as_main(input)
do_setup
run_all
end
# wrap the input in Space (main is assumed to be part of it)
def run_space(input)
@string_input = in_Space(input)
do_setup
run_all
end
def run_all
@interpreter.tick while(@interpreter.instruction)
end
# for chaning the tests quickly output all instructions that are executed
def show_ticks
classes = all_classes
output_classes(classes)
end
# show all instructions of the main only
def show_main_ticks
classes = all_classes
classes = classes.slice(main_at , 1000)
output_classes(classes)
end
def output_classes(classes)
str = classes.to_s.gsub("Risc::","")
all = str.split(",").each_slice(5).collect {|line| " " + line.join(",")}
puts all.join(",\n")
puts "length = #{classes.length}"
exit(1)
end
end
end