(define lua-truthy? (fn (v) (and (not (= v nil)) (not (= v false))))) (define lua-to-number (fn (v) (cond ((= (type-of v) "number") v) ((= (type-of v) "string") (let ((n (parse-number v))) (if (= n nil) nil n))) (else nil)))) (define lua-to-string (fn (v) (cond ((= v nil) "nil") ((= v true) "true") ((= v false) "false") ((= (type-of v) "number") (str v)) ((= (type-of v) "string") v) (else (str v))))) (define lua-num-op (fn (op a b) (let ((na (lua-to-number a)) (nb (lua-to-number b))) (begin (when (or (= na nil) (= nb nil)) (error (str "lua: arith on non-number: " a " " op " " b))) (cond ((= op "+") (+ na nb)) ((= op "-") (- na nb)) ((= op "*") (* na nb)) ((= op "/") (/ na nb)) ((= op "%") (- na (* nb (floor (/ na nb))))) ((= op "^") (pow na nb)) (else (error (str "lua: unknown arith op " op)))))))) (define lua-add (fn (a b) (lua-num-op "+" a b))) (define lua-sub (fn (a b) (lua-num-op "-" a b))) (define lua-mul (fn (a b) (lua-num-op "*" a b))) (define lua-div (fn (a b) (lua-num-op "/" a b))) (define lua-mod (fn (a b) (lua-num-op "%" a b))) (define lua-pow (fn (a b) (lua-num-op "^" a b))) (define lua-neg (fn (a) (let ((na (lua-to-number a))) (begin (when (= na nil) (error (str "lua: neg on non-number: " a))) (- 0 na))))) (define lua-concat-coerce (fn (v) (cond ((= (type-of v) "string") v) ((= (type-of v) "number") (str v)) (else (error (str "lua: cannot concat " v)))))) (define lua-concat (fn (a b) (let ((sa (lua-concat-coerce a)) (sb (lua-concat-coerce b))) (str sa sb)))) (define lua-eq (fn (a b) (cond ((and (= a nil) (= b nil)) true) ((or (= a nil) (= b nil)) false) ((and (= (type-of a) (type-of b)) (= a b)) true) (else false)))) (define lua-neq (fn (a b) (not (lua-eq a b)))) (define lua-lt (fn (a b) (cond ((and (= (type-of a) "number") (= (type-of b) "number")) (< a b)) ((and (= (type-of a) "string") (= (type-of b) "string")) (< a b)) (else (error "lua: attempt to compare incompatible types"))))) (define lua-le (fn (a b) (or (lua-lt a b) (lua-eq a b)))) (define lua-gt (fn (a b) (lua-lt b a))) (define lua-ge (fn (a b) (lua-le b a))) (define lua-len (fn (a) (cond ((= (type-of a) "string") (len a)) ((= (type-of a) "list") (len a)) ((= (type-of a) "dict") (let ((n 0)) (begin (define count-loop (fn (i) (if (has-key? a (str i)) (begin (set! n i) (count-loop (+ i 1))) n))) (count-loop 1)))) (else (error (str "lua: len on non-len type: " (type-of a))))))) (define lua-for-continue? (fn (i stop step) (if (> step 0) (<= i stop) (>= i stop)))) (define lua-make-table (fn (&rest fields) (let ((t {}) (array-idx 1)) (begin (define process (fn (fs) (when (> (len fs) 0) (begin (let ((f (first fs))) (cond ((= (first f) "pos") (begin (set! t (assoc t (str array-idx) (nth f 1))) (set! array-idx (+ array-idx 1)))) ((= (first f) "kv") (let ((k (nth f 1)) (v (nth f 2))) (set! t (assoc t (str k) v)))))) (process (rest fs)))))) (process fields) t)))) (define lua-get (fn (t k) (if (= t nil) nil (let ((v (get t (str k)))) (if (= v nil) nil v))))) (define lua-set! (fn (t k v) (dict-set! t (str k) v))) (define lua-multi? (fn (v) (and (= (type-of v) "list") (> (len v) 0) (= (first v) (quote lua-multi))))) (define lua-first (fn (v) (cond ((lua-multi? v) (if (> (len v) 1) (nth v 1) nil)) (else v)))) (define lua-nth-ret (fn (v i) (cond ((lua-multi? v) (let ((idx (+ i 1))) (if (< idx (len v)) (nth v idx) nil))) (else (if (= i 0) v nil))))) (define lua-pack-build (fn (vals i) (cond ((>= i (len vals)) (list)) ((= i (- (len vals) 1)) (let ((last (nth vals i))) (if (lua-multi? last) (rest last) (list last)))) (else (cons (nth vals i) (lua-pack-build vals (+ i 1))))))) (define lua-pack-return (fn (vals) (cond ((= (len vals) 0) (list (quote lua-multi))) (else (cons (quote lua-multi) (lua-pack-build vals 0))))))