2018-04-19 18:33:40 +02:00
|
|
|
require "util/eventable"
|
|
|
|
require "risc/interpreter"
|
|
|
|
require_relative "compiling"
|
2019-09-13 21:06:18 +02:00
|
|
|
require_relative "output"
|
2018-04-19 18:33:40 +02:00
|
|
|
|
2017-04-10 15:12:15 +02:00
|
|
|
module Risc
|
2018-04-19 18:33:40 +02:00
|
|
|
module Ticker
|
2018-06-29 22:04:50 +02:00
|
|
|
include ScopeHelper
|
2019-08-23 14:31:04 +02:00
|
|
|
include Output
|
2019-09-13 13:07:12 +02:00
|
|
|
include Preloader
|
2018-04-19 18:33:40 +02:00
|
|
|
|
|
|
|
def setup
|
2019-02-09 11:44:35 +01:00
|
|
|
compiler = RubyX::RubyXCompiler.new(RubyX.interpreter_test_options)
|
2019-09-13 13:07:12 +02:00
|
|
|
@linker = compiler.ruby_to_binary(preload + @string_input, :interpreter)
|
2018-07-02 16:29:26 +02:00
|
|
|
@interpreter = Interpreter.new(@linker)
|
2018-07-02 22:03:33 +02:00
|
|
|
@interpreter.start_program
|
2018-04-19 18:33:40 +02:00
|
|
|
end
|
2018-04-23 13:05:37 +02:00
|
|
|
alias :do_setup :setup
|
2018-04-19 18:33:40 +02:00
|
|
|
|
2018-07-27 09:48:45 +02:00
|
|
|
def yielder
|
2018-07-30 13:10:24 +02:00
|
|
|
"def yielder; return yield ; end"
|
2018-07-27 09:48:45 +02:00
|
|
|
end
|
2018-08-01 15:31:16 +02:00
|
|
|
def tenner
|
|
|
|
"def tenner; return yield(10) ;end"
|
|
|
|
end
|
2018-07-27 09:48:45 +02:00
|
|
|
def block_main( main , extra = yielder)
|
|
|
|
in_Space("#{extra} ; def main(arg) ; #{main} ; end")
|
|
|
|
end
|
|
|
|
|
2018-04-04 19:05:09 +02:00
|
|
|
# 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
|
2017-04-10 15:12:15 +02:00
|
|
|
should.each_with_index do |name , index|
|
|
|
|
got = ticks(1)
|
2018-07-20 20:00:47 +02:00
|
|
|
assert_equal got.class ,name , "Wrong class for #{index + 1}, expect #{name} , got #{got}"
|
2017-04-10 15:12:15 +02:00
|
|
|
end
|
|
|
|
end
|
2018-04-04 19:05:09 +02:00
|
|
|
# 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
|
2020-03-15 11:58:39 +01:00
|
|
|
Risc.init_length
|
2018-04-04 19:05:09 +02:00
|
|
|
end
|
2017-04-10 15:12:15 +02:00
|
|
|
|
2020-03-22 10:29:56 +01:00
|
|
|
# the return of syscall should be an integer
|
2018-03-23 19:02:17 +01:00
|
|
|
def get_return
|
2020-03-22 10:29:56 +01:00
|
|
|
saved_in = @interpreter.std_reg(:saved_message)
|
|
|
|
assert_equal Parfait::Message , @interpreter.get_register(saved_in).class
|
|
|
|
@interpreter.get_register(@interpreter.std_reg(:syscall_1))
|
2017-04-10 15:12:15 +02:00
|
|
|
end
|
|
|
|
|
2018-04-04 19:05:09 +02:00
|
|
|
# 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
|
2018-03-23 17:55:23 +01:00
|
|
|
def ticks( num )
|
2017-04-10 15:12:15 +02:00
|
|
|
last = nil
|
|
|
|
num.times do
|
|
|
|
last = @interpreter.instruction
|
|
|
|
@interpreter.tick
|
|
|
|
end
|
|
|
|
return last
|
|
|
|
end
|
2020-03-15 11:58:39 +01:00
|
|
|
def risc(num)
|
|
|
|
return @instruction if @instruction
|
|
|
|
@instruction = main_ticks(num)
|
|
|
|
end
|
2017-04-10 15:12:15 +02:00
|
|
|
|
2018-04-04 19:05:09 +02:00
|
|
|
# collect the classes of all executed istructions
|
2018-04-23 13:05:37 +02:00
|
|
|
def all_classes(max = 300)
|
2017-04-10 15:12:15 +02:00
|
|
|
classes = []
|
|
|
|
tick = 1
|
|
|
|
begin
|
2018-07-02 22:03:33 +02:00
|
|
|
while(classes.length < max)
|
2017-04-10 15:12:15 +02:00
|
|
|
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
|
2018-04-04 19:05:09 +02:00
|
|
|
classes
|
|
|
|
end
|
2018-04-19 18:59:48 +02:00
|
|
|
|
2018-04-26 11:33:33 +02:00
|
|
|
# do the setup, compile and run the input (a main) to the end
|
2018-05-25 19:40:39 +02:00
|
|
|
def run_main_return(input)
|
|
|
|
run_main("return #{input}")
|
|
|
|
end
|
|
|
|
|
2018-06-19 17:55:47 +02:00
|
|
|
# get the return from the message (not exit code)
|
|
|
|
# exit code must be int
|
|
|
|
def get_message_return
|
2020-03-22 10:29:56 +01:00
|
|
|
@interpreter.get_register(@interpreter.std_reg(:saved_message)).return_value
|
2018-06-19 17:55:47 +02:00
|
|
|
end
|
2018-08-18 18:42:14 +02:00
|
|
|
|
|
|
|
# wrap the input so it is a main, compile and run it
|
2018-04-24 19:12:49 +02:00
|
|
|
def run_main(input)
|
2018-08-18 18:42:14 +02:00
|
|
|
run_input as_main(input)
|
|
|
|
end
|
|
|
|
|
|
|
|
# use the input as it, compile and run it
|
|
|
|
# input muts contain a Space.main, but may contain more classes and methods
|
|
|
|
def run_input(input)
|
2019-09-24 20:20:12 +02:00
|
|
|
@string_input = input
|
2018-04-19 18:59:48 +02:00
|
|
|
do_setup
|
2018-04-23 13:05:37 +02:00
|
|
|
run_all
|
2018-04-19 18:59:48 +02:00
|
|
|
end
|
2018-04-26 11:33:33 +02:00
|
|
|
|
2018-04-23 13:05:37 +02:00
|
|
|
def run_all
|
2019-08-23 18:25:02 +02:00
|
|
|
while(@interpreter.instruction)
|
|
|
|
@interpreter.tick
|
|
|
|
#puts @interpreter.instruction
|
|
|
|
end
|
2018-08-06 13:13:39 +02:00
|
|
|
@interpreter.clock
|
2018-04-23 13:05:37 +02:00
|
|
|
end
|
|
|
|
|
2018-04-04 19:05:09 +02:00
|
|
|
# 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)
|
2019-08-23 14:31:04 +02:00
|
|
|
puts class_list(classes)
|
2017-04-10 15:12:15 +02:00
|
|
|
exit(1)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|