erlang: guard BIFs + call dispatch (+20 tests)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
This commit is contained in:
@@ -96,6 +96,7 @@
|
||||
(= ty "block") (er-eval-body (get node :exprs) env)
|
||||
(= ty "if") (er-eval-if node env)
|
||||
(= ty "case") (er-eval-case node env)
|
||||
(= ty "call") (er-eval-call node env)
|
||||
(= ty "match") (er-eval-match node env)
|
||||
:else (error (str "Erlang eval: unsupported node type '" ty "'"))))))
|
||||
|
||||
@@ -439,3 +440,119 @@
|
||||
(er-truthy? (er-eval-expr (nth conj i) env))
|
||||
(er-eval-guard-conj-iter conj (+ i 1) env)
|
||||
false))))
|
||||
|
||||
;; ── function calls ───────────────────────────────────────────────
|
||||
(define
|
||||
er-eval-call
|
||||
(fn
|
||||
(node env)
|
||||
(let
|
||||
((fun (get node :fun)) (args (get node :args)))
|
||||
(cond
|
||||
(= (get fun :type) "atom")
|
||||
(er-eval-local-call (get fun :value) args env)
|
||||
(= (get fun :type) "remote")
|
||||
(er-eval-remote-call
|
||||
(get (get fun :mod) :value)
|
||||
(get (get fun :fun) :value)
|
||||
args
|
||||
env)
|
||||
:else (error "Erlang: unsupported call target")))))
|
||||
|
||||
(define
|
||||
er-eval-args
|
||||
(fn
|
||||
(args env)
|
||||
(let
|
||||
((out (list)))
|
||||
(for-each
|
||||
(fn (i) (append! out (er-eval-expr (nth args i) env)))
|
||||
(range 0 (len args)))
|
||||
out)))
|
||||
|
||||
(define
|
||||
er-eval-local-call
|
||||
(fn
|
||||
(name args env)
|
||||
(let
|
||||
((vs (er-eval-args args env)))
|
||||
(er-apply-bif name vs))))
|
||||
|
||||
(define
|
||||
er-eval-remote-call
|
||||
(fn
|
||||
(mod name args env)
|
||||
(error
|
||||
(str "Erlang: undefined function '" mod ":" name "/" (len args) "'"))))
|
||||
|
||||
;; ── BIFs ─────────────────────────────────────────────────────────
|
||||
(define
|
||||
er-apply-bif
|
||||
(fn
|
||||
(name vs)
|
||||
(cond
|
||||
(= name "is_integer") (er-bif-is-integer vs)
|
||||
(= name "is_atom") (er-bif-is-atom vs)
|
||||
(= name "is_list") (er-bif-is-list vs)
|
||||
(= name "is_tuple") (er-bif-is-tuple vs)
|
||||
(= name "is_number") (er-bif-is-number vs)
|
||||
(= name "is_float") (er-bif-is-float vs)
|
||||
(= name "is_boolean") (er-bif-is-boolean vs)
|
||||
:else (error
|
||||
(str "Erlang: undefined function '" name "/" (len vs) "'")))))
|
||||
|
||||
(define
|
||||
er-bif-arg1
|
||||
(fn
|
||||
(vs name)
|
||||
(if
|
||||
(= (len vs) 1)
|
||||
(nth vs 0)
|
||||
(error (str "Erlang: " name ": wrong arity")))))
|
||||
|
||||
(define
|
||||
er-bif-is-integer
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "is_integer")))
|
||||
(er-bool (and (= (type-of v) "number") (integer? v))))))
|
||||
|
||||
(define
|
||||
er-bif-is-atom
|
||||
(fn (vs) (er-bool (er-atom? (er-bif-arg1 vs "is_atom")))))
|
||||
|
||||
(define
|
||||
er-bif-is-list
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "is_list")))
|
||||
(er-bool (or (er-nil? v) (er-cons? v))))))
|
||||
|
||||
(define
|
||||
er-bif-is-tuple
|
||||
(fn (vs) (er-bool (er-tuple? (er-bif-arg1 vs "is_tuple")))))
|
||||
|
||||
(define
|
||||
er-bif-is-number
|
||||
(fn
|
||||
(vs)
|
||||
(er-bool (= (type-of (er-bif-arg1 vs "is_number")) "number"))))
|
||||
|
||||
(define
|
||||
er-bif-is-float
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "is_float")))
|
||||
(er-bool (and (= (type-of v) "number") (not (integer? v)))))))
|
||||
|
||||
(define
|
||||
er-bif-is-boolean
|
||||
(fn
|
||||
(vs)
|
||||
(let
|
||||
((v (er-bif-arg1 vs "is_boolean")))
|
||||
(er-bool
|
||||
(or (er-is-atom-named? v "true") (er-is-atom-named? v "false"))))))
|
||||
|
||||
Reference in New Issue
Block a user