#(c) Copyright 2008 Darren Smith. All Rights Reserved. $lb = [] class Gtype def go $stack<(rhs) @val<=>rhs.val end end class Gint < Gtype def initialize(i) @val = case i when true then 1 when false then 0 else;i end end def factory(a) Gint.new(a) end def to_gs Gstring.new(@val.to_s) end def to_int #for pack @val end def ginspect to_gs end def class_id; 0; end def coerce(b) [if b.class == Garray Garray.new([self]) elsif b.class == Gstring to_gs else #Gblock to_gs.to_s.compile end,b] end def ~ Gint.new(~@val) end def notop Gint.new(@val == 0) end '*/%<>'.each_byte{|i| eval'def %c(rhs) Gint.new(@val %c rhs.val) end'%[i,i] } def equalop(rhs) Gint.new(@val == rhs.val) end def question(b) Gint.new(@val**b.val) end def base(a) if Garray===a r=0 a.val.each{|i| r*=@val r+=i.val } Gint.new(r) else i=a.val.abs r=[] while i!=0 r.unshift Gint.new(i%@val) i/=@val end Garray.new(r) end end def leftparen Gint.new(@val-1) end def rightparen Gint.new(@val+1) end end class Garray < Gtype def initialize(a) @val = a end def factory(a) Garray.new(a) end def to_gs @val.inject(Gstring.new("")){|s,i|s+i.to_gs} end def flatten #maybe name to_a ? Garray.new(@val.inject([]){|s,i|s+case i when Gstring then i.val when Gint then [i] when Garray then i.flatten.val when Gblock then i.val end }) end def ginspect Gstring.new('[')+Garray.new(@val.map{|i|i.ginspect})*Gstring.new(' ')+Gstring.new(']') end def go $stack<(b) if b.class == Gint factory(@val[[b.val,-@val.size].max..-1]) else Gint.new(@val>b.val) end end def sort factory(@val.sort) end def zip r=[] @val.size.times{|x| @val[x].val.size.times{|y| (r[y]||=@val[0].factory([])).val<<@val[x].val[y] } } Garray.new(r) end def ~ val end end class Gstring < Garray def initialize(a) @val=case a when String then a.unpack('C*').map{|i|Gint.new(i)} when Array then a when Garray then a.flatten.val end end def factory(a) Gstring.new(a) end def to_gs self end def ginspect factory(to_s.inspect) end def to_s @val.pack('C*') end def class_id; 2; end def coerce(b) if b.class == Gblock [to_s.compile,b] else b.coerce(self).reverse end end def ~ to_s.compile.go nil end end class Gblock < Garray def initialize(a,b=nil) @val=Gstring.new(b).val @native = eval("lambda{#{a}}") end def go @native.call end def factory(b) Gstring.new(b).to_s.compile end def class_id; 3; end def to_gs Gstring.new("{"+Gstring.new(@val).to_s+"}") end def ginspect to_gs end def coerce(b) b.coerce(self).reverse end def +(b) if b.class != self.class a,b=coerce(b) a+b else Gstring.new(@val+Gstring.new(" ").val+b.val).to_s.compile end end def *(b) if b.class == Gint b.val.times{go} else gpush b.val.first (b.val[1..-1]||[]).each{|i|$stack<','gpush a>b'.order var'!','gpush a.notop'.cc1 var'?','gpush a.question(b)'.order var'$','gpush (a.class==Gint ? $stack[~a.val] : a.sort)'.cc1 var',','gpush case a when Gint then Garray.new([*0...a.val].map{|i|Gint.new(i)}) when Gblock then a.select(gpop) when Garray then Gint.new(a.val.size) end'.cc1 var')','gpush a.rightparen'.cc1 var'(','gpush a.leftparen'.cc1 var'rand','gpush Gint.new(rand([1,a.val].max))'.cc1 var'abs','gpush Gint.new(a.val.abs)'.cc1 var'print','print a.to_gs'.cc1 var'if',"#{var'!'}.go;(gpop.val==0?a:b).go".cc2 var'do',"loop{a.go; #{var'!'}.go; break if gpop.val!=0}".cc1 var'while',"loop{a.go; #{var'!'}.go; break if gpop.val!=0; b.go}".cc2 var'until',"loop{a.go; #{var'!'}.go; break if gpop.val==0; b.go}".cc2 var'zip','gpush a.zip'.cc1 var'base','gpush b.base(a)'.cc2 '"\n":n; {print n print}:puts; {`puts}:p; {1$if}:and; {1$\if}:or; {\!!{!}*}:xor; '.compile.go code.compile.go gpush Garray.new($stack) 'puts'.compile.go