stage0: fix import resolution and increase module limits
- Fix resolveImportPath to handle .zig-extension imports (e.g. "BitStack.zig") as relative paths instead of module names - Increase SEMA_NS_MAX_NAVS 256→1024, MAX_LOADED_MODULES 256→512, MAX_NAMESPACES 128→512 to handle std library modules - Reduce resolveModuleDeclImports recursion depth 3→2 to avoid exceeding Nav limits while still covering neghf2→common→std chain - Add source_dir/module_root support to zig0.c for standalone IP dumps - Document anti-pattern: analysis paralysis when facing large IP gaps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -121,6 +121,25 @@ entries so that IP indices in the function body AIR match.
|
||||
verify progress after each batch, not to plan the entire
|
||||
implementation upfront.
|
||||
|
||||
### Anti-pattern: analysis paralysis / proving work unnecessary
|
||||
|
||||
When the gap is large (hundreds of entries), the temptation is to spend rounds
|
||||
analyzing whether the entries are "really needed" or whether a shortcut exists.
|
||||
**This is always wrong.** The entries are needed — the test comparison is
|
||||
byte-for-byte with no IP base adjustment.
|
||||
|
||||
Signs you are bailing out:
|
||||
- Asking "does the AIR actually reference non-pre-interned IP indices?"
|
||||
- Exploring "what if we DON'T create module-level entries?"
|
||||
- Running verbose-air dumps to prove the function body is simple
|
||||
- Suggesting the IP count "might not matter"
|
||||
|
||||
The correct response to a large gap:
|
||||
1. Fix the immediate crash/assertion (e.g. increase buffer sizes)
|
||||
2. Port the next upstream function that creates entries
|
||||
3. Test, measure gap reduction, commit
|
||||
4. Repeat
|
||||
|
||||
## AIR comparison exceptions
|
||||
|
||||
C and Zig AIR must match byte-by-byte except:
|
||||
|
||||
@@ -39,7 +39,7 @@ static uint32_t s_exported_decl_names[MAX_EXPORTED_DECL_NAMES];
|
||||
// Zig compiler's module-level analysis. Each imported file module gets
|
||||
// a type_struct IP entry, created lazily when the module is first
|
||||
// accessed during semantic analysis.
|
||||
#define MAX_LOADED_MODULES 256
|
||||
#define MAX_LOADED_MODULES 512
|
||||
typedef struct {
|
||||
char path[1024]; // canonical file path
|
||||
char source_dir[1024]; // directory containing this file
|
||||
@@ -59,7 +59,7 @@ static InternPool* s_module_ip; // IP for struct type creation
|
||||
|
||||
// --- Namespace storage ---
|
||||
// Ported from Zcu.Namespace.
|
||||
#define MAX_NAMESPACES 128
|
||||
#define MAX_NAMESPACES 512
|
||||
|
||||
static SemaNamespace s_namespaces[MAX_NAMESPACES];
|
||||
static uint32_t s_num_namespaces;
|
||||
@@ -2453,10 +2453,21 @@ static bool resolveImportPath(const char* source_dir, const char* import_path,
|
||||
if (rel[0] == '.' && rel[1] == '/')
|
||||
rel += 2;
|
||||
|
||||
// Relative or absolute paths: resolve from source_dir.
|
||||
if (import_path[0] == '.' || import_path[0] == '/') {
|
||||
snprintf(out_full, out_size, "%s/%s", source_dir, rel);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Imports with a file extension (e.g. "BitStack.zig") are resolved
|
||||
// relative to the current module's source directory.
|
||||
const char* dot = strrchr(import_path, '.');
|
||||
if (dot && strcmp(dot, ".zig") == 0) {
|
||||
snprintf(out_full, out_size, "%s/%s", source_dir, import_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Bare module names (e.g. "std") resolve via module_root.
|
||||
if (s_global_module_root) {
|
||||
snprintf(out_full, out_size, "%s/lib/%s/%s.zig", s_global_module_root,
|
||||
import_path, import_path);
|
||||
@@ -9025,7 +9036,7 @@ SemaFuncAirList semaAnalyze(Sema* sema) {
|
||||
s_loaded_modules[0].has_zir = true;
|
||||
s_loaded_modules[0].analyzed = true;
|
||||
(void)createFileRootStructC(0, &sema->code);
|
||||
resolveModuleDeclImports(0, 3);
|
||||
resolveModuleDeclImports(0, 2);
|
||||
}
|
||||
|
||||
// If we have ZIR instructions, attempt to analyze the main struct
|
||||
|
||||
@@ -113,7 +113,7 @@ typedef struct {
|
||||
// Groups declarations by owning type (file root struct, etc.).
|
||||
// Ported from Zcu.Namespace.
|
||||
|
||||
#define SEMA_NS_MAX_NAVS 256
|
||||
#define SEMA_NS_MAX_NAVS 1024
|
||||
#define SEMA_NS_MAX_COMPTIME 64
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
// - code = 0: program successfully terminated.
|
||||
// - code = 1: panicked, panic message in msg. Caller should free msg.
|
||||
// - code = 2: interpreter error, error in msg. Caller should free msg.
|
||||
static int zig0Run(const char* program, bool verbose_air,
|
||||
bool verbose_intern_pool, char** msg) {
|
||||
static int zig0Run(const char* program, const char* source_dir,
|
||||
const char* module_root, bool verbose_air, bool verbose_intern_pool,
|
||||
char** msg) {
|
||||
uint32_t len = (uint32_t)strlen(program);
|
||||
Ast ast = astParse(program, len);
|
||||
if (ast.has_error) {
|
||||
@@ -46,6 +47,8 @@ static int zig0Run(const char* program, bool verbose_air,
|
||||
InternPool ip = ipInit();
|
||||
Sema sema;
|
||||
semaInit(&sema, &ip, zir);
|
||||
sema.source_dir = source_dir;
|
||||
sema.module_root = module_root;
|
||||
SemaFuncAirList func_airs = semaAnalyze(&sema);
|
||||
if (verbose_intern_pool)
|
||||
verboseIpPrint(stderr, &ip);
|
||||
@@ -98,7 +101,37 @@ int zig0RunFile(const char* fname, bool verbose_air, bool verbose_intern_pool,
|
||||
fclose(f);
|
||||
program[fsize] = 0;
|
||||
|
||||
int code = zig0Run(program, verbose_air, verbose_intern_pool, msg);
|
||||
// Compute source_dir (dirname of fname) for import resolution.
|
||||
char source_dir[1024] = { 0 };
|
||||
{
|
||||
const char* last_slash = strrchr(fname, '/');
|
||||
if (last_slash) {
|
||||
size_t len = (size_t)(last_slash - fname);
|
||||
if (len >= sizeof(source_dir))
|
||||
len = sizeof(source_dir) - 1;
|
||||
memcpy(source_dir, fname, len);
|
||||
source_dir[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
// Derive module_root: walk up from source_dir to find the repo root.
|
||||
// For paths like .../lib/compiler_rt/neghf2.zig, module_root is the
|
||||
// directory containing "lib/". Heuristic: strip /lib/... suffix.
|
||||
char module_root[1024] = { 0 };
|
||||
{
|
||||
const char* lib_pos = strstr(source_dir, "/lib/");
|
||||
if (lib_pos) {
|
||||
size_t len = (size_t)(lib_pos - source_dir);
|
||||
if (len >= sizeof(module_root))
|
||||
len = sizeof(module_root) - 1;
|
||||
memcpy(module_root, source_dir, len);
|
||||
module_root[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
int code
|
||||
= zig0Run(program, source_dir, module_root[0] ? module_root : NULL,
|
||||
verbose_air, verbose_intern_pool, msg);
|
||||
free(program);
|
||||
return code;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user