flan/test/programs/char-arith.flan

64 lines
2.4 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, with "dyn" a dyn char below zero does, and
;;;; with "u64" a char plus the largest u64 does rather than wrapping round,
;;;; and with "i64" and "dyn-i64" a char plus the largest i64 does, naming it.
(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))
;; A char minus a char where an integer is wanted is that integer.
(defn digit [c char] i32 (- c \0))
(defn gap [a char b char] u8 (- a b))
(defn gaps [a char b char] i32
(let [v (vec-new i32)]
(push v (- a b))
(+ (- a b) (at v 0) 1)))
(defn plus-u64 [c char n u64] char (+ c n))
(defn plus-i64 [c char n i64] char (+ c n))
(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 \é))
(println (digit \7) (gap \c \a) (gaps \c \a) (plus-u64 \a (u64 2)))
;; Longer chains fold left, each step by its own operands.
(println (- \z \a 1) (+ 1 2 \a) (- \z 1 \a))
;; += 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)))
(= (at args 1) "u64")
(println (plus-u64 \a (- (u64 0) (u64 (- k 1)))))
(= (at args 1) "i64")
(println (plus-i64 \a (- (max-value i64) (i64 (- k 2)))))
(= (at args 1) "dyn-i64")
(println (add \a (- (max-value i64) (i64 (- k 2)))))
:else
(println (sub \a (* k 100))))))
0)