IR: all structs anonymous

This commit is contained in:
Andrew Kelley 2016-12-18 16:56:50 -05:00
parent 2e6aa6d813
commit e50ced44a2
11 changed files with 167 additions and 196 deletions

View File

@ -38,7 +38,6 @@ include_directories(
) )
set(ZIG_SOURCES set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/ir.cpp"
"${CMAKE_SOURCE_DIR}/src/analyze.cpp" "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
"${CMAKE_SOURCE_DIR}/src/ast_render.cpp" "${CMAKE_SOURCE_DIR}/src/ast_render.cpp"
"${CMAKE_SOURCE_DIR}/src/bignum.cpp" "${CMAKE_SOURCE_DIR}/src/bignum.cpp"
@ -48,6 +47,7 @@ set(ZIG_SOURCES
"${CMAKE_SOURCE_DIR}/src/errmsg.cpp" "${CMAKE_SOURCE_DIR}/src/errmsg.cpp"
"${CMAKE_SOURCE_DIR}/src/error.cpp" "${CMAKE_SOURCE_DIR}/src/error.cpp"
"${CMAKE_SOURCE_DIR}/src/eval.cpp" "${CMAKE_SOURCE_DIR}/src/eval.cpp"
"${CMAKE_SOURCE_DIR}/src/ir.cpp"
"${CMAKE_SOURCE_DIR}/src/ir_print.cpp" "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
"${CMAKE_SOURCE_DIR}/src/link.cpp" "${CMAKE_SOURCE_DIR}/src/link.cpp"
"${CMAKE_SOURCE_DIR}/src/main.cpp" "${CMAKE_SOURCE_DIR}/src/main.cpp"

View File

@ -7,7 +7,7 @@ Root = many(TopLevelItem) "EOF"
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | TypeDecl | UseDecl) TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl)
TypeDecl = "type" Symbol "=" TypeExpr ";" TypeDecl = "type" Symbol "=" TypeExpr ";"
@ -17,9 +17,7 @@ GlobalVarDecl = VariableDeclaration ";"
VariableDeclaration = option("inline") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression VariableDeclaration = option("inline") ("var" | "const") Symbol option(":" TypeExpr) "=" Expression
ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}" StructMember = (StructField | FnDef | GlobalVarDecl)
StructMember = (StructField | FnDef | GlobalVarDecl | ContainerDecl)
StructField = Symbol option(":" Expression) ",") StructField = Symbol option(":" Expression) ",")
@ -143,7 +141,7 @@ StructLiteralField = "." Symbol "=" Expression
PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%" PrefixOp = "!" | "-" | "~" | "*" | ("&" option("const")) | "?" | "%" | "%%" | "??" | "-%"
PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
ArrayType = "[" option(Expression) "]" option("const") TypeExpr ArrayType = "[" option(Expression) "]" option("const") TypeExpr
@ -152,6 +150,9 @@ GotoExpression = option("inline") "goto" Symbol
GroupedExpression = "(" Expression ")" GroupedExpression = "(" Expression ")"
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this"
ContainerDecl = ("struct" | "enum" | "union") "{" many(StructMember) "}"
``` ```
## Operator Precedence ## Operator Precedence

View File

@ -44,6 +44,7 @@ struct IrGotoItem {
struct IrExecutable { struct IrExecutable {
ZigList<IrBasicBlock *> basic_block_list; ZigList<IrBasicBlock *> basic_block_list;
Buf *name;
size_t mem_slot_count; size_t mem_slot_count;
size_t next_debug_id; size_t next_debug_id;
size_t *backward_branch_count; size_t *backward_branch_count;
@ -195,7 +196,6 @@ struct Tld {
// set this flag temporarily to detect infinite loops // set this flag temporarily to detect infinite loops
bool dep_loop_flag; bool dep_loop_flag;
TldResolution resolution; TldResolution resolution;
Tld *parent_tld;
}; };
struct TldVar { struct TldVar {
@ -594,12 +594,8 @@ enum ContainerKind {
ContainerKindUnion, ContainerKindUnion,
}; };
struct AstNodeStructDecl { struct AstNodeContainerDecl {
VisibMod visib_mod;
Buf *name;
ContainerKind kind; ContainerKind kind;
ZigList<AstNode *> generic_params;
bool generic_params_is_var_args; // always an error but it can happen from parsing
ZigList<AstNode *> fields; ZigList<AstNode *> fields;
ZigList<AstNode *> decls; ZigList<AstNode *> decls;
}; };
@ -722,7 +718,7 @@ struct AstNode {
AstNodeGoto goto_expr; AstNodeGoto goto_expr;
AstNodeAsmExpr asm_expr; AstNodeAsmExpr asm_expr;
AstNodeFieldAccessExpr field_access_expr; AstNodeFieldAccessExpr field_access_expr;
AstNodeStructDecl struct_decl; AstNodeContainerDecl container_decl;
AstNodeStructField struct_field; AstNodeStructField struct_field;
AstNodeStringLiteral string_literal; AstNodeStringLiteral string_literal;
AstNodeCharLiteral char_literal; AstNodeCharLiteral char_literal;

View File

@ -831,10 +831,7 @@ static TypeTableEntryId container_to_type(ContainerKind kind) {
zig_unreachable(); zig_unreachable();
} }
TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, Scope *scope, TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name) {
ContainerKind kind, AstNode *decl_node, const char *name)
{
TypeTableEntryId type_id = container_to_type(kind); TypeTableEntryId type_id = container_to_type(kind);
TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope); TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, scope);
@ -852,6 +849,7 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
unsigned line = decl_node->line; unsigned line = decl_node->line;
ImportTableEntry *import = get_scope_import(scope);
entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), name); entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), name);
entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder,
ZigLLVMTag_DW_structure_type(), name, ZigLLVMTag_DW_structure_type(), name,
@ -862,15 +860,6 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
return entry; return entry;
} }
static TypeTableEntry *get_partial_container_type_tld(CodeGen *g, Scope *scope, TldContainer *tld_container) {
ImportTableEntry *import = tld_container->base.import;
AstNode *container_node = tld_container->base.source_node;
assert(container_node->type == NodeTypeContainerDecl);
ContainerKind kind = container_node->data.struct_decl.kind;
return get_partial_container_type(g, import, scope, kind, container_node, buf_ptr(tld_container->base.name));
}
TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) { TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {
if (type_entry->id == TypeTableEntryIdTypeDecl) { if (type_entry->id == TypeTableEntryIdTypeDecl) {
return type_entry->data.type_decl.canonical_type; return type_entry->data.type_decl.canonical_type;
@ -879,15 +868,15 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry) {
} }
} }
static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, TypeTableEntry *type_entry) { static IrInstruction *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, TypeTableEntry *type_entry, Buf *type_name) {
size_t backward_branch_count = 0; size_t backward_branch_count = 0;
return ir_eval_const_value(g, scope, node, type_entry, return ir_eval_const_value(g, scope, node, type_entry,
&backward_branch_count, default_backward_branch_quota, &backward_branch_count, default_backward_branch_quota,
nullptr, nullptr, node); nullptr, nullptr, node, type_name);
} }
TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type); IrInstruction *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr);
if (result->type_entry->id == TypeTableEntryIdInvalid) if (result->type_entry->id == TypeTableEntryIdInvalid)
return g->builtin_types.entry_invalid; return g->builtin_types.entry_invalid;
@ -1069,7 +1058,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
assert(decl_node->type == NodeTypeContainerDecl); assert(decl_node->type == NodeTypeContainerDecl);
assert(enum_type->di_type); assert(enum_type->di_type);
uint32_t field_count = decl_node->data.struct_decl.fields.length; uint32_t field_count = decl_node->data.container_decl.fields.length;
enum_type->data.enumeration.src_field_count = field_count; enum_type->data.enumeration.src_field_count = field_count;
enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count); enum_type->data.enumeration.fields = allocate<TypeEnumField>(field_count);
@ -1091,7 +1080,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
size_t gen_field_index = 0; size_t gen_field_index = 0;
for (uint32_t i = 0; i < field_count; i += 1) { for (uint32_t i = 0; i < field_count; i += 1) {
AstNode *field_node = decl_node->data.struct_decl.fields.at(i); AstNode *field_node = decl_node->data.container_decl.fields.at(i);
TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i];
type_enum_field->name = field_node->data.struct_field.name; type_enum_field->name = field_node->data.struct_field.name;
TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); TypeTableEntry *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type);
@ -1201,7 +1190,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref); uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, enum_type->type_ref);
ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
ZigLLVMFileToScope(import->di_file), ZigLLVMFileToScope(import->di_file),
buf_ptr(decl_node->data.struct_decl.name), buf_ptr(&enum_type->name),
import->di_file, decl_node->line + 1, import->di_file, decl_node->line + 1,
debug_size_in_bits, debug_size_in_bits,
debug_align_in_bits, debug_align_in_bits,
@ -1217,7 +1206,7 @@ static void resolve_enum_type(CodeGen *g, TypeTableEntry *enum_type) {
uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref); uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type_entry->type_ref);
uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, tag_type_entry->type_ref); uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, tag_type_entry->type_ref);
ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder,
ZigLLVMFileToScope(import->di_file), buf_ptr(decl_node->data.struct_decl.name), ZigLLVMFileToScope(import->di_file), buf_ptr(&enum_type->name),
import->di_file, decl_node->line + 1, import->di_file, decl_node->line + 1,
tag_debug_size_in_bits, tag_debug_size_in_bits,
tag_debug_align_in_bits, tag_debug_align_in_bits,
@ -1257,7 +1246,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
assert(decl_node->type == NodeTypeContainerDecl); assert(decl_node->type == NodeTypeContainerDecl);
assert(struct_type->di_type); assert(struct_type->di_type);
size_t field_count = decl_node->data.struct_decl.fields.length; size_t field_count = decl_node->data.container_decl.fields.length;
struct_type->data.structure.src_field_count = field_count; struct_type->data.structure.src_field_count = field_count;
struct_type->data.structure.fields = allocate<TypeStructField>(field_count); struct_type->data.structure.fields = allocate<TypeStructField>(field_count);
@ -1274,7 +1263,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
size_t gen_field_index = 0; size_t gen_field_index = 0;
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
AstNode *field_node = decl_node->data.struct_decl.fields.at(i); AstNode *field_node = decl_node->data.container_decl.fields.at(i);
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
type_struct_field->name = field_node->data.struct_field.name; type_struct_field->name = field_node->data.struct_field.name;
TypeTableEntry *field_type = analyze_type_expr(g, scope, TypeTableEntry *field_type = analyze_type_expr(g, scope,
@ -1316,7 +1305,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(gen_field_count); ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(gen_field_count);
for (size_t i = 0; i < field_count; i += 1) { for (size_t i = 0; i < field_count; i += 1) {
AstNode *field_node = decl_node->data.struct_decl.fields.at(i); AstNode *field_node = decl_node->data.container_decl.fields.at(i);
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
gen_field_index = type_struct_field->gen_index; gen_field_index = type_struct_field->gen_index;
if (gen_field_index == SIZE_MAX) { if (gen_field_index == SIZE_MAX) {
@ -1348,7 +1337,7 @@ static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) {
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, struct_type->type_ref); uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, struct_type->type_ref);
ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder,
ZigLLVMFileToScope(import->di_file), ZigLLVMFileToScope(import->di_file),
buf_ptr(decl_node->data.struct_decl.name), buf_ptr(&struct_type->name),
import->di_file, decl_node->line + 1, import->di_file, decl_node->line + 1,
debug_size_in_bits, debug_size_in_bits,
debug_align_in_bits, debug_align_in_bits,
@ -1364,14 +1353,28 @@ static void resolve_union_type(CodeGen *g, TypeTableEntry *union_type) {
zig_panic("TODO"); zig_panic("TODO");
} }
static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) { static void get_fully_qualified_decl_name_internal(Buf *buf, Scope *scope, uint8_t sep) {
if (tld->parent_tld) { if (!scope)
get_fully_qualified_decl_name(buf, tld->parent_tld, sep); return;
buf_append_char(buf, sep);
buf_append_buf(buf, tld->name); if (scope->id == ScopeIdDecls) {
} else { get_fully_qualified_decl_name_internal(buf, scope->parent, sep);
buf_init_from_buf(buf, tld->name);
ScopeDecls *scope_decls = (ScopeDecls *)scope;
if (scope_decls->container_type) {
buf_append_buf(buf, &scope_decls->container_type->name);
buf_append_char(buf, sep);
}
return;
} }
get_fully_qualified_decl_name_internal(buf, scope->parent, sep);
}
static void get_fully_qualified_decl_name(Buf *buf, Tld *tld, uint8_t sep) {
buf_resize(buf, 0);
get_fully_qualified_decl_name_internal(buf, tld->parent_scope, sep);
buf_append_buf(buf, tld->name);
} }
FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) { FnTableEntry *create_fn_raw(FnInline inline_value, bool internal_linkage) {
@ -1401,6 +1404,17 @@ FnTableEntry *create_fn(AstNode *proto_node) {
return fn_entry; return fn_entry;
} }
static bool scope_is_root_decls(Scope *scope) {
while (scope) {
if (scope->id == ScopeIdDecls) {
ScopeDecls *scope_decls = (ScopeDecls *)scope;
return (scope_decls->container_type == nullptr);
}
scope = scope->parent;
}
zig_unreachable();
}
static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
ImportTableEntry *import = tld_fn->base.import; ImportTableEntry *import = tld_fn->base.import;
AstNode *proto_node = tld_fn->base.source_node; AstNode *proto_node = tld_fn->base.source_node;
@ -1448,9 +1462,8 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
if (fn_def_node) if (fn_def_node)
g->fn_defs.append(fn_table_entry); g->fn_defs.append(fn_table_entry);
Tld *parent_tld = tld_fn->base.parent_tld; bool is_main_fn = scope_is_root_decls(tld_fn->base.parent_scope) &&
bool is_main_fn = !parent_tld && (import == g->root_import) && (import == g->root_import) && buf_eql_str(&fn_table_entry->symbol_name, "main");
buf_eql_str(&fn_table_entry->symbol_name, "main");
if (is_main_fn) if (is_main_fn)
g->main_fn = fn_table_entry; g->main_fn = fn_table_entry;
@ -1480,23 +1493,6 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
} }
} }
static void scan_struct_decl(CodeGen *g, ScopeDecls *decls_scope, TldContainer *tld_container) {
assert(!tld_container->type_entry);
AstNode *container_node = tld_container->base.source_node;
assert(container_node->type == NodeTypeContainerDecl);
TypeTableEntry *container_type = get_partial_container_type_tld(g, &decls_scope->base, tld_container);
tld_container->type_entry = container_type;
// handle the member function definitions independently
for (size_t i = 0; i < container_node->data.struct_decl.decls.length; i += 1) {
AstNode *child_node = container_node->data.struct_decl.decls.at(i);
ScopeDecls *child_scope = get_container_scope(container_type);
scan_decls(g, tld_container->base.import, child_scope, child_node, &tld_container->base);
}
}
static void preview_error_value_decl(CodeGen *g, AstNode *node) { static void preview_error_value_decl(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeErrorValueDecl); assert(node->type == NodeTypeErrorValueDecl);
@ -1525,7 +1521,7 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
} }
void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node,
Scope *parent_scope, Tld *parent_tld) Scope *parent_scope)
{ {
tld->id = id; tld->id = id;
tld->name = name; tld->name = name;
@ -1533,40 +1529,25 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source
tld->source_node = source_node; tld->source_node = source_node;
tld->import = source_node->owner; tld->import = source_node->owner;
tld->parent_scope = parent_scope; tld->parent_scope = parent_scope;
tld->parent_tld = parent_tld;
} }
void scan_decls(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, AstNode *node, Tld *parent_tld) { void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
switch (node->type) { switch (node->type) {
case NodeTypeRoot: case NodeTypeRoot:
for (size_t i = 0; i < import->root->data.root.top_level_decls.length; i += 1) { for (size_t i = 0; i < node->data.root.top_level_decls.length; i += 1) {
AstNode *child = import->root->data.root.top_level_decls.at(i); AstNode *child = node->data.root.top_level_decls.at(i);
scan_decls(g, import, decls_scope, child, parent_tld); scan_decls(g, decls_scope, child);
}
break;
case NodeTypeContainerDecl:
{
Buf *name = node->data.struct_decl.name;
VisibMod visib_mod = node->data.struct_decl.visib_mod;
TldContainer *tld_container = allocate<TldContainer>(1);
init_tld(&tld_container->base, TldIdContainer, name, visib_mod, node, &decls_scope->base, parent_tld);
add_top_level_decl(g, decls_scope, &tld_container->base);
if (node->data.struct_decl.generic_params.length == 0) {
scan_struct_decl(g, decls_scope, tld_container);
} else {
zig_panic("TODO all structs anonymous?");
}
} }
break; break;
case NodeTypeFnDef: case NodeTypeFnDef:
scan_decls(g, import, decls_scope, node->data.fn_def.fn_proto, parent_tld); scan_decls(g, decls_scope, node->data.fn_def.fn_proto);
break; break;
case NodeTypeVariableDeclaration: case NodeTypeVariableDeclaration:
{ {
Buf *name = node->data.variable_declaration.symbol; Buf *name = node->data.variable_declaration.symbol;
VisibMod visib_mod = node->data.variable_declaration.visib_mod; VisibMod visib_mod = node->data.variable_declaration.visib_mod;
TldVar *tld_var = allocate<TldVar>(1); TldVar *tld_var = allocate<TldVar>(1);
init_tld(&tld_var->base, TldIdVar, name, visib_mod, node, &decls_scope->base, parent_tld); init_tld(&tld_var->base, TldIdVar, name, visib_mod, node, &decls_scope->base);
add_top_level_decl(g, decls_scope, &tld_var->base); add_top_level_decl(g, decls_scope, &tld_var->base);
break; break;
} }
@ -1575,7 +1556,7 @@ void scan_decls(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, A
Buf *name = node->data.type_decl.symbol; Buf *name = node->data.type_decl.symbol;
VisibMod visib_mod = node->data.type_decl.visib_mod; VisibMod visib_mod = node->data.type_decl.visib_mod;
TldTypeDef *tld_typedef = allocate<TldTypeDef>(1); TldTypeDef *tld_typedef = allocate<TldTypeDef>(1);
init_tld(&tld_typedef->base, TldIdTypeDef, name, visib_mod, node, &decls_scope->base, parent_tld); init_tld(&tld_typedef->base, TldIdTypeDef, name, visib_mod, node, &decls_scope->base);
add_top_level_decl(g, decls_scope, &tld_typedef->base); add_top_level_decl(g, decls_scope, &tld_typedef->base);
break; break;
} }
@ -1590,13 +1571,14 @@ void scan_decls(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, A
VisibMod visib_mod = node->data.fn_proto.visib_mod; VisibMod visib_mod = node->data.fn_proto.visib_mod;
TldFn *tld_fn = allocate<TldFn>(1); TldFn *tld_fn = allocate<TldFn>(1);
init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base, parent_tld); init_tld(&tld_fn->base, TldIdFn, fn_name, visib_mod, node, &decls_scope->base);
add_top_level_decl(g, decls_scope, &tld_fn->base); add_top_level_decl(g, decls_scope, &tld_fn->base);
break; break;
} }
case NodeTypeUse: case NodeTypeUse:
{ {
g->use_queue.append(node); g->use_queue.append(node);
ImportTableEntry *import = get_scope_import(&decls_scope->base);
import->use_decls.append(node); import->use_decls.append(node);
break; break;
} }
@ -1604,6 +1586,7 @@ void scan_decls(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, A
// error value declarations do not depend on other top level decls // error value declarations do not depend on other top level decls
preview_error_value_decl(g, node); preview_error_value_decl(g, node);
break; break;
case NodeTypeContainerDecl:
case NodeTypeParamDecl: case NodeTypeParamDecl:
case NodeTypeFnDecl: case NodeTypeFnDecl:
case NodeTypeReturnExpr: case NodeTypeReturnExpr:
@ -1787,7 +1770,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) { if (explicit_type && explicit_type->id == TypeTableEntryIdInvalid) {
implicit_type = explicit_type; implicit_type = explicit_type;
} else if (var_decl->expr) { } else if (var_decl->expr) {
init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type); init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol);
assert(init_value); assert(init_value);
implicit_type = init_value->type_entry; implicit_type = init_value->type_entry;
@ -1837,13 +1820,6 @@ static void resolve_decl_typedef(CodeGen *g, TldTypeDef *tld_typedef) {
void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) { void resolve_top_level_decl(CodeGen *g, Tld *tld, bool pointer_only) {
if (tld->resolution != TldResolutionUnresolved) if (tld->resolution != TldResolutionUnresolved)
return; return;
if (pointer_only && tld->id == TldIdContainer) {
g->resolve_queue.append(tld);
return;
}
ImportTableEntry *import = tld->import;
assert(import);
if (tld->dep_loop_flag) { if (tld->dep_loop_flag) {
add_node_error(g, tld->source_node, buf_sprintf("'%s' depends on itself", buf_ptr(tld->name))); add_node_error(g, tld->source_node, buf_sprintf("'%s' depends on itself", buf_ptr(tld->name)));
@ -2222,7 +2198,6 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
FnTypeParamInfo *param_info = &fn_type_id->param_info[i]; FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
AstNode *param_decl_node = get_param_decl_node(fn_table_entry, i); AstNode *param_decl_node = get_param_decl_node(fn_table_entry, i);
AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl; AstNodeParamDecl *param_decl = &param_decl_node->data.param_decl;
TypeTableEntry *param_type = param_info->type; TypeTableEntry *param_type = param_info->type;
bool is_noalias = param_info->is_noalias; bool is_noalias = param_info->is_noalias;
@ -2350,7 +2325,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
assert(node->type == NodeTypeUse); assert(node->type == NodeTypeUse);
IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base, IrInstruction *result = analyze_const_value(g, &node->owner->decls_scope->base,
node->data.use.expr, g->builtin_types.entry_namespace); node->data.use.expr, g->builtin_types.entry_namespace, nullptr);
if (result->type_entry->id == TypeTableEntryIdInvalid) if (result->type_entry->id == TypeTableEntryIdInvalid)
node->owner->any_imports_failed = true; node->owner->any_imports_failed = true;
@ -2438,7 +2413,7 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
void semantic_analyze(CodeGen *g) { void semantic_analyze(CodeGen *g) {
for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) { for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) {
ImportTableEntry *import = g->import_queue.at(g->import_queue_index); ImportTableEntry *import = g->import_queue.at(g->import_queue_index);
scan_decls(g, import, import->decls_scope, import->root, nullptr); scan_decls(g, import->decls_scope, import->root);
} }
for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) { for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) {

View File

@ -26,8 +26,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type); TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type);
TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size); TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t array_size);
TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, Scope *scope, TypeTableEntry *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, AstNode *decl_node, const char *name);
ContainerKind kind, AstNode *decl_node, const char *name);
TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type); TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type);
TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry); TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry);
@ -60,13 +59,12 @@ TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name);
ScopeDecls *get_container_scope(TypeTableEntry *type_entry); ScopeDecls *get_container_scope(TypeTableEntry *type_entry);
TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name);
bool is_container_ref(TypeTableEntry *type_entry); bool is_container_ref(TypeTableEntry *type_entry);
void scan_decls(CodeGen *g, ImportTableEntry *import, ScopeDecls *decls_scope, AstNode *node, Tld *parent_tld); void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node);
void preview_use_decl(CodeGen *g, AstNode *node); void preview_use_decl(CodeGen *g, AstNode *node);
void resolve_use_decl(CodeGen *g, AstNode *node); void resolve_use_decl(CodeGen *g, AstNode *node);
FnTableEntry *scope_fn_entry(Scope *scope); FnTableEntry *scope_fn_entry(Scope *scope);
ImportTableEntry *get_scope_import(Scope *scope); ImportTableEntry *get_scope_import(Scope *scope);
void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source_node, Scope *parent_scope);
Scope *parent_scope, Tld *parent_tld);
VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name, VariableTableEntry *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf *name,
TypeTableEntry *type_entry, bool is_const, ConstExprValue *init_value); TypeTableEntry *type_entry, bool is_const, ConstExprValue *init_value);
TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node); TypeTableEntry *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node);

View File

@ -585,13 +585,11 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
break; break;
case NodeTypeContainerDecl: case NodeTypeContainerDecl:
{ {
const char *struct_name = buf_ptr(node->data.struct_decl.name); const char *container_str = container_string(node->data.container_decl.kind);
const char *pub_str = visib_mod_string(node->data.struct_decl.visib_mod); fprintf(ar->f, "%s {\n", container_str);
const char *container_str = container_string(node->data.struct_decl.kind);
fprintf(ar->f, "%s%s %s {\n", pub_str, container_str, struct_name);
ar->indent += ar->indent_size; ar->indent += ar->indent_size;
for (size_t field_i = 0; field_i < node->data.struct_decl.fields.length; field_i += 1) { for (size_t field_i = 0; field_i < node->data.container_decl.fields.length; field_i += 1) {
AstNode *field_node = node->data.struct_decl.fields.at(field_i); AstNode *field_node = node->data.container_decl.fields.at(field_i);
assert(field_node->type == NodeTypeStructField); assert(field_node->type == NodeTypeStructField);
print_indent(ar); print_indent(ar);
print_symbol(ar, field_node->data.struct_field.name); print_symbol(ar, field_node->data.struct_field.name);

View File

@ -2306,6 +2306,8 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld
return irb->codegen->invalid_instruction; return irb->codegen->invalid_instruction;
switch (tld->id) { switch (tld->id) {
case TldIdContainer:
zig_unreachable();
case TldIdVar: case TldIdVar:
{ {
TldVar *tld_var = (TldVar *)tld; TldVar *tld_var = (TldVar *)tld;
@ -2327,16 +2329,6 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld
else else
return ref_instruction; return ref_instruction;
} }
case TldIdContainer:
{
TldContainer *tld_container = (TldContainer *)tld;
IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, tld_container->type_entry);
if (lval != LValPurposeNone)
return ir_build_ref(irb, scope, source_node, ref_instruction);
else
return ref_instruction;
}
case TldIdTypeDef: case TldIdTypeDef:
{ {
TldTypeDef *tld_typedef = (TldTypeDef *)tld; TldTypeDef *tld_typedef = (TldTypeDef *)tld;
@ -3861,6 +3853,52 @@ static IrInstruction *ir_gen_err_ok_or(IrBuilder *irb, Scope *parent_scope, AstN
return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values); return ir_build_phi(irb, parent_scope, node, 2, incoming_blocks, incoming_values);
} }
static const char *container_string(ContainerKind kind) {
switch (kind) {
case ContainerKindEnum: return "enum";
case ContainerKindStruct: return "struct";
case ContainerKindUnion: return "union";
}
zig_unreachable();
}
static IrInstruction *ir_gen_container_decl(IrBuilder *irb, Scope *parent_scope, AstNode *node) {
assert(node->type == NodeTypeContainerDecl);
ContainerKind kind = node->data.container_decl.kind;
Buf *name;
if (irb->exec->name) {
name = irb->exec->name;
} else {
FnTableEntry *fn_entry = exec_fn_entry(irb->exec);
if (fn_entry) {
zig_panic("TODO name the container inside the function");
} else {
name = buf_sprintf("(anonymous %s at %s:%zu:%zu)", container_string(kind),
buf_ptr(node->owner->path), node->line + 1, node->column + 1);
}
}
VisibMod visib_mod = VisibModPub;
TldContainer *tld_container = allocate<TldContainer>(1);
init_tld(&tld_container->base, TldIdContainer, name, visib_mod, node, parent_scope);
TypeTableEntry *container_type = get_partial_container_type(irb->codegen, parent_scope, kind, node, buf_ptr(name));
ScopeDecls *child_scope = get_container_scope(container_type);
tld_container->type_entry = container_type;
tld_container->decls_scope = child_scope;
for (size_t i = 0; i < node->data.container_decl.decls.length; i += 1) {
AstNode *child_node = node->data.container_decl.decls.at(i);
scan_decls(irb->codegen, child_scope, child_node);
}
irb->codegen->resolve_queue.append(&tld_container->base);
return ir_build_const_type(irb, parent_scope, node, container_type);
}
static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope, static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scope,
LValPurpose lval) LValPurpose lval)
{ {
@ -3872,6 +3910,7 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
case NodeTypeUse: case NodeTypeUse:
case NodeTypeSwitchProng: case NodeTypeSwitchProng:
case NodeTypeSwitchRange: case NodeTypeSwitchRange:
case NodeTypeStructField:
zig_unreachable(); zig_unreachable();
case NodeTypeBlock: case NodeTypeBlock:
return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval); return ir_lval_wrap(irb, scope, ir_gen_block(irb, scope, node), lval);
@ -3941,11 +3980,11 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval); return ir_lval_wrap(irb, scope, ir_gen_slice(irb, scope, node), lval);
case NodeTypeUnwrapErrorExpr: case NodeTypeUnwrapErrorExpr:
return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval); return ir_lval_wrap(irb, scope, ir_gen_err_ok_or(irb, scope, node), lval);
case NodeTypeContainerDecl:
return ir_lval_wrap(irb, scope, ir_gen_container_decl(irb, scope, node), lval);
case NodeTypeFnProto: case NodeTypeFnProto:
case NodeTypeFnDef: case NodeTypeFnDef:
case NodeTypeFnDecl: case NodeTypeFnDecl:
case NodeTypeContainerDecl:
case NodeTypeStructField:
case NodeTypeErrorValueDecl: case NodeTypeErrorValueDecl:
case NodeTypeTypeDecl: case NodeTypeTypeDecl:
zig_panic("TODO more IR gen for node types"); zig_panic("TODO more IR gen for node types");
@ -4558,9 +4597,10 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node) FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name)
{ {
IrExecutable ir_executable = {0}; IrExecutable ir_executable = {0};
ir_executable.name = exec_name;
ir_executable.is_inline = true; ir_executable.is_inline = true;
ir_executable.fn_entry = fn_entry; ir_executable.fn_entry = fn_entry;
ir_executable.c_import_buf = c_import_buf; ir_executable.c_import_buf = c_import_buf;
@ -4577,6 +4617,7 @@ IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node
fprintf(stderr, "}\n"); fprintf(stderr, "}\n");
} }
IrExecutable analyzed_executable = {0}; IrExecutable analyzed_executable = {0};
analyzed_executable.name = exec_name;
analyzed_executable.is_inline = true; analyzed_executable.is_inline = true;
analyzed_executable.fn_entry = fn_entry; analyzed_executable.fn_entry = fn_entry;
analyzed_executable.c_import_buf = c_import_buf; analyzed_executable.c_import_buf = c_import_buf;
@ -6017,7 +6058,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal
AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body; AstNode *body_node = fn_entry->fn_def_node->data.fn_def.body;
IrInstruction *result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, IrInstruction *result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
nullptr, call_instruction->base.source_node); nullptr, call_instruction->base.source_node, nullptr);
if (result->type_entry->id == TypeTableEntryIdInvalid) if (result->type_entry->id == TypeTableEntryIdInvalid)
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;
@ -6772,6 +6813,8 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;
switch (tld->id) { switch (tld->id) {
case TldIdContainer:
zig_unreachable();
case TldIdVar: case TldIdVar:
{ {
TldVar *tld_var = (TldVar *)tld; TldVar *tld_var = (TldVar *)tld;
@ -6794,21 +6837,6 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source
return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry,
depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const); depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const);
} }
case TldIdContainer:
{
TldContainer *tld_container = (TldContainer *)tld;
assert(tld_container->type_entry);
// TODO instead of allocating this every time, put it in the tld value and we can reference
// the same one every time
ConstExprValue *const_val = allocate<ConstExprValue>(1);
const_val->special = ConstValSpecialStatic;
const_val->data.x_type = tld_container->type_entry;
bool ptr_is_const = true;
return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type,
depends_on_compile_var, ConstPtrSpecialNone, ptr_is_const);
}
case TldIdTypeDef: case TldIdTypeDef:
{ {
TldTypeDef *tld_typedef = (TldTypeDef *)tld; TldTypeDef *tld_typedef = (TldTypeDef *)tld;
@ -7928,7 +7956,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi
ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, ImportTableEntry *target_import = add_source_file(ira->codegen, target_package,
abs_full_path, search_dir, import_target_path, import_code); abs_full_path, search_dir, import_target_path, import_code);
scan_decls(ira->codegen, target_import, target_import->decls_scope, target_import->root, nullptr); scan_decls(ira->codegen, target_import->decls_scope, target_import->root);
ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base, depends_on_compile_var); ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base, depends_on_compile_var);
out_val->data.x_import = target_import; out_val->data.x_import = target_import;
@ -8303,7 +8331,7 @@ static TypeTableEntry *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruc
TypeTableEntry *void_type = ira->codegen->builtin_types.entry_void; TypeTableEntry *void_type = ira->codegen->builtin_types.entry_void;
IrInstruction *result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, IrInstruction *result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
&cimport_scope->buf, block_node); &cimport_scope->buf, block_node, nullptr);
if (result->type_entry->id == TypeTableEntryIdInvalid) if (result->type_entry->id == TypeTableEntryIdInvalid)
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;

View File

@ -15,7 +15,7 @@ IrInstruction *ir_gen_fn(CodeGen *g, FnTableEntry *fn_entry);
IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, IrInstruction *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, TypeTableEntry *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node); FnTableEntry *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name);
TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, TypeTableEntry *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
TypeTableEntry *expected_type, AstNode *expected_type_source_node); TypeTableEntry *expected_type, AstNode *expected_type_source_node);

View File

@ -120,7 +120,7 @@ static const char *decl_name(const Decl *decl) {
} }
static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) { static void parseh_init_tld(Context *c, Tld *tld, TldId id, Buf *name) {
init_tld(tld, id, name, c->visib_mod, c->source_node, &c->import->decls_scope->base, nullptr); init_tld(tld, id, name, c->visib_mod, c->source_node, &c->import->decls_scope->base);
tld->resolution = TldResolutionOk; tld->resolution = TldResolutionOk;
} }
@ -184,7 +184,7 @@ static Tld *create_global_num_lit_ap(Context *c, const Decl *source_decl, Buf *n
} }
static void add_const_type(Context *c, Buf *name, TypeTableEntry *type_entry) { static Tld *add_const_type(Context *c, Buf *name, TypeTableEntry *type_entry) {
ConstExprValue *var_value = allocate<ConstExprValue>(1); ConstExprValue *var_value = allocate<ConstExprValue>(1);
var_value->special = ConstValSpecialStatic; var_value->special = ConstValSpecialStatic;
var_value->data.x_type = type_entry; var_value->data.x_type = type_entry;
@ -192,15 +192,11 @@ static void add_const_type(Context *c, Buf *name, TypeTableEntry *type_entry) {
add_global(c, &tld_var->base); add_global(c, &tld_var->base);
c->global_type_table.put(name, type_entry); c->global_type_table.put(name, type_entry);
return &tld_var->base;
} }
static Tld *add_container_tld(Context *c, TypeTableEntry *type_entry) { static Tld *add_container_tld(Context *c, TypeTableEntry *type_entry) {
TldContainer *tld_container = allocate<TldContainer>(1); return add_const_type(c, &type_entry->name, type_entry);
parseh_init_tld(c, &tld_container->base, TldIdContainer, &type_entry->name);
tld_container->type_entry = type_entry;
add_global(c, &tld_container->base);
return &tld_container->base;
} }
static Tld *add_typedef_tld(Context *c, TypeTableEntry *type_decl) { static Tld *add_typedef_tld(Context *c, TypeTableEntry *type_decl) {
@ -690,8 +686,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
const EnumDecl *enum_def = enum_decl->getDefinition(); const EnumDecl *enum_def = enum_decl->getDefinition();
if (!enum_def) { if (!enum_def) {
TypeTableEntry *enum_type = get_partial_container_type(c->codegen, c->import, TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
&c->import->decls_scope->base,
ContainerKindEnum, c->source_node, buf_ptr(full_type_name)); ContainerKindEnum, c->source_node, buf_ptr(full_type_name));
c->enum_type_table.put(bare_name, enum_type); c->enum_type_table.put(bare_name, enum_type);
c->decl_table.put(enum_decl, enum_type); c->decl_table.put(enum_decl, enum_type);
@ -715,8 +710,7 @@ static TypeTableEntry *resolve_enum_decl(Context *c, const EnumDecl *enum_decl)
TypeTableEntry *tag_type_entry = resolve_qual_type(c, enum_decl->getIntegerType(), enum_decl); TypeTableEntry *tag_type_entry = resolve_qual_type(c, enum_decl->getIntegerType(), enum_decl);
if (pure_enum) { if (pure_enum) {
TypeTableEntry *enum_type = get_partial_container_type(c->codegen, c->import, TypeTableEntry *enum_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
&c->import->decls_scope->base,
ContainerKindEnum, c->source_node, buf_ptr(full_type_name)); ContainerKindEnum, c->source_node, buf_ptr(full_type_name));
c->enum_type_table.put(bare_name, enum_type); c->enum_type_table.put(bare_name, enum_type);
c->decl_table.put(enum_decl, enum_type); c->decl_table.put(enum_decl, enum_type);
@ -855,8 +849,8 @@ static TypeTableEntry *resolve_record_decl(Context *c, const RecordDecl *record_
Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name)); Buf *full_type_name = buf_sprintf("struct_%s", buf_ptr(bare_name));
TypeTableEntry *struct_type = get_partial_container_type(c->codegen, c->import, TypeTableEntry *struct_type = get_partial_container_type(c->codegen, &c->import->decls_scope->base,
&c->import->decls_scope->base, ContainerKindStruct, c->source_node, buf_ptr(full_type_name)); ContainerKindStruct, c->source_node, buf_ptr(full_type_name));
c->struct_type_table.put(bare_name, struct_type); c->struct_type_table.put(bare_name, struct_type);
c->decl_table.put(record_decl, struct_type); c->decl_table.put(record_decl, struct_type);

View File

@ -216,6 +216,7 @@ static AstNode *ast_parse_prefix_op_expr(ParseContext *pc, size_t *token_index,
static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod); static AstNode *ast_parse_fn_proto(ParseContext *pc, size_t *token_index, bool mandatory, VisibMod visib_mod);
static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index); static AstNode *ast_parse_return_expr(ParseContext *pc, size_t *token_index);
static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory); static AstNode *ast_parse_grouped_expr(ParseContext *pc, size_t *token_index, bool mandatory);
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory);
static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) { static void ast_expect_token(ParseContext *pc, Token *token, TokenId token_id) {
if (token->id == token_id) { if (token->id == token_id) {
@ -618,7 +619,7 @@ static AstNode *ast_parse_goto_expr(ParseContext *pc, size_t *token_index, bool
return node; return node;
} }
/* /*
PrimaryExpression = "Number" | "String" | "CharLiteral" | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | "Symbol" | ("@" "Symbol" FnCallExpression) | ArrayType | FnProto | AsmExpression | ("error" "." "Symbol") PrimaryExpression = Number | String | CharLiteral | KeywordLiteral | GroupedExpression | GotoExpression | BlockExpression | Symbol | ("@" Symbol FnCallExpression) | ArrayType | (option("extern") FnProto) | AsmExpression | ("error" "." Symbol) | ContainerDecl
KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this" KeywordLiteral = "true" | "false" | "null" | "break" | "continue" | "undefined" | "zeroes" | "error" | "type" | "this"
*/ */
static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) { static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bool mandatory) {
@ -737,6 +738,10 @@ static AstNode *ast_parse_primary_expr(ParseContext *pc, size_t *token_index, bo
return asm_expr; return asm_expr;
} }
AstNode *container_decl = ast_parse_container_decl(pc, token_index, false);
if (container_decl)
return container_decl;
if (!mandatory) if (!mandatory)
return nullptr; return nullptr;
@ -2219,43 +2224,31 @@ static AstNode *ast_parse_use(ParseContext *pc, size_t *token_index, VisibMod vi
} }
/* /*
ContainerDecl = ("struct" | "enum" | "union") Symbol option(ParamDeclList) "{" many(StructMember) "}" ContainerDecl = ("struct" | "enum" | "union") "{" many(StructMember) "}"
StructMember = (StructField | FnDef | GlobalVarDecl | ContainerDecl) StructMember = (StructField | FnDef | GlobalVarDecl)
StructField = Symbol option(":" Expression) ",") StructField = Symbol option(":" Expression) ",")
*/ */
static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, VisibMod visib_mod) { static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index, bool mandatory) {
Token *first_token = &pc->tokens->at(*token_index); Token *first_token = &pc->tokens->at(*token_index);
ContainerKind kind; ContainerKind kind;
if (first_token->id == TokenIdKeywordStruct) { if (first_token->id == TokenIdKeywordStruct) {
kind = ContainerKindStruct; kind = ContainerKindStruct;
} else if (first_token->id == TokenIdKeywordEnum) { } else if (first_token->id == TokenIdKeywordEnum) {
kind = ContainerKindEnum; kind = ContainerKindEnum;
} else if (first_token->id == TokenIdKeywordUnion) { } else if (first_token->id == TokenIdKeywordUnion) {
kind = ContainerKindUnion; kind = ContainerKindUnion;
} else if (mandatory) {
ast_invalid_token_error(pc, first_token);
} else { } else {
return nullptr; return nullptr;
} }
*token_index += 1; *token_index += 1;
Token *struct_name = ast_eat_token(pc, token_index, TokenIdSymbol);
AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token); AstNode *node = ast_create_node(pc, NodeTypeContainerDecl, first_token);
node->data.struct_decl.kind = kind; node->data.container_decl.kind = kind;
node->data.struct_decl.name = token_buf(struct_name);
node->data.struct_decl.visib_mod = visib_mod;
Token *paren_or_brace = &pc->tokens->at(*token_index); ast_eat_token(pc, token_index, TokenIdLBrace);
if (paren_or_brace->id == TokenIdLParen) {
ast_parse_param_decl_list(pc, token_index, &node->data.struct_decl.generic_params,
&node->data.struct_decl.generic_params_is_var_args);
ast_eat_token(pc, token_index, TokenIdLBrace);
} else if (paren_or_brace->id == TokenIdLBrace) {
*token_index += 1;
} else {
ast_invalid_token_error(pc, paren_or_brace);
}
for (;;) { for (;;) {
Token *visib_tok = &pc->tokens->at(*token_index); Token *visib_tok = &pc->tokens->at(*token_index);
@ -2272,20 +2265,14 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, visib_mod); AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, visib_mod);
if (fn_def_node) { if (fn_def_node) {
node->data.struct_decl.decls.append(fn_def_node); node->data.container_decl.decls.append(fn_def_node);
continue; continue;
} }
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
if (var_decl_node) { if (var_decl_node) {
ast_eat_token(pc, token_index, TokenIdSemicolon); ast_eat_token(pc, token_index, TokenIdSemicolon);
node->data.struct_decl.decls.append(var_decl_node); node->data.container_decl.decls.append(var_decl_node);
continue;
}
AstNode *container_decl_node = ast_parse_container_decl(pc, token_index, visib_mod);
if (container_decl_node) {
node->data.struct_decl.decls.append(container_decl_node);
continue; continue;
} }
@ -2311,7 +2298,7 @@ static AstNode *ast_parse_container_decl(ParseContext *pc, size_t *token_index,
ast_eat_token(pc, token_index, TokenIdComma); ast_eat_token(pc, token_index, TokenIdComma);
} }
node->data.struct_decl.fields.append(field_node); node->data.container_decl.fields.append(field_node);
} else { } else {
ast_invalid_token_error(pc, token); ast_invalid_token_error(pc, token);
} }
@ -2368,7 +2355,7 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, size_t *token_index, Visib
/* /*
TopLevelItem = ErrorValueDecl | Block | TopLevelDecl TopLevelItem = ErrorValueDecl | Block | TopLevelDecl
TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | TypeDecl | UseDecl) TopLevelDecl = option(VisibleMod) (FnDef | ExternDecl | GlobalVarDecl | TypeDecl | UseDecl)
*/ */
static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) { static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, ZigList<AstNode *> *top_level_decls) {
for (;;) { for (;;) {
@ -2402,12 +2389,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, size_t *token_index, Zig
continue; continue;
} }
AstNode *struct_node = ast_parse_container_decl(pc, token_index, visib_mod);
if (struct_node) {
top_level_decls->append(struct_node);
continue;
}
AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod); AstNode *var_decl_node = ast_parse_variable_declaration_expr(pc, token_index, false, visib_mod);
if (var_decl_node) { if (var_decl_node) {
ast_eat_token(pc, token_index, TokenIdSemicolon); ast_eat_token(pc, token_index, TokenIdSemicolon);
@ -2630,8 +2611,8 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
} }
break; break;
case NodeTypeContainerDecl: case NodeTypeContainerDecl:
visit_node_list(&node->data.struct_decl.fields, visit, context); visit_node_list(&node->data.container_decl.fields, visit, context);
visit_node_list(&node->data.struct_decl.decls, visit, context); visit_node_list(&node->data.container_decl.decls, visit, context);
break; break;
case NodeTypeStructField: case NodeTypeStructField:
visit_field(&node->data.struct_field.type, visit, context); visit_field(&node->data.struct_field.type, visit, context);

View File

@ -87,9 +87,9 @@ var goto_counter: i32 = 0;
struct FooA { const FooA = struct {
fn add(a: i32, b: i32) -> i32 { a + b } fn add(a: i32, b: i32) -> i32 { a + b }
} };
const foo_a = FooA {}; const foo_a = FooA {};
fn testStructStatic() { fn testStructStatic() {