576c494e53 2010-11-27 kinaba: # Lift to types 576c494e53 2010-11-27 kinaba: @@type (x) 576c494e53 2010-11-27 kinaba: { 576c494e53 2010-11-27 kinaba: if _isint(x): "int" 576c494e53 2010-11-27 kinaba: else if _isstr(x): "str" 576c494e53 2010-11-27 kinaba: else if _isbot(x): "RE" 576c494e53 2010-11-27 kinaba: else if _istbl(x): 576c494e53 2010-11-27 kinaba: if x.?car && x.?cdr: 576c494e53 2010-11-27 kinaba: let xa = x.car in let xd = x.cdr in 576c494e53 2010-11-27 kinaba: mergeType( {list: @type(xa)}, @type(xd) ) 576c494e53 2010-11-27 kinaba: else 576c494e53 2010-11-27 kinaba: {list: "RE"} # tenuki 576c494e53 2010-11-27 kinaba: else ... da7559b744 2010-11-21 kinaba: }; da7559b744 2010-11-21 kinaba: 576c494e53 2010-11-27 kinaba: # unify two types 576c494e53 2010-11-27 kinaba: def mergeType(a, b) 576c494e53 2010-11-27 kinaba: { 576c494e53 2010-11-27 kinaba: if a == "RE": b 576c494e53 2010-11-27 kinaba: else if b == "RE": a 576c494e53 2010-11-27 kinaba: else if _istbl(a) && _istbl(b): 576c494e53 2010-11-27 kinaba: if a.?list && b.?list: 576c494e53 2010-11-27 kinaba: let rt = mergeType(a.list, b.list) in 576c494e53 2010-11-27 kinaba: if rt=="TE" || rt=="RE" then rt else {list: rt} 576c494e53 2010-11-27 kinaba: else: 576c494e53 2010-11-27 kinaba: "TE" # type error 576c494e53 2010-11-27 kinaba: else if a == b: a 576c494e53 2010-11-27 kinaba: else "TE" # type error 5afe8e3f26 2010-11-13 kinaba: }; 5afe8e3f26 2010-11-13 kinaba: 576c494e53 2010-11-27 kinaba: # helper function 576c494e53 2010-11-27 kinaba: def Tuni(t1, t0) 576c494e53 2010-11-27 kinaba: { 576c494e53 2010-11-27 kinaba: fun(x) {@value( 576c494e53 2010-11-27 kinaba: if @type(x)=="RE": "RE" 576c494e53 2010-11-27 kinaba: else if @type(x)=="TE": "TE" 576c494e53 2010-11-27 kinaba: else if @type(x)==t1: t0 576c494e53 2010-11-27 kinaba: else "TE" 576c494e53 2010-11-27 kinaba: )} 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 kinaba: def Tuniany(t0) 576c494e53 2010-11-27 kinaba: { 576c494e53 2010-11-27 kinaba: fun(x) {@value( 576c494e53 2010-11-27 kinaba: if @type(x)=="RE": "RE" 576c494e53 2010-11-27 kinaba: else if @type(x)=="TE": "TE" 576c494e53 2010-11-27 kinaba: else t0 576c494e53 2010-11-27 kinaba: )} 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 kinaba: def Tbin(t1, t2, t0) 576c494e53 2010-11-27 kinaba: { 576c494e53 2010-11-27 kinaba: fun(x,y) {@value( 576c494e53 2010-11-27 kinaba: if @type(x)=="RE" || @type(y)=="RE": "RE" 576c494e53 2010-11-27 kinaba: else if @type(x)=="TE" || @type(y)=="TE": "TE" 576c494e53 2010-11-27 kinaba: else if @type(x)==t1 && @type(y)==t2: t0 576c494e53 2010-11-27 kinaba: else "TE" 576c494e53 2010-11-27 kinaba: )} 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 kinaba: def Tbinany(t0) b993a8ad16 2010-11-24 kinaba: { 576c494e53 2010-11-27 kinaba: fun(x,y){@value( 576c494e53 2010-11-27 kinaba: if @type(x)=="RE" || @type(y)=="RE": "RE" 576c494e53 2010-11-27 kinaba: else if @type(x)=="TE" || @type(y)=="TE": "TE" 576c494e53 2010-11-27 kinaba: else t0 576c494e53 2010-11-27 kinaba: )} 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: # type annotation for built-in ops 576c494e53 2010-11-27 kinaba: @type "+" = Tbin("int", "int", "int"); 576c494e53 2010-11-27 kinaba: @type "-" = Tbin("int", "int", "int"); 576c494e53 2010-11-27 kinaba: @type "*" = Tbin("int", "int", "int"); 576c494e53 2010-11-27 kinaba: @type "/" = Tbin("int", "int", "int"); 576c494e53 2010-11-27 kinaba: @type "%" = Tbin("int", "int", "int"); 576c494e53 2010-11-27 kinaba: @type "&&" = Tbin("int", "int", "int"); 576c494e53 2010-11-27 kinaba: @type "||" = Tbin("int", "int", "int"); 576c494e53 2010-11-27 kinaba: @type print = fun(x){x}; 576c494e53 2010-11-27 kinaba: @type gensym = fun(){"str"}; 576c494e53 2010-11-27 kinaba: @type argv = {list: "str"}; 576c494e53 2010-11-27 kinaba: @type rand = Tuni("int","int"); 576c494e53 2010-11-27 kinaba: @type "~" = Tbinany("str"); 576c494e53 2010-11-27 kinaba: @type "<" = Tbinany("int"); 576c494e53 2010-11-27 kinaba: @type "<=" = Tbinany("int"); 576c494e53 2010-11-27 kinaba: @type ">" = Tbinany("int"); 576c494e53 2010-11-27 kinaba: @type ">=" = Tbinany("int"); 576c494e53 2010-11-27 kinaba: @type "==" = Tbinany("int"); 576c494e53 2010-11-27 kinaba: @type "!=" = Tbinany("int"); 576c494e53 2010-11-27 kinaba: @type "if" (c,t,e) {@value( 576c494e53 2010-11-27 kinaba: if @type(c)=="RE": "RE" 576c494e53 2010-11-27 kinaba: else if @type(c)!="int": "TE" 576c494e53 2010-11-27 kinaba: else mergeType( @type(t()), @type(e()) ); 576c494e53 2010-11-27 kinaba: )}; 576c494e53 2010-11-27 kinaba: @type _isint = Tuniany("int"); 576c494e53 2010-11-27 kinaba: @type _isstr = Tuniany("int"); 576c494e53 2010-11-27 kinaba: @type _isfun = Tuniany("int"); 576c494e53 2010-11-27 kinaba: @type _istbl = Tuniany("int"); 576c494e53 2010-11-27 kinaba: @type _isbot = Tuniany("int"); 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: ################################### 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: # for lists 576c494e53 2010-11-27 kinaba: @type "{}"() {@value( {list: "RE"} )}; 576c494e53 2010-11-27 kinaba: @type ".?"(t, s) {@value( 576c494e53 2010-11-27 kinaba: if @type(t)=="RE": "RE" 576c494e53 2010-11-27 kinaba: else if @type(t)=="TE": "TE" 576c494e53 2010-11-27 kinaba: else if _istbl( @type(t) ): "int" 576c494e53 2010-11-27 kinaba: else "TE" 576c494e53 2010-11-27 kinaba: )}; 576c494e53 2010-11-27 kinaba: @type ".="(t, s@value, v) {@value( 576c494e53 2010-11-27 kinaba: var tt = @type(t); 576c494e53 2010-11-27 kinaba: if tt == "TE": "TE" 576c494e53 2010-11-27 kinaba: else if tt == "RE": "RE" 576c494e53 2010-11-27 kinaba: else if _istbl(tt) && tt.?list: 576c494e53 2010-11-27 kinaba: if s == "car": 576c494e53 2010-11-27 kinaba: mergeType(tt, {list: @type(v)}) 576c494e53 2010-11-27 kinaba: else if s == "cdr": 576c494e53 2010-11-27 kinaba: mergeType(tt, @type(v)) 576c494e53 2010-11-27 kinaba: else: 576c494e53 2010-11-27 kinaba: tt 576c494e53 2010-11-27 kinaba: else: 576c494e53 2010-11-27 kinaba: "TE" 576c494e53 2010-11-27 kinaba: )}; 576c494e53 2010-11-27 kinaba: @type "."(t, s@value) {@value( 576c494e53 2010-11-27 kinaba: var tt = @type(t); 576c494e53 2010-11-27 kinaba: if tt == "TE": "TE" 576c494e53 2010-11-27 kinaba: else if tt == "RE": "RE" 576c494e53 2010-11-27 kinaba: else if _istbl(tt) && tt.?list: 576c494e53 2010-11-27 kinaba: if s == "car": 576c494e53 2010-11-27 kinaba: tt.list 576c494e53 2010-11-27 kinaba: else if s == "cdr": 576c494e53 2010-11-27 kinaba: tt 576c494e53 2010-11-27 kinaba: else: 576c494e53 2010-11-27 kinaba: "TE" 576c494e53 2010-11-27 kinaba: else: 576c494e53 2010-11-27 kinaba: "TE" 576c494e53 2010-11-27 kinaba: )}; 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: ################################### 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: def fib(x) { if x < 2 then 1 else fib(x-1) + fib(x-2) }; 576c494e53 2010-11-27 kinaba: def fibE1(x) { if "true!" then 1 else fib(x-1) + fib(x-2) }; 576c494e53 2010-11-27 kinaba: def fibE2(x) { if x<2 then "ichi" else fib(x-1) + fib(x-2) }; 576c494e53 2010-11-27 kinaba: def fibE3(x) { if x<2 then 1 else fib(x-1) ~ fib(x-2) }; 576c494e53 2010-11-27 kinaba: def fibS(x) { if x<2 then "1" else fib(x-1) ~ fib(x-2) }; 576c494e53 2010-11-27 kinaba: def fibBadButTypeIsOK(x) { if x < "2" then 1 else fib(x-1) + fib(x-2) }; 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: print( @type(fib(999)) ); 576c494e53 2010-11-27 kinaba: print( @type(fibE1(999)) ); 576c494e53 2010-11-27 kinaba: print( @type(fibE2(999)) ); 576c494e53 2010-11-27 kinaba: print( @type(fibE3(999)) ); 576c494e53 2010-11-27 kinaba: print( @type(fibS(999)) ); 576c494e53 2010-11-27 kinaba: print( @type(fibBadButTypeIsOK(999)) ); 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: ################################### 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: def nil = {}; 576c494e53 2010-11-27 kinaba: def cons(a, d) { {car: a, cdr: d} }; 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: print( @type(nil) ); 576c494e53 2010-11-27 kinaba: print( @type(cons(1,nil)) ); 576c494e53 2010-11-27 kinaba: print( @type(cons("foo",nil)) ); 576c494e53 2010-11-27 kinaba: print( @type(cons(123, cons("foo",nil))) ); # TE 576c494e53 2010-11-27 kinaba: 576c494e53 2010-11-27 kinaba: def rev(xs) { 576c494e53 2010-11-27 kinaba: def revi(xs, ys) { 576c494e53 2010-11-27 kinaba: case xs 576c494e53 2010-11-27 kinaba: when {car: x, cdr: xs}: revi(xs, cons(x,ys)) 576c494e53 2010-11-27 kinaba: when {}: ys 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 kinaba: revi(xs, {}) b993a8ad16 2010-11-24 kinaba: }; b993a8ad16 2010-11-24 kinaba: 576c494e53 2010-11-27 kinaba: var xs = cons(1, cons(2, cons(3, nil))); 576c494e53 2010-11-27 kinaba: print( @type( rev(xs) ) );