Unlambdaインタプリタ by Ruby
Schemeのインタプリタに行き詰まってきたので、とりあえず超難解プログラミング言語、Unlambdaのインタプリタを作っちゃいました。
http://hw001.gate01.com/eggplant/tcf/unlambda/
たぶん、それなりに動くものが出来たと思います。
まあ、俺自身Unlambdaのプログラムが書けないのに、ちゃんと動くっぽいってのも変だけど。
そういや、Rubyでプログラム書いたの久しぶりかもしれないな。
次はWhitespaceのインタプリタを作ろう!
class Proc @delay attr_accessor :delay end class UnlambdaInterpriter def initialize @cur = nil @i = make_function("i") @v = make_function("v") end def read_delay_block(chars ) cmd = next_command(chars) if cmd == "`" cmd + read_delay_block(chars) + read_delay_block(chars) else cmd end end def next_command(chars) if chars.empty? return nil end ret = nil op = chars.shift if op == "." or op == "?" unless chars.empty? ret = op + chars.shift end elsif op == "#" while chars.shift != "\n" # skip end ret = next_command(chars) elsif op =~ /\s/ ret = next_command(chars) else ret = op end return ret end def _eval(chars) #p chars case c = next_command(chars) when "`" op = _eval(chars) if op.delay op.delay = false return op else arg, dummy = _eval(chars) return op[arg] end when nil raise "nil !" else return make_function(c, chars) end end def make_function(c, chars=[]) ret = nil case c when "i" return proc{|x| x } when "k" return proc{|a| proc{|b| a } } when "s" return proc{|a| proc{|b| proc{|c| a[c][b[c]] } } } when /\A\.(.)\Z/ return proc{|x| print $1 x } when "r" return proc{|x| print "\n" x } when "e" return proc{|x| exit } when "d" delay_str = read_delay_block(chars) ret = proc{|a| #p :delaycalled self.eval(delay_str) } ret.delay = true return ret when "v" ret = proc{|v| ret } return ret when "@" return proc{|x| if STDIN.eof? x[@v] else @cur = STDIN.getc.chr x[@i] end } when /\A\?(.)\Z/ return proc{|x| if $1 == @cur x[@i] else x[@v] end } when "|" return proc{|x| if @cur print @cur x[@i] else x[@v] end } when "c" return proc{|x| callcc{|c| x[ proc{|y| c.call(y) } ] } } else return _eval(chars) end end def eval(str) #p str chars = str.unpack("c*").map{|e|e.chr} _eval(chars) end end if __FILE__ == $0 # CTRL-Cで止める str = <<-EOT ```s``s``sii`ki `k.*``s``s`ks ``s`k`s`ks``s``s`ks``s`k`s`kr``s`k`sikk `k``s`ksk EOT #str = "````skk.ai" #str = "`c``s`kr``si`ki" #str = "`d`ri" #str = "``d`.aii" #str = "````.a.b.c.di" #str = "`.a`vi" #str = "`|`@i" intp = UnlambdaInterpriter.new intp.eval(str) end