class RPxem::Interpreter

Attributes

mapping[RW]
stack[R]
temp[R]

Public Class Methods

new(mapping={}) click to toggle source
# File lib/rpxem/interpreter.rb, line 9
def initialize(mapping={})
  @mapping = default_mapping().merge(mapping)
end

Public Instance Methods

default_mapping() click to toggle source
# File lib/rpxem/interpreter.rb, line 40
def default_mapping
  {
    # I/O
    'p' => 'output_all',
    'o' => 'output',
    'n' => 'output_num',
    'i' => 'input',
    '_' => 'input_num',

    # Stack
    'c' => 'copy',
    's' => 'throw_away',
    'v' => 'reverse',

    # File contents
    'f' => 'read_file',
    'e' => 'emurate',

    # Rand
    'r' => 'rand',

    # Loop
    'w' => 'w',
    'x' => 'x',
    'y' => 'y',
    'z' => 'z',
    'a' => 'a',

    # Temporary area
    't' => 'to_temp',
    'm' => 'from_temp',

    # Terminate execution
    'd' => 'terminate',

    # Math
    '+' => 'addition',
    '-' => 'subtraction',
    '!' => 'multiplication',
    '$' => 'quotient',
    '%' => 'surplus',
  }
end
open(file, stack=RPxem::Stack.new, temp=nil) click to toggle source

Open and execute a Pxem file

# File lib/rpxem/interpreter.rb, line 14
def open(file, stack=RPxem::Stack.new, temp=nil)
  run(File.basename(file), File.open(file).read, stack, temp)
end
run(filename, source='', stack=RPxem::Stack.new, temp=nil) click to toggle source

Execute a Pxem code

# File lib/rpxem/interpreter.rb, line 19
def run(filename, source='', stack=RPxem::Stack.new, temp=nil)
  @filename, @source, @stack, @temp = filename.each_byte.to_a, source, stack, temp
  buffer, @cursor, length = RPxem::Stack.new, 0, @filename.length

  while (@cursor < length)
    char = @filename[@cursor]
    @cursor += 1
    if (@cursor < length && 46 == char && name = @mapping[@filename[@cursor].chr.downcase])
      @stack.push(*buffer)
      buffer = RPxem::Stack.new
      break if name == 'terminate'
      __send__(name)
      @cursor += 1
    else
      buffer.unshift(char)
    end
  end

  return @stack
end

Private Instance Methods

a() click to toggle source

.a:

# File lib/rpxem/interpreter.rb, line 179
def a
  @cursor -= 2
  count = -1
  while (count.nonzero?)
    if (46 == @filename[@cursor])
      if (['w','x','y','z'].include? @filename[@cursor+1].chr.downcase)
        count += 1
      elsif ('a' == @filename[@cursor+1].chr.downcase)
        count -= 1
      end
    end
    @cursor -= 1
  end
end
addition() click to toggle source

.+:

# File lib/rpxem/interpreter.rb, line 205
def addition
  @stack.push(@stack.pop + @stack.pop) if 2 <= @stack.size
end
copy() click to toggle source

.c:

# File lib/rpxem/interpreter.rb, line 113
def copy
  @stack.push(@stack.last) unless @stack.empty?
end
emurate() click to toggle source

.e:

# File lib/rpxem/interpreter.rb, line 133
def emurate
  @stack.push(*clone.run(@source, @source, @stack.clone))
end
from_temp() click to toggle source

.m:

# File lib/rpxem/interpreter.rb, line 200
def from_temp
  @stack.push(@temp) if @temp
end
input() click to toggle source

.i:

# File lib/rpxem/interpreter.rb, line 102
def input
  stdin = STDIN.getc
  @stack.push(stdin ? stdin.ord : -1)
end
input_num() click to toggle source

._:

# File lib/rpxem/interpreter.rb, line 108
def input_num
  @stack.push(*scanf('%d'))
end
jump() click to toggle source

Jump forward to correspondent .a

# File lib/rpxem/interpreter.rb, line 163
def jump
  count = 1
  while (count.nonzero?)
    @cursor += 1
    if (46 == @filename[@cursor])
      if (['w','x','y','z'].include? @filename[@cursor+1].chr.downcase)
        count += 1
      elsif ('a' == @filename[@cursor+1].chr.downcase)
        count -= 1
      end
    end
  end
  @cursor += 1
end
multiplication() click to toggle source

.!:

# File lib/rpxem/interpreter.rb, line 215
def multiplication
  @stack.push(@stack.pop * @stack.pop) if 2 <= @stack.size
end
output() click to toggle source

.o:

# File lib/rpxem/interpreter.rb, line 92
def output
  putc @stack.pop unless @stack.empty?
end
output_all() click to toggle source

.p:

# File lib/rpxem/interpreter.rb, line 87
def output_all
  while output; end
end
output_num() click to toggle source

.n:

# File lib/rpxem/interpreter.rb, line 97
def output_num
  print @stack.pop
end
quotient() click to toggle source

.$:

# File lib/rpxem/interpreter.rb, line 220
def quotient
  @stack.push((f=@stack.pop)>(s=@stack.pop)? f/s : s/f) if 2 <= @stack.size
end
rand() click to toggle source

.r:

Calls superclass method
# File lib/rpxem/interpreter.rb, line 138
def rand
  @stack.push((super * @stack.pop).to_i)
end
read_file() click to toggle source

.f:

# File lib/rpxem/interpreter.rb, line 128
def read_file
  @stack.push(*@source.each_byte.to_a.reverse)
end
reverse() click to toggle source

.v:

# File lib/rpxem/interpreter.rb, line 123
def reverse
  @stack.reverse!
end
subtraction() click to toggle source

.-:

# File lib/rpxem/interpreter.rb, line 210
def subtraction
  @stack.push((@stack.pop - @stack.pop).abs) if 2 <= @stack.size
end
surplus() click to toggle source

.%:

# File lib/rpxem/interpreter.rb, line 225
def surplus
  @stack.push((f=@stack.pop)>(s=@stack.pop)? f%s : s%f) if 2 <= @stack.size
end
throw_away() click to toggle source

.s:

# File lib/rpxem/interpreter.rb, line 118
def throw_away
  @stack.pop
end
to_temp() click to toggle source

.t:

# File lib/rpxem/interpreter.rb, line 195
def to_temp
  @temp = @stack.pop
end
w() click to toggle source

.w:

# File lib/rpxem/interpreter.rb, line 143
def w
  jump if (!@stack.empty? && 0 == @stack.pop)
end
x() click to toggle source

.x:

# File lib/rpxem/interpreter.rb, line 148
def x
  jump if (2 <= @stack.size && @stack.pop >= @stack.pop)
end
y() click to toggle source

.y:

# File lib/rpxem/interpreter.rb, line 153
def y
  jump if (2 <= @stack.size && @stack.pop <= @stack.pop)
end
z() click to toggle source

.z:

# File lib/rpxem/interpreter.rb, line 158
def z
  jump if (2 <= @stack.size && @stack.pop == @stack.pop)
end