class SyntaxTree::YARV::Bf
Parses the given source code into a syntax tree, compiles that syntax tree into YARV
bytecode.
Attributes
source[R]
Public Class Methods
new(source)
click to toggle source
# File lib/syntax_tree/yarv/bf.rb, line 10 def initialize(source) @source = source end
Public Instance Methods
compile()
click to toggle source
# File lib/syntax_tree/yarv/bf.rb, line 14 def compile # Set up the top-level instruction sequence that will be returned. iseq = InstructionSequence.new("<compiled>", "<compiled>", 1, :top) # Set up the $tape global variable that will hold our state. iseq.duphash({ 0 => 0 }) iseq.setglobal(:$tape) iseq.getglobal(:$tape) iseq.putobject(0) iseq.send(YARV.calldata(:default=, 1)) # Set up the $cursor global variable that will hold the current position # in the tape. iseq.putobject(0) iseq.setglobal(:$cursor) stack = [] source .each_char .chunk do |char| # For each character, we're going to assign a type to it. This # allows a couple of optimizations to be made by combining multiple # instructions into single instructions, e.g., +++ becomes a single # change_by(3) instruction. case char when "+", "-" :change when ">", "<" :shift when "." :output when "," :input when "[", "]" :loop else :ignored end end .each do |type, chunk| # For each chunk, we're going to emit the appropriate instruction. case type when :change change_by(iseq, chunk.count("+") - chunk.count("-")) when :shift shift_by(iseq, chunk.count(">") - chunk.count("<")) when :output chunk.length.times { output_char(iseq) } when :input chunk.length.times { input_char(iseq) } when :loop chunk.each do |char| case char when "[" stack << loop_start(iseq) when "]" loop_end(iseq, *stack.pop) end end end end iseq.leave iseq.compile! iseq end