(input) (output "logical: 1 1 0" "bitwise: 7 2 5" "shifts: 48 0 12" "increment: 7" "decayed: 2 2 there" "unsigned wins either way: 4294967295 4294967295" "toplevel: 1 2.5 hi 12" "closure in place: 5" "a type is not a call: 7") (return 0) ;;; The walk types an expression by its head, and the heads it had a ;;; rule for were the ones inference was written against. `&&', the ;;; bitwise operators, the shifts and `++' were not among them and each ;;; stopped with `cannot infer'. ;;; ;;; The rest of this is the same mistake in three other places: an array ;;; is a pointer the moment it is an operand, a rank tie is not decided ;;; by which operand was written first, and `_' is not a local's ;;; privilege. (include stdio.h) (fn area ((w int) (h int)) int (return (* w h))) ;;; a toplevel `_' reads the same table a local's does, so it can name ;;; anything declared above it (var n _ 1) (var d _ 2.5) (var s _ "hi") (var a _ (+ 3 (* 3 3))) (fn make-adder ((k int)) (closure ((int)) int) (return (closure ((b int)) int (k) (return (+ k b))))) (pub fn main () int (var x int 6) (var y int 3) (var ok _ (&& x y)) (var orr _ (|| x y)) (var neg _ (! x)) (printf "logical: %d %d %d\n" ok orr neg) (var bor _ (| x y)) (var band _ (& x y)) (var bxor _ (^ x y)) (printf "bitwise: %d %d %d\n" bor band bxor) ;; a shift is the promoted left operand, not a join: the right one ;; says only how far (var c char 12) (var shl _ (<< x y)) (var shr _ (>> x y)) (var wide _ (>> c 0)) (printf "shifts: %d %d %d\n" shl shr wide) ;; ...and an increment is the operand, unpromoted (var inc _ (++ x)) (printf "increment: %d\n" inc) ;; an array operand decays, so this is a pointer and not an array (var xs (¤ int 4) #(1 2 3 4)) (var p _ (+ xs 1)) (var q _ (+ 1 xs)) (var names (¤ (* const char) 2) #("hi" "there")) (var np _ (+ names 1)) (printf "decayed: %d %d %s\n" (* p) (* q) (* np)) ;; at equal rank C takes the unsigned operand, whichever side it is on (var i int -1) (var u (unsigned int) 1) (var u1 _ (+ i u)) (var u2 _ (+ u i)) (printf "unsigned wins either way: %u %u\n" (- u1 1) (- u2 1)) (printf "toplevel: %d %g %s %d\n" n d s a) ;; a closure literal is its own type, so it can be called where it is ;; written, the way a lambda already could (printf "closure in place: %d\n" ((closure ((v int)) int () (return v)) 5)) ;; a `fn' type's parameter list looks exactly like a call; with a ;; closure named `f' in scope it used to be read as one (var f (closure ((int)) int) (make-adder 1)) (var fp (fn ((f int) (g int)) int) area) (printf "a type is not a call: %d\n" (f 6)) (return 0))