Created
November 23, 2012 17:26
-
-
Save corecode/4136563 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Mango | |
def initialize(source) | |
source.gsub!(/\/[*].*?[*]\//m, ' ') # remove comments | |
@toks = source.split(/\s+/) | |
@toks = @toks[1..-1] if @toks[0].empty? | |
@pc = 0 | |
@vars = {} | |
@vec = [] | |
@stack = [] | |
@exit = false | |
parse_labels | |
end | |
def parse_labels | |
pos = 0 | |
while pos < @toks.size | |
if /^(\w+):$/ === @toks[pos] | |
@vars[$1] = pos | |
@toks.slice! pos | |
else | |
pos += 1 | |
end | |
end | |
end | |
def run | |
while !@exit | |
instr = @toks[@pc] | |
@pc += 1 | |
# $stderr.puts "executing `#{instr}'" | |
val = case instr | |
when /\d+/ # integer literal | |
Integer(instr) | |
when /\w+/ # var, label, or opcode ref | |
if self.methods.include? "opc_#{instr}".to_sym | |
self.send('opc_' + instr) | |
else | |
{:sym => instr, :val => @vars[instr]} | |
end | |
end | |
# $stderr.puts " => #{val}" | |
@stack.push val unless val.nil? | |
# $stderr.puts "stack: #{@stack.reverse.map(&:to_s).join(' ')}" | |
end | |
end | |
def pop(literal=false) | |
val = @stack.pop | |
if Hash === val | |
val = if literal | |
val[:sym] | |
else | |
val[:val] | |
end | |
end | |
# $stderr.print " #{val}" | |
val | |
end | |
def opc_read_num | |
Integer($stdin.readline) | |
end | |
def opc_dup | |
val = pop | |
# $stderr.print " => #{val}" | |
@stack.push val | |
val | |
end | |
def opc_call | |
oldpc = @pc | |
@pc = pop | |
oldpc | |
end | |
def opc_exit | |
@exit = true | |
nil | |
end | |
def opc_add | |
pop + pop | |
end | |
def opc_sub | |
- pop + pop | |
end | |
def opc_mod | |
v1 = pop | |
v2 = pop | |
v2 % v1 | |
end | |
def opc_xor | |
pop ^ pop | |
end | |
def opc_vstore | |
val = pop | |
loc = pop | |
@vec[loc] = val | |
nil | |
end | |
def opc_vload | |
@vec[pop] | |
end | |
def opc_jump | |
@pc = pop | |
nil | |
end | |
def opc_store | |
name = pop true | |
val = pop | |
@vars[name] = val | |
nil | |
end | |
def cond_helper | |
l_false = pop | |
l_true = pop | |
cond = yield pop | |
@pc = if cond | |
l_true | |
else | |
l_false | |
end | |
nil | |
end | |
def opc_ifz | |
cond_helper {|c| c == 0} | |
end | |
def opc_ifg | |
cond_helper {|c| c > 0} | |
end | |
def opc_print_byte | |
$stdout.putc pop | |
nil | |
end | |
def opc_print_num | |
$stdout.print pop | |
end | |
end | |
if __FILE__ == $0 | |
source = File.read(ARGV[0]) | |
m = Mango.new(source) | |
m.run | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment