`walk-parts' walked the whole `var' form, and a `fn' type's parameter list is shaped like a call: `(fn ((c int)) int)' came out as `int (*fp)(c int)'. A closure literal had no type, so calling one in place missed the rewrite; sextest fed sexc symbols Sex cannot read.
91 lines
2.7 KiB
Scheme
91 lines
2.7 KiB
Scheme
(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))
|