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 ... 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 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 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 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: )} b993a8ad16 2010-11-24 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: )} da7559b744 2010-11-21 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: )} 5afe8e3f26 2010-11-13 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 88827b8336 2010-12-02 kinaba: @type + = Tbin("int", "int", "int"); 88827b8336 2010-12-02 kinaba: @type - = Tbin("int", "int", "int"); 88827b8336 2010-12-02 kinaba: @type * = Tbin("int", "int", "int"); 88827b8336 2010-12-02 kinaba: @type / = Tbin("int", "int", "int"); 88827b8336 2010-12-02 kinaba: @type % = Tbin("int", "int", "int"); 88827b8336 2010-12-02 kinaba: @type && = Tbin("int", "int", "int"); 88827b8336 2010-12-02 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"); 88827b8336 2010-12-02 kinaba: @type ~ = Tbinany("str"); 88827b8336 2010-12-02 kinaba: @type < = Tbinany("int"); 88827b8336 2010-12-02 kinaba: @type <= = Tbinany("int"); 88827b8336 2010-12-02 kinaba: @type > = Tbinany("int"); 88827b8336 2010-12-02 kinaba: @type >= = Tbinany("int"); 88827b8336 2010-12-02 kinaba: @type == = Tbinany("int"); 88827b8336 2010-12-02 kinaba: @type != = Tbinany("int"); 88827b8336 2010-12-02 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"} )}; 88827b8336 2010-12-02 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: )}; 88827b8336 2010-12-02 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: )}; 88827b8336 2010-12-02 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, {}) 576c494e53 2010-11-27 kinaba: }; 576c494e53 2010-11-27 kinaba: 3fb4d6f9ad 2010-11-30 kinaba: def str_app(xs, ys) { 3fb4d6f9ad 2010-11-30 kinaba: case xs 3fb4d6f9ad 2010-11-30 kinaba: when {car: x, cdr: xs}: cons(""~x, str_app(xs, ys)) 3fb4d6f9ad 2010-11-30 kinaba: when {}: ys 3fb4d6f9ad 2010-11-30 kinaba: }; 3fb4d6f9ad 2010-11-30 kinaba: 576c494e53 2010-11-27 kinaba: var xs = cons(1, cons(2, cons(3, nil))); 3fb4d6f9ad 2010-11-30 kinaba: var ys = cons("four", cons("five", cons("six", nil))); 576c494e53 2010-11-27 kinaba: print( @type( rev(xs) ) ); 3fb4d6f9ad 2010-11-30 kinaba: print( @type( rev(ys) ) ); 3fb4d6f9ad 2010-11-30 kinaba: print( @type( str_app(xs,ys) ) ); 3fb4d6f9ad 2010-11-30 kinaba: print( @type( str_app(xs,xs) ) );