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