Compiling to Gcode

早速、G-machine COSC406 Compiler Implementation Techniques p.16-18のCompiling to GcodeをRubyで実装すると、こんな感じかな?

def comp_sc(f, xs, e)
  # p [:comp_sc, f, xs, e]
  xs1 = xs.inject([{}, 0]) {|(h, i), x| h[x] = i; [h, i + 1] }.first
  comp_r(e, xs1, xs.size)
end

def comp_r(e, q, d)
  # p [:comp_r, e, q, d]
  comp_c(e, q) + [[:slide, d + 1], [:unwind]]
end

def comp_c(e, q)
  # p [:comp_c, e, q]
  case e
  when Symbol
    if e =~ /\A[A-Z]/
      [[:push_global, e]]
    else
      [[:push, q[e]]]
    end
  when Integer
    [[:push_int, e]]
  when Array
    case e.size
    when 0
      []
    when 1
      comp_c(e.first, q)
    else
      e0, e1 = e[0 .. -2], e[-1]
      q1 = q.inject({}) {|h, (k, v)| h[k] = v + 1; h }
      comp_c(e1, q) + comp_c(e0, q1) + [[:mkap]]
    end
  else
    raise 'invalid e.'
  end
end

if $0 == __FILE__
  require 'pp'
  pp comp_sc(:S, [:f, :g, :x], [:f, :x, [:g, :x]])
  # => [[:push, 2],
  #     [:push, 2],
  #     [:mkap],
  #     [:push, 3],
  #     [:push, 2],
  #     [:mkap],
  #     [:mkap],
  #     [:slide, 4],
  #     [:unwind]]
end

(追記)
こんなサイトもありました。
エロと風俗情報満載 どう抜く?