mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-25 02:20:33 +00:00
Moving definitions to use dedicated scratch register.
This commit is contained in:
@@ -275,7 +275,7 @@ typedef Struct_(RegUse_build_normalize_v3s4) {
|
|||||||
Reg scratch; /* scratchpad base; loaded via load_word_imm below. */
|
Reg scratch; /* scratchpad base; loaded via load_word_imm below. */
|
||||||
Reg src_ptr;
|
Reg src_ptr;
|
||||||
Reg dst_ptr;
|
Reg dst_ptr;
|
||||||
Reg recip_est; /* |v|² sum + shift-input + sqrtbl[index] */
|
Reg recip_est; /* |v|² sum + shift-input + sqrtbl[index] */
|
||||||
Reg norm; Reg shift;
|
Reg norm; Reg shift;
|
||||||
Reg src_x;
|
Reg src_x;
|
||||||
union { Reg mac1_scratch, dst_offset; } t3;
|
union { Reg mac1_scratch, dst_offset; } t3;
|
||||||
@@ -372,7 +372,7 @@ atom_info(atom_bind(Binds_gte_cross_v3s4)) MipsAtom_Proc_(aa, {
|
|||||||
load_word(r.y.src_a, R_TapePtr, O_(Binds_gte_cross_v3s4,src_a)),
|
load_word(r.y.src_a, R_TapePtr, O_(Binds_gte_cross_v3s4,src_a)),
|
||||||
load_word(r.z.src_b, R_TapePtr, O_(Binds_gte_cross_v3s4,src_b)),
|
load_word(r.z.src_b, R_TapePtr, O_(Binds_gte_cross_v3s4,src_b)),
|
||||||
load_word(r.x.out, R_TapePtr, O_(Binds_gte_cross_v3s4,out)),
|
load_word(r.x.out, R_TapePtr, O_(Binds_gte_cross_v3s4,out)),
|
||||||
LdSlot_ add_ui_self(R_TapePtr, S_(Binds_gte_cross_v3s4)),
|
LdSlot_ add_ui_self( R_TapePtr, S_(Binds_gte_cross_v3s4)),
|
||||||
|
|
||||||
mac_load_v3s4(r.a, r.y.src_a, 0), LdSlot_
|
mac_load_v3s4(r.a, r.y.src_a, 0), LdSlot_
|
||||||
mac_load_v3s4(r.b, r.z.src_b, 0), LdSlot_
|
mac_load_v3s4(r.b, r.z.src_b, 0), LdSlot_
|
||||||
|
|||||||
@@ -97,8 +97,8 @@ enum {
|
|||||||
R_Atom5 = R_T5,
|
R_Atom5 = R_T5,
|
||||||
R_Atom6 = R_T6,
|
R_Atom6 = R_T6,
|
||||||
R_Atom7 = R_T7,
|
R_Atom7 = R_T7,
|
||||||
R_Atom8 = R_T8,
|
R_Atom8 = R_T8,
|
||||||
R_Atom9 = R_T9,
|
R_Atom9 = R_T9,
|
||||||
R_Atom10 = R_V0, // Tend to be used with gte DMAs
|
R_Atom10 = R_V0, // Tend to be used with gte DMAs
|
||||||
R_Atom11 = R_V1, // Tend to be used with gte DMAs
|
R_Atom11 = R_V1, // Tend to be used with gte DMAs
|
||||||
R_Atom12 = R_A0,
|
R_Atom12 = R_A0,
|
||||||
@@ -383,8 +383,8 @@ FI_ Reg regfile__alloc_helper(A2_U2 file, Reg r_id) {
|
|||||||
* any of them while R0, R1, R26-R31 remain reserved. */
|
* any of them while R0, R1, R26-R31 remain reserved. */
|
||||||
I_ Reg regfile_alloc(RegFile_R rf) {
|
I_ Reg regfile_alloc(RegFile_R rf) {
|
||||||
Reg allocated = 0;
|
Reg allocated = 0;
|
||||||
for index_iter(U4, idx, 0, <, Array_len(regfile_alloc_order)) {
|
for index_iter(U4, r_id, R_V0, <, R_T9) {
|
||||||
allocated = regfile__alloc_helper(rf->GPR, idx);
|
allocated = regfile__alloc_helper(rf->GPR, r_id);
|
||||||
Jmp_nZero_(allocated,resolved);
|
Jmp_nZero_(allocated,resolved);
|
||||||
}
|
}
|
||||||
assert(allocated != 0);
|
assert(allocated != 0);
|
||||||
|
|||||||
@@ -111,58 +111,51 @@ typedef AtomBundle_(resolve_look_at) { MipsAtom
|
|||||||
*pop_mv_trans;
|
*pop_mv_trans;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
typedef Struct_(ResolveLookAtScratch) {
|
||||||
// TODO(Ed): We can resolve scratch at anytime its fixed to a specific address.
|
V3_S4 fwd;
|
||||||
R_ResolveScratch = R_T4 atom_reg atom_type(U4*),
|
V3_S4 uz;
|
||||||
#define R_ResolveScratch_Code R_T4_Code
|
V3_S4 right;
|
||||||
|
V3_S4 ux;
|
||||||
|
V3_S4 up;
|
||||||
|
V3_S4 uy;
|
||||||
|
P3_S4 eye;
|
||||||
|
P3_S4 target;
|
||||||
|
V3_S4 up_in;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Binds_ResolveLookAtSub — what the C side pushes onto the tape before input_and_sub.
|
||||||
|
* The scratchpad base is no longer pushed because R_ScratchBase (= R_SP) is a tape carrier
|
||||||
|
* preserved across atoms; the atom body reads 0x1F800000 directly from R_SP. */
|
||||||
typedef Struct_(Binds_ResolveLookAt) {
|
typedef Struct_(Binds_ResolveLookAt) {
|
||||||
MT3_S2S4* look_at;
|
MT3_S2S4* look_at;
|
||||||
P3_S4* eye;
|
P3_S4* eye;
|
||||||
P3_S4* target;
|
P3_S4* target;
|
||||||
V3_S4* up_in;
|
V3_S4* up_in;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ─── ResolveLookAtScratch — offset schema for the resolve_look_at bundle's */
|
|
||||||
typedef Struct_(ResolveLookAtScratch) {
|
|
||||||
V3_S4 fwd; /* offset +0 (16 bytes — 4 S4 fields incl. internal pad) */
|
|
||||||
V3_S4 uz; /* offset +16 (16 bytes) */
|
|
||||||
V3_S4 right; /* offset +32 (16 bytes) */
|
|
||||||
V3_S4 ux; /* offset +48 (16 bytes) */
|
|
||||||
V3_S4 up; /* offset +64 (16 bytes) */
|
|
||||||
V3_S4 uy; /* offset +80 (16 bytes) */
|
|
||||||
P3_S4 eye; /* offset +96 (16 bytes; storage alias of V3_S4) */
|
|
||||||
P3_S4 target; /* offset +112 (16 bytes; storage alias of V3_S4) */
|
|
||||||
V3_S4 up_in; /* offset +128 (16 bytes) */
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef Struct_(Binds_ResolveLookAtSub) {
|
typedef Struct_(Binds_ResolveLookAtSub) {
|
||||||
P3_S4* target;
|
P3_S4* target;
|
||||||
P3_S4* eye;
|
P3_S4* eye;
|
||||||
V3_S4* up_in;
|
V3_S4* up_in;
|
||||||
ResolveLookAtScratch* scratchpad;
|
|
||||||
};
|
};
|
||||||
typedef Struct_(RegUse_resolve_look_at_input_and_sub) {
|
typedef Struct_(RegUse_resolve_look_at_input_and_sub) {
|
||||||
Reg scratch;
|
|
||||||
Reg target; Reg eye; Reg up_in;
|
Reg target; Reg eye; Reg up_in;
|
||||||
Reg t0; Reg t1; Reg t2; Reg t3; Reg t4;
|
Reg t0; Reg t1; Reg t2; Reg t3; Reg t4;
|
||||||
};
|
};
|
||||||
/* Atom 0 in the bundle: input_and_sub. Stages C-side inputs into the scratchpad and computes fwd = target - eye. */
|
/* Atom 0 in the bundle: input_and_sub. Stages C-side inputs into the scratchpad and computes fwd = target - eye. */
|
||||||
internal MipsAtom* AtomBundleEntry_(resolve_look_at,input_and_sub)(AtomArena_R aa, RegUse_resolve_look_at_input_and_sub r)
|
internal MipsAtom* AtomBundleEntry_(resolve_look_at,input_and_sub)(AtomArena_R aa, RegUse_resolve_look_at_input_and_sub r)
|
||||||
atom_info(atom_bind(Binds_ResolveLookAtSub)) MipsAtom_Proc_(aa, {
|
atom_info(atom_bind(Binds_ResolveLookAtSub)) MipsAtom_Proc_(aa, {
|
||||||
load_word(r.target, R_TapePtr, O_(Binds_ResolveLookAtSub,target)),
|
load_word(r.target, R_TapePtr, O_(Binds_ResolveLookAtSub,target)),
|
||||||
load_word(r.eye, R_TapePtr, O_(Binds_ResolveLookAtSub,eye)),
|
load_word(r.eye, R_TapePtr, O_(Binds_ResolveLookAtSub,eye)),
|
||||||
load_word(r.up_in, R_TapePtr, O_(Binds_ResolveLookAtSub,up_in)),
|
load_word(r.up_in, R_TapePtr, O_(Binds_ResolveLookAtSub,up_in)),
|
||||||
load_word(r.scratch, R_TapePtr, O_(Binds_ResolveLookAtSub,scratchpad)),
|
LdSlot_ add_ui_self(R_TapePtr, S_(Binds_ResolveLookAtSub)),
|
||||||
LdSlot_ add_ui_self( R_TapePtr, S_(Binds_ResolveLookAtSub)),
|
|
||||||
|
|
||||||
/* Stage up_in.x/y/z into the scratchpad. */
|
/* Stage up_in.x/y/z into the scratchpad. R_ScratchBase = R_SP = 0x1F800000. */
|
||||||
mac_load_word_v3( r.t0, r.t1, r.t2, r.up_in, 0), LdSlot_
|
mac_load_word_v3( r.t0, r.t1, r.t2, r.up_in, 0), LdSlot_
|
||||||
mac_store_word_v3(r.t0, r.t1, r.t2, r.scratch, O_(ResolveLookAtScratch,up_in)),
|
mac_store_word_v3(r.t0, r.t1, r.t2, R_ScratchBase, O_(ResolveLookAtScratch,up_in)),
|
||||||
|
|
||||||
// Stage eye.x/y/z into the scratchpad (atom 6 reads these for the translation column).
|
// Stage eye.x/y/z into the scratchpad (atom 6 reads these for the translation column).
|
||||||
mac_load_word_v3( r.t0, r.t1, r.t2, r.eye, 0), LdSlot_
|
mac_load_word_v3( r.t0, r.t1, r.t2, r.eye, 0), LdSlot_
|
||||||
mac_store_word_v3(r.t0, r.t1, r.t2, r.scratch, O_(ResolveLookAtScratch,eye)),
|
mac_store_word_v3(r.t0, r.t1, r.t2, R_ScratchBase, O_(ResolveLookAtScratch,eye)),
|
||||||
|
|
||||||
/* Compute fwd = target - eye. */
|
/* Compute fwd = target - eye. */
|
||||||
// mac_load_p3s4(t3, R_AT, t4, r.eye, 0),
|
// mac_load_p3s4(t3, R_AT, t4, r.eye, 0),
|
||||||
@@ -170,7 +163,7 @@ atom_info(atom_bind(Binds_ResolveLookAtSub)) MipsAtom_Proc_(aa, {
|
|||||||
mac_sub_s_v3_self(
|
mac_sub_s_v3_self(
|
||||||
r.t3, R_AT, r.t4,
|
r.t3, R_AT, r.t4,
|
||||||
r.t0, r.t1, r.t2),
|
r.t0, r.t1, r.t2),
|
||||||
mac_store_word_v3(r.t3, R_AT, r.t4, r.scratch, O_(ResolveLookAtScratch,fwd)),
|
mac_store_word_v3(r.t3, R_AT, r.t4, R_ScratchBase, O_(ResolveLookAtScratch,fwd)),
|
||||||
|
|
||||||
mac_yield()
|
mac_yield()
|
||||||
})
|
})
|
||||||
@@ -180,8 +173,6 @@ typedef Struct_(Binds_ResolveLookAtPopMvTrans) {
|
|||||||
U4 look_at; /* MT3_S2S4* — destination matrix address */
|
U4 look_at; /* MT3_S2S4* — destination matrix address */
|
||||||
};
|
};
|
||||||
typedef Struct_(RegUse_resolve_look_at__pop_mv_trans) {
|
typedef Struct_(RegUse_resolve_look_at__pop_mv_trans) {
|
||||||
Reg scratch; /* loaded via load_word_imm below — can't rely on
|
|
||||||
* R_T4 surviving across the tape_run boundary */
|
|
||||||
Reg look_at;
|
Reg look_at;
|
||||||
Reg_(V3_S4) row; /* populate phase: load ux/uy/uz */
|
Reg_(V3_S4) row; /* populate phase: load ux/uy/uz */
|
||||||
union { Reg ux, v_x; } t6; /* populate addr (canonical) → matrix_vector v_x */
|
union { Reg ux, v_x; } t6; /* populate addr (canonical) → matrix_vector v_x */
|
||||||
@@ -236,17 +227,13 @@ internal MipsAtom* resolve_look_at__pop_mv_trans(AtomArena_R aa,
|
|||||||
load_word(r.look_at, R_TapePtr, O_(Binds_ResolveLookAtPopMvTrans,look_at)),
|
load_word(r.look_at, R_TapePtr, O_(Binds_ResolveLookAtPopMvTrans,look_at)),
|
||||||
LdSlot_ add_ui_self(R_TapePtr, S_(Binds_ResolveLookAtPopMvTrans)),
|
LdSlot_ add_ui_self(R_TapePtr, S_(Binds_ResolveLookAtPopMvTrans)),
|
||||||
|
|
||||||
/* Load scratch base via immediate (Scratchpad_Loc = 0x1F800000). We can't rely on
|
/* --- Scratch addresses for ux/uy/uz/eye (populate phase; t6/t7/t8 alias ux/uy/uz).
|
||||||
* R_T4 (= R_ResolveScratch) surviving across the tape_run boundary — the compiler
|
* R_ScratchBase (= R_SP) holds 0x1F800000; no per-atom bake is required because
|
||||||
* treats it as clobberable per the tape_run asm_clobber list. Baking the scratch
|
* R_SP is a tape carrier preserved across atoms. --- */
|
||||||
* address via load_word_imm is robust. */
|
add_si(r.t6.ux, R_ScratchBase, O_(ResolveLookAtScratch, ux)), LdSlot_
|
||||||
mac_load_word_imm(r.scratch, Scratchpad_Loc),
|
add_si(r.t7.uy, R_ScratchBase, O_(ResolveLookAtScratch, uy)),
|
||||||
|
add_si(r.t8.uz, R_ScratchBase, O_(ResolveLookAtScratch, uz)),
|
||||||
/* --- Scratch addresses for ux/uy/uz/eye (populate phase; t6/t7/t8 alias ux/uy/uz) --- */
|
add_si(r.eye, R_ScratchBase, O_(ResolveLookAtScratch, eye)),
|
||||||
add_si(r.t6.ux, r.scratch, O_(ResolveLookAtScratch, ux)), LdSlot_
|
|
||||||
add_si(r.t7.uy, r.scratch, O_(ResolveLookAtScratch, uy)),
|
|
||||||
add_si(r.t8.uz, r.scratch, O_(ResolveLookAtScratch, uz)),
|
|
||||||
add_si(r.eye, r.scratch, O_(ResolveLookAtScratch, eye)),
|
|
||||||
|
|
||||||
/* --- POPULATE phase: write look_at->m[][] from ux/uy/uz as packed S2 --- */
|
/* --- POPULATE phase: write look_at->m[][] from ux/uy/uz as packed S2 --- */
|
||||||
mac_load_v3s4(r.row, r.t6.ux, 0), LdSlot_ mac_store_v3s2(r.row, r.look_at, O_(MT3_S2S4, m[0])),
|
mac_load_v3s4(r.row, r.t6.ux, 0), LdSlot_ mac_store_v3s2(r.row, r.look_at, O_(MT3_S2S4, m[0])),
|
||||||
|
|||||||
@@ -151,16 +151,17 @@ internal void compile_init_atoms(void) {
|
|||||||
|
|
||||||
smem.normalize_v3s4 = build_normalize_v3s4(& ab,
|
smem.normalize_v3s4 = build_normalize_v3s4(& ab,
|
||||||
RegUse_(build_normalize_v3s4) {
|
RegUse_(build_normalize_v3s4) {
|
||||||
.scratch = ralloc(),
|
.scratch = ralloc(),
|
||||||
.src_ptr = ralloc(),
|
.src_ptr = ralloc(),
|
||||||
.dst_ptr = ralloc(),
|
.dst_ptr = ralloc(),
|
||||||
.recip_est = ralloc(),
|
.recip_est = ralloc(),
|
||||||
.norm = ralloc(),
|
.norm = ralloc(),
|
||||||
.shift = ralloc(),
|
.shift = ralloc(),
|
||||||
.src_x = ralloc(),
|
.src_x = ralloc(),
|
||||||
.t3 = ralloc(),
|
// .shift_count = ralloc(), /* dedicated slot for stage-3 → stage-4 shift count */
|
||||||
.t4 = ralloc(),
|
.t3 = ralloc(),
|
||||||
.t5 = ralloc(),
|
.t4 = ralloc(),
|
||||||
|
.t5 = ralloc(),
|
||||||
});
|
});
|
||||||
regfile_reset(& rf);
|
regfile_reset(& rf);
|
||||||
|
|
||||||
@@ -173,14 +174,14 @@ internal void compile_resolve_look_at(void) {
|
|||||||
AtomArena ab = atomarena_make(slice_ut_arr(smem.resolve_look_at_mem));
|
AtomArena ab = atomarena_make(slice_ut_arr(smem.resolve_look_at_mem));
|
||||||
AtomBundle_resolve_look_at_R bundle = C_(void*, smem.resolve_look_at_bundle);
|
AtomBundle_resolve_look_at_R bundle = C_(void*, smem.resolve_look_at_bundle);
|
||||||
|
|
||||||
U4 pin_mask = regfile_abi_mask | (1 << R_ResolveScratch);
|
/* R_ScratchBase (= R_SP) is a tape carrier preserved across atoms; no carrier
|
||||||
RegFile rf = regfile(pin_mask);
|
* pin is needed in the regfile. The standard 24-register pool is sufficient. */
|
||||||
|
RegFile rf = regfile(regfile_abi_mask);
|
||||||
#define ralloc() regfile_alloc(& rf)
|
#define ralloc() regfile_alloc(& rf)
|
||||||
#define ralloc_v3() { ralloc(), ralloc(), ralloc() }
|
#define ralloc_v3() { ralloc(), ralloc(), ralloc() }
|
||||||
|
|
||||||
bundle->input_and_sub = AtomBundleEntry_(resolve_look_at, input_and_sub)(& ab,
|
bundle->input_and_sub = AtomBundleEntry_(resolve_look_at, input_and_sub)(& ab,
|
||||||
RegUse_(resolve_look_at_input_and_sub) {
|
RegUse_(resolve_look_at_input_and_sub) {
|
||||||
.scratch = R_ResolveScratch,
|
|
||||||
.target = ralloc(),
|
.target = ralloc(),
|
||||||
.eye = ralloc(),
|
.eye = ralloc(),
|
||||||
.up_in = ralloc(),
|
.up_in = ralloc(),
|
||||||
@@ -190,7 +191,7 @@ internal void compile_resolve_look_at(void) {
|
|||||||
.t3 = ralloc(),
|
.t3 = ralloc(),
|
||||||
.t4 = ralloc(),
|
.t4 = ralloc(),
|
||||||
});
|
});
|
||||||
regfile_reset_to_mask(& rf, pin_mask);
|
regfile_reset(& rf);
|
||||||
|
|
||||||
bundle->normalize_fwd_uz = smem.normalize_v3s4;
|
bundle->normalize_fwd_uz = smem.normalize_v3s4;
|
||||||
bundle->cross_to_right = smem.gte_cross_v3s4;
|
bundle->cross_to_right = smem.gte_cross_v3s4;
|
||||||
@@ -200,7 +201,6 @@ internal void compile_resolve_look_at(void) {
|
|||||||
|
|
||||||
bundle->pop_mv_trans = resolve_look_at__pop_mv_trans(& ab,
|
bundle->pop_mv_trans = resolve_look_at__pop_mv_trans(& ab,
|
||||||
RegUse_(resolve_look_at__pop_mv_trans){
|
RegUse_(resolve_look_at__pop_mv_trans){
|
||||||
.scratch = R_ResolveScratch,
|
|
||||||
.look_at = ralloc(),
|
.look_at = ralloc(),
|
||||||
.eye = ralloc(),
|
.eye = ralloc(),
|
||||||
.row = ralloc_v3(),
|
.row = ralloc_v3(),
|
||||||
@@ -229,7 +229,6 @@ I_ void resolve_look_at(TapeBuilder_R tb
|
|||||||
tb_data(tb, u4_(target));
|
tb_data(tb, u4_(target));
|
||||||
tb_data(tb, u4_(eye));
|
tb_data(tb, u4_(eye));
|
||||||
tb_data(tb, u4_(up_in));
|
tb_data(tb, u4_(up_in));
|
||||||
tb_data(tb, u4_(smem.scratchpad));
|
|
||||||
}
|
}
|
||||||
tb_emit(tb, bundle->normalize_fwd_uz); {
|
tb_emit(tb, bundle->normalize_fwd_uz); {
|
||||||
tb_data(tb, u4_(O_(ResolveLookAtScratch, fwd) | (O_(ResolveLookAtScratch, uz) << 16)));
|
tb_data(tb, u4_(O_(ResolveLookAtScratch, fwd) | (O_(ResolveLookAtScratch, uz) << 16)));
|
||||||
|
|||||||
@@ -130,6 +130,60 @@ local function extract_arg_names(args_str)
|
|||||||
for _, tok in ipairs(tokens) do
|
for _, tok in ipairs(tokens) do
|
||||||
local trimmed = duffle.trim(tok)
|
local trimmed = duffle.trim(tok)
|
||||||
if trimmed ~= "" then
|
if trimmed ~= "" then
|
||||||
|
-- Strip trailing block comment (/* ... */) from the token, if present.
|
||||||
|
-- split_top_level_commas only skips block comments at TOP LEVEL (between commas),
|
||||||
|
-- not block comments embedded WITHIN a token between a parameter and a trailing comma.
|
||||||
|
-- Without this strip, the identifier-walk below stops at the `/` of `*/` and returns
|
||||||
|
-- the wrong name (or nothing). See `test_extract_arg_names_handles_trailing_block_comments`.
|
||||||
|
local trimmed_end = #trimmed
|
||||||
|
if trimmed_end >= 2 and trimmed:sub(trimmed_end - 1, trimmed_end) == "*/" then
|
||||||
|
-- Find the matching `/*` that opens the trailing comment.
|
||||||
|
-- Walk back from the `*/` looking for `/*` (whitespace + `/*`).
|
||||||
|
local close_pos = trimmed_end - 1 -- position of the second-to-last char
|
||||||
|
-- Walk back: skip trailing whitespace, then look for the `/*` opener.
|
||||||
|
while close_pos > 1 do
|
||||||
|
local ch = trimmed:sub(close_pos, close_pos)
|
||||||
|
if ch == " " or ch == "\t" or ch == "\n" or ch == "\r" then
|
||||||
|
close_pos = close_pos - 1
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Now scan back from close_pos for the `/*` opener (slashes are at close_pos-1 and close_pos-2).
|
||||||
|
local opener_pos = nil
|
||||||
|
local scan = close_pos - 3
|
||||||
|
while scan >= 1 do
|
||||||
|
if trimmed:sub(scan, scan + 1) == "/*" then
|
||||||
|
opener_pos = scan
|
||||||
|
break
|
||||||
|
end
|
||||||
|
scan = scan - 1
|
||||||
|
end
|
||||||
|
if opener_pos then
|
||||||
|
-- Truncate everything from opener_pos onwards.
|
||||||
|
trimmed = duffle.trim(trimmed:sub(1, opener_pos - 1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if trimmed == "" then goto continue end
|
||||||
|
-- Strip trailing array suffix `[N]` if present.
|
||||||
|
-- Example: `Reg r_data[4]` → identifier is `r_data`, not `4`.
|
||||||
|
trimmed_end = #trimmed
|
||||||
|
if trimmed_end >= 4 and trimmed:sub(trimmed_end, trimmed_end) == "]" then
|
||||||
|
-- Walk back: skip digits, expect `[`.
|
||||||
|
local bracket_pos = trimmed_end - 1
|
||||||
|
while bracket_pos > 1 do
|
||||||
|
local ch = trimmed:sub(bracket_pos, bracket_pos)
|
||||||
|
if ch >= "0" and ch <= "9" then
|
||||||
|
bracket_pos = bracket_pos - 1
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if bracket_pos >= 1 and trimmed:sub(bracket_pos, bracket_pos) == "[" then
|
||||||
|
trimmed = duffle.trim(trimmed:sub(1, bracket_pos - 1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if trimmed == "" then goto continue end
|
||||||
-- Find the identifier at the end: walk back over trailers (whitespace + `*` + `[]`),
|
-- Find the identifier at the end: walk back over trailers (whitespace + `*` + `[]`),
|
||||||
-- then walk back over the identifier chars (alnum + `_`).
|
-- then walk back over the identifier chars (alnum + `_`).
|
||||||
local ident_end = #trimmed
|
local ident_end = #trimmed
|
||||||
@@ -153,6 +207,7 @@ local function extract_arg_names(args_str)
|
|||||||
ident_start = ident_start + 1
|
ident_start = ident_start + 1
|
||||||
local name = trimmed:sub(ident_start, ident_end)
|
local name = trimmed:sub(ident_start, ident_end)
|
||||||
if name ~= "" then names[#names + 1] = name end
|
if name ~= "" then names[#names + 1] = name end
|
||||||
|
::continue::
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if #names == 0 then return nil end
|
if #names == 0 then return nil end
|
||||||
|
|||||||
Reference in New Issue
Block a user