astgen: implement namespace scopes, identifier resolution across scope boundaries
Add ScopeNamespace struct with per-namespace declaration tables and capture storage, replacing the flat decl_table on AstGenCtx. Implement tunnelThroughClosure for cross-namespace captures (closure_get ZIR instruction). Modify identifierExpr to walk past namespace scopes, checking namespace decls and tracking num_namespaces_out for proper closure tunneling. Key changes: - ScopeNamespace with decl_names/decl_nodes, capture_keys/capture_vals - scanContainer populates per-namespace decls instead of flat table - structDeclInner/enumDeclInner create namespace scopes, write captures - globalVarDecl/fnDecl/testDecl/comptimeDecl receive scope parameter - localVarRef properly tunnels through namespace boundaries - scopeParent helper for generic scope chain walking Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
574
stage0/astgen.c
574
stage0/astgen.c
@@ -79,12 +79,6 @@ typedef struct {
|
|||||||
ImportEntry* imports;
|
ImportEntry* imports;
|
||||||
uint32_t imports_len;
|
uint32_t imports_len;
|
||||||
uint32_t imports_cap;
|
uint32_t imports_cap;
|
||||||
// Namespace decl table: maps string indices to node indices.
|
|
||||||
// Populated by scanContainer, used by identifier resolution.
|
|
||||||
uint32_t* decl_names; // string indices
|
|
||||||
uint32_t* decl_nodes; // node indices
|
|
||||||
uint32_t decl_table_len;
|
|
||||||
uint32_t decl_table_cap;
|
|
||||||
// Shared dynamic array for GenZir instructions (AstGen.zig:11796).
|
// Shared dynamic array for GenZir instructions (AstGen.zig:11796).
|
||||||
// Sub-blocks share this array and track their slice via
|
// Sub-blocks share this array and track their slice via
|
||||||
// instructions_top.
|
// instructions_top.
|
||||||
@@ -304,6 +298,126 @@ typedef struct {
|
|||||||
uint32_t block_inst; // instruction index (not ref)
|
uint32_t block_inst; // instruction index (not ref)
|
||||||
} ScopeLabel;
|
} ScopeLabel;
|
||||||
|
|
||||||
|
// Scope.Namespace (AstGen.zig:11737-11762) — represents a type declaration
|
||||||
|
// scope (struct, enum, union, opaque) that has declarations in it.
|
||||||
|
typedef struct {
|
||||||
|
Scope base; // tag = SCOPE_NAMESPACE
|
||||||
|
Scope* parent;
|
||||||
|
uint32_t node; // AST node of the container decl
|
||||||
|
uint32_t inst; // instruction index of the container decl
|
||||||
|
GenZir* declaring_gz; // the GenZir containing this namespace
|
||||||
|
bool maybe_generic; // true if inside a function (astgen.within_fn)
|
||||||
|
// Per-namespace declaration table (maps name string index → node index).
|
||||||
|
uint32_t* decl_names;
|
||||||
|
uint32_t* decl_nodes;
|
||||||
|
uint32_t decl_len;
|
||||||
|
uint32_t decl_cap;
|
||||||
|
// Captures (populated by tunnelThroughClosure).
|
||||||
|
// Keys are packed Capture u32 values, values are NullTerminatedString.
|
||||||
|
uint32_t* capture_keys;
|
||||||
|
uint32_t* capture_vals;
|
||||||
|
uint32_t captures_len;
|
||||||
|
uint32_t captures_cap;
|
||||||
|
} ScopeNamespace;
|
||||||
|
|
||||||
|
// Initialize a ScopeNamespace on the stack.
|
||||||
|
static void scopeNamespaceInit(ScopeNamespace* ns, Scope* parent,
|
||||||
|
uint32_t node, uint32_t inst, GenZir* declaring_gz, bool maybe_generic) {
|
||||||
|
memset(ns, 0, sizeof(*ns));
|
||||||
|
ns->base.tag = SCOPE_NAMESPACE;
|
||||||
|
ns->parent = parent;
|
||||||
|
ns->node = node;
|
||||||
|
ns->inst = inst;
|
||||||
|
ns->declaring_gz = declaring_gz;
|
||||||
|
ns->maybe_generic = maybe_generic;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free dynamic arrays in a ScopeNamespace.
|
||||||
|
static void scopeNamespaceDeinit(ScopeNamespace* ns) {
|
||||||
|
free(ns->decl_names);
|
||||||
|
free(ns->decl_nodes);
|
||||||
|
free(ns->capture_keys);
|
||||||
|
free(ns->capture_vals);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a declaration to a namespace's decl table.
|
||||||
|
static void scopeNamespaceAddDecl(
|
||||||
|
ScopeNamespace* ns, uint32_t name_str, uint32_t decl_node) {
|
||||||
|
if (ns->decl_len >= ns->decl_cap) {
|
||||||
|
uint32_t new_cap = ns->decl_cap > 0 ? ns->decl_cap * 2 : 8;
|
||||||
|
uint32_t* n = realloc(ns->decl_names, new_cap * sizeof(uint32_t));
|
||||||
|
uint32_t* d = realloc(ns->decl_nodes, new_cap * sizeof(uint32_t));
|
||||||
|
if (!n || !d)
|
||||||
|
exit(1);
|
||||||
|
ns->decl_names = n;
|
||||||
|
ns->decl_nodes = d;
|
||||||
|
ns->decl_cap = new_cap;
|
||||||
|
}
|
||||||
|
ns->decl_names[ns->decl_len] = name_str;
|
||||||
|
ns->decl_nodes[ns->decl_len] = decl_node;
|
||||||
|
ns->decl_len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up a name in a namespace's decl table. Returns the node index,
|
||||||
|
// or UINT32_MAX if not found.
|
||||||
|
static uint32_t scopeNamespaceFindDecl(
|
||||||
|
const ScopeNamespace* ns, uint32_t name_str) {
|
||||||
|
for (uint32_t i = 0; i < ns->decl_len; i++) {
|
||||||
|
if (ns->decl_names[i] == name_str)
|
||||||
|
return ns->decl_nodes[i];
|
||||||
|
}
|
||||||
|
return UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a capture to a namespace. Returns the capture index (position).
|
||||||
|
// If the capture already exists, returns the existing index.
|
||||||
|
// key is a packed Capture u32 (3-bit tag | 29-bit data).
|
||||||
|
static uint32_t scopeNamespaceAddCapture(
|
||||||
|
ScopeNamespace* ns, uint32_t key, uint32_t name_str) {
|
||||||
|
// Check for existing capture with same key.
|
||||||
|
for (uint32_t i = 0; i < ns->captures_len; i++) {
|
||||||
|
if (ns->capture_keys[i] == key)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (ns->captures_len >= ns->captures_cap) {
|
||||||
|
uint32_t new_cap = ns->captures_cap > 0 ? ns->captures_cap * 2 : 4;
|
||||||
|
uint32_t* k = realloc(ns->capture_keys, new_cap * sizeof(uint32_t));
|
||||||
|
uint32_t* v = realloc(ns->capture_vals, new_cap * sizeof(uint32_t));
|
||||||
|
if (!k || !v)
|
||||||
|
exit(1);
|
||||||
|
ns->capture_keys = k;
|
||||||
|
ns->capture_vals = v;
|
||||||
|
ns->captures_cap = new_cap;
|
||||||
|
}
|
||||||
|
uint32_t idx = ns->captures_len;
|
||||||
|
ns->capture_keys[idx] = key;
|
||||||
|
ns->capture_vals[idx] = name_str;
|
||||||
|
ns->captures_len++;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk to a scope's parent. Returns NULL if there is no parent.
|
||||||
|
static Scope* scopeParent(Scope* s) {
|
||||||
|
switch (s->tag) {
|
||||||
|
case SCOPE_GEN_ZIR:
|
||||||
|
return ((GenZir*)s)->parent;
|
||||||
|
case SCOPE_LOCAL_VAL:
|
||||||
|
return ((ScopeLocalVal*)s)->parent;
|
||||||
|
case SCOPE_LOCAL_PTR:
|
||||||
|
return ((ScopeLocalPtr*)s)->parent;
|
||||||
|
case SCOPE_DEFER_NORMAL:
|
||||||
|
case SCOPE_DEFER_ERROR:
|
||||||
|
return ((ScopeDefer*)s)->parent;
|
||||||
|
case SCOPE_NAMESPACE:
|
||||||
|
return ((ScopeNamespace*)s)->parent;
|
||||||
|
case SCOPE_LABEL:
|
||||||
|
return ((ScopeLabel*)s)->parent;
|
||||||
|
case SCOPE_TOP:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// --- GenZir instruction helpers (AstGen.zig:11830-11850) ---
|
// --- GenZir instruction helpers (AstGen.zig:11830-11850) ---
|
||||||
|
|
||||||
// Returns the number of instructions in this scope.
|
// Returns the number of instructions in this scope.
|
||||||
@@ -612,6 +726,25 @@ static uint32_t addNodeExtended(
|
|||||||
return idx + ZIR_REF_START_INDEX;
|
return idx + ZIR_REF_START_INDEX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mirrors GenZir.addExtendedNodeSmall (AstGen.zig:12479-12499).
|
||||||
|
// Creates an extended instruction with operand = node offset and custom small.
|
||||||
|
static uint32_t addNodeExtendedSmall(
|
||||||
|
GenZir* gz, uint16_t opcode, uint32_t src_node, uint16_t small) {
|
||||||
|
AstGenCtx* ag = gz->astgen;
|
||||||
|
ensureInstCapacity(ag, 1);
|
||||||
|
uint32_t idx = ag->inst_len;
|
||||||
|
ag->inst_tags[idx] = ZIR_INST_EXTENDED;
|
||||||
|
ZirInstData data;
|
||||||
|
data.extended.opcode = opcode;
|
||||||
|
data.extended.small = small;
|
||||||
|
data.extended.operand
|
||||||
|
= (uint32_t)((int32_t)src_node - (int32_t)gz->decl_node_index);
|
||||||
|
ag->inst_datas[idx] = data;
|
||||||
|
ag->inst_len++;
|
||||||
|
gzAppendInstruction(gz, idx);
|
||||||
|
return idx + ZIR_REF_START_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
// Mirrors GenZir.addExtendedPayload (AstGen.zig:12781).
|
// Mirrors GenZir.addExtendedPayload (AstGen.zig:12781).
|
||||||
// Creates an extended instruction with given payload_index and small=0.
|
// Creates an extended instruction with given payload_index and small=0.
|
||||||
static uint32_t addExtendedPayload(
|
static uint32_t addExtendedPayload(
|
||||||
@@ -1873,28 +2006,10 @@ static void setStruct(AstGenCtx* ag, uint32_t inst, uint32_t src_node,
|
|||||||
|
|
||||||
// --- scanContainer (AstGen.zig:13384) ---
|
// --- scanContainer (AstGen.zig:13384) ---
|
||||||
|
|
||||||
// Add a name→node entry to the decl table.
|
|
||||||
static void addDeclToTable(
|
|
||||||
AstGenCtx* ag, uint32_t name_str_index, uint32_t node) {
|
|
||||||
if (ag->decl_table_len >= ag->decl_table_cap) {
|
|
||||||
uint32_t new_cap = ag->decl_table_cap > 0 ? ag->decl_table_cap * 2 : 8;
|
|
||||||
uint32_t* n = realloc(ag->decl_names, new_cap * sizeof(uint32_t));
|
|
||||||
uint32_t* d = realloc(ag->decl_nodes, new_cap * sizeof(uint32_t));
|
|
||||||
if (!n || !d)
|
|
||||||
exit(1);
|
|
||||||
ag->decl_names = n;
|
|
||||||
ag->decl_nodes = d;
|
|
||||||
ag->decl_table_cap = new_cap;
|
|
||||||
}
|
|
||||||
ag->decl_names[ag->decl_table_len] = name_str_index;
|
|
||||||
ag->decl_nodes[ag->decl_table_len] = node;
|
|
||||||
ag->decl_table_len++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mirrors scanContainer (AstGen.zig:13384).
|
// Mirrors scanContainer (AstGen.zig:13384).
|
||||||
// Also populates the decl table (namespace.decls) for identifier resolution.
|
// Populates the namespace's decl table for identifier resolution.
|
||||||
static uint32_t scanContainer(
|
static uint32_t scanContainer(AstGenCtx* ag, ScopeNamespace* ns,
|
||||||
AstGenCtx* ag, const uint32_t* members, uint32_t member_count) {
|
const uint32_t* members, uint32_t member_count) {
|
||||||
const Ast* tree = ag->tree;
|
const Ast* tree = ag->tree;
|
||||||
uint32_t decl_count = 0;
|
uint32_t decl_count = 0;
|
||||||
for (uint32_t i = 0; i < member_count; i++) {
|
for (uint32_t i = 0; i < member_count; i++) {
|
||||||
@@ -1908,7 +2023,7 @@ static uint32_t scanContainer(
|
|||||||
decl_count++;
|
decl_count++;
|
||||||
uint32_t name_token = tree->nodes.main_tokens[member] + 1;
|
uint32_t name_token = tree->nodes.main_tokens[member] + 1;
|
||||||
uint32_t name_str = identAsString(ag, name_token);
|
uint32_t name_str = identAsString(ag, name_token);
|
||||||
addDeclToTable(ag, name_str, member);
|
scopeNamespaceAddDecl(ns, name_str, member);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AST_NODE_FN_PROTO_SIMPLE:
|
case AST_NODE_FN_PROTO_SIMPLE:
|
||||||
@@ -1919,7 +2034,7 @@ static uint32_t scanContainer(
|
|||||||
decl_count++;
|
decl_count++;
|
||||||
uint32_t name_token = tree->nodes.main_tokens[member] + 1;
|
uint32_t name_token = tree->nodes.main_tokens[member] + 1;
|
||||||
uint32_t name_str = identAsString(ag, name_token);
|
uint32_t name_str = identAsString(ag, name_token);
|
||||||
addDeclToTable(ag, name_str, member);
|
scopeNamespaceAddDecl(ns, name_str, member);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Container fields: add field name to string table for ordering
|
// Container fields: add field name to string table for ordering
|
||||||
@@ -3525,6 +3640,234 @@ static uint32_t tryResolvePrimitiveIdent(GenZir* gz, uint32_t node) {
|
|||||||
return ZIR_REF_NONE;
|
return ZIR_REF_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capture tag values for packed Capture u32 (Zir.zig:3391-3435).
|
||||||
|
#define CAPTURE_TAG_NESTED 0
|
||||||
|
#define CAPTURE_TAG_INSTRUCTION 1
|
||||||
|
#define CAPTURE_TAG_INSTRUCTION_LOAD 2
|
||||||
|
#define CAPTURE_TAG_DECL_VAL 3
|
||||||
|
#define CAPTURE_TAG_DECL_REF 4
|
||||||
|
|
||||||
|
static uint32_t packCapture(uint32_t tag, uint32_t data) {
|
||||||
|
return (tag & 0x7u) | (data << 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mirrors tunnelThroughClosure (AstGen.zig:8526-8624).
|
||||||
|
// Access a ZIR instruction/decl through closure. May tunnel through
|
||||||
|
// arbitrarily many namespaces, adding closure captures as required.
|
||||||
|
// Returns the ref of the closure_get instruction added to gz.
|
||||||
|
//
|
||||||
|
// capture_tag: one of CAPTURE_TAG_* constants.
|
||||||
|
// capture_data: the instruction index or NullTerminatedString index.
|
||||||
|
static uint32_t tunnelThroughClosure(GenZir* gz, uint32_t inner_ref_node,
|
||||||
|
uint32_t num_tunnels, uint32_t capture_tag, uint32_t capture_data,
|
||||||
|
uint32_t name_str_index) {
|
||||||
|
// For trivial refs (instruction tag with data mapping to a non-index ref),
|
||||||
|
// no tunnel is needed. In the upstream, this checks if
|
||||||
|
// ref.toIndex()==null. A ref with index < ZIR_REF_START_INDEX is
|
||||||
|
// non-indexed (e.g. void, true).
|
||||||
|
if (capture_tag == CAPTURE_TAG_INSTRUCTION
|
||||||
|
&& capture_data + ZIR_REF_START_INDEX < ZIR_REF_START_INDEX) {
|
||||||
|
return capture_data + ZIR_REF_START_INDEX;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk gz->parent to find the namespace scopes we're tunneling through.
|
||||||
|
// The root namespace is the outermost (first found when counting
|
||||||
|
// num_tunnels-1 intermediate tunnels from the inside).
|
||||||
|
// Allocate on the stack for typical small counts.
|
||||||
|
ScopeNamespace* intermediates[16];
|
||||||
|
ScopeNamespace** inter = intermediates;
|
||||||
|
ScopeNamespace** inter_heap = NULL;
|
||||||
|
if (num_tunnels > 17) {
|
||||||
|
inter_heap = malloc((num_tunnels - 1) * sizeof(ScopeNamespace*));
|
||||||
|
if (!inter_heap)
|
||||||
|
exit(1);
|
||||||
|
inter = inter_heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the root namespace and intermediate tunnels (AstGen.zig:8568-8582).
|
||||||
|
ScopeNamespace* root_ns = NULL;
|
||||||
|
{
|
||||||
|
uint32_t remaining = num_tunnels - 1;
|
||||||
|
Scope* s = gz->parent;
|
||||||
|
while (s != NULL && remaining > 0) {
|
||||||
|
if (s->tag == SCOPE_NAMESPACE) {
|
||||||
|
remaining--;
|
||||||
|
inter[remaining] = (ScopeNamespace*)s;
|
||||||
|
}
|
||||||
|
s = scopeParent(s);
|
||||||
|
}
|
||||||
|
// Find the root namespace.
|
||||||
|
while (s != NULL) {
|
||||||
|
if (s->tag == SCOPE_NAMESPACE) {
|
||||||
|
root_ns = (ScopeNamespace*)s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s = scopeParent(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// root_ns must have been found — we are tunneling through at least one
|
||||||
|
// namespace, so there must be a root namespace in the scope chain.
|
||||||
|
if (root_ns == NULL) {
|
||||||
|
free(inter_heap);
|
||||||
|
SET_ERROR(gz->astgen);
|
||||||
|
return ZIR_REF_VOID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the root capture (AstGen.zig:8584-8594).
|
||||||
|
uint32_t root_capture = packCapture(capture_tag, capture_data);
|
||||||
|
uint32_t cur_capture_index
|
||||||
|
= scopeNamespaceAddCapture(root_ns, root_capture, name_str_index);
|
||||||
|
|
||||||
|
// Chain through intermediate namespaces (AstGen.zig:8596-8616).
|
||||||
|
for (uint32_t i = 0; i < num_tunnels - 1; i++) {
|
||||||
|
uint32_t nested_capture
|
||||||
|
= packCapture(CAPTURE_TAG_NESTED, cur_capture_index);
|
||||||
|
cur_capture_index = scopeNamespaceAddCapture(
|
||||||
|
inter[i], nested_capture, name_str_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(inter_heap);
|
||||||
|
|
||||||
|
// Add closure_get instruction (AstGen.zig:8622-8623).
|
||||||
|
return addNodeExtendedSmall(gz, (uint16_t)ZIR_EXT_CLOSURE_GET,
|
||||||
|
inner_ref_node, (uint16_t)cur_capture_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mirrors localVarRef (AstGen.zig:8367-8521).
|
||||||
|
static uint32_t localVarRef(GenZir* gz, Scope* scope, ResultLoc rl,
|
||||||
|
uint32_t node, uint32_t ident_token, uint32_t name_str) {
|
||||||
|
AstGenCtx* ag = gz->astgen;
|
||||||
|
uint32_t found_already = UINT32_MAX; // node index if found
|
||||||
|
bool found_needs_tunnel = false;
|
||||||
|
uint32_t found_namespaces_out = 0;
|
||||||
|
uint32_t num_namespaces_out = 0;
|
||||||
|
ScopeNamespace* capturing_namespace = NULL;
|
||||||
|
|
||||||
|
for (Scope* s = scope; s != NULL;) {
|
||||||
|
switch (s->tag) {
|
||||||
|
case SCOPE_LOCAL_VAL: {
|
||||||
|
ScopeLocalVal* lv = (ScopeLocalVal*)s;
|
||||||
|
if (lv->name == name_str) {
|
||||||
|
// Locals cannot shadow, no ambiguity check needed.
|
||||||
|
uint32_t value_inst;
|
||||||
|
if (num_namespaces_out != 0) {
|
||||||
|
value_inst = tunnelThroughClosure(gz, node,
|
||||||
|
num_namespaces_out, CAPTURE_TAG_INSTRUCTION,
|
||||||
|
lv->inst - ZIR_REF_START_INDEX, name_str);
|
||||||
|
} else {
|
||||||
|
value_inst = lv->inst;
|
||||||
|
}
|
||||||
|
return rvalueNoCoercePreRef(gz, rl, value_inst, node);
|
||||||
|
}
|
||||||
|
s = lv->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case SCOPE_LOCAL_PTR: {
|
||||||
|
ScopeLocalPtr* lp = (ScopeLocalPtr*)s;
|
||||||
|
if (lp->name == name_str) {
|
||||||
|
// Can't close over a runtime variable
|
||||||
|
// (AstGen.zig:8424-8432).
|
||||||
|
if (num_namespaces_out != 0 && !lp->maybe_comptime
|
||||||
|
&& !gz->is_typeof) {
|
||||||
|
SET_ERROR(ag);
|
||||||
|
return ZIR_REF_VOID_VALUE;
|
||||||
|
}
|
||||||
|
if (RL_IS_REF(rl)) {
|
||||||
|
uint32_t ptr_inst;
|
||||||
|
if (num_namespaces_out != 0) {
|
||||||
|
ptr_inst = tunnelThroughClosure(gz, node,
|
||||||
|
num_namespaces_out, CAPTURE_TAG_INSTRUCTION,
|
||||||
|
lp->ptr - ZIR_REF_START_INDEX, name_str);
|
||||||
|
} else {
|
||||||
|
ptr_inst = lp->ptr;
|
||||||
|
}
|
||||||
|
return ptr_inst;
|
||||||
|
} else {
|
||||||
|
uint32_t val_inst;
|
||||||
|
if (num_namespaces_out != 0) {
|
||||||
|
val_inst = tunnelThroughClosure(gz, node,
|
||||||
|
num_namespaces_out, CAPTURE_TAG_INSTRUCTION_LOAD,
|
||||||
|
lp->ptr - ZIR_REF_START_INDEX, name_str);
|
||||||
|
} else {
|
||||||
|
val_inst = addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node);
|
||||||
|
}
|
||||||
|
return rvalueNoCoercePreRef(gz, rl, val_inst, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s = lp->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case SCOPE_GEN_ZIR: {
|
||||||
|
s = ((GenZir*)s)->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case SCOPE_DEFER_NORMAL:
|
||||||
|
case SCOPE_DEFER_ERROR: {
|
||||||
|
s = ((ScopeDefer*)s)->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case SCOPE_LABEL: {
|
||||||
|
s = ((ScopeLabel*)s)->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case SCOPE_NAMESPACE: {
|
||||||
|
// Check namespace decls, then continue walking
|
||||||
|
// (AstGen.zig:8455-8472).
|
||||||
|
ScopeNamespace* ns = (ScopeNamespace*)s;
|
||||||
|
uint32_t decl_node = scopeNamespaceFindDecl(ns, name_str);
|
||||||
|
if (decl_node != UINT32_MAX) {
|
||||||
|
if (found_already != UINT32_MAX) {
|
||||||
|
// Ambiguous reference (AstGen.zig:8458-8462).
|
||||||
|
SET_ERROR(ag);
|
||||||
|
return ZIR_REF_VOID_VALUE;
|
||||||
|
}
|
||||||
|
found_already = decl_node;
|
||||||
|
found_needs_tunnel = ns->maybe_generic;
|
||||||
|
found_namespaces_out = num_namespaces_out;
|
||||||
|
}
|
||||||
|
num_namespaces_out++;
|
||||||
|
capturing_namespace = ns;
|
||||||
|
s = ns->parent;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case SCOPE_TOP:
|
||||||
|
goto done_walk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done_walk:
|
||||||
|
(void)capturing_namespace;
|
||||||
|
|
||||||
|
if (found_already == UINT32_MAX) {
|
||||||
|
SET_ERROR(ag);
|
||||||
|
return ZIR_REF_VOID_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decl references (AstGen.zig:8484-8520).
|
||||||
|
if (found_namespaces_out > 0 && found_needs_tunnel) {
|
||||||
|
if (RL_IS_REF(rl)) {
|
||||||
|
return tunnelThroughClosure(gz, node, found_namespaces_out,
|
||||||
|
CAPTURE_TAG_DECL_REF, name_str, name_str);
|
||||||
|
} else {
|
||||||
|
uint32_t result
|
||||||
|
= tunnelThroughClosure(gz, node, found_namespaces_out,
|
||||||
|
CAPTURE_TAG_DECL_VAL, name_str, name_str);
|
||||||
|
return rvalueNoCoercePreRef(gz, rl, result, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple decl reference (AstGen.zig:8512-8520).
|
||||||
|
ZirInstData data;
|
||||||
|
data.str_tok.start = name_str;
|
||||||
|
data.str_tok.src_tok = tokenIndexToRelative(gz, ident_token);
|
||||||
|
if (RL_IS_REF(rl)) {
|
||||||
|
return addInstruction(gz, ZIR_INST_DECL_REF, data);
|
||||||
|
} else {
|
||||||
|
uint32_t result = addInstruction(gz, ZIR_INST_DECL_VAL, data);
|
||||||
|
return rvalueNoCoercePreRef(gz, rl, result, node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t identifierExpr(
|
static uint32_t identifierExpr(
|
||||||
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
GenZir* gz, Scope* scope, ResultLoc rl, uint32_t node) {
|
||||||
AstGenCtx* ag = gz->astgen;
|
AstGenCtx* ag = gz->astgen;
|
||||||
@@ -3535,68 +3878,10 @@ static uint32_t identifierExpr(
|
|||||||
if (prim != ZIR_REF_NONE)
|
if (prim != ZIR_REF_NONE)
|
||||||
return rvalue(gz, rl, prim, node);
|
return rvalue(gz, rl, prim, node);
|
||||||
|
|
||||||
// Scope chain walk (AstGen.zig:8340-8461).
|
// Local variables and container-level declarations
|
||||||
uint32_t name_str = identAsString(ag, ident_token);
|
// (AstGen.zig:8340-8365).
|
||||||
for (Scope* s = scope; s != NULL;) {
|
return localVarRef(
|
||||||
switch (s->tag) {
|
gz, scope, rl, node, ident_token, identAsString(ag, ident_token));
|
||||||
case SCOPE_LOCAL_VAL: {
|
|
||||||
ScopeLocalVal* lv = (ScopeLocalVal*)s;
|
|
||||||
if (lv->name == name_str)
|
|
||||||
return rvalueNoCoercePreRef(gz, rl, lv->inst, node);
|
|
||||||
s = lv->parent;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case SCOPE_LOCAL_PTR: {
|
|
||||||
ScopeLocalPtr* lp = (ScopeLocalPtr*)s;
|
|
||||||
if (lp->name == name_str) {
|
|
||||||
if (RL_IS_REF(rl))
|
|
||||||
return lp->ptr;
|
|
||||||
uint32_t val = addUnNode(gz, ZIR_INST_LOAD, lp->ptr, node);
|
|
||||||
return rvalueNoCoercePreRef(gz, rl, val, node);
|
|
||||||
}
|
|
||||||
s = lp->parent;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case SCOPE_GEN_ZIR: {
|
|
||||||
GenZir* gzs = (GenZir*)s;
|
|
||||||
s = gzs->parent;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case SCOPE_DEFER_NORMAL:
|
|
||||||
case SCOPE_DEFER_ERROR: {
|
|
||||||
ScopeDefer* sd = (ScopeDefer*)s;
|
|
||||||
s = sd->parent;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case SCOPE_LABEL: {
|
|
||||||
ScopeLabel* sl = (ScopeLabel*)s;
|
|
||||||
s = sl->parent;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case SCOPE_NAMESPACE:
|
|
||||||
case SCOPE_TOP:
|
|
||||||
goto decl_table;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
decl_table:
|
|
||||||
|
|
||||||
// Decl table lookup (AstGen.zig:8462-8520).
|
|
||||||
for (uint32_t i = 0; i < ag->decl_table_len; i++) {
|
|
||||||
if (ag->decl_names[i] == name_str) {
|
|
||||||
ZirInstData data;
|
|
||||||
data.str_tok.start = name_str;
|
|
||||||
data.str_tok.src_tok = tokenIndexToRelative(gz, ident_token);
|
|
||||||
if (RL_IS_REF(rl)) {
|
|
||||||
return addInstruction(gz, ZIR_INST_DECL_REF, data);
|
|
||||||
} else {
|
|
||||||
uint32_t result = addInstruction(gz, ZIR_INST_DECL_VAL, data);
|
|
||||||
return rvalueNoCoercePreRef(gz, rl, result, node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_ERROR(ag);
|
|
||||||
return ZIR_REF_VOID_VALUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- fieldAccess (AstGen.zig:6154) ---
|
// --- fieldAccess (AstGen.zig:6154) ---
|
||||||
@@ -10598,8 +10883,8 @@ static uint32_t addFuncFancy(GenZir* gz, uint32_t src_node,
|
|||||||
|
|
||||||
// --- testDecl (AstGen.zig:4708) ---
|
// --- testDecl (AstGen.zig:4708) ---
|
||||||
|
|
||||||
static void testDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
static void testDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||||
uint32_t* decl_idx, uint32_t node) {
|
uint32_t* wip_decl_insts, uint32_t* decl_idx, uint32_t node) {
|
||||||
const Ast* tree = ag->tree;
|
const Ast* tree = ag->tree;
|
||||||
AstData nd = tree->nodes.datas[node];
|
AstData nd = tree->nodes.datas[node];
|
||||||
uint32_t body_node = nd.rhs;
|
uint32_t body_node = nd.rhs;
|
||||||
@@ -10640,7 +10925,7 @@ static void testDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir decl_block;
|
GenZir decl_block;
|
||||||
memset(&decl_block, 0, sizeof(decl_block));
|
memset(&decl_block, 0, sizeof(decl_block));
|
||||||
decl_block.base.tag = SCOPE_GEN_ZIR;
|
decl_block.base.tag = SCOPE_GEN_ZIR;
|
||||||
decl_block.parent = NULL;
|
decl_block.parent = scope;
|
||||||
decl_block.astgen = ag;
|
decl_block.astgen = ag;
|
||||||
decl_block.decl_node_index = node;
|
decl_block.decl_node_index = node;
|
||||||
decl_block.decl_line = decl_line;
|
decl_block.decl_line = decl_line;
|
||||||
@@ -10739,8 +11024,8 @@ static void testDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
// Handles function declarations with bodies (fn_decl) and
|
// Handles function declarations with bodies (fn_decl) and
|
||||||
// function prototypes without bodies (fn_proto*).
|
// function prototypes without bodies (fn_proto*).
|
||||||
|
|
||||||
static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||||
uint32_t* decl_idx, uint32_t node) {
|
uint32_t* wip_decl_insts, uint32_t* decl_idx, uint32_t node) {
|
||||||
const Ast* tree = ag->tree;
|
const Ast* tree = ag->tree;
|
||||||
AstNodeTag node_tag = tree->nodes.tags[node];
|
AstNodeTag node_tag = tree->nodes.tags[node];
|
||||||
AstData nd = tree->nodes.datas[node];
|
AstData nd = tree->nodes.datas[node];
|
||||||
@@ -10873,7 +11158,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir decl_gz;
|
GenZir decl_gz;
|
||||||
memset(&decl_gz, 0, sizeof(decl_gz));
|
memset(&decl_gz, 0, sizeof(decl_gz));
|
||||||
decl_gz.base.tag = SCOPE_GEN_ZIR;
|
decl_gz.base.tag = SCOPE_GEN_ZIR;
|
||||||
decl_gz.parent = NULL;
|
decl_gz.parent = scope;
|
||||||
decl_gz.astgen = ag;
|
decl_gz.astgen = ag;
|
||||||
decl_gz.decl_node_index = proto_node;
|
decl_gz.decl_node_index = proto_node;
|
||||||
decl_gz.decl_line = decl_line;
|
decl_gz.decl_line = decl_line;
|
||||||
@@ -11321,8 +11606,8 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
|
|
||||||
// --- comptimeDecl (AstGen.zig:4645) ---
|
// --- comptimeDecl (AstGen.zig:4645) ---
|
||||||
|
|
||||||
static void comptimeDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
static void comptimeDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||||
uint32_t* decl_idx, uint32_t node) {
|
uint32_t* wip_decl_insts, uint32_t* decl_idx, uint32_t node) {
|
||||||
// makeDeclaration before advanceSourceCursorToNode (AstGen.zig:4663-4665).
|
// makeDeclaration before advanceSourceCursorToNode (AstGen.zig:4663-4665).
|
||||||
uint32_t decl_inst = makeDeclaration(ag, node);
|
uint32_t decl_inst = makeDeclaration(ag, node);
|
||||||
wip_decl_insts[*decl_idx] = decl_inst;
|
wip_decl_insts[*decl_idx] = decl_inst;
|
||||||
@@ -11337,7 +11622,7 @@ static void comptimeDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir value_gz;
|
GenZir value_gz;
|
||||||
memset(&value_gz, 0, sizeof(value_gz));
|
memset(&value_gz, 0, sizeof(value_gz));
|
||||||
value_gz.base.tag = SCOPE_GEN_ZIR;
|
value_gz.base.tag = SCOPE_GEN_ZIR;
|
||||||
value_gz.parent = NULL;
|
value_gz.parent = scope;
|
||||||
value_gz.astgen = ag;
|
value_gz.astgen = ag;
|
||||||
value_gz.decl_node_index = node;
|
value_gz.decl_node_index = node;
|
||||||
value_gz.decl_line = decl_line;
|
value_gz.decl_line = decl_line;
|
||||||
@@ -11545,8 +11830,8 @@ static bool nameStratExpr(GenZir* gz, Scope* scope, ResultLoc rl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void globalVarDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
static void globalVarDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
|
||||||
uint32_t* decl_idx, uint32_t node) {
|
uint32_t* wip_decl_insts, uint32_t* decl_idx, uint32_t node) {
|
||||||
const Ast* tree = ag->tree;
|
const Ast* tree = ag->tree;
|
||||||
VarDeclInfo vd = extractVarDecl(tree, node);
|
VarDeclInfo vd = extractVarDecl(tree, node);
|
||||||
uint32_t name_token = vd.mut_token + 1;
|
uint32_t name_token = vd.mut_token + 1;
|
||||||
@@ -11607,6 +11892,7 @@ static void globalVarDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir type_gz;
|
GenZir type_gz;
|
||||||
memset(&type_gz, 0, sizeof(type_gz));
|
memset(&type_gz, 0, sizeof(type_gz));
|
||||||
type_gz.base.tag = SCOPE_GEN_ZIR;
|
type_gz.base.tag = SCOPE_GEN_ZIR;
|
||||||
|
type_gz.parent = scope;
|
||||||
type_gz.astgen = ag;
|
type_gz.astgen = ag;
|
||||||
type_gz.decl_node_index = node;
|
type_gz.decl_node_index = node;
|
||||||
type_gz.instructions_top = ag->scratch_inst_len;
|
type_gz.instructions_top = ag->scratch_inst_len;
|
||||||
@@ -11626,6 +11912,7 @@ static void globalVarDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir align_gz;
|
GenZir align_gz;
|
||||||
memset(&align_gz, 0, sizeof(align_gz));
|
memset(&align_gz, 0, sizeof(align_gz));
|
||||||
align_gz.base.tag = SCOPE_GEN_ZIR;
|
align_gz.base.tag = SCOPE_GEN_ZIR;
|
||||||
|
align_gz.parent = scope;
|
||||||
align_gz.astgen = ag;
|
align_gz.astgen = ag;
|
||||||
align_gz.decl_node_index = node;
|
align_gz.decl_node_index = node;
|
||||||
align_gz.instructions_top = type_top;
|
align_gz.instructions_top = type_top;
|
||||||
@@ -11651,6 +11938,7 @@ static void globalVarDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir linksection_gz;
|
GenZir linksection_gz;
|
||||||
memset(&linksection_gz, 0, sizeof(linksection_gz));
|
memset(&linksection_gz, 0, sizeof(linksection_gz));
|
||||||
linksection_gz.base.tag = SCOPE_GEN_ZIR;
|
linksection_gz.base.tag = SCOPE_GEN_ZIR;
|
||||||
|
linksection_gz.parent = scope;
|
||||||
linksection_gz.astgen = ag;
|
linksection_gz.astgen = ag;
|
||||||
linksection_gz.decl_node_index = node;
|
linksection_gz.decl_node_index = node;
|
||||||
linksection_gz.instructions_top = align_top;
|
linksection_gz.instructions_top = align_top;
|
||||||
@@ -11676,6 +11964,7 @@ static void globalVarDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir addrspace_gz;
|
GenZir addrspace_gz;
|
||||||
memset(&addrspace_gz, 0, sizeof(addrspace_gz));
|
memset(&addrspace_gz, 0, sizeof(addrspace_gz));
|
||||||
addrspace_gz.base.tag = SCOPE_GEN_ZIR;
|
addrspace_gz.base.tag = SCOPE_GEN_ZIR;
|
||||||
|
addrspace_gz.parent = scope;
|
||||||
addrspace_gz.astgen = ag;
|
addrspace_gz.astgen = ag;
|
||||||
addrspace_gz.decl_node_index = node;
|
addrspace_gz.decl_node_index = node;
|
||||||
addrspace_gz.instructions_top = linksection_top;
|
addrspace_gz.instructions_top = linksection_top;
|
||||||
@@ -11703,6 +11992,7 @@ static void globalVarDecl(AstGenCtx* ag, GenZir* gz, uint32_t* wip_decl_insts,
|
|||||||
GenZir value_gz;
|
GenZir value_gz;
|
||||||
memset(&value_gz, 0, sizeof(value_gz));
|
memset(&value_gz, 0, sizeof(value_gz));
|
||||||
value_gz.base.tag = SCOPE_GEN_ZIR;
|
value_gz.base.tag = SCOPE_GEN_ZIR;
|
||||||
|
value_gz.parent = scope;
|
||||||
value_gz.astgen = ag;
|
value_gz.astgen = ag;
|
||||||
value_gz.decl_node_index = node;
|
value_gz.decl_node_index = node;
|
||||||
value_gz.instructions_top = addrspace_top;
|
value_gz.instructions_top = addrspace_top;
|
||||||
@@ -12334,16 +12624,21 @@ static uint32_t enumDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
uint32_t decl_inst = reserveInstructionIndex(ag);
|
uint32_t decl_inst = reserveInstructionIndex(ag);
|
||||||
gzAppendInstruction(gz, decl_inst);
|
gzAppendInstruction(gz, decl_inst);
|
||||||
|
|
||||||
|
// Create namespace scope (AstGen.zig:5618-5623).
|
||||||
|
ScopeNamespace namespace;
|
||||||
|
scopeNamespaceInit(
|
||||||
|
&namespace, &gz->base, node, decl_inst, gz, ag->within_fn);
|
||||||
|
|
||||||
advanceSourceCursorToNode(ag, node);
|
advanceSourceCursorToNode(ag, node);
|
||||||
|
|
||||||
// scanContainer to register names in string table (AstGen.zig:5635).
|
// scanContainer to register names in string table (AstGen.zig:5635).
|
||||||
scanContainer(ag, members, members_len);
|
scanContainer(ag, &namespace, members, members_len);
|
||||||
|
|
||||||
// Set up block_scope for tag value expressions (AstGen.zig:5624-5632).
|
// Set up block_scope for tag value expressions (AstGen.zig:5624-5632).
|
||||||
GenZir block_scope;
|
GenZir block_scope;
|
||||||
memset(&block_scope, 0, sizeof(block_scope));
|
memset(&block_scope, 0, sizeof(block_scope));
|
||||||
block_scope.base.tag = SCOPE_GEN_ZIR;
|
block_scope.base.tag = SCOPE_GEN_ZIR;
|
||||||
block_scope.parent = NULL;
|
block_scope.parent = &namespace.base;
|
||||||
block_scope.astgen = ag;
|
block_scope.astgen = ag;
|
||||||
block_scope.decl_node_index = node;
|
block_scope.decl_node_index = node;
|
||||||
block_scope.decl_line = ag->source_line;
|
block_scope.decl_line = ag->source_line;
|
||||||
@@ -12368,19 +12663,23 @@ static uint32_t enumDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
AstNodeTag mtag = tree->nodes.tags[member_node];
|
AstNodeTag mtag = tree->nodes.tags[member_node];
|
||||||
switch (mtag) {
|
switch (mtag) {
|
||||||
case AST_NODE_COMPTIME:
|
case AST_NODE_COMPTIME:
|
||||||
comptimeDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
comptimeDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_SIMPLE_VAR_DECL:
|
case AST_NODE_SIMPLE_VAR_DECL:
|
||||||
case AST_NODE_GLOBAL_VAR_DECL:
|
case AST_NODE_GLOBAL_VAR_DECL:
|
||||||
case AST_NODE_LOCAL_VAR_DECL:
|
case AST_NODE_LOCAL_VAR_DECL:
|
||||||
case AST_NODE_ALIGNED_VAR_DECL:
|
case AST_NODE_ALIGNED_VAR_DECL:
|
||||||
globalVarDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
globalVarDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_FN_DECL:
|
case AST_NODE_FN_DECL:
|
||||||
fnDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
fnDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_TEST_DECL:
|
case AST_NODE_TEST_DECL:
|
||||||
testDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
testDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_CONTAINER_FIELD_INIT:
|
case AST_NODE_CONTAINER_FIELD_INIT:
|
||||||
case AST_NODE_CONTAINER_FIELD_ALIGN:
|
case AST_NODE_CONTAINER_FIELD_ALIGN:
|
||||||
@@ -12432,19 +12731,26 @@ static uint32_t enumDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
uint32_t body_len = countBodyLenAfterFixups(ag, body, raw_body_len);
|
uint32_t body_len = countBodyLenAfterFixups(ag, body, raw_body_len);
|
||||||
|
|
||||||
// setEnum (AstGen.zig:5705-5715).
|
// setEnum (AstGen.zig:5705-5715).
|
||||||
setEnum(ag, decl_inst, node, arg_inst, 0 /* captures_len */, body_len,
|
setEnum(ag, decl_inst, node, arg_inst, namespace.captures_len, body_len,
|
||||||
total_fields, decl_count, nonexhaustive, name_strategy);
|
total_fields, decl_count, nonexhaustive, name_strategy);
|
||||||
|
|
||||||
wipMembersFinishBitsEnum(&wm);
|
wipMembersFinishBitsEnum(&wm);
|
||||||
|
|
||||||
// Append trailing data (AstGen.zig:5718-5725):
|
// Append trailing data (AstGen.zig:5718-5725):
|
||||||
// captures (none), decls, body, fields.
|
// captures, decls, body, fields.
|
||||||
uint32_t decls_len_out;
|
uint32_t decls_len_out;
|
||||||
const uint32_t* decls_slice = wipMembersDeclsSlice(&wm, &decls_len_out);
|
const uint32_t* decls_slice = wipMembersDeclsSlice(&wm, &decls_len_out);
|
||||||
uint32_t fields_len_out;
|
uint32_t fields_len_out;
|
||||||
const uint32_t* fields_slice = wipMembersFieldsSlice(&wm, &fields_len_out);
|
const uint32_t* fields_slice = wipMembersFieldsSlice(&wm, &fields_len_out);
|
||||||
|
|
||||||
ensureExtraCapacity(ag, decls_len_out + body_len + fields_len_out);
|
ensureExtraCapacity(ag,
|
||||||
|
namespace.captures_len * 2 + decls_len_out + body_len
|
||||||
|
+ fields_len_out);
|
||||||
|
// Captures (AstGen.zig:5721-5722).
|
||||||
|
for (uint32_t i = 0; i < namespace.captures_len; i++)
|
||||||
|
ag->extra[ag->extra_len++] = namespace.capture_keys[i];
|
||||||
|
for (uint32_t i = 0; i < namespace.captures_len; i++)
|
||||||
|
ag->extra[ag->extra_len++] = namespace.capture_vals[i];
|
||||||
for (uint32_t i = 0; i < decls_len_out; i++)
|
for (uint32_t i = 0; i < decls_len_out; i++)
|
||||||
ag->extra[ag->extra_len++] = decls_slice[i];
|
ag->extra[ag->extra_len++] = decls_slice[i];
|
||||||
// Body instructions with fixups (AstGen.zig:5724).
|
// Body instructions with fixups (AstGen.zig:5724).
|
||||||
@@ -12456,6 +12762,7 @@ static uint32_t enumDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
|
|
||||||
gzUnstack(&block_scope);
|
gzUnstack(&block_scope);
|
||||||
wipMembersDeinit(&wm);
|
wipMembersDeinit(&wm);
|
||||||
|
scopeNamespaceDeinit(&namespace);
|
||||||
return decl_inst;
|
return decl_inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12669,9 +12976,15 @@ static uint32_t structDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Non-empty container (AstGen.zig:4973-5189).
|
// Non-empty container (AstGen.zig:4973-5189).
|
||||||
|
|
||||||
|
// Create namespace scope (AstGen.zig:4973-4979).
|
||||||
|
ScopeNamespace namespace;
|
||||||
|
scopeNamespaceInit(
|
||||||
|
&namespace, &gz->base, node, decl_inst, gz, ag->within_fn);
|
||||||
|
|
||||||
advanceSourceCursorToNode(ag, node);
|
advanceSourceCursorToNode(ag, node);
|
||||||
|
|
||||||
uint32_t decl_count = scanContainer(ag, members, members_len);
|
uint32_t decl_count = scanContainer(ag, &namespace, members, members_len);
|
||||||
uint32_t field_count = members_len - decl_count;
|
uint32_t field_count = members_len - decl_count;
|
||||||
|
|
||||||
WipMembers wm = wipMembersInit(decl_count, field_count);
|
WipMembers wm = wipMembersInit(decl_count, field_count);
|
||||||
@@ -12681,7 +12994,7 @@ static uint32_t structDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
GenZir block_scope;
|
GenZir block_scope;
|
||||||
memset(&block_scope, 0, sizeof(block_scope));
|
memset(&block_scope, 0, sizeof(block_scope));
|
||||||
block_scope.base.tag = SCOPE_GEN_ZIR;
|
block_scope.base.tag = SCOPE_GEN_ZIR;
|
||||||
block_scope.parent = NULL;
|
block_scope.parent = &namespace.base;
|
||||||
block_scope.astgen = ag;
|
block_scope.astgen = ag;
|
||||||
block_scope.decl_node_index = node;
|
block_scope.decl_node_index = node;
|
||||||
block_scope.decl_line = gz->decl_line; // Fix #7: use gz->decl_line
|
block_scope.decl_line = gz->decl_line; // Fix #7: use gz->decl_line
|
||||||
@@ -12730,29 +13043,35 @@ static uint32_t structDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
AstNodeTag mtag = tree->nodes.tags[member_node];
|
AstNodeTag mtag = tree->nodes.tags[member_node];
|
||||||
switch (mtag) {
|
switch (mtag) {
|
||||||
case AST_NODE_COMPTIME:
|
case AST_NODE_COMPTIME:
|
||||||
comptimeDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
comptimeDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_SIMPLE_VAR_DECL:
|
case AST_NODE_SIMPLE_VAR_DECL:
|
||||||
globalVarDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
globalVarDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_TEST_DECL:
|
case AST_NODE_TEST_DECL:
|
||||||
testDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
testDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_FN_DECL:
|
case AST_NODE_FN_DECL:
|
||||||
fnDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
fnDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
// fn_proto* dispatch (AstGen.zig:5809-5813, issue #9).
|
// fn_proto* dispatch (AstGen.zig:5809-5813, issue #9).
|
||||||
case AST_NODE_FN_PROTO_SIMPLE:
|
case AST_NODE_FN_PROTO_SIMPLE:
|
||||||
case AST_NODE_FN_PROTO_MULTI:
|
case AST_NODE_FN_PROTO_MULTI:
|
||||||
case AST_NODE_FN_PROTO_ONE:
|
case AST_NODE_FN_PROTO_ONE:
|
||||||
case AST_NODE_FN_PROTO:
|
case AST_NODE_FN_PROTO:
|
||||||
fnDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
fnDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_USINGNAMESPACE:
|
case AST_NODE_USINGNAMESPACE:
|
||||||
case AST_NODE_GLOBAL_VAR_DECL:
|
case AST_NODE_GLOBAL_VAR_DECL:
|
||||||
case AST_NODE_LOCAL_VAR_DECL:
|
case AST_NODE_LOCAL_VAR_DECL:
|
||||||
case AST_NODE_ALIGNED_VAR_DECL:
|
case AST_NODE_ALIGNED_VAR_DECL:
|
||||||
globalVarDecl(ag, gz, wm.payload, &wm.decl_index, member_node);
|
globalVarDecl(ag, gz, &namespace.base, wm.payload, &wm.decl_index,
|
||||||
|
member_node);
|
||||||
break;
|
break;
|
||||||
case AST_NODE_CONTAINER_FIELD_INIT:
|
case AST_NODE_CONTAINER_FIELD_INIT:
|
||||||
case AST_NODE_CONTAINER_FIELD_ALIGN:
|
case AST_NODE_CONTAINER_FIELD_ALIGN:
|
||||||
@@ -12929,6 +13248,7 @@ static uint32_t structDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
// setStruct (AstGen.zig:5152-5166).
|
// setStruct (AstGen.zig:5152-5166).
|
||||||
StructDeclSmall small;
|
StructDeclSmall small;
|
||||||
memset(&small, 0, sizeof(small));
|
memset(&small, 0, sizeof(small));
|
||||||
|
small.has_captures_len = (namespace.captures_len > 0);
|
||||||
small.has_decls_len = (decl_count > 0);
|
small.has_decls_len = (decl_count > 0);
|
||||||
small.has_fields_len = (field_count > 0);
|
small.has_fields_len = (field_count > 0);
|
||||||
small.has_backing_int = (backing_int_ref != ZIR_REF_NONE);
|
small.has_backing_int = (backing_int_ref != ZIR_REF_NONE);
|
||||||
@@ -12939,9 +13259,10 @@ static uint32_t structDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
small.any_aligned_fields = any_aligned_fields;
|
small.any_aligned_fields = any_aligned_fields;
|
||||||
small.layout = layout;
|
small.layout = layout;
|
||||||
small.name_strategy = name_strategy;
|
small.name_strategy = name_strategy;
|
||||||
setStruct(ag, decl_inst, node, small, 0, field_count, decl_count);
|
setStruct(ag, decl_inst, node, small, namespace.captures_len, field_count,
|
||||||
|
decl_count);
|
||||||
|
|
||||||
// Append: captures (none), backing_int, decls, fields, bodies
|
// Append: captures, backing_int, decls, fields, bodies
|
||||||
// (AstGen.zig:5172-5186).
|
// (AstGen.zig:5172-5186).
|
||||||
uint32_t decls_len;
|
uint32_t decls_len;
|
||||||
const uint32_t* decls_slice = wipMembersDeclsSlice(&wm, &decls_len);
|
const uint32_t* decls_slice = wipMembersDeclsSlice(&wm, &decls_len);
|
||||||
@@ -12955,8 +13276,14 @@ static uint32_t structDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
ag, backing_int_body_raw, backing_int_body_raw_len);
|
ag, backing_int_body_raw, backing_int_body_raw_len);
|
||||||
}
|
}
|
||||||
ensureExtraCapacity(ag,
|
ensureExtraCapacity(ag,
|
||||||
(backing_int_ref != ZIR_REF_NONE ? backing_int_body_len + 2 : 0)
|
namespace.captures_len * 2
|
||||||
|
+ (backing_int_ref != ZIR_REF_NONE ? backing_int_body_len + 2 : 0)
|
||||||
+ decls_len + fields_len + wm.bodies_len);
|
+ decls_len + fields_len + wm.bodies_len);
|
||||||
|
// Captures (AstGen.zig:5174-5175).
|
||||||
|
for (uint32_t i = 0; i < namespace.captures_len; i++)
|
||||||
|
ag->extra[ag->extra_len++] = namespace.capture_keys[i];
|
||||||
|
for (uint32_t i = 0; i < namespace.captures_len; i++)
|
||||||
|
ag->extra[ag->extra_len++] = namespace.capture_vals[i];
|
||||||
// backing_int (AstGen.zig:5176-5183).
|
// backing_int (AstGen.zig:5176-5183).
|
||||||
if (backing_int_ref != ZIR_REF_NONE) {
|
if (backing_int_ref != ZIR_REF_NONE) {
|
||||||
ag->extra[ag->extra_len++] = backing_int_body_len;
|
ag->extra[ag->extra_len++] = backing_int_body_len;
|
||||||
@@ -12977,6 +13304,7 @@ static uint32_t structDeclInner(AstGenCtx* ag, GenZir* gz, uint32_t node,
|
|||||||
|
|
||||||
gzUnstack(&block_scope);
|
gzUnstack(&block_scope);
|
||||||
wipMembersDeinit(&wm);
|
wipMembersDeinit(&wm);
|
||||||
|
scopeNamespaceDeinit(&namespace);
|
||||||
return decl_inst;
|
return decl_inst;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14254,8 +14582,6 @@ Zir astGen(const Ast* ast) {
|
|||||||
zir.has_compile_errors = ag.has_compile_errors;
|
zir.has_compile_errors = ag.has_compile_errors;
|
||||||
|
|
||||||
free(ag.imports);
|
free(ag.imports);
|
||||||
free(ag.decl_names);
|
|
||||||
free(ag.decl_nodes);
|
|
||||||
free(ag.scratch_instructions);
|
free(ag.scratch_instructions);
|
||||||
free(ag.scratch_extra);
|
free(ag.scratch_extra);
|
||||||
free(ag.ref_table_keys);
|
free(ag.ref_table_keys);
|
||||||
|
|||||||
@@ -853,7 +853,7 @@ test "astgen: corpus astgen_test.zig" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "astgen: corpus array_list.zig" {
|
test "astgen: corpus array_list.zig" {
|
||||||
if (true) return error.SkipZigTest; // TODO: identifier resolution across namespace scopes (fn params in returned struct)
|
if (true) return error.SkipZigTest; // TODO: missing assign_destructure handler
|
||||||
const gpa = std.testing.allocator;
|
const gpa = std.testing.allocator;
|
||||||
try corpusCheck(gpa, @embedFile("../lib/std/array_list.zig"));
|
try corpusCheck(gpa, @embedFile("../lib/std/array_list.zig"));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user