jank
jank copied to clipboard
Start analyzing & evaluating `meta`
Description
We should begin analyzing the metadata as well. At present, we store the metadata source directly without proper analysis or evaluation, resulting in the following code executing despite being semantically incorrect:
user=> (def ^{:pp #(println foo)} bar 0)
#'user/bar
user=> (meta bar)
nil
user=> (meta #'bar)
{:jank/source {:file "/var/folders/xd/9v1dcg0d46l7d19830vq0lhc0000gn/T/jank-repl-fYkERF", :start {:offset 27, :line 1, :col 28}, :end {:offset 30, :line 1, :col 31}}, :pp (fn* [] (println foo))}
user=> ((-> #'bar meta :pp))
Uncaught exception: Invalid call with 0 args to: (fn* [] (println foo))
There are two issues being highlighted here:
- Although the
foosymbol is not in scope during the definition of thebarvar, jank does not emit any analysis failure warnings. - Due to lack of evaluation currently the
:ppkey in the metadata of thebarvar contains the source code instead of a compiled function, preventing us from invoking the function.
Goal
Within the scope of this PR I wish to start analyzing the metadata such that the above cases behave as would be expected:
user=> (def ^{:pp #(println foo)} bar 0)
─ analyze/unresolved-symbol ────────────────────────────────────────────────────────────────────────
error: Unable to resolve symbol 'foo'.
─────┬──────────────────────────────────────────────────────────────────────────────────────────────
│ /var/folders/xd/9v1dcg0d46l7d19830vq0lhc0000gn/T/jank-repl-hKkVT2
─────┼──────────────────────────────────────────────────────────────────────────────────────────────
1 │ (def ^{:pp #(println foo)} bar 0)
│ ^^^ Found here.
─────┴──────────────────────────────────────────────────────────────────────────────────────────────
user=> (def foo 0)
#'user/foo
user=> (def ^{:pp #(println foo)} bar 0)
#'user/bar
user=> (meta #'bar)
{:jank/source {:file "/var/folders/xd/9v1dcg0d46l7d19830vq0lhc0000gn/T/jank-repl-hKkVT2", :start {:offset 27, :line 1, :col 28}, :end {:offset 30, :line 1, :col 31}}, :pp #object [user/user-fn-53 jit_function 0x10ec383f8]}
user=> ((-> #'bar meta :pp))
0
nil
Fixes
Resolves https://github.com/jank-lang/jank/issues/197.
Currently the following doesn't work:
(let* [foo 42]
(def ^{:pp #(println foo)} bar 0)
(assert (= ((-> #'bar meta :pp)) 42)))
But before I dive deeper I thought best align on where to store the analysis results for meta.