flan/test/programs/char-arith.flan

44 lines
1.5 KiB
Plaintext

;;;; Char arithmetic (decision 131, Kotlin's rules): a char plus or minus an
;;;; integer is a char, an integer plus a char is too, and a char minus a char
;;;; is the distance, an i32. Dyn chars do the same. Byte code beside it is
;;;; unchanged. With "past" a char past U+10FFFF traps, with "surrogate" one
;;;; landing on a surrogate does, and with "dyn" a dyn char below zero does.
(defn show [x] () (println x))
(defn add [a b] dyn (+ a b))
(defn sub [a b] dyn (- a b))
(defn upper [c char] char (if (and (>= c \a) (<= c \z)) (- c 32) c))
(defn main [args [str]] i32
;; The fork case with arithmetic: a let-bound char stays a char.
(let [c \a]
(show c)
(show (+ c 1)))
;; Each rule, typed.
(let [c (char 100)
n 3]
(println (+ c n) (+ n c) (- c n) (- c \a) (- \a \A) (+ \a 1 1)))
(println (upper \q) (upper \Q) (upper \é))
;; += and -= on a char local.
(let [c \a]
(set c (+ c 2))
(set c (- c 1))
(println c))
;; Dyn chars follow the same rules.
(println (add \a 1) (add 1 \a) (sub \z 1) (sub \a \A) (add (char 120) (the dyn 2)))
;; Byte code: a char difference where a byte is wanted is a byte.
(let [b (u8 65)
v (vec-new u8)]
(push v (+ b (- \a \A)))
(println (at v 0) (= (at v 0) \a)))
(when (> (length args) 1)
(let [k (length args)]
(cond
(= (at args 1) "past")
(println (+ (char 0x10FFFF) (- k 1)))
(= (at args 1) "surrogate")
(println (+ (char 0xD7FF) (- k 1)))
:else
(println (sub \a (* k 100))))))
0)