adjustments, studying

This commit is contained in:
2026-07-06 13:08:16 -04:00
parent 352a8c9c25
commit ffcd43c1ea
6 changed files with 180 additions and 192 deletions
+3 -41
View File
@@ -1,50 +1,12 @@
// Auto-generated by gen_atom_offsets.lua — DO NOT EDIT
// Source: C:\projects\Pikuma\ps1\code\duffle\lottes_tape.h
#ifndef LOTTES_TAPE_OFFSETS_H
#define LOTTES_TAPE_OFFSETS_H
#pragma once
#pragma region lottes_tape
// Override the placeholder atom_offset() to dispatch via token pasting.
// Dispatch macro: token-pastes <tag>_<target> to the enum name
#undef atom_offset
#define atom_offset(name) atom_offset_##name
// --- atom: sym (8 words) ---
// --- atom: tape_exit (2 words) ---
// --- atom: yield (4 words) ---
// --- atom: mips_flush_icache (13 words) ---
// --- atom: sync_prim_cursor (6 words) ---
// --- atom: set_gte_world (22 words) ---
// --- atom: rbind_cube_tri (6 words) ---
// --- atom: cube_tri (74 words) ---
// --- atom: rbind_floor_tri (6 words) ---
// --- atom: diag_yield (4 words) ---
// --- atom: diag_color (28 words) ---
// --- atom: diag_gte (34 words) ---
#define atom_offset(tag, name) atom_offset_##tag##_##name
#pragma endregion lottes_tape
#endif // LOTTES_TAPE_OFFSETS_H
+2 -1
View File
@@ -62,7 +62,8 @@ FI_ void tape_run(Slice_U4 tape) { register U4* tp rgcc(R_TapePtr) = tape.ptr; a
typedef Relative_(FArena) Struct_(TapeBuilder) { U4 ptr; U4 capacity; U4 used; };
FI_ void tb_init(TapeBuilder* tb, FArena* arena) { tb->ptr = arena->start; tb->used = 0; }
FI_ TapeBuilder tb_make( FArena* arena) { return (TapeBuilder){ arena->start, 0 }; }
FI_ TapeBuilder tb_make_old( FArena* arena) { return (TapeBuilder){ arena->start, 0 }; }
FI_ TapeBuilder tb_make(Slice mem) { return (TapeBuilder){ mem.ptr, mem.len, 0 }; }
#define tb_emit_(tb, atom) tb_emit(tb, tmpl(code,atom))
FI_ void tb_emit(TapeBuilder* tb, MipsCode* atom) { u4_r(tb->ptr)[tb->used] = u4_(atom); ++ tb->used; }
+11 -7
View File
@@ -1,18 +1,22 @@
// Auto-generated by gen_atom_offsets.lua — DO NOT EDIT
// Source: C:\projects\Pikuma\ps1\code\gte_hello\hello_gte_tape.c
#ifndef HELLO_GTE_TAPE_OFFSETS_H
#define HELLO_GTE_TAPE_OFFSETS_H
#pragma once
#pragma region hello_gte_tape
// Override the placeholder atom_offset() to dispatch via token pasting.
// Dispatch macro: token-pastes <tag>_<target> to the enum name
#undef atom_offset
#define atom_offset(name) atom_offset_##name
#define atom_offset(tag, name) atom_offset_##tag##_##name
// --- atom: floor_tri (49 words) ---
// --- atom: floor_tri (51 words) ---
#define atom_offset_floor_tri_exit (17)
#define _atom_offset_culling_floor_tri_exit 17
#define _atom_offset_bounds_chk_floor_tri_exit 3
enum {
atom_offset_culling_floor_tri_exit = _atom_offset_culling_floor_tri_exit,
atom_offset_bounds_chk_floor_tri_exit = _atom_offset_bounds_chk_floor_tri_exit,
};
#pragma endregion hello_gte_tape
#endif // HELLO_GTE_TAPE_OFFSETS_H
+5 -6
View File
@@ -246,7 +246,7 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
U4 prim_cursor = prim_base + pa->used;
LP_ U4 mem_temp_tape[512]; FArena tape_arena; farena_init(& tape_arena, slice_ut_arr(mem_temp_tape));
TapeBuilder tb = tb_make(&tape_arena); tb_scope(& tb) {
TapeBuilder tb = tb_make_old(&tape_arena); tb_scope(& tb) {
tb_emit(& tb, code_rbind_cube_tri);
tb_data(& tb, prim_cursor);
tb_data(& tb, u4_(static_mem.cube.faces));
@@ -334,12 +334,11 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
U4 prim_cursor = prim_base + pa->used;
// Prepare the tape.
LP_ U4 mem_temp_tape[512]; FArena tape_arena; farena_init(& tape_arena, slice_ut_arr(mem_temp_tape));
TapeBuilder tb = tb_make(&tape_arena); tb_scope(& tb) {
LP_ U4 mem_temp_tape[512];
TapeBuilder tb = tb_make(slice_ut_arr(mem_temp_tape)); tb_scope(& tb) {
// Push "Protocol" to tape
tb_emit(& tb, code_rbind_floor_tri);
// Note(Ed): This is technically argument shuffle and would be better if we did a single reference at most to a global batch context.
// Note(Ed): We can technically allocate a single ptr with the global offset to the working context instead of utilizing the tape for this stack of refs.
// TODO(Ed): Just use a single context struct ref
tb_data(& tb, prim_cursor);
tb_data(& tb, u4_(static_mem.floor.faces));
tb_data(& tb, u4_(static_mem.floor.verts));
@@ -367,7 +366,7 @@ void update(PrimitiveArena* pa, U4* ordering_buf)
if (0)
{
LP_ U4 mem_temp_tape[512]; FArena tape_arena; farena_init(& tape_arena, slice_ut_arr(mem_temp_tape));
TapeBuilder tb = tb_make(& tape_arena); tb_scope(& tb) {
TapeBuilder tb = tb_make_old(& tape_arena); tb_scope(& tb) {
// Skip set_gte_world atom for diagnostics to isolate the triangle loop
for (U4 i = 0; i < Floor_num_faces; i++) {
// =======================================================
+15 -7
View File
@@ -5,7 +5,7 @@
# include "gen/hello_gte_tape.offsets.h"
#endif
#pragma region MACs
#pragma region MACs (Mips Atom components)
/* Words: 3; High: 0x20/B, Low: G/R */
#define mac_format_f3_color(color_hi, color_lo) \
@@ -24,17 +24,25 @@
internal MipsAtom_(floor_tri) {
// T0-T2 allocated
mac_load_tri_indices(R_T0, R_T1, R_T2),
mac_load_tri_verts( R_T0, R_T1, R_T2),
// mac_load_tri_indices(R_T0, R_T1, R_T2),
load_half_u(R_T0, R_FaceCur, 0 * S_(S2))
, load_half_u(R_T1, R_FaceCur, 1 * S_(S2))
, load_half_u(R_T2, R_FaceCur, 2 * S_(S2))
,
// mac_load_tri_verts( R_T0, R_T1, R_T2),
shift_ll(R_AT, R_T0, 3), add_u(R_AT, R_AT, R_VertBase), load_word(R_V0, R_AT, 0), load_word(R_V1, R_AT, 4), gte_mt(R_V0, C2_VXY0), gte_mt(R_V1, C2_VZ0)
, shift_ll(R_AT, R_T1, 3), add_u(R_AT, R_AT, R_VertBase), load_word(R_V0, R_AT, 0), load_word(R_V1, R_AT, 4), gte_mt(R_V0, C2_VXY1), gte_mt(R_V1, C2_VZ1)
, shift_ll(R_AT, R_T2, 3), add_u(R_AT, R_AT, R_VertBase), load_word(R_V0, R_AT, 0), load_word(R_V1, R_AT, 4), gte_mt(R_V0, C2_VXY2), gte_mt(R_V1, C2_VZ2)
,
/* 3. Execute Math */
nop, nop, gte_cmdw_rotate_translate_perspective_triple,
nop, nop, gte_cmdw_nclip,
nop, nop,
/* 4. Culling (Branch forward 29 instructions if Backface) */
/* 4. Culling (Branch forward if Backface) */
gte_mf(R_T0, C2_MAC0),
nop, branch_le_zero(R_T0, atom_offset(floor_tri_exit)),
nop, branch_le_zero(R_T0, atom_offset(culling, floor_tri_exit)),
nop,
/* 5. Format Primitive */
@@ -45,10 +53,10 @@ internal MipsAtom_(floor_tri) {
nop, nop, gte_avg_sort_z3,
nop, nop, gte_mf(R_T1, C2_OTZ),
/* 7. Bounds Check OTZ < 2048 (Branch forward 13 instructions to skip insertion) */
/* 7. Bounds Check OTZ < 2048 (Branch forward to skip insertion) */
add_ui( R_AT, R_0, OrderingTbl_Len),
slt_u( R_AT, R_T1, R_AT),
branch_equal(R_AT, R_0, 13),
branch_equal(R_AT, R_0, atom_offset(bounds_chk, floor_tri_exit)),
nop,
/* 8. Insert into Ordering Table Linked List */
+144 -130
View File
@@ -1,10 +1,23 @@
#!/usr/bin/env lua
-- gen_atom_offsets.lua
-- gen_atom_offsets.lua — hand-rolled, no patterns, no regex, no region pragmas.
--
-- Finds every `MipsAtom_(name) { ... }` declaration in the given sources,
-- counts the words in each body using the WORD_COUNT manifest, computes
-- branch offsets for atom_label(name)/atom_offset(name) markers, and writes
-- one header per source into `<source_dir>/gen/<basename>.offsets.h`.
-- branch offsets for atom_label(name) / atom_offset(tag, name) markers,
-- and writes one header per source into <source_dir>/gen/<basename>.offsets.h
--
-- Generated header layout (per source):
-- #pragma region <basename>
-- #undef atom_offset
-- #define atom_offset(tag, name) atom_offset_##tag##_##name
-- // --- atom: <name> (<n> words) ---
-- #define atom_offset_<tag>_<target> (N) // preprocessor form
-- #undef atom_offset_<tag>_<target> // (so enum can reuse)
-- enum {
-- atom_offset_<tag>_<target> = N, // C enum form
-- };
-- #define atom_offset_<tag>_<target> (N) // re-define for preprocessor
-- #pragma endregion <basename>
--
-- Usage:
-- lua gen_atom_offsets.lua <metadata.h> <source1> [source2 ...]
@@ -56,7 +69,7 @@ local function ensure_dir(path)
end
-- ============================================================
-- String primitives (no patterns)
-- String primitives
-- ============================================================
local function trim(s)
@@ -144,7 +157,7 @@ local function pad_right(s, width)
end
-- ============================================================
-- Skip whitespace and comments
-- Lexer helpers
-- ============================================================
local function skip_ws_and_comments(source, i)
@@ -171,10 +184,6 @@ local function skip_ws_and_comments(source, i)
return i
end
-- ============================================================
-- Read identifier
-- ============================================================
local function read_ident(source, i)
if not is_alpha(source:sub(i, i)) then return nil, i end
local a = i
@@ -183,11 +192,6 @@ local function read_ident(source, i)
return source:sub(a, i - 1), i
end
-- ============================================================
-- Read balanced (open_char, close_char) group, return inner + new pos
-- Skips strings and comments inside.
-- ============================================================
local function read_balanced(source, open_char, close_char, i)
if source:sub(i, i) ~= open_char then return nil, i end
i = i + 1
@@ -235,28 +239,19 @@ local function read_balanced(source, open_char, close_char, i)
return source:sub(a, i - 1), i + 1
end
local function read_parens(source, i) return read_balanced(source, "(", ")", i) end
local function read_braces(source, i) return read_balanced(source, "{", "}", i) end
local function read_parens(source, i) return read_balanced(source, "(", ")", i) end
local function read_braces(source, i) return read_balanced(source, "{", "}", i) end
local function read_brackets(source, i) return read_balanced(source, "[", "]", i) end
-- ============================================================
-- Scan forward from `start`, skipping balanced (), [], {}, strings, comments.
-- Returns position of first occurrence of `target` char at top level, or nil.
-- ============================================================
local function scan_to_char(source, target, start)
local len = #source
local i = start
while i <= len do
local c = source:sub(i, i)
if c == target then
return i
elseif c == "(" then
local _, after = read_parens(source, i); i = after
elseif c == "{" then
local _, after = read_braces(source, i); i = after
elseif c == "[" then
local _, after = read_brackets(source, i); i = after
if c == target then return i
elseif c == "(" then local _, a = read_parens(source, i); i = a
elseif c == "{" then local _, a = read_braces(source, i); i = a
elseif c == "[" then local _, a = read_brackets(source, i); i = a
elseif c == '"' then
i = i + 1
while i <= len do
@@ -290,7 +285,37 @@ local function scan_to_char(source, target, start)
end
-- ============================================================
-- Load WORD_COUNT manifest from metadata.h
-- Extract comma-separated identifier args from a parenthesized group
-- after a function-like macro call.
-- ============================================================
local function extract_ident_args(token, after_ident)
local arg_start = skip_ws_and_comments(token, after_ident)
if token:sub(arg_start, arg_start) ~= "(" then return {}, nil end
local inner, after_paren = read_parens(token, arg_start)
local args = {}
local n = 1
local len = #inner
while n <= len do
n = skip_ws_and_comments(inner, n)
if n > len then break end
local ident, after = read_ident(inner, n)
if ident and ident ~= "" then
table.insert(args, ident)
n = after
else
n = n + 1
end
n = skip_ws_and_comments(inner, n)
if n <= len and inner:sub(n, n) == "," then n = n + 1 end
end
return args, after_paren
end
-- ============================================================
-- Load WORD_COUNT manifest
-- ============================================================
local function load_word_counts(metadata_path)
@@ -304,17 +329,14 @@ local function load_word_counts(metadata_path)
local line_end = nl or (len + 1)
local line = content:sub(i, line_end - 1)
local trimmed = trim(line)
if starts_with(trimmed, prefix) and ends_with(trimmed, ")") then
local inner = trimmed:sub(#prefix + 1, #trimmed - 1)
local comma = find_byte(inner, ",", 1)
if comma then
local name = trim(inner:sub(1, comma - 1))
local cnt = trim(inner:sub(comma + 1))
counts[name] = tonumber(cnt)
counts[trim(inner:sub(1, comma - 1))] =
tonumber(trim(inner:sub(comma + 1)))
end
end
i = line_end + 1
end
return counts
@@ -352,12 +374,9 @@ local function split_top_level_commas(body)
local token_start = 1
while i <= len do
local c = body:sub(i, i)
if c == "(" then
local _, after = read_parens(body, i); i = after
elseif c == "{" then
local _, after = read_braces(body, i); i = after
elseif c == "[" then
local _, after = read_brackets(body, i); i = after
if c == "(" then local _, a = read_parens(body, i); i = a
elseif c == "{" then local _, a = read_braces(body, i); i = a
elseif c == "[" then local _, a = read_brackets(body, i); i = a
elseif c == '"' then
i = i + 1
while i <= len do
@@ -392,14 +411,13 @@ local function split_top_level_commas(body)
end
end
local last = body:sub(token_start, len)
if trim(last) ~= "" then
table.insert(tokens, last)
end
if trim(last) ~= "" then table.insert(tokens, last) end
return tokens
end
-- ============================================================
-- Scan an atom body for atom_label/atom_offset markers, count words
-- Scan token for atom_label/atom_offset markers, walking through
-- balanced groups transparently (so nested calls are found)
-- ============================================================
local function scan_for_atom_markers(token, at_pos, labels, branches)
@@ -410,7 +428,6 @@ local function scan_for_atom_markers(token, at_pos, labels, branches)
if i > len then break end
local c = token:sub(i, i)
if c == '"' then
-- Skip string literal
i = i + 1
while i <= len do
if token:sub(i, i) == "\\" then i = i + 2
@@ -418,7 +435,6 @@ local function scan_for_atom_markers(token, at_pos, labels, branches)
else i = i + 1 end
end
elseif c == "'" then
-- Skip char literal
i = i + 1
while i <= len do
if token:sub(i, i) == "\\" then i = i + 2
@@ -438,36 +454,33 @@ local function scan_for_atom_markers(token, at_pos, labels, branches)
end
elseif is_alpha(c) then
local ident, after = read_ident(token, i)
if ident == "atom_label" or ident == "atom_offset" then
local arg_start = skip_ws_and_comments(token, after)
if token:sub(arg_start, arg_start) == "(" then
local inner, after_paren = read_parens(token, arg_start)
local n = 1
while n <= #inner and is_space(inner:sub(n, n)) do n = n + 1 end
local ns = n
while n <= #inner and is_alnum(inner:sub(n, n)) do n = n + 1 end
local name = inner:sub(ns, n - 1)
if name ~= "" then
if ident == "atom_label" then
labels[name] = at_pos
else
table.insert(branches, {pos = at_pos, target = name})
end
end
i = after_paren
else
i = arg_start
if ident == "atom_label" then
local args, after_paren = extract_ident_args(token, after)
if #args >= 1 then labels[args[1]] = at_pos end
if after_paren then i = after_paren else i = after end
elseif ident == "atom_offset" then
local args, after_paren = extract_ident_args(token, after)
if #args >= 2 then
table.insert(branches, {
pos = at_pos,
target = args[2],
tag = args[1]
})
end
if after_paren then i = after_paren else i = after end
else
i = after
end
else
-- Anything else (parens, brackets, braces, commas, operators) — walk past
i = i + 1
end
end
end
-- ============================================================
-- Scan atom body, count words, find markers
-- ============================================================
local function scan_atom_body(body, word_counts)
local pos = 0
local labels = {}
@@ -492,13 +505,17 @@ local function scan_atom_body(body, word_counts)
end
-- ============================================================
-- Token classification for atom detection
-- Find every MipsAtom_(name) { ... } in a source
-- ============================================================
-- Skip past storage-class / qualifier noise. These appear before MipsCode
-- in raw expanded forms: `static`, `const`, the user's `internal`/`LP_`/
-- `global` macros (which all expand to `static`), `RO_` (which expands to
-- a section attribute), plus standard C qualifiers.
local function has_prefix(s, prefix)
if #s < #prefix then return false end
for i = 1, #prefix do
if s:sub(i, i) ~= prefix:sub(i, i) then return false end
end
return true
end
local function skip_qualifiers(source, i)
local keywords = {
["static"]=true, ["const"]=true, ["volatile"]=true,
@@ -510,60 +527,37 @@ local function skip_qualifiers(source, i)
i = skip_ws_and_comments(source, i)
local ident, after = read_ident(source, i)
if not ident then return i end
if keywords[ident] then
i = after
else
return i
end
if keywords[ident] then i = after else return i end
end
end
-- Test whether `s` starts with literal `prefix` (no patterns).
local function has_prefix(s, prefix)
if #s < #prefix then return false end
for i = 1, #prefix do
if s:sub(i, i) ~= prefix:sub(i, i) then return false end
end
return true
end
-- ============================================================
-- Find every atom declaration in a source, both wrapped and raw
-- ============================================================
local function find_atoms(source_text)
local atoms = {}
local len = #source_text
local i = 1
-- First, scan inside source_text normally
local function try_wrapped_form(ident_pos)
local paren_pos = skip_ws_and_comments(source_text, ident_pos)
if source_text:sub(paren_pos, paren_pos) ~= "(" then
return nil -- not a MipsAtom_() call
end
local function try_wrapped(after_pos)
local paren_pos = skip_ws_and_comments(source_text, after_pos)
if source_text:sub(paren_pos, paren_pos) ~= "(" then return nil end
local inner, after_paren = read_parens(source_text, paren_pos)
-- Extract name (first identifier from inner)
local n = 1
while n <= #inner and is_space(inner:sub(n, n)) do n = n + 1 end
local ns = n
while n <= #inner and is_alnum(inner:sub(n, n)) do n = n + 1 end
local name = inner:sub(ns, n - 1)
if name == "" then return nil end
local brace_pos = scan_to_char(source_text, "{", after_paren)
if not brace_pos then return nil end
local body, after_brace = read_braces(source_text, brace_pos)
return {name = name, body = body, after_brace = after_brace}
end
local function try_raw_form(after_type_pos)
local next_pos = skip_ws_and_comments(source_text, after_type_pos)
local function try_raw(after_pos)
local next_pos = skip_ws_and_comments(source_text, after_pos)
local next_ident, next_after = read_ident(source_text, next_pos)
if not next_ident then return nil end
if not has_prefix(next_ident, "code_") then return nil end
if #next_ident <= 5 then return nil end -- bare "code_" — not an atom
if #next_ident <= 5 then return nil end
local atom_name = next_ident:sub(6)
local brace_pos = scan_to_char(source_text, "{", next_after)
if not brace_pos then return nil end
@@ -574,8 +568,6 @@ local function find_atoms(source_text)
while i <= len do
i = skip_ws_and_comments(source_text, i)
if i > len then break end
-- Skip past storage-class noise
i = skip_qualifiers(source_text, i)
if i > len then break end
@@ -583,34 +575,30 @@ local function find_atoms(source_text)
if not ident then
i = i + 1
elseif ident == "MipsAtom_" then
local atom = try_wrapped_form(after)
local atom = try_wrapped(after)
if atom then
table.insert(atoms, {name = atom.name, body = atom.body})
i = atom.after_brace
else
i = i + 1 -- not actually MipsAtom_(), skip and continue
i = i + 1
end
elseif ident == "MipsCode" then
local atom = try_raw_form(after)
local atom = try_raw(after)
if atom then
table.insert(atoms, {name = atom.name, body = atom.body})
i = atom.after_brace
else
i = after -- some other MipsCode use; skip just this token
i = after
end
else
-- Anything else: skip just this identifier. The next loop
-- iteration will see whatever follows (might be more qualifiers,
-- another type keyword, etc.).
i = after
end
end
return atoms
end
-- ============================================================
-- Compute branch offsets: target - branch - 1
-- Compute branch offsets (target - branch - 1)
-- ============================================================
local function compute_offsets(labels, branches)
@@ -618,9 +606,14 @@ local function compute_offsets(labels, branches)
for _, br in ipairs(branches) do
local target = labels[br.target]
if not target then
error("Branch target '" .. br.target .. "' has no atom_label (at word " .. br.pos .. ")")
error("Branch target '" .. br.target ..
"' has no atom_label (at word " .. br.pos .. ")")
end
table.insert(results, {target = br.target, offset = target - br.pos - 1})
table.insert(results, {
target = br.target,
tag = br.tag,
offset = target - br.pos - 1
})
end
return results
end
@@ -631,36 +624,59 @@ end
local function generate_header(source_path, atoms_data)
local basename = basename_no_ext(source_path)
local guard = to_alnum_underscore(to_upper(basename)) .. "_OFFSETS_H"
local guard = to_alnum_underscore(to_upper(basename)) .. "_OFFSETS_H"
local lines = {}
local function add(s) table.insert(lines, s) end
add("// Auto-generated by gen_atom_offsets.lua — DO NOT EDIT")
add("// Source: " .. source_path)
add("#ifndef " .. guard)
add("#define " .. guard)
add("#pragma once")
add("")
add("#pragma region " .. basename)
add("")
add("// Override the placeholder atom_offset() to dispatch via token pasting.")
add("// Dispatch macro: token-pastes <tag>_<target> to the enum name")
add("#undef atom_offset")
add("#define atom_offset(name) atom_offset_##name")
add("#define atom_offset(tag, name) atom_offset_##tag##_##name")
add("")
for _, atom in ipairs(atoms_data) do
add("// --- atom: " .. atom.name .. " (" .. atom.total_words .. " words) ---")
add("")
for _, r in ipairs(atom.offsets) do
local const_name = "atom_offset_" .. r.target
add("#define " .. pad_right(const_name, 40) .. " (" .. r.offset .. ")")
if #atom.offsets > 0 then
add("// --- atom: " .. atom.name .. " (" .. atom.total_words .. " words) ---")
add("")
-- Build constant list once
local consts = {}
for _, r in ipairs(atom.offsets) do
table.insert(consts, {
macro_name = "_atom_offset_" .. r.tag .. "_" .. r.target,
enum_name = "atom_offset_" .. r.tag .. "_" .. r.target,
value = r.offset
})
end
-- Macro form: single source of truth for the literal value.
-- Underscore prefix keeps it out of the C namespace so the
-- enum can use the same identifier name without conflict.
for _, c in ipairs(consts) do
add("#define " .. pad_right(c.macro_name, 44) .. " " .. c.value .. "")
end
add("")
-- Enum form: C code uses the natural name, value comes
-- from the underscore-prefixed macro so the literal is
-- defined in exactly one place.
add("enum {")
for _, c in ipairs(consts) do
add(" " .. c.enum_name .. " = " .. c.macro_name .. ",")
end
add("};")
add("")
end
add("")
end
add("#pragma endregion " .. basename)
add("")
add("#endif // " .. guard)
return table.concat(lines, "\n") .. "\n"
end
@@ -699,7 +715,7 @@ local function process_source(source_path, word_counts)
print(" " .. basename .. ": " .. #atoms_data .. " atom(s), " .. total_branches .. " branch(es)")
for _, a in ipairs(atoms_data) do
for _, r in ipairs(a.offsets) do
print(" " .. a.name .. " -> " .. r.target .. " : " .. r.offset)
print(" " .. a.name .. " -> " .. r.tag .. ":" .. r.target .. " : " .. r.offset)
end
end
end
@@ -713,11 +729,9 @@ local function main(args)
print("Usage: gen_atom_offsets.lua <metadata.h> <source1> [source2 ...]")
os.exit(1)
end
local metadata_path = args[1]
local sources = {}
for i = 2, #args do table.insert(sources, args[i]) end
local word_counts = load_word_counts(metadata_path)
for _, src in ipairs(sources) do process_source(src, word_counts) end
end