Grass 処理系

プログラミング言語 GrassRuby 1.9 による処理系です。

# parse
A, L = Struct.new(:m, :n), Struct.new(:code)
code = File.read(ARGV[0])
code = code.gsub("\uFF37", "W").gsub("\uFF57", "w").gsub("\uFF56", "v")
code = code.gsub(/[^wWv]/, "")
code = code[/w.*\z/m].split(/v/).map do |sub|
  sub = sub.scan(/w+|W+/)
  arity = sub.first[0] == "w" ? sub.shift.size : 0
  sub = sub.each_slice(2).map {|n, m| A[n.size - 1, m.size - 1] }
  arity.times { sub = [L[sub]] }
  sub
end.flatten(1)

# eval
eval = ->(code, env) do
  ctrue = ->(arg) { eval[[L[[A[2, 1]]]], [arg, ->(arg) { eval[[], [arg]] }]] }
  cfalse = ->(arg) { eval[[L[[]]], [arg]] }
  code.inject(env) do |env, insn|
    val = case insn
    when A
      clos, arg = env[insn.m], env[insn.n]
      case clos
      when Proc   then clos[arg]
      when Fixnum then clos == arg ? ctrue : cfalse
      when :out   then putc(arg); arg
      when :in    then $stdin.getc.ord || arg
      when :succ  then arg.succ & 0xff
      end
    when L
      ->(arg) { eval[insn.code, [arg] + env] }
    end
    [val] + env
  end.first
end
eval[[], [eval[[A[0, 0]], [eval[code, [:out, :succ, "w".ord, :in]]]]]]

実行例。

$ cat hello.www
wwvwwwWWWwwWwwWWWWwvwWWwwwWwwvwWwwwWwwvwWWwWWWWWwvwWWWwwwwWWWWwWWWWwWW
WWWWwWWWWWWWwWWWWWWWwWWWWWWWWwWwwwwwwwwvwWWWwwwwwWWWWWwWWWWWwWWWWWWWwW
WWWWWWWwWWWWWWWWWwWwwwwwwwvwWWWWwwwwwwWWWWWWwWWWWWWwWWWWWWWwWWWWWWWWWw
WWWWWWWWWwWwwwwwwwvwWWWWWwwwwwwwWWWWWWWwWWWWWWWWwWWWWWWWWwWWWWWWWWWWwW
WWWWWWWWWwWwwwwwwwvwWWWWWWWwwwwwwwwWWWWWWWWwWWWWWWWWWwWWWWWWWWWwWWWWWW
WWWWWwWwwwwwwvwWWWWWWWWwwwwwwwwwWWWWWWWWwWWWWWWWWWwWWWWWWWWWWWwWWWWWWW
WWWWwWWWWWWWWWWWWWwWwwwwwwwvwWWWWWWWWwwwwwwwwwwWWWWWWWWWwWWWWWWWWWWwWW
WWWWWWWWWwWWWWWWWWWWWWWwWwwwwwwvwWWWWWWWWWWwwwwwwwwwwwWWWWWWWWWWwWWWWW
WWWWWWwWWWWWWWWWWWWWwWwwwwwvwWWWWWWWWWWwwwwwwwwwwwwWWWWWWWWWWWWwWWWWWW
WWWWWWWwWWWWWWWWWWWWWWwWWWWWWWWWWWWWWwWWWWWWWWWWWWWWWWwWwwwwwwwvwWWWWW
WWWWWwwwwwwwwwwwwwwwwwWwwwwwwwwwwwwwwwwwwwWWWwwwwwwwwwwwwwwwwwwwWwwWWW
WWWWWWWWWWWWWWWWWwvwWWwwwwWWWwwwwwwwwwwWWWWwwwwwwwwwwWWWWWwwwwwwwwwwww
wWWWWWWwwwwwwwWWWWWWWwwwwwwwwwwwWWWWWWWWwwwwwwwwwwwwwwwwwwwwwwvwWWWWWW
WWWWWWWWWWwwwwwwwWwwvwWWWWwwwwwwwWWWWWwwwWWWWWWwwwwwwwWWWWWWWwwwwwwwwW
WWWWWWWwwwwwwwwwwwwwwWWWWWWWWWwwwwwwwwwwwwwwvwWWwWWWWWw

$ ruby19 grass.rb hello.www
Hello, world

30 分くらいで動くものは書けたけど、清書に 3 時間くらいかかった。でもあんまり綺麗くない。
まだ誰も Ruby で処理系を書いてないのかと思って書いたけど、実は Grass 設計者のうえのさん自身が書かれてました。後で気がついた。
とりあえず、LLVM の練習課題にいいんじゃないでしょうか > 誰か

追記:
github で公開。バグ修正あり。ライセンスつけたらコメントの方が長くなった。
http://github.com/mame/grass-misc/tree/master/yagi.rb