Migrate to mcpyrate macro expander
Closed this issue · 5 comments
Migrate to the new mcpyrate
macro expander, because:
- correct test coverage reporting (less need for
# noqa
) - identifier macros, to make magic variables such as
it
that may only appear in certain contexts (and raise an error at macro expansion time otherwise) - advanced quasiquotes
- don't auto-expand macros inside quotes; may allow us to clean up some macro code
- can hygienically unquote macro names, too
- can define macros in the REPL, too
- integrated agile tools and dialect system (like
imacropy
andpydialect
, but developed slightly further)
It's a 3rd-gen expander (after macropy
and mcpy
), and by design, not drop-in compatible, so this will have to wait until 0.15.0.
mcpyrate
is now on PyPI.
Two steps:
- Port existing code to use
mcpyrate
with minimal changes. (To be done in 0.15.0.) - Exploit the new opportunities afforded by
mcpyrate
. (To be done later, possibly in 0.15.x or in 0.16.0.)
As of this writing, the latest released macropy3
(1.1.0b2) does not seem to run on Python 3.8 at all, so this migration just became top priority for the future development of unpythonic
.
Status (❌ = no, ✅ = yes):
✅ Boots up on Python 3.8 and mcpyrate
✅ Passes test suite on Python 3.8 and mcpyrate
✅ Final touches for initial version running on mcpyrate
As of ab9c836, done so far:
- Drop Python 3.4 and 3.5 support,
mcpyrate
runs on 3.6+. - Add support for Python 3.8 and 3.9.
- Drop
macropy3
bootstrapper. The solution is to usemacropython
frommcpyrate
instead. - Remove most mentions of
pydialect
; this technology is now part ofmcpyrate
. - Raise exception normally instead of
assert
when an error occurs during macro expansion (custom macro-related syntax errors, mostly). - Change macro interface call signatures to
mcpyrate
format. - Recurse explicitly in the syntax transformers.
- The code to pass in the
expander
argument viadyn
, so that the syntax transformer canexpander.visit(tree)
, is already in place in the macro interfaces.
- The code to pass in the
- Convert MacroPy
Walker
s intomcpyrate
AST walkers.- Port the scope analyzer.
expose_unhygienic
does not exist inmcpyrate
. Storedbgprint_expr
indyn
.- Update quasiquote code, especially parts using hygienic quasiquotes (
mcpyrate
's work slightly differently). - Implement
lazy
, which was previously provided by MacroPy. - Implement the
f[]
macro ofquick_lambda
, which was previously provided by MacroPy. - Update
quicklambda
documentation to match new implementation. @macro_stub
does not exist inmcpyrate
. Make a regular macro that raisesSyntaxError
.- Make some magic variables (such as anaphoric if's
it
), that error out at compile time when the name appears outside a meaningful context.the
in thetestingtools
modulecall_cc
incontinuations
local
,delete
indo
it
inaif
block
andexpr
inlet_syntax
/abbrev
q
,u
,kw
inprefix
block
andexpr
inlet_syntax
/abbrev
: for syntactic consistency, would be nice to pass their arguments using brackets. These are not actually macros, but AST patterns matched bylet_syntax
/abbrev
itself...mcpyrate
does not auto-expand macros in quasiquoted code. Consider when we should do so, and when let the expander iterate on its own. (We don't emit many macro invocations; the ones we do, should be correct.)- If macros need to invoke other macros in their output, use hygienic macro capture in the quasiquoted code.
- Investigate: do we still need to set
ctx
in our macros?- No, but we need to call
mcpyrate.astfixers.fix_ctx
when it is critical for the operation of some macro that thectx
are filled in correctly. Eliminated manualctx
filling and added those calls where needed.
- No, but we need to call
- Update macro docs: first pass → outside in and second pass → inside out.
mcpyrate
doesn't use a two-pass system, but performs outside-in iteration on each statement in the module until no macros remain; inside-out expansion must be explicitly asked for (by recursing explicitly). - Grep for any other interface changes for 0.15 I've forgotten about. Maybe move some of these to 0.16.
- Replace obsolete function calls:
gen_sym
switched tomcpyrate.gensym
unpythonic.syntax.util.splice
removed and switched tomcpyrate.splicing.splice_expression
macropy.tracing.show_expanded
switched tomcpyrate.debug.step_expansion
- Grep for any remaining mentions of MacroPy.
- Ones of historical interest left in; ones of current interest changed to point to
mcpyrate
.
- Ones of historical interest left in; ones of current interest changed to point to
- Update
setup.py
. - Update contribution guidelines.
Items postponed until later:
Consider movingisx
andgetname
fromunpythonic.syntax.nameutil
intomcpyrate
.- This is hardly the only project that needs to detect names and/or values of hygienic captures in the AST, so beside the low-level workhorse to get the actual data (
mcpyrate.quotes.is_captured_value
), maybemcpyrate
should present a friendly high-level interface, too. - Now there's also
is_unexpanded_expr_macro
andis_unexpanded_block_macro
. This is starting to look like the beginnings of a macro destructuring subsystem... - Also, consider making a simple AST pattern-matching utility; this would simplify AST analysis in macros.
- This stuff is important, but not for 0.15. Moving for later.
- This is hardly the only project that needs to detect names and/or values of hygienic captures in the AST, so beside the low-level workhorse to get the actual data (
Consider renaming 0.15 as 1.0.0.- Semantically, it's definitely 1.0, but the up-and-coming version has been known as "0.15" for such a long time (since 2019, maybe?) that maybe the number shouldn't be changed at this point.
- Decided: not changing the version at this time. Maybe "0.16" could be 1.0.
Remaining items have been documented in the TODO comments at the start of the module unpythonic.syntax.__init__
. It's a living development note that might not exactly match this occasionally updated one here in the issue comments.
As of ab9c836, we're "done enough" for a first version that runs on mcpyrate
and Python 3.6 through 3.9.