# Macro Enhancements — Test Requirements Maps each enhancement from `docs/macro-enhancements.md` to specific automated test cases. Slug: `macro-enh` --- ## Enhancement 1: Opcode Parameters ### macro-enh.E1.1: Grammar accepts `param_ref` in opcode position - **E1.1a Success:** `&r <| ${op}` parses without error inside a macro body - **E1.1b Success:** `${op} &src |> &dst` (strong_edge with param opcode) parses - **E1.1c Success:** `&dst ${op} <| &src` (weak_edge with param opcode) parses - **Test type:** Unit (parse + lower) - **File:** `tests/test_opcode_params.py` ### macro-enh.E1.2: Lower pass stores ParamRef in IRNode.opcode - **E1.2a Success:** After lowering a macro body with `${op}`, the IRNode has `opcode` as `ParamRef(param="op")` - **E1.2b Success:** Anonymous nodes from strong/weak edges with `${op}` also have ParamRef opcode - **Test type:** Unit (lower) - **File:** `tests/test_opcode_params.py` ### macro-enh.E1.3: OPCODE accepted as positional macro argument - **E1.3a Success:** `#reduce_2 add` parses — bare `add` in macro call argument position is accepted - **E1.3b Success:** Lower pass wraps the OPCODE token as a string `"add"` in `IRMacroCall.positional_args` - **Test type:** Unit (parse + lower) - **File:** `tests/test_opcode_params.py` ### macro-enh.E1.4: Expand pass resolves opcode ParamRef - **E1.4a Success:** Macro `#wrap op |> { &n <| ${op} }` invoked as `#wrap add` produces node with `opcode=ArithOp.ADD` - **E1.4b Success:** Macro invoked with `sub`, `gate`, `read` (different op types) all resolve correctly - **E1.4c Failure:** Macro invoked with `#wrap banana` produces MACRO error — invalid opcode mnemonic - **E1.4d Failure:** Macro invoked with `#wrap 42` (numeric, not opcode) produces MACRO error - **Test type:** Unit (expand) - **File:** `tests/test_opcode_params.py` ### macro-enh.E1.5: Full pipeline with opcode params - **E1.5a Success:** `#reduce_2 op |> { &r <| ${op} }` + `#reduce_2 add` assembles through full pipeline (parse → lower → expand → resolve → place → allocate → codegen) - **E1.5b Success:** Output PEConfig has correct ALUInst with ArithOp.ADD - **Test type:** Integration (full pipeline via `assemble()`) - **File:** `tests/test_opcode_params.py` --- ## Enhancement 2: Parameterized Placement and Port Qualifiers ### macro-enh.E2.1: Grammar accepts `param_ref` in placement position - **E2.1a Success:** `&n <| add |${pe}` parses inside macro body - **E2.1b Success:** Lower pass returns `ParamRef` (wrapped as `PlacementRef`) from placement handler - **Test type:** Unit (parse + lower) - **File:** `tests/test_qualified_ref_params.py` ### macro-enh.E2.2: Grammar accepts `param_ref` in port position - **E2.2a Success:** `&src |> &dst:${port}` parses inside macro body - **E2.2b Success:** Lower pass returns `ParamRef` (wrapped as `PortRef`) from port handler - **Test type:** Unit (parse + lower) - **File:** `tests/test_qualified_ref_params.py` ### macro-enh.E2.3: Context slot bracket syntax parses - **E2.3a Success:** `&node[2]` parses (literal context slot) - **E2.3b Success:** `&node|pe0[2]:L` parses (full qualifier chain) - **E2.3c Success:** `&node[${ctx}]` parses (parameterized context slot) - **E2.3d Success:** `&node[0..4]` parses (range reservation) - **Test type:** Unit (parse + lower) - **File:** `tests/test_qualified_ref_params.py` ### macro-enh.E2.4: Expand pass resolves placement ParamRef - **E2.4a Success:** Macro with `|${pe}` invoked with `pe0` places node on PE 0 - **E2.4b Success:** Macro with `|${pe}` invoked with `pe1` places node on PE 1 - **E2.4c Failure:** Macro invoked with `|${pe}` where arg is `"banana"` produces MACRO error - **Test type:** Unit (expand) - **File:** `tests/test_qualified_ref_params.py` ### macro-enh.E2.5: Expand pass resolves port ParamRef - **E2.5a Success:** Macro with `:${port}` invoked with `L` resolves to `Port.L` - **E2.5b Success:** Macro with `:${port}` invoked with `R` resolves to `Port.R` - **E2.5c Failure:** Macro invoked with invalid port value produces MACRO error - **Test type:** Unit (expand) - **File:** `tests/test_qualified_ref_params.py` ### macro-enh.E2.6: Expand pass resolves context slot ParamRef - **E2.6a Success:** Macro with `[${ctx}]` invoked with `2` resolves to ctx slot 2 - **E2.6b Failure:** Non-numeric ctx slot value produces MACRO error - **Test type:** Unit (expand) - **File:** `tests/test_qualified_ref_params.py` ### macro-enh.E2.7: Full pipeline with placement/port params - **E2.7a Success:** Macro parameterizing PE placement assembles through full pipeline; node placed on correct PE - **E2.7b Success:** Macro parameterizing port assembles through full pipeline; edge targets correct port - **Test type:** Integration (full pipeline) - **File:** `tests/test_qualified_ref_params.py` --- ## Enhancement 3: @ret Wiring for Macros ### macro-enh.E3.1: Grammar accepts output list on macro_call_stmt - **E3.1a Success:** `#macro args |> &dest` parses - **E3.1b Success:** `#macro args |> name=&dest` parses (named output) - **E3.1c Success:** `#macro args |> &a, &b` parses (multiple outputs) - **E3.1d Success:** `#macro args |> name1=&a, name2=&b` parses (multiple named outputs) - **Test type:** Unit (parse + lower) - **File:** `tests/test_macro_ret_wiring.py` ### macro-enh.E3.2: Lower pass stores output_dests on IRMacroCall - **E3.2a Success:** `IRMacroCall.output_dests` contains positional output refs - **E3.2b Success:** `IRMacroCall.output_dests` contains named output refs (name, ref) tuples - **Test type:** Unit (lower) - **File:** `tests/test_macro_ret_wiring.py` ### macro-enh.E3.3: Expand pass rewrites @ret edges - **E3.3a Success:** Macro body edge `&src |> @ret` becomes `&src |> &actual_dest` after expansion - **E3.3b Success:** Named `@ret_body` maps to `body=&dest` in call site output - **E3.3c Success:** Multiple @ret variants (e.g., `@ret_body` + `@ret_exit`) each map to their named outputs - **E3.3d Failure:** `@ret_body` in macro body but call site has no `body=` output → MACRO error - **E3.3e Failure:** Macro body has `@ret` but call site provides zero outputs → MACRO error - **E3.3f Success:** Positional @ret maps to first positional output - **Test type:** Unit (expand) - **File:** `tests/test_macro_ret_wiring.py` ### macro-enh.E3.4: @ret port preservation - **E3.4a Success:** `&src |> @ret:R` rewrites to `&src |> &dest:R` — port on @ret is preserved - **E3.4b Success:** `&src |> @ret_exit:R` also preserves port - **Test type:** Unit (expand) - **File:** `tests/test_macro_ret_wiring.py` ### macro-enh.E3.5: Nested macro @ret scoping - **E3.5a Success:** Macro A calls macro B which has @ret; B's @ret resolves at B's call site (inside A's body), A's @ret resolves at A's call site - **Test type:** Unit (expand) - **File:** `tests/test_macro_ret_wiring.py` ### macro-enh.E3.6: Full pipeline with @ret macros - **E3.6a Success:** Macro with @ret + call site output list assembles through full pipeline - **E3.6b Success:** Generated edges connect expanded macro internals to call-site-specified destinations - **Test type:** Integration (full pipeline) - **File:** `tests/test_macro_ret_wiring.py` --- ## Enhancement 4: Built-in Macro Rewrite ### macro-enh.E4.1: New builtins use opcode params - **E4.1a Success:** `#reduce_2 add` expands correctly (single node with ArithOp.ADD) - **E4.1b Success:** `#reduce_3 sub` expands correctly (two nodes with ArithOp.SUB, wired) - **E4.1c Success:** `#reduce_4 add` expands correctly (three nodes, tree structure) - **Test type:** Unit (expand) - **File:** `tests/test_builtins.py` ### macro-enh.E4.2: New builtins use @ret wiring - **E4.2a Success:** `#loop_counted |> body=&proc, exit=&done` wires @ret_body → &proc, @ret_exit → &done - **E4.2b Success:** `#loop_while |> body=&proc, exit=&done` wires similarly - **Test type:** Unit (expand) - **File:** `tests/test_builtins.py` ### macro-enh.E4.3: Backwards compatibility - **E4.3a:** Old macro names that are removed are documented in CHANGELOG or similar - **Test type:** Manual verification (pre-1.0, acceptable breakage) ### macro-enh.E4.4: Full pipeline with new builtins - **E4.4a Success:** Program using `#loop_counted |> body=&body, exit=&done` + `#reduce_2 add` assembles through full pipeline - **Test type:** Integration (full pipeline) - **File:** `tests/test_builtins.py` --- ## Human Verification ### macro-enh.HV1: dfgraph renders programs using new macros - Verify that dfgraph correctly visualises programs using opcode params, @ret wiring - **Justification:** Graph rendering depends on pipeline output; visual verification needed ### macro-enh.HV2: Error messages are useful - Verify that error messages for invalid opcode params, mismatched @ret, etc. include actionable context (macro name, line, suggestions) - **Justification:** Error message quality is subjective; automated tests check presence but not clarity