mirror of
https://github.com/carp-lang/Carp.git
synced 2024-09-17 08:27:45 +03:00
2701517753
* fix: don't expand inner module macros on first pass; privacy This commit changes the behavior of expansions to avoid expanding module expressions until we're actually processing the module in question. Previously, the following form would be entirely expanded at the time of evaluating A: ```clojure (defmodule A <- current environment (some-macro) <- expand (defmodule B (some-macro f) <- expand, current env is A, *NOT* B. so if this expands to (private f) (defn f ....) the f of the expansion is added to *A*, and we have a duplicate ghost binder. ) (defn foo [] B.f) <- expand, B.f does not exist yet, any meta on the binding will be ignored, permitting privacy errors since expansion ignores undefined bindings, instead, we'll look this up at eval time, and not check privacy as doing so would cause problems for legitimate cases. ) ``` This meant that if the macro happened to have side-effects, e.g. calling `meta-set!` we'd produce side-effects in the wrong environment, A, resulting in duplicate bindings, missing bindings at evaluation time, and other problems. Now, we instead process the form as follows: ```clojure (defmodule A <- current environment (some-macro) <- expand (defmodule B (some-macro f) <- wait ) (defn foo [] B.f) ) ;; step 2 (defmodule A (foo-bar ) <- previously expanded macro (defmodule B <- current environment (some-macro f) <- expand ) .... ) ``` In general, this prevents the generation of a bunch of unintentional and incorrectly added bindings when calling `meta-set!` from various macros. Additionally, privacy constraints are now carried across nested modules: ``` (defmodule A (defmodule B (private f) (defn f [] 0) ) (defn g [] (B.f)) ;; Privacy error! ) ``` This change also fixed an issue whereby recursive functions with `sig` annotations could trick the compiler. Again, this had to do with the unintentionally added bindings stemming from expansion of nested module expressions via meta-set. Fixes #1213, Fixes #467 * fix: ensure we check privacy against the path of found binders
9 lines
139 B
Plaintext
9 lines
139 B
Plaintext
(Project.config "file-path-print-length" "short")
|
|
(defmodule A
|
|
(defmodule B
|
|
(private f)
|
|
(defn f [] 1)
|
|
)
|
|
(defn g [] (B.f))
|
|
)
|