Two new dialects, esoteric and qualitatively different.
The dialects
unpythonic.dialects.bf— Brainfuck as a dialect. Source-to-source transpiler with legible Python output (bf.compile(src)returns the generated code as a string for inspection). 8-bit wrapping tape viadefaultdict[int, int];bfsource comments preserved as Python comments;resetline clears the tape between programs.unpythonic.dialects.befunge— Befunge-93 as a dialect. Runtime interpreter for a strict 80×25 toroidal playfield with byte cells and an unbounded-int stack. All Befunge-93 commands supported, including?(random direction; seedable viarun(src, *, seed=...)for tests),p/g(self-modifying code), and&/~(integer/character input). Thebf/befungepair demonstratesmcpyrate'sDialect.transform_sourcehook in two qualitatively different modes: dialect-as-transpiler (bf) and dialect-as-reader (befunge — Befunge's 2D self-modifying control flow has no statically-soundable structure).
Other new
expect[]— new expr macro for declaring the tested expression insidewith test:. Replacesreturn expr, which still works but emits aDeprecationWarningand will be un-hijacked in 3.0.0 soreturnregains its standard Python meaning insidewith test:.unpythonic.excutil.withf—withas a function. Expression form completing theraisef/tryf/withfsuite. Single CM or tuple; body arity auto-detected.@multishot,myield,myield_from,MultishotIterator— multi-shot generators. A@multishotfunction is generator-shaped but everymyieldcaptures the execution state as a continuation, so it can be resumed from any earliermyieldarbitrarily many times.MultishotIteratorexposes a subset of the standard generator protocol pluscopy.copy(mi)forking. Only meaningful insidewith continuations:. Closes #80.Valuesunpacking inunpythonic.funutil.callandcallwith. EachValuesin positional args expands in place (left-to-right), splicingretsinto positional args and mergingkwretsinto kwargs. Mirrors Python's[*a, *b, c]/{**a, **b}semantics.FrozenAttributeError— compatibility shim multiply inheriting fromTypeError(legacy) anddataclasses.FrozenInstanceError(stdlib convention). Raised byconson attribute write/delete. TheTypeErrorbase will be dropped in 3.0.0.redirect_stdin— context manager feedingsys.stdinfrom a stream. The third sibling ofcontextlib.redirect_stdout/stderr, which the stdlib never shipped.
Fixed
unpythonic.misc.callsite_filenamenow usessys._getframeinstead ofinspect.stack(). Latent PyPy-3.11 / macOS / Windows bug:inspect.stack()raisedTypeErrorwhen any frame in the walk reportedf_lineno = None.unpythonic.llist.cons.__delattr__now raisesFrozenAttributeError. Latent bug:del c.carpreviously corrupted the cell.unpythonic.assignoncenow forbidsdel e.fooon a defined name. Latent bug: the assign-once contract could be bypassed viadel; rebind.
Changed
lispython,listhell,pytkelldialects propagate the Python 3.8+ source-location fieldsend_lineno/end_col_offsetthroughsplice_dialectalongsidelineno/col_offset. Tooling that consumes precise source ranges (debuggers, PEP 657 traceback formatters) gets richer information. Closes #83.- Requires
mcpyrate >= 4.2.0.
Docs
doc/macros.md: new "Topology of continuations" and "Scoping of locals in continuations" subsections. Closes #82.
Milestone 2.2.0 complete. Closes #35, #76, #80, #82, #83, #85 (step 1; step 2 milestoned to 3.0.0), #86.