erlang: -module/M:F cross-module calls (+10 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:
@@ -742,3 +742,75 @@
|
||||
(er-proc-set! target :exit-result nil)
|
||||
(er-proc-set! target :continuation nil)
|
||||
(er-propagate-exit! target reason)))
|
||||
|
||||
;; ── module registry ─────────────────────────────────────────────
|
||||
;; Global mutable dict from module name -> module env (which itself
|
||||
;; binds each function name to a fun value capturing the same env, so
|
||||
;; sibling functions can call each other recursively).
|
||||
(define er-modules (list {}))
|
||||
(define er-modules-get (fn () (nth er-modules 0)))
|
||||
(define er-modules-reset! (fn () (set-nth! er-modules 0 {})))
|
||||
|
||||
;; Load an Erlang module declaration. Source must start with
|
||||
;; `-module(Name).` and contain function definitions. Functions
|
||||
;; sharing a name (different arities) get their clauses concatenated
|
||||
;; into a single fun value — `er-apply-fun-clauses` already filters
|
||||
;; by arity, so multi-arity dispatch falls out for free.
|
||||
(define
|
||||
erlang-load-module
|
||||
(fn
|
||||
(src)
|
||||
(let
|
||||
((module-ast (er-parse-module src)))
|
||||
(let
|
||||
((mod-name (get module-ast :name))
|
||||
(functions (get module-ast :functions))
|
||||
(mod-env (er-env-new))
|
||||
(by-name {}))
|
||||
(for-each
|
||||
(fn
|
||||
(i)
|
||||
(let
|
||||
((f (nth functions i)))
|
||||
(let
|
||||
((name (get f :name)) (clauses (get f :clauses)))
|
||||
(if
|
||||
(dict-has? by-name name)
|
||||
(let
|
||||
((existing (get by-name name)))
|
||||
(for-each
|
||||
(fn (j) (append! existing (nth clauses j)))
|
||||
(range 0 (len clauses))))
|
||||
(let
|
||||
((init (list)))
|
||||
(for-each
|
||||
(fn (j) (append! init (nth clauses j)))
|
||||
(range 0 (len clauses)))
|
||||
(dict-set! by-name name init))))))
|
||||
(range 0 (len functions)))
|
||||
(for-each
|
||||
(fn
|
||||
(k)
|
||||
(let
|
||||
((all-clauses (get by-name k)))
|
||||
(er-env-bind! mod-env k (er-mk-fun all-clauses mod-env))))
|
||||
(keys by-name))
|
||||
(dict-set! (er-modules-get) mod-name mod-env)
|
||||
(er-mk-atom mod-name)))))
|
||||
|
||||
(define
|
||||
er-apply-user-module
|
||||
(fn
|
||||
(mod name vs)
|
||||
(let
|
||||
((mod-env (get (er-modules-get) mod)))
|
||||
(if
|
||||
(not (dict-has? mod-env name))
|
||||
(raise
|
||||
(er-mk-error-marker
|
||||
(er-mk-tuple
|
||||
(list
|
||||
(er-mk-atom "undef")
|
||||
(er-mk-atom mod)
|
||||
(er-mk-atom name)))))
|
||||
(er-apply-fun (get mod-env name) vs)))))
|
||||
|
||||
Reference in New Issue
Block a user