Files
sex/tests/sex-programs/operators.sex
alex-eg fe72a109bf read a var's type as a type, not as a call
`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.
2026-09-30 23:51:55 +03:00

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))