diff --git a/NEXT.md b/NEXT.md index 64e53d6..f2e0393 100644 --- a/NEXT.md +++ b/NEXT.md @@ -1621,14 +1621,15 @@ The shape it wants: accessors. That is the real work, and it is bigger than the expander itself: the compiler and the compiled macro have to agree on the *layout* of a `Form`, not merely its shape, so whatever the checker does for unions has to - be exact here. Until unions are values this cannot start; that is milestone 6 - work landing before milestone 5's. -2. **Expansion is a pass between `Parse` and `Check`**, over `Ast`, not over - `Form` — or, better, over `Form` before `Parse` ever runs, which is why - `Parse` refusing `defmacro` rather than storing it is not a dead end: the - expander runs first and `Parse` never sees a macro call at all. That is the - Clojure ordering and the one to prefer, because a macro expanding to a - special form is then ordinary rather than a special case. + be exact here. Until unions are values this cannot start — `check.ml` puts + union values and `match` on a union at **milestone 6**, so that is milestone + 6 work landing before milestone 5's. +2. **Expansion runs over `Form`, before `Parse`.** Not a pass over `Ast`: + there is no `Ast.Defmacro` and `Parse` refuses `defmacro` outright, so an + `Ast`-level pass would have nothing to work with. That refusal is not a dead + end, it is the ordering — the expander runs first and `Parse` never sees a + macro call at all. It is also the Clojure ordering, and the reason a macro + expanding to a special form is ordinary rather than a special case. 3. **Order matters and files do not have one.** Top-level names in a package are order-independent everywhere else (`declared_types`, the constant fixpoint in `check.ml`). Macros cannot be: a macro must be compiled and diff --git a/test/test_flan.ml b/test/test_flan.ml index 54a7edc..7b1c6d3 100644 --- a/test/test_flan.ml +++ b/test/test_flan.ml @@ -113,6 +113,7 @@ let () = reads "quote in quasi" "`(a 'b)" "(quasiquote (a (quote b)))"; (* The delimiter half of the fix: without it ~x is one symbol named "~x". *) reads "tilde ends a name" "(f a~b)" "(f a (unquote b))"; + reads "backtick ends a name" "(f a`b)" "(f a (quasiquote b))"; reads "backtick in vec" "[`a ~b]" "[(quasiquote a) (unquote b)]"; (* The whole class: no reader-significant character may end up inside a name. *) @@ -127,7 +128,7 @@ let () = in let corpus = "(invoke-restart 'skip-form) (a 'b [c 'd] {:e 'f}) '(g 'h) \ - `(i ~j ~@k) `(l `(m ~n)) [`o ~p] {:q `r}" + `(i ~j ~@k) `(l `(m ~n)) [`o ~p] {:q `r} (f a~b x`y)" in check "no sigils leak into names" (bad_names (Form.make (Form.List (Reader.read_all ~file:"" corpus))