Redesign: Not making local var in MipsAtom_Proc_ or MipsAtomComp_Proc_ have sym tied to proc name. Adjusted parser as well base do that.

This commit is contained in:
ed
2026-08-13 21:42:06 -04:00
parent b8e31123e4
commit 5c9c61720f
12 changed files with 236 additions and 92 deletions
+8 -35
View File
@@ -96,48 +96,21 @@ local M = {}
-- so this file reads it forward rather than re-walking the source.
-- ════════════════════════════════════════════════════════════════════════════
--- Find the args of the function declaration that immediately precedes a `MipsAtomComp_Proc_` invocation of the given name.
--- Find the args of the function declaration that immediately precedes a `MipsAtomComp_Proc_` invocation.
--- Returns the args string (e.g., `"U4 off, U4 code, U1 r, U1 g, U1 b"`) or nil if no function declaration is found.
---
--- Convention: function form is
--- `FI_ Slice_MipsCode ac_X(args) MipsAtomComp_Proc_(ac_X, { body })`
--- We find the LAST occurrence of `"ac_X("` before `before_pos` and extract the args from inside the parens.
--- We then verify the preceding context ends with `Slice_MipsCode`
--- (the function-decl keyword with possible qualifiers between).
--- After the `sym` arg was dropped from MipsAtomComp_Proc_, the component name
--- and the args both come from the preceding `FI_ Slice_MipsCode ac_X(args)`
--- declaration. The shared `duffle.find_function_decl_for` helper does the
--- backward walk; this function returns just the args.
---
--- @param source string
--- @param name string
--- @param name string (retained for signature stability; unused — the walk derives the name)
--- @param before_pos integer
--- @return string|nil
local function find_function_args_for(source, name, before_pos)
-- Find the LAST occurrence of `name + "("` in `source[1..before_pos]`.
local name_open = name .. "("
local last_idx = nil
local scan_pos = 1
while true do
-- Pass `before_pos + 1` so string.find only returns positions < before_pos + 1
-- (string.find's 4th arg `plain` is true; we use the 3rd arg `init` for the upper bound).
local found = source:find(name_open, scan_pos, true)
if not found or found >= before_pos then break end
last_idx = found
scan_pos = found + #name_open
end
if not last_idx then return nil end
-- Verify the preceding context ends with "MipsAtom" (with possible qualifiers between).
local before = source:sub(1, last_idx - 1)
local trimmed = duffle.trim(before)
if trimmed:sub(-#MIPS_ATOM) ~= MIPS_ATOM then
-- Preceding context is not a function declaration.
return nil
end
local open_paren = last_idx + #name -- position of "("
-- scan: MipsAtom ac_X(
local inner = duffle.read_parens(source, open_paren)
-- scan: MipsAtom ac_X(<args>)
if not inner then return nil end
return inner
local _, args_inner = duffle.find_function_decl_for(source, before_pos, #MIPS_ATOM)
return args_inner
end
-- ════════════════════════════════════════════════════════════════════════════
+21 -4
View File
@@ -137,6 +137,16 @@ local QUALIFIER_KEYWORDS = {
local AC_PREFIX = "ac_"
local AC_PREFIX_LEN = 3
-- The function-decl keyword that precedes a MipsAtomComp_Proc_ call.
-- Used by the backward walk in duffle.find_function_decl_for.
local SLICE_MIPS_CODE = "Slice_MipsCode"
local SLICE_MIPS_CODE_LEN = #SLICE_MIPS_CODE
-- The return type that precedes a MipsAtom_Proc_ function declaration.
-- Used by the backward walk in duffle.find_atom_proc_decl_for.
local MIPS_ATOM_PTR = "MipsAtom*"
local MIPS_ATOM_PTR_LEN = #MIPS_ATOM_PTR
--- Strip the "ac_" prefix from a component name.
--- Returns the input unchanged if it doesn't start with the prefix.
--- @param raw_name string
@@ -1357,7 +1367,11 @@ local function parse_mips_atom_comp_proc(source, pos, ident_end, line_of, out)
local body, close_pos = duffle.read_braces(inner, last_brace_pos)
if close_pos > #inner + 1 then return after_paren end
local raw_name = inner:match("^%s*([%w_]+)") or "?"
-- The component name is derived from the preceding function declaration
-- (`FI_ Slice_MipsCode ac_X(...)`), not from the first macro arg (which
-- is now `ab`). The backward walk finds the function decl before open_paren.
local raw_name = duffle.find_function_decl_for(source, open_paren, SLICE_MIPS_CODE_LEN)
if not raw_name then raw_name = "?" end
local name = strip_ac_prefix(raw_name)
-- Position of body[1] in source = open_paren + 1 (start of inner) + last_brace_pos + 1 (past '{').
local body_off = open_paren + 2 + last_brace_pos
@@ -1398,9 +1412,12 @@ local function parse_mips_atom_proc(source, pos, ident_end, line_of, out)
local body, close_pos = duffle.read_braces(inner, last_brace_pos)
if close_pos > #inner + 1 then return after_paren end
-- The atom name is the FIRST ident of the args (matches MipsAtomComp_Proc_'s "first ident" rule).
-- MipsAtom_Proc_ has no `ac_` prefix; `strip_ac_prefix` is a no-op for unprefixed names.
local raw_name = inner:match("^%s*([%w_]+)") or "?"
-- The atom name is derived from the preceding function declaration
-- (`internal MipsAtom* X_proc(...)`), not from the first macro arg (which
-- is now `aa`). The backward walk finds the function decl before open_paren
-- and strips the `_proc` suffix.
local raw_name = duffle.find_atom_proc_decl_for(source, open_paren, MIPS_ATOM_PTR_LEN)
if not raw_name then raw_name = "?" end
local name = strip_ac_prefix(raw_name)
-- Position of body[1] in source = open_paren + 1 (start of inner) + last_brace_pos + 1 (past '{').
local body_off = open_paren + 2 + last_brace_pos