a basic interpret command for cli
part of the benchmark effort determine amount of objects
This commit is contained in:
parent
00bf38a0e6
commit
14c965360d
@ -8,7 +8,8 @@ module Risc
|
|||||||
# will be executed by method execute_SlotToReg
|
# will be executed by method execute_SlotToReg
|
||||||
#
|
#
|
||||||
# The Interpreter (a bit like a cpu) has a state flag, a current instruction and registers
|
# The Interpreter (a bit like a cpu) has a state flag, a current instruction and registers
|
||||||
# We collect the stdout (as a hack not to interpret the OS)
|
# We collect the stdout (as a hack not to interpret the OS) in a string. It can also be passed
|
||||||
|
# in to the init, as an IO
|
||||||
#
|
#
|
||||||
class Interpreter
|
class Interpreter
|
||||||
# fire events for changed pc and register contents
|
# fire events for changed pc and register contents
|
||||||
@ -18,11 +19,13 @@ module Risc
|
|||||||
|
|
||||||
attr_reader :instruction , :clock , :pc # current instruction and pc
|
attr_reader :instruction , :clock , :pc # current instruction and pc
|
||||||
attr_reader :registers # the registers, 16 (a hash, sym -> contents)
|
attr_reader :registers # the registers, 16 (a hash, sym -> contents)
|
||||||
attr_reader :stdout, :state , :flags # somewhat like the lags on a cpu, hash sym => bool (zero .. . )
|
attr_reader :stdout, :state , :flags # somewhat like the flags on a cpu, hash sym => bool (zero .. . )
|
||||||
|
|
||||||
#start in state :stopped and set registers to unknown
|
# start in state :stopped and set registers to unknown
|
||||||
def initialize( linker )
|
# Linker gives the state of the program
|
||||||
@stdout , @clock , @pc , @state = "", 0 , 0 , :stopped
|
# Passing a stdout in (an IO, only << called) can be used to get output immediately.
|
||||||
|
def initialize( linker , stdout = "")
|
||||||
|
@stdout , @clock , @pc , @state = stdout, 0 , 0 , :stopped
|
||||||
@registers = {}
|
@registers = {}
|
||||||
@flags = { :zero => false , :plus => false ,
|
@flags = { :zero => false , :plus => false ,
|
||||||
:minus => false , :overflow => false }
|
:minus => false , :overflow => false }
|
||||||
@ -32,8 +35,7 @@ module Risc
|
|||||||
@linker = linker
|
@linker = linker
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_program(linker = nil)
|
def start_program()
|
||||||
initialize(linker || @linker)
|
|
||||||
init = @linker.cpu_init
|
init = @linker.cpu_init
|
||||||
set_state(:running)
|
set_state(:running)
|
||||||
set_pc( Position.get(init).at )
|
set_pc( Position.get(init).at )
|
||||||
@ -249,10 +251,12 @@ module Risc
|
|||||||
str = get_register( :r1 ) # should test length, ie r2
|
str = get_register( :r1 ) # should test length, ie r2
|
||||||
case str
|
case str
|
||||||
when Symbol
|
when Symbol
|
||||||
@stdout += str.to_s
|
@stdout << str.to_s
|
||||||
|
@stdout.flush if @stdout.respond_to?(:flush)
|
||||||
return str.to_s.length
|
return str.to_s.length
|
||||||
when Parfait::Word
|
when Parfait::Word
|
||||||
@stdout += str.to_string
|
@stdout << str.to_string
|
||||||
|
@stdout.flush if @stdout.respond_to?(:flush)
|
||||||
return str.char_length
|
return str.char_length
|
||||||
else
|
else
|
||||||
raise "NO string for putstring #{str.class}:#{str.object_id}" unless str.is_a?(Symbol)
|
raise "NO string for putstring #{str.class}:#{str.object_id}" unless str.is_a?(Symbol)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
require "thor"
|
require "thor"
|
||||||
require "rubyx"
|
require "rubyx"
|
||||||
|
require "risc/interpreter"
|
||||||
|
|
||||||
class RubyXC < Thor
|
class RubyXC < Thor
|
||||||
desc "compile FILE" , "Compile given FILE to binary"
|
desc "compile FILE" , "Compile given FILE to binary"
|
||||||
@ -27,7 +28,44 @@ class RubyXC < Thor
|
|||||||
|
|
||||||
outfile = file.split("/").last.gsub(".rb" , ".o")
|
outfile = file.split("/").last.gsub(".rb" , ".o")
|
||||||
writer.save outfile
|
writer.save outfile
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "interpret FILE" , "Interpret given FILE "
|
||||||
|
long_desc <<-LONGDESC
|
||||||
|
Compiles the given file to an intermediate RISC format, and runs the
|
||||||
|
Interpreter.
|
||||||
|
|
||||||
|
RISC is the last abstract layer inside the compiler. It is in nature
|
||||||
|
very close to arm (without quirks and much smaller).
|
||||||
|
|
||||||
|
An interpreter was originally developed for the RISC layer for debugging purposes.
|
||||||
|
Running the interpreter is about 50k slower than binary, but it can be used
|
||||||
|
to veryfy simple programs.
|
||||||
|
|
||||||
|
No output file will be generated, the only output is generated by the
|
||||||
|
given program.
|
||||||
|
|
||||||
|
The program must define a main method on the Space class, which will be invoked.
|
||||||
|
LONGDESC
|
||||||
|
|
||||||
|
def interpret(file)
|
||||||
|
begin
|
||||||
|
ruby = File.read(file)
|
||||||
|
rescue
|
||||||
|
fail MalformattedArgumentError , "No such file #{file}"
|
||||||
|
end
|
||||||
|
options = {
|
||||||
|
parfait: { factory: 3*1024, },
|
||||||
|
load_parfait: false ,
|
||||||
|
}
|
||||||
|
compiler = RubyX::RubyXCompiler.new(options)
|
||||||
|
linker = compiler.ruby_to_binary(ruby, :interpreter)
|
||||||
|
|
||||||
|
puts "interpreting #{file}"
|
||||||
|
|
||||||
|
interpreter = Risc::Interpreter.new(linker , STDOUT )
|
||||||
|
interpreter.start_program
|
||||||
|
interpreter.tick while(interpreter.instruction)
|
||||||
|
|
||||||
return outfile
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user