aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp1526
1 files changed, 649 insertions, 877 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index e73902f118..04980b05e8 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -14,8 +14,10 @@
#include "config.h"
#include "ast_render.hpp"
-static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
+static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node);
+static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEntry *import,
+ BlockContext *context, TypeTableEntry *expected_type, AstNode *node, bool pointer_only);
static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
@@ -27,13 +29,18 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node);
static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
-static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context,
- FnTableEntry *fn);
+static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type);
static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
TypeTableEntry *expected_type, uint64_t x);
-static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);
-static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node);
+static AstNode *find_decl(BlockContext *context, Buf *name);
+static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node, bool pointer_only);
+static TopLevelDecl *get_as_top_level_decl(AstNode *node);
+static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
+ BlockContext *context, AstNode *source_node,
+ AstNodeVariableDeclaration *variable_declaration,
+ bool expr_is_maybe, AstNode *decl_node);
+static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);
static AstNode *first_executing_node(AstNode *node) {
switch (node->type) {
@@ -52,7 +59,6 @@ static AstNode *first_executing_node(AstNode *node) {
case NodeTypeSwitchRange:
return first_executing_node(node->data.switch_range.start);
case NodeTypeRoot:
- case NodeTypeRootExportDecl:
case NodeTypeFnProto:
case NodeTypeFnDef:
case NodeTypeFnDecl:
@@ -69,8 +75,7 @@ static AstNode *first_executing_node(AstNode *node) {
case NodeTypeCharLiteral:
case NodeTypeSymbol:
case NodeTypePrefixOpExpr:
- case NodeTypeImport:
- case NodeTypeCImport:
+ case NodeTypeUse:
case NodeTypeBoolLiteral:
case NodeTypeNullLiteral:
case NodeTypeUndefinedLiteral:
@@ -109,43 +114,47 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
return err;
}
+ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
+ // if this assert fails, then parseh generated code that
+ // failed semantic analysis, which isn't supposed to happen
+ assert(!node->owner->c_import_node);
+
+ ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
+ node->owner->source_code, node->owner->line_offsets, msg);
+
+ err_msg_add_note(parent_msg, err);
+ return err;
+}
+
TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
TypeTableEntry *entry = allocate<TypeTableEntry>(1);
entry->arrays_by_size.init(2);
entry->id = id;
+ return entry;
+}
- switch (id) {
- case TypeTableEntryIdInvalid:
- case TypeTableEntryIdMetaType:
- case TypeTableEntryIdVoid:
- case TypeTableEntryIdBool:
- case TypeTableEntryIdUnreachable:
- case TypeTableEntryIdInt:
- case TypeTableEntryIdFloat:
- case TypeTableEntryIdPointer:
- case TypeTableEntryIdArray:
- case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdNumLitInt:
- case TypeTableEntryIdMaybe:
- case TypeTableEntryIdFn:
- case TypeTableEntryIdErrorUnion:
- case TypeTableEntryIdPureError:
- case TypeTableEntryIdUndefLit:
- case TypeTableEntryIdTypeDecl:
- // nothing to init
- break;
- case TypeTableEntryIdStruct:
- entry->data.structure.fn_table.init(8);
- break;
- case TypeTableEntryIdEnum:
- entry->data.enumeration.fn_table.init(8);
- break;
-
+static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry) {
+ if (type_entry->id == TypeTableEntryIdStruct) {
+ return &type_entry->data.structure.block_context;
+ } else if (type_entry->id == TypeTableEntryIdEnum) {
+ return &type_entry->data.enumeration.block_context;
}
+ zig_unreachable();
+}
+static BlockContext *get_container_block_context(TypeTableEntry *type_entry) {
+ return *get_container_block_context_ptr(type_entry);
+}
+
+static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *source_node,
+ BlockContext *parent_context)
+{
+ TypeTableEntry *entry = new_type_table_entry(id);
+ *get_container_block_context_ptr(entry) = new_block_context(source_node, parent_context);
return entry;
}
+
static int bits_needed_for_unsigned(uint64_t x) {
if (x <= UINT8_MAX) {
return 8;
@@ -182,6 +191,7 @@ static bool type_is_complete(TypeTableEntry *type_entry) {
case TypeTableEntryIdPureError:
case TypeTableEntryIdFn:
case TypeTableEntryIdTypeDecl:
+ case TypeTableEntryIdNamespace:
return true;
}
zig_unreachable();
@@ -671,7 +681,7 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
ContainerKind kind, AstNode *decl_node, const char *name)
{
TypeTableEntryId type_id = container_to_type(kind);
- TypeTableEntry *entry = new_type_table_entry(type_id);
+ TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, import->block_context);
switch (kind) {
case ContainerKindStruct:
@@ -730,13 +740,19 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
return const_val->data.x_type;
}
+static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEntry *import,
+ BlockContext *context, AstNode *node, bool pointer_only)
+{
+ AstNode **node_ptr = node->parent_field;
+ analyze_expression_pointer_only(g, import, context, nullptr, *node_ptr, pointer_only);
+ return resolve_type(g, *node_ptr);
+}
+
// Calls analyze_expression on node, and then resolve_type.
static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
AstNode *node)
{
- AstNode **node_ptr = node->parent_field;
- analyze_expression(g, import, context, nullptr, *node_ptr);
- return resolve_type(g, *node_ptr);
+ return analyze_type_expr_pointer_only(g, import, context, node, false);
}
static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,
@@ -750,7 +766,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
}
FnTypeId fn_type_id = {0};
- fn_type_id.is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);
+ fn_type_id.is_extern = fn_proto->is_extern || (fn_proto->top_level_decl.visib_mod == VisibModExport);
fn_type_id.is_naked = is_naked;
fn_type_id.is_cold = is_cold;
fn_type_id.param_count = node->data.fn_proto.params.length;
@@ -782,6 +798,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdUnreachable:
+ case TypeTableEntryIdNamespace:
fn_proto->skip = true;
add_node_error(g, child->data.param_decl.type,
buf_sprintf("parameter of type '%s' not allowed'", buf_ptr(&type_entry->name)));
@@ -880,9 +897,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
bool is_naked = false;
bool is_test = false;
- if (fn_proto->directives) {
- for (int i = 0; i < fn_proto->directives->length; i += 1) {
- AstNode *directive_node = fn_proto->directives->at(i);
+ if (fn_proto->top_level_decl.directives) {
+ for (int i = 0; i < fn_proto->top_level_decl.directives->length; i += 1) {
+ AstNode *directive_node = fn_proto->top_level_decl.directives->at(i);
Buf *name = &directive_node->data.directive.name;
if (buf_eql_str(name, "attribute")) {
@@ -907,12 +924,12 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
}
} else if (buf_eql_str(name, "condition")) {
- if (fn_proto->visib_mod == VisibModExport) {
+ if (fn_proto->top_level_decl.visib_mod == VisibModExport) {
bool include;
bool ok = resolve_const_expr_bool(g, import, import->block_context,
&directive_node->data.directive.expr, &include);
if (ok && !include) {
- fn_proto->visib_mod = VisibModPub;
+ fn_proto->top_level_decl.visib_mod = VisibModPub;
}
} else {
add_node_error(g, directive_node,
@@ -925,12 +942,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
}
}
- bool is_internal = (fn_proto->visib_mod != VisibModExport);
+ bool is_internal = (fn_proto->top_level_decl.visib_mod != VisibModExport);
bool is_c_compat = !is_internal || fn_proto->is_extern;
fn_table_entry->internal_linkage = !is_c_compat;
- if (!is_internal) {
- fn_table_entry->ref_count += 1;
- }
@@ -972,18 +986,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoUnwindAttribute);
}
- // Add debug info.
- unsigned line_number = node->line + 1;
- unsigned scope_line = line_number;
- bool is_definition = fn_table_entry->fn_def_node != nullptr;
- unsigned flags = 0;
- bool is_optimized = g->is_release_build;
- LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
- import->block_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
- import->di_file, line_number,
- fn_type->di_type, fn_table_entry->internal_linkage,
- is_definition, scope_line, flags, is_optimized, fn_table_entry->fn_value);
if (fn_table_entry->fn_def_node) {
+ // Add debug info.
+ unsigned line_number = node->line + 1;
+ unsigned scope_line = line_number;
+ bool is_definition = fn_table_entry->fn_def_node != nullptr;
+ unsigned flags = 0;
+ bool is_optimized = g->is_release_build;
+ LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
+ import->block_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
+ import->di_file, line_number,
+ fn_type->di_type, fn_table_entry->internal_linkage,
+ is_definition, scope_line, flags, is_optimized, fn_table_entry->fn_value);
+
BlockContext *context = new_block_context(fn_table_entry->fn_def_node, import->block_context);
fn_table_entry->fn_def_node->data.fn_def.block_context = context;
context->di_scope = LLVMZigSubprogramToScope(subprogram);
@@ -1295,59 +1310,43 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
struct_type->zero_bits = (debug_size_in_bits == 0);
}
-static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
- AstNode *proto_node)
-{
+static void get_fully_qualified_decl_name(Buf *buf, AstNode *decl_node, uint8_t sep) {
+ TopLevelDecl *tld = get_as_top_level_decl(decl_node);
+ AstNode *parent_decl = tld->parent_decl;
+
+ if (parent_decl) {
+ get_fully_qualified_decl_name(buf, parent_decl, sep);
+ buf_append_char(buf, sep);
+ buf_append_buf(buf, tld->name);
+ } else {
+ buf_init_from_buf(buf, tld->name);
+ }
+}
+
+static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *proto_node) {
if (proto_node->data.fn_proto.skip) {
return;
}
+
+ AstNode *parent_decl = proto_node->data.fn_proto.top_level_decl.parent_decl;
+
AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;
- AstNode *struct_node = proto_node->data.fn_proto.struct_node;
bool is_extern = proto_node->data.fn_proto.is_extern;
- TypeTableEntry *struct_type;
- if (struct_node) {
- assert(struct_node->type == NodeTypeStructDecl);
- struct_type = struct_node->data.struct_decl.type_entry;
- } else {
- struct_type = nullptr;
- }
Buf *proto_name = &proto_node->data.fn_proto.name;
- auto fn_table = struct_type ? &struct_type->data.structure.fn_table : &import->fn_table;
-
- auto entry = fn_table->maybe_get(proto_name);
- bool skip = false;
- bool is_pub = (proto_node->data.fn_proto.visib_mod != VisibModPrivate);
- if (entry) {
- add_node_error(g, proto_node,
- buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
- proto_node->data.fn_proto.skip = true;
- skip = true;
- }
if (!is_extern && proto_node->data.fn_proto.is_var_args) {
add_node_error(g, proto_node,
buf_sprintf("variadic arguments only allowed in extern functions"));
}
- if (skip) {
- return;
- }
FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
fn_table_entry->import_entry = import;
fn_table_entry->proto_node = proto_node;
fn_table_entry->fn_def_node = fn_def_node;
fn_table_entry->is_extern = is_extern;
- fn_table_entry->member_of_struct = struct_type;
- if (struct_type) {
- buf_resize(&fn_table_entry->symbol_name, 0);
- buf_appendf(&fn_table_entry->symbol_name, "%s_%s",
- buf_ptr(&struct_type->name),
- buf_ptr(proto_name));
- } else {
- buf_init_from_buf(&fn_table_entry->symbol_name, proto_name);
- }
+ get_fully_qualified_decl_name(&fn_table_entry->symbol_name, proto_node, '_');
g->fn_protos.append(fn_table_entry);
@@ -1355,39 +1354,13 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
g->fn_defs.append(fn_table_entry);
}
- fn_table->put(proto_name, fn_table_entry);
-
- bool is_main_fn = !struct_type && (import == g->root_import) && buf_eql_str(proto_name, "main");
+ bool is_main_fn = !parent_decl && (import == g->root_import) && buf_eql_str(proto_name, "main");
if (is_main_fn) {
g->main_fn = fn_table_entry;
-
- if (g->bootstrap_import && !g->is_test_build) {
- g->bootstrap_import->fn_table.put(buf_create_from_str("zig_user_main"), fn_table_entry);
- }
- }
- bool is_test_main_fn = !struct_type && (import == g->test_runner_import) && buf_eql_str(proto_name, "main");
- if (is_test_main_fn) {
- assert(g->bootstrap_import);
- assert(g->is_test_build);
- g->bootstrap_import->fn_table.put(proto_name, fn_table_entry);
}
proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
resolve_function_proto(g, proto_node, fn_table_entry, import);
-
- if (is_pub && !struct_type) {
- for (int i = 0; i < import->importers.length; i += 1) {
- ImporterInfo importer = import->importers.at(i);
- auto table_entry = importer.import->fn_table.maybe_get(proto_name);
- if (table_entry) {
- add_node_error(g, importer.source_node,
- buf_sprintf("import of function '%s' overrides existing definition",
- buf_ptr(proto_name)));
- } else {
- importer.import->fn_table.put(proto_name, fn_table_entry);
- }
- }
- }
}
static void preview_error_value_decl(CodeGen *g, AstNode *node) {
@@ -1403,110 +1376,40 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
// duplicate error definitions allowed and they get the same value
err->value = existing_entry->value->value;
} else {
+ assert(g->error_value_count < (1 << g->err_tag_type->data.integral.bit_count));
err->value = g->error_value_count;
g->error_value_count += 1;
g->error_table.put(&err->name, err);
}
node->data.error_value_decl.err = err;
+ node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;
}
-static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
- assert(node->type == NodeTypeErrorValueDecl);
-
- ErrorTableEntry *err = node->data.error_value_decl.err;
-
- import->error_table.put(&err->name, err);
-
- bool is_pub = (node->data.error_value_decl.visib_mod != VisibModPrivate);
- if (is_pub) {
- for (int i = 0; i < import->importers.length; i += 1) {
- ImporterInfo importer = import->importers.at(i);
- importer.import->error_table.put(&err->name, err);
- }
- }
-}
-
-static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, AstNode *node) {
- assert(node->type == NodeTypeCImport);
-
- AstNode *block_node = node->data.c_import.block;
-
- BlockContext *child_context = new_block_context(node, parent_import->block_context);
- child_context->c_import_buf = buf_alloc();
-
- TypeTableEntry *resolved_type = analyze_block_expr(g, parent_import, child_context,
- g->builtin_types.entry_void, block_node);
-
- if (resolved_type->id == TypeTableEntryIdInvalid) {
+static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) {
+ TopLevelDecl *tld = get_as_top_level_decl(node);
+ if (tld->resolution != TldResolutionUnresolved) {
return;
}
-
- find_libc_include_path(g);
-
- ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
- child_import->fn_table.init(32);
- child_import->type_table.init(8);
- child_import->error_table.init(8);
- child_import->c_import_node = node;
-
- child_import->importers.append({parent_import, node});
-
- if (node->data.c_import.visib_mod != VisibModPrivate) {
- for (int i = 0; i < parent_import->importers.length; i += 1) {
- ImporterInfo importer = parent_import->importers.at(i);
- child_import->importers.append(importer);
- }
- }
-
- ZigList<ErrorMsg *> errors = {0};
-
- int err;
- if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
- zig_panic("unable to parse h file: %s\n", err_str(err));
- }
-
- if (errors.length > 0) {
- ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
- for (int i = 0; i < errors.length; i += 1) {
- ErrorMsg *err_msg = errors.at(i);
- err_msg_add_note(parent_err_msg, err_msg);
- }
-
- for (int i = 0; i < child_import->importers.length; i += 1) {
- child_import->importers.at(i).import->any_imports_failed = true;
- }
+ if (pointer_only && node->type == NodeTypeStructDecl) {
return;
}
- if (g->verbose) {
- fprintf(stderr, "\nc_import:\n");
- fprintf(stderr, "-----------\n");
- ast_render(stderr, child_import->root, 4);
- }
+ ImportTableEntry *import = tld->import;
+ assert(import);
- child_import->di_file = parent_import->di_file;
- child_import->block_context = new_block_context(child_import->root, nullptr);
-
- detect_top_level_decl_deps(g, child_import, child_import->root);
- analyze_top_level_decls_root(g, child_import, child_import->root);
-}
-
-static void satisfy_dep(CodeGen *g, AstNode *node) {
- Buf *name = get_resolved_top_level_decl(node)->name;
- if (name) {
- g->unresolved_top_level_decls.maybe_remove(name);
+ if (tld->dep_loop_flag) {
+ add_node_error(g, node, buf_sprintf("'%s' depends on itself", buf_ptr(tld->name)));
+ tld->resolution = TldResolutionInvalid;
+ return;
+ } else {
+ tld->dep_loop_flag = true;
}
-}
-static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
switch (node->type) {
case NodeTypeFnProto:
preview_fn_proto(g, import, node);
break;
- case NodeTypeRootExportDecl:
- // handled earlier
- return;
case NodeTypeStructDecl:
{
TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
@@ -1526,8 +1429,10 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
}
case NodeTypeVariableDeclaration:
{
- VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context,
- nullptr, node);
+ AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
+ VariableTableEntry *var = analyze_variable_declaration_raw(g, import, import->block_context,
+ node, variable_declaration, false, node);
+
g->global_vars.append(var);
break;
}
@@ -1547,34 +1452,13 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
entry = get_typedecl_type(g, buf_ptr(decl_name), child_type);
}
}
-
- import->type_table.put(decl_name, entry);
-
- bool is_pub = (node->data.type_decl.visib_mod != VisibModPrivate);
- if (is_pub) {
- for (int i = 0; i < import->importers.length; i += 1) {
- ImporterInfo importer = import->importers.at(i);
- auto table_entry = importer.import->type_table.maybe_get(&entry->name);
- if (table_entry) {
- add_node_error(g, importer.source_node,
- buf_sprintf("import of type '%s' overrides existing definition",
- buf_ptr(&entry->name)));
- } else {
- importer.import->type_table.put(&entry->name, entry);
- }
- }
- }
-
+ node->data.type_decl.child_type_entry = entry;
break;
}
case NodeTypeErrorValueDecl:
- resolve_error_value_decl(g, import, node);
break;
- case NodeTypeImport:
- // nothing to do here
- return;
- case NodeTypeCImport:
- resolve_c_import_decl(g, import, node);
+ case NodeTypeUse:
+ zig_panic("TODO resolve_top_level_decl NodeTypeUse");
break;
case NodeTypeFnDef:
case NodeTypeDirective:
@@ -1619,8 +1503,8 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
zig_unreachable();
}
-
- satisfy_dep(g, node);
+ tld->resolution = TldResolutionOk;
+ tld->dep_loop_flag = false;
}
static FnTableEntry *get_context_fn_entry(BlockContext *context) {
@@ -1656,6 +1540,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
case TypeTableEntryIdNumLitFloat:
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNamespace:
return false;
case TypeTableEntryIdBool:
@@ -2063,7 +1948,8 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
BlockContext *context = allocate<BlockContext>(1);
context->node = node;
context->parent = parent;
- context->variable_table.init(4);
+ context->decl_table.init(1);
+ context->var_table.init(1);
if (parent) {
context->parent_loop_node = parent->parent_loop_node;
@@ -2085,23 +1971,28 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
return context;
}
-static VariableTableEntry *find_variable(BlockContext *context, Buf *name, bool local_only) {
- while (context && (!local_only || context->fn_entry)) {
- auto entry = context->variable_table.maybe_get(name);
- if (entry)
+static AstNode *find_decl(BlockContext *context, Buf *name) {
+ while (context) {
+ auto entry = context->decl_table.maybe_get(name);
+ if (entry) {
return entry->value;
-
+ }
context = context->parent;
}
return nullptr;
}
-static TypeTableEntry *find_container(ImportTableEntry *import, Buf *name) {
- auto entry = import->type_table.maybe_get(name);
- if (entry)
- return entry->value;
- else
- return nullptr;
+static VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name) {
+ BlockContext *context = orig_context;
+ while (context) {
+ auto entry = context->var_table.maybe_get(name);
+ if (entry) {
+ return entry->value;
+ }
+ context = context->parent;
+ }
+
+ return nullptr;
}
static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {
@@ -2155,6 +2046,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
assert(type_entry->id == TypeTableEntryIdStruct);
+ assert(type_entry->data.structure.complete);
for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
TypeStructField *field = &type_entry->data.structure.fields[i];
if (buf_eql_buf(field->name, name)) {
@@ -2330,8 +2222,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
{
assert(node->type == NodeTypeFieldAccessExpr);
- AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;
- TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node);
+ AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr;
+ TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node);
Buf *field_name = &node->data.field_access_expr.field_name;
bool wrapped_in_fn_call = node->data.field_access_expr.is_fn_call;
@@ -2342,17 +2234,30 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
struct_type : struct_type->data.pointer.child_type;
+ if (!bare_struct_type->data.structure.complete) {
+ resolve_struct_type(g, bare_struct_type->data.structure.decl_node->owner, bare_struct_type);
+ }
+
node->data.field_access_expr.bare_struct_type = bare_struct_type;
node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name);
if (node->data.field_access_expr.type_struct_field) {
return node->data.field_access_expr.type_struct_field->type_entry;
} else if (wrapped_in_fn_call) {
- auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name);
- if (table_entry) {
+ BlockContext *container_block_context = get_container_block_context(bare_struct_type);
+ auto entry = container_block_context->decl_table.maybe_get(field_name);
+ AstNode *fn_decl_node = entry ? entry->value : nullptr;
+ if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) {
+ resolve_top_level_decl(g, fn_decl_node, false);
+ TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node);
+ if (tld->resolution == TldResolutionInvalid) {
+ return g->builtin_types.entry_invalid;
+ }
+
node->data.field_access_expr.is_member_fn = true;
- return resolve_expr_const_val_as_fn(g, node, context, table_entry->value);
+ FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry;
+ return resolve_expr_const_val_as_fn(g, node, fn_entry);
} else {
- add_node_error(g, node, buf_sprintf("no member named '%s' in '%s'",
+ add_node_error(g, node, buf_sprintf("no function named '%s' in '%s'",
buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
return g->builtin_types.entry_invalid;
}
@@ -2372,7 +2277,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
return g->builtin_types.entry_invalid;
}
} else if (struct_type->id == TypeTableEntryIdMetaType) {
- TypeTableEntry *child_type = resolve_type(g, struct_expr_node);
+ TypeTableEntry *child_type = resolve_type(g, *struct_expr_node);
if (child_type->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid;
@@ -2381,12 +2286,15 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
} else if (child_type->id == TypeTableEntryIdEnum) {
return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name);
} else if (child_type->id == TypeTableEntryIdStruct) {
- auto entry = child_type->data.structure.fn_table.maybe_get(field_name);
- if (entry) {
- return resolve_expr_const_val_as_fn(g, node, context, entry->value);
+ BlockContext *container_block_context = get_container_block_context(child_type);
+ auto entry = container_block_context->decl_table.maybe_get(field_name);
+ AstNode *decl_node = entry ? entry->value : nullptr;
+ if (decl_node) {
+ bool pointer_only = false;
+ return analyze_decl_ref(g, node, decl_node, pointer_only);
} else {
add_node_error(g, node,
- buf_sprintf("struct '%s' has no function called '%s'",
+ buf_sprintf("container '%s' has no member called '%s'",
buf_ptr(&child_type->name), buf_ptr(field_name)));
return g->builtin_types.entry_invalid;
}
@@ -2397,6 +2305,26 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
return g->builtin_types.entry_invalid;
}
+ } else if (struct_type->id == TypeTableEntryIdNamespace) {
+ ConstExprValue *const_val = &get_resolved_expr(*struct_expr_node)->const_val;
+ assert(const_val->ok);
+ ImportTableEntry *namespace_import = const_val->data.x_import;
+ AstNode *decl_node = find_decl(namespace_import->block_context, field_name);
+ if (decl_node) {
+ TopLevelDecl *tld = get_as_top_level_decl(decl_node);
+ if (tld->visib_mod == VisibModPrivate) {
+ ErrorMsg *msg = add_node_error(g, node,
+ buf_sprintf("'%s' is private", buf_ptr(field_name)));
+ add_error_note(g, msg, decl_node, buf_sprintf("declared here"));
+ }
+ bool pointer_only = false;
+ return analyze_decl_ref(g, node, decl_node, pointer_only);
+ } else {
+ add_node_error(g, node,
+ buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
+ buf_ptr(namespace_import->path)));
+ return g->builtin_types.entry_invalid;
+ }
} else {
if (struct_type->id != TypeTableEntryIdInvalid) {
add_node_error(g, node,
@@ -2500,12 +2428,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode
return other_expr->type_entry;
}
-static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context,
- FnTableEntry *fn)
-{
- if (!context->codegen_excluded) {
- fn->ref_count += 1;
- }
+static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
Expr *expr = get_resolved_expr(node);
expr->const_val.ok = true;
expr->const_val.data.x_fn = fn;
@@ -2635,7 +2558,7 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *
static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
BlockContext *context, AstNode *node, Buf *err_name)
{
- auto err_table_entry = import->error_table.maybe_get(err_name);
+ auto err_table_entry = g->error_table.maybe_get(err_name);
if (err_table_entry) {
return resolve_expr_const_val_as_err(g, node, err_table_entry->value);
@@ -2647,9 +2570,48 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
return g->builtin_types.entry_invalid;
}
+static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var) {
+ get_resolved_expr(source_node)->variable = var;
+ if (var->is_const) {
+ AstNode *decl_node = var->decl_node;
+ if (decl_node->type == NodeTypeVariableDeclaration) {
+ AstNode *expr_node = decl_node->data.variable_declaration.expr;
+ ConstExprValue *other_const_val = &get_resolved_expr(expr_node)->const_val;
+ if (other_const_val->ok) {
+ return resolve_expr_const_val_as_other_expr(g, source_node, expr_node);
+ }
+ }
+ }
+ return var->type;
+}
+
+static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
+ bool pointer_only)
+{
+ resolve_top_level_decl(g, decl_node, pointer_only);
+ TopLevelDecl *tld = get_as_top_level_decl(decl_node);
+ if (tld->resolution == TldResolutionInvalid) {
+ return g->builtin_types.entry_invalid;
+ }
+
+ if (decl_node->type == NodeTypeVariableDeclaration) {
+ VariableTableEntry *var = decl_node->data.variable_declaration.variable;
+ return analyze_var_ref(g, source_node, var);
+ } else if (decl_node->type == NodeTypeFnProto) {
+ FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
+ assert(fn_entry->type_entry);
+ return resolve_expr_const_val_as_fn(g, source_node, fn_entry);
+ } else if (decl_node->type == NodeTypeStructDecl) {
+ return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry);
+ } else if (decl_node->type == NodeTypeTypeDecl) {
+ return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry);
+ } else {
+ zig_unreachable();
+ }
+}
static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
- TypeTableEntry *expected_type, AstNode *node)
+ TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
{
if (node->data.symbol_expr.override_type_entry) {
return resolve_expr_const_val_as_type(g, node, node->data.symbol_expr.override_type_entry);
@@ -2662,32 +2624,14 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
}
- VariableTableEntry *var = find_variable(context, variable_name, false);
+ VariableTableEntry *var = find_variable(g, context, variable_name);
if (var) {
- node->data.symbol_expr.variable = var;
- if (var->is_const) {
- AstNode *decl_node = var->decl_node;
- if (decl_node->type == NodeTypeVariableDeclaration) {
- AstNode *expr_node = decl_node->data.variable_declaration.expr;
- ConstExprValue *other_const_val = &get_resolved_expr(expr_node)->const_val;
- if (other_const_val->ok) {
- return resolve_expr_const_val_as_other_expr(g, node, expr_node);
- }
- }
- }
- return var->type;
+ return analyze_var_ref(g, node, var);
}
- TypeTableEntry *container_type = find_container(import, variable_name);
- if (container_type) {
- return resolve_expr_const_val_as_type(g, node, container_type);
- }
-
- auto fn_table_entry = import->fn_table.maybe_get(variable_name);
- if (fn_table_entry) {
- assert(fn_table_entry->value->type_entry);
- node->data.symbol_expr.fn_entry = fn_table_entry->value;
- return resolve_expr_const_val_as_fn(g, node, context, fn_table_entry->value);
+ AstNode *decl_node = find_decl(context, variable_name);
+ if (decl_node) {
+ return analyze_decl_ref(g, node, decl_node, pointer_only);
}
if (import->any_imports_failed) {
@@ -2760,18 +2704,21 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
TypeTableEntry *expected_rhs_type = nullptr;
lhs_node->block_context = block_context;
if (lhs_node->type == NodeTypeSymbol) {
- Buf *name = &lhs_node->data.symbol_expr.symbol;
- if (purpose == LValPurposeAddressOf) {
- expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);
- } else {
- VariableTableEntry *var = find_variable(block_context, name, false);
+ bool pointer_only = purpose == LValPurposeAddressOf;
+ expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node, pointer_only);
+ if (expected_rhs_type->id == TypeTableEntryIdInvalid) {
+ return g->builtin_types.entry_invalid;
+ }
+ if (purpose != LValPurposeAddressOf) {
+ Buf *name = &lhs_node->data.symbol_expr.symbol;
+ VariableTableEntry *var = find_variable(g, block_context, name);
if (var) {
if (var->is_const) {
add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
expected_rhs_type = g->builtin_types.entry_invalid;
} else {
expected_rhs_type = var->type;
- lhs_node->data.symbol_expr.variable = var;
+ get_resolved_expr(lhs_node)->variable = var;
}
} else {
add_node_error(g, lhs_node,
@@ -3176,29 +3123,36 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor
if (name) {
buf_init_from_buf(&variable_entry->name, name);
- VariableTableEntry *existing_var;
- existing_var = find_variable(context, name, context->fn_entry != nullptr);
-
- if (existing_var) {
- add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
- variable_entry->type = g->builtin_types.entry_invalid;
- } else {
- auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
- TypeTableEntry *type;
- if (primitive_table_entry) {
- type = primitive_table_entry->value;
- } else {
- type = find_container(import, name);
- }
- if (type) {
- add_node_error(g, source_node, buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
+ if (type_entry->id != TypeTableEntryIdInvalid) {
+ VariableTableEntry *existing_var = find_variable(g, context, name);
+ if (existing_var) {
+ ErrorMsg *msg = add_node_error(g, source_node,
+ buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
+ add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
variable_entry->type = g->builtin_types.entry_invalid;
+ } else {
+ auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
+ if (primitive_table_entry) {
+ TypeTableEntry *type = primitive_table_entry->value;
+ add_node_error(g, source_node,
+ buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
+ variable_entry->type = g->builtin_types.entry_invalid;
+ } else {
+ AstNode *decl_node = find_decl(context, name);
+ if (decl_node && decl_node->type != NodeTypeVariableDeclaration) {
+ ErrorMsg *msg = add_node_error(g, source_node,
+ buf_sprintf("redefinition of '%s'", buf_ptr(name)));
+ add_error_note(g, msg, decl_node, buf_sprintf("previous definition is here"));
+ variable_entry->type = g->builtin_types.entry_invalid;
+ }
+ }
}
}
- context->variable_table.put(&variable_entry->name, variable_entry);
+ context->var_table.put(&variable_entry->name, variable_entry);
} else {
+ // TODO replace _anon with @anon and make sure all tests still pass
buf_init_from_str(&variable_entry->name, "_anon");
}
if (context->fn_entry) {
@@ -3248,10 +3202,10 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i
static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
BlockContext *context, AstNode *source_node,
AstNodeVariableDeclaration *variable_declaration,
- bool expr_is_maybe)
+ bool expr_is_maybe, AstNode *decl_node)
{
bool is_const = variable_declaration->is_const;
- bool is_export = (variable_declaration->visib_mod == VisibModExport);
+ bool is_export = (variable_declaration->top_level_decl.visib_mod == VisibModExport);
bool is_extern = variable_declaration->is_extern;
TypeTableEntry *explicit_type = nullptr;
@@ -3312,22 +3266,6 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
variable_declaration->variable = var;
-
- bool is_pub = (variable_declaration->visib_mod != VisibModPrivate);
- if (is_pub) {
- for (int i = 0; i < import->importers.length; i += 1) {
- ImporterInfo importer = import->importers.at(i);
- auto table_entry = importer.import->block_context->variable_table.maybe_get(&var->name);
- if (table_entry) {
- add_node_error(g, importer.source_node,
- buf_sprintf("import of variable '%s' overrides existing definition",
- buf_ptr(&var->name)));
- } else {
- importer.import->block_context->variable_table.put(&var->name, var);
- }
- }
- }
-
return var;
}
@@ -3335,7 +3273,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE
BlockContext *context, TypeTableEntry *expected_type, AstNode *node)
{
AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
- return analyze_variable_declaration_raw(g, import, context, node, variable_declaration, false);
+ return analyze_variable_declaration_raw(g, import, context, node, variable_declaration, false, nullptr);
}
static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *import,
@@ -3516,7 +3454,8 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
AstNode *elem_var_node = node->data.for_expr.elem_node;
elem_var_node->block_context = child_context;
Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;
- node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name, child_type, true);
+ node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name,
+ child_type, true);
AstNode *index_var_node = node->data.for_expr.index_node;
if (index_var_node) {
@@ -3673,7 +3612,8 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
BlockContext *child_context = new_block_context(node, parent_context);
- analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true);
+ analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true,
+ nullptr);
VariableTableEntry *var = node->data.if_var_expr.var_decl.variable;
if (var->type->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid;
@@ -4069,6 +4009,145 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
return g->builtin_types.entry_invalid;
}
+static TypeTableEntry *resolve_expr_const_val_as_import(CodeGen *g, AstNode *node, ImportTableEntry *import) {
+ Expr *expr = get_resolved_expr(node);
+ expr->const_val.ok = true;
+ expr->const_val.data.x_import = import;
+ return g->builtin_types.entry_namespace;
+}
+
+static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,
+ AstNode *node)
+{
+ assert(node->type == NodeTypeFnCallExpr);
+
+ if (context != import->block_context) {
+ add_node_error(g, node, buf_sprintf("@import valid only at top level scope"));
+ return g->builtin_types.entry_invalid;
+ }
+
+ AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
+ Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
+ if (!import_target_str) {
+ return g->builtin_types.entry_invalid;
+ }
+
+ Buf *import_target_path;
+ Buf *search_dir;
+ assert(import->package);
+ PackageTableEntry *target_package;
+ auto package_entry = import->package->package_table.maybe_get(import_target_str);
+ if (package_entry) {
+ target_package = package_entry->value;
+ import_target_path = &target_package->root_src_path;
+ search_dir = &target_package->root_src_dir;
+ } else {
+ // try it as a filename
+ target_package = import->package;
+ import_target_path = import_target_str;
+ search_dir = &import->package->root_src_dir;
+ }
+
+ Buf full_path = BUF_INIT;
+ os_path_join(search_dir, import_target_path, &full_path);
+
+ Buf *import_code = buf_alloc();
+ Buf *abs_full_path = buf_alloc();
+ int err;
+ if ((err = os_path_real(&full_path, abs_full_path))) {
+ if (err == ErrorFileNotFound) {
+ add_node_error(g, node,
+ buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
+ return g->builtin_types.entry_invalid;
+ } else {
+ g->error_during_imports = true;
+ add_node_error(g, node,
+ buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
+ return g->builtin_types.entry_invalid;
+ }
+ }
+
+ auto import_entry = g->import_table.maybe_get(abs_full_path);
+ if (import_entry) {
+ return resolve_expr_const_val_as_import(g, node, import_entry->value);
+ }
+
+ if ((err = os_fetch_file_path(abs_full_path, import_code))) {
+ if (err == ErrorFileNotFound) {
+ add_node_error(g, node,
+ buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
+ return g->builtin_types.entry_invalid;
+ } else {
+ add_node_error(g, node,
+ buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
+ return g->builtin_types.entry_invalid;
+ }
+ }
+ ImportTableEntry *target_import = add_source_file(g, target_package,
+ abs_full_path, search_dir, import_target_path, import_code);
+
+ scan_decls(g, target_import, target_import->block_context, target_import->root);
+
+ return resolve_expr_const_val_as_import(g, node, target_import);
+}
+
+static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,
+ BlockContext *parent_context, AstNode *node)
+{
+ assert(node->type == NodeTypeFnCallExpr);
+
+ if (parent_context != parent_import->block_context) {
+ add_node_error(g, node, buf_sprintf("@c_import valid only at top level scope"));
+ return g->builtin_types.entry_invalid;
+ }
+
+ AstNode *block_node = node->data.fn_call_expr.params.at(0);
+
+ BlockContext *child_context = new_block_context(node, parent_context);
+ child_context->c_import_buf = buf_alloc();
+
+ TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context,
+ g->builtin_types.entry_void, block_node);
+
+ if (resolved_type->id == TypeTableEntryIdInvalid) {
+ return resolved_type;
+ }
+
+ find_libc_include_path(g);
+
+ ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
+ child_import->c_import_node = node;
+
+ ZigList<ErrorMsg *> errors = {0};
+
+ int err;
+ if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
+ zig_panic("unable to parse h file: %s\n", err_str(err));
+ }
+
+ if (errors.length > 0) {
+ ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
+ for (int i = 0; i < errors.length; i += 1) {
+ ErrorMsg *err_msg = errors.at(i);
+ err_msg_add_note(parent_err_msg, err_msg);
+ }
+
+ return g->builtin_types.entry_invalid;
+ }
+
+ if (g->verbose) {
+ fprintf(stderr, "\nc_import:\n");
+ fprintf(stderr, "-----------\n");
+ ast_render(stderr, child_import->root, 4);
+ }
+
+ child_import->di_file = parent_import->di_file;
+ child_import->block_context = new_block_context(child_import->root, nullptr);
+
+ scan_decls(g, child_import, child_import->block_context, child_import->root);
+ return resolve_expr_const_val_as_import(g, node, child_import);
+}
+
static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
TypeTableEntry *expected_type, AstNode *node)
{
@@ -4252,6 +4331,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
case TypeTableEntryIdNumLitFloat:
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNamespace:
add_node_error(g, expr_node,
buf_sprintf("type '%s' not eligible for @typeof", buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
@@ -4391,6 +4471,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
return g->builtin_types.entry_invalid;
}
}
+ case BuiltinFnIdImport:
+ return analyze_import(g, import, context, node);
+ case BuiltinFnIdCImport:
+ return analyze_c_import(g, import, context, node);
}
zig_unreachable();
@@ -4456,12 +4540,7 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
node->data.fn_call_expr.fn_entry = fn_table_entry;
- if (!context->codegen_excluded) {
- fn_table_entry->ref_count += 1;
- }
-
return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
-
}
static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
@@ -4515,10 +4594,16 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
}
} else if (child_type->id == TypeTableEntryIdStruct) {
Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
- auto entry = child_type->data.structure.fn_table.maybe_get(field_name);
- if (entry) {
- return analyze_fn_call_raw(g, import, context, expected_type, node,
- entry->value, nullptr);
+ BlockContext *container_block_context = get_container_block_context(child_type);
+ auto entry = container_block_context->decl_table.maybe_get(field_name);
+ AstNode *decl_node = entry ? entry->value : nullptr;
+ if (decl_node && decl_node->type == NodeTypeFnProto) {
+ bool pointer_only = false;
+ resolve_top_level_decl(g, decl_node, pointer_only);
+
+ FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
+ assert(fn_entry);
+ return analyze_fn_call_raw(g, import, context, expected_type, node, fn_entry, nullptr);
} else {
add_node_error(g, node,
buf_sprintf("struct '%s' has no function called '%s'",
@@ -4565,19 +4650,19 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
TypeTableEntry *expected_type, AstNode *node)
{
PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
- AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
+ AstNode **expr_node = &node->data.prefix_op_expr.primary_expr;
switch (prefix_op) {
case PrefixOpInvalid:
zig_unreachable();
case PrefixOpBoolNot:
{
TypeTableEntry *type_entry = analyze_expression(g, import, context, g->builtin_types.entry_bool,
- expr_node);
+ *expr_node);
if (type_entry->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_bool;
}
- ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;
+ ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
if (!target_const_val->ok) {
return g->builtin_types.entry_bool;
}
@@ -4588,7 +4673,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
case PrefixOpBinNot:
{
TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
- expr_node);
+ *expr_node);
if (expr_type->id == TypeTableEntryIdInvalid) {
return expr_type;
} else if (expr_type->id == TypeTableEntryIdInt ||
@@ -4596,7 +4681,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
{
return expr_type;
} else {
- add_node_error(g, expr_node, buf_sprintf("invalid binary not type: '%s'",
+ add_node_error(g, *expr_node, buf_sprintf("invalid binary not type: '%s'",
buf_ptr(&expr_type->name)));
return g->builtin_types.entry_invalid;
}
@@ -4604,8 +4689,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
}
case PrefixOpNegation:
{
- TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
- expr_node);
+ TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type, *expr_node);
if (expr_type->id == TypeTableEntryIdInvalid) {
return expr_type;
} else if ((expr_type->id == TypeTableEntryIdInt &&
@@ -4614,7 +4698,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
expr_type->id == TypeTableEntryIdNumLitInt ||
expr_type->id == TypeTableEntryIdNumLitFloat)
{
- ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;
+ ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
if (!target_const_val->ok) {
return expr_type;
}
@@ -4635,12 +4719,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
bool is_const = (prefix_op == PrefixOpConstAddressOf);
TypeTableEntry *child_type = analyze_lvalue(g, import, context,
- expr_node, LValPurposeAddressOf, is_const);
+ *expr_node, LValPurposeAddressOf, is_const);
if (child_type->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid;
} else if (child_type->id == TypeTableEntryIdMetaType) {
- TypeTableEntry *meta_type = analyze_type_expr(g, import, context, expr_node);
+ TypeTableEntry *meta_type = analyze_type_expr_pointer_only(g, import, context,
+ *expr_node, true);
if (meta_type->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid;
} else if (meta_type->id == TypeTableEntryIdUnreachable) {
@@ -4653,7 +4738,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
} else if (child_type->id == TypeTableEntryIdNumLitInt ||
child_type->id == TypeTableEntryIdNumLitFloat)
{
- add_node_error(g, expr_node,
+ add_node_error(g, *expr_node,
buf_sprintf("unable to get address of type '%s'", buf_ptr(&child_type->name)));
return g->builtin_types.entry_invalid;
} else {
@@ -4662,13 +4747,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
}
case PrefixOpDereference:
{
- TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
+ TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
if (type_entry->id == TypeTableEntryIdInvalid) {
return type_entry;
} else if (type_entry->id == TypeTableEntryIdPointer) {
return type_entry->data.pointer.child_type;
} else {
- add_node_error(g, expr_node,
+ add_node_error(g, *expr_node,
buf_sprintf("indirection requires pointer operand ('%s' invalid)",
buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
@@ -4676,12 +4761,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
}
case PrefixOpMaybe:
{
- TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
+ TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
if (type_entry->id == TypeTableEntryIdInvalid) {
return type_entry;
} else if (type_entry->id == TypeTableEntryIdMetaType) {
- TypeTableEntry *meta_type = resolve_type(g, expr_node);
+ TypeTableEntry *meta_type = resolve_type(g, *expr_node);
if (meta_type->id == TypeTableEntryIdInvalid) {
return g->builtin_types.entry_invalid;
} else if (meta_type->id == TypeTableEntryIdUnreachable) {
@@ -4691,10 +4776,10 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type));
}
} else if (type_entry->id == TypeTableEntryIdUnreachable) {
- add_node_error(g, expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
+ add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
return g->builtin_types.entry_invalid;
} else {
- ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;
+ ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
TypeTableEntry *maybe_type = get_maybe_type(g, type_entry);
if (!target_const_val->ok) {
return maybe_type;
@@ -4704,12 +4789,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
}
case PrefixOpError:
{
- TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
+ TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
if (type_entry->id == TypeTableEntryIdInvalid) {
return type_entry;
} else if (type_entry->id == TypeTableEntryIdMetaType) {
- TypeTableEntry *meta_type = resolve_type(g, expr_node);
+ TypeTableEntry *meta_type = resolve_type(g, *expr_node);
if (meta_type->id == TypeTableEntryIdInvalid) {
return meta_type;
} else if (meta_type->id == TypeTableEntryIdUnreachable) {
@@ -4719,7 +4804,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type));
}
} else if (type_entry->id == TypeTableEntryIdUnreachable) {
- add_node_error(g, expr_node, buf_sprintf("unable to wrap unreachable in error type"));
+ add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type"));
return g->builtin_types.entry_invalid;
} else {
// TODO eval const expr
@@ -4729,28 +4814,28 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
}
case PrefixOpUnwrapError:
{
- TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
+ TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
if (type_entry->id == TypeTableEntryIdInvalid) {
return type_entry;
} else if (type_entry->id == TypeTableEntryIdErrorUnion) {
return type_entry->data.error.child_type;
} else {
- add_node_error(g, expr_node,
+ add_node_error(g, *expr_node,
buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
}
}
case PrefixOpUnwrapMaybe:
{
- TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);
+ TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
if (type_entry->id == TypeTableEntryIdInvalid) {
return type_entry;
} else if (type_entry->id == TypeTableEntryIdMaybe) {
return type_entry->data.maybe.child_type;
} else {
- add_node_error(g, expr_node,
+ add_node_error(g, *expr_node,
buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));
return g->builtin_types.entry_invalid;
}
@@ -5094,7 +5179,7 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl
}
} else {
Buf *variable_name = &asm_output->variable_name;
- VariableTableEntry *var = find_variable(context, variable_name, false);
+ VariableTableEntry *var = find_variable(g, context, variable_name);
if (var) {
asm_output->variable = var;
return var->type;
@@ -5120,10 +5205,8 @@ static TypeTableEntry *analyze_goto(CodeGen *g, ImportTableEntry *import, BlockC
return g->builtin_types.entry_unreachable;
}
-// When you call analyze_expression, the node you pass might no longer be the child node
-// you thought it was due to implicit casting rewriting the AST.
-static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
- TypeTableEntry *expected_type, AstNode *node)
+static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEntry *import,
+ BlockContext *context, TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
{
assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
TypeTableEntry *return_type = nullptr;
@@ -5197,7 +5280,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
return_type = analyze_undefined_literal_expr(g, import, context, expected_type, node);
break;
case NodeTypeSymbol:
- return_type = analyze_symbol_expr(g, import, context, expected_type, node);
+ return_type = analyze_symbol_expr(g, import, context, expected_type, node, pointer_only);
break;
case NodeTypePrefixOpExpr:
return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);
@@ -5235,10 +5318,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
case NodeTypeFnDecl:
case NodeTypeParamDecl:
case NodeTypeRoot:
- case NodeTypeRootExportDecl:
case NodeTypeFnDef:
- case NodeTypeImport:
- case NodeTypeCImport:
+ case NodeTypeUse:
case NodeTypeLabel:
case NodeTypeStructDecl:
case NodeTypeStructField:
@@ -5263,7 +5344,17 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
return resolved_type;
}
-static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node) {
+// When you call analyze_expression, the node you pass might no longer be the child node
+// you thought it was due to implicit casting rewriting the AST.
+static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
+ TypeTableEntry *expected_type, AstNode *node)
+{
+ return analyze_expression_pointer_only(g, import, context, expected_type, node, false);
+}
+
+static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
+ ImportTableEntry *import = fn_table_entry->import_entry;
+ AstNode *node = fn_table_entry->fn_def_node;
assert(node->type == NodeTypeFnDef);
AstNode *fn_proto_node = node->data.fn_def.fn_proto;
@@ -5277,7 +5368,6 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
BlockContext *context = node->data.fn_def.block_context;
- FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry;
TypeTableEntry *fn_type = fn_table_entry->type_entry;
AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
for (int i = 0; i < fn_proto->params.length; i += 1) {
@@ -5302,7 +5392,8 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));
}
- VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, &param_decl->name, type, true);
+ VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, &param_decl->name,
+ type, true);
var->src_arg_index = i;
param_decl_node->data.param_decl.variable = var;
@@ -5315,375 +5406,71 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
node->data.fn_def.implicit_return_type = block_return_type;
}
-static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
- switch (node->type) {
- case NodeTypeFnDef:
- analyze_top_level_fn_def(g, import, node);
- break;
- case NodeTypeStructDecl:
- {
- for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
- AstNode *fn_def_node = node->data.struct_decl.fns.at(i);
- analyze_top_level_fn_def(g, import, fn_def_node);
- }
- break;
- }
- case NodeTypeRootExportDecl:
- case NodeTypeImport:
- case NodeTypeCImport:
- case NodeTypeVariableDeclaration:
- case NodeTypeErrorValueDecl:
- case NodeTypeFnProto:
- case NodeTypeTypeDecl:
- // already took care of these
- break;
- case NodeTypeDirective:
- case NodeTypeParamDecl:
- case NodeTypeFnDecl:
- case NodeTypeReturnExpr:
- case NodeTypeDefer:
- case NodeTypeRoot:
- case NodeTypeBlock:
- case NodeTypeBinOpExpr:
- case NodeTypeUnwrapErrorExpr:
- case NodeTypeFnCallExpr:
- case NodeTypeArrayAccessExpr:
- case NodeTypeSliceExpr:
- case NodeTypeNumberLiteral:
- case NodeTypeStringLiteral:
- case NodeTypeCharLiteral:
- case NodeTypeBoolLiteral:
- case NodeTypeNullLiteral:
- case NodeTypeUndefinedLiteral:
- case NodeTypeSymbol:
- case NodeTypePrefixOpExpr:
- case NodeTypeIfBoolExpr:
- case NodeTypeIfVarExpr:
- case NodeTypeWhileExpr:
- case NodeTypeForExpr:
- case NodeTypeSwitchExpr:
- case NodeTypeSwitchProng:
- case NodeTypeSwitchRange:
- case NodeTypeLabel:
- case NodeTypeGoto:
- case NodeTypeBreak:
- case NodeTypeContinue:
- case NodeTypeAsmExpr:
- case NodeTypeFieldAccessExpr:
- case NodeTypeStructField:
- case NodeTypeStructValueField:
- case NodeTypeContainerInitExpr:
- case NodeTypeArrayType:
- case NodeTypeErrorType:
- case NodeTypeTypeLiteral:
- zig_unreachable();
+static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
+ AstNode *node, Buf *name)
+{
+ assert(import);
+
+ TopLevelDecl *tld = get_as_top_level_decl(node);
+ tld->import = import;
+ tld->name = name;
+
+ if (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport) {
+ g->export_queue.append(node);
}
-}
-static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node,
- TopLevelDecl *decl_node)
-{
- switch (node->type) {
- case NodeTypeNumberLiteral:
- case NodeTypeStringLiteral:
- case NodeTypeCharLiteral:
- case NodeTypeBoolLiteral:
- case NodeTypeNullLiteral:
- case NodeTypeUndefinedLiteral:
- case NodeTypeGoto:
- case NodeTypeBreak:
- case NodeTypeContinue:
- case NodeTypeErrorValueDecl:
- case NodeTypeErrorType:
- case NodeTypeTypeLiteral:
- // no dependencies on other top level declarations
- break;
- case NodeTypeSymbol:
- {
- if (node->data.symbol_expr.override_type_entry) {
- break;
- }
- Buf *name = &node->data.symbol_expr.symbol;
- auto table_entry = g->primitive_type_table.maybe_get(name);
- if (!table_entry) {
- table_entry = import->type_table.maybe_get(name);
- }
- if (!table_entry || !type_is_complete(table_entry->value)) {
- decl_node->deps.put(name, node);
- }
- break;
- }
- case NodeTypeBinOpExpr:
- collect_expr_decl_deps(g, import, node->data.bin_op_expr.op1, decl_node);
- collect_expr_decl_deps(g, import, node->data.bin_op_expr.op2, decl_node);
- break;
- case NodeTypeUnwrapErrorExpr:
- collect_expr_decl_deps(g, import, node->data.unwrap_err_expr.op1, decl_node);
- collect_expr_decl_deps(g, import, node->data.unwrap_err_expr.op2, decl_node);
- break;
- case NodeTypeReturnExpr:
- collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
- break;
- case NodeTypeDefer:
- collect_expr_decl_deps(g, import, node->data.defer.expr, decl_node);
- break;
- case NodeTypePrefixOpExpr:
- collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
- break;
- case NodeTypeFnCallExpr:
- if (!node->data.fn_call_expr.is_builtin) {
- collect_expr_decl_deps(g, import, node->data.fn_call_expr.fn_ref_expr, decl_node);
- }
- for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
- AstNode *arg_node = node->data.fn_call_expr.params.at(i);
- collect_expr_decl_deps(g, import, arg_node, decl_node);
- }
- break;
- case NodeTypeArrayAccessExpr:
- collect_expr_decl_deps(g, import, node->data.array_access_expr.array_ref_expr, decl_node);
- collect_expr_decl_deps(g, import, node->data.array_access_expr.subscript, decl_node);
- break;
- case NodeTypeSliceExpr:
- collect_expr_decl_deps(g, import, node->data.slice_expr.array_ref_expr, decl_node);
- collect_expr_decl_deps(g, import, node->data.slice_expr.start, decl_node);
- if (node->data.slice_expr.end) {
- collect_expr_decl_deps(g, import, node->data.slice_expr.end, decl_node);
- }
- break;
- case NodeTypeFieldAccessExpr:
- collect_expr_decl_deps(g, import, node->data.field_access_expr.struct_expr, decl_node);
- break;
- case NodeTypeIfBoolExpr:
- collect_expr_decl_deps(g, import, node->data.if_bool_expr.condition, decl_node);
- collect_expr_decl_deps(g, import, node->data.if_bool_expr.then_block, decl_node);
- if (node->data.if_bool_expr.else_node) {
- collect_expr_decl_deps(g, import, node->data.if_bool_expr.else_node, decl_node);
- }
- break;
- case NodeTypeIfVarExpr:
- if (node->data.if_var_expr.var_decl.type) {
- collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.type, decl_node);
- }
- if (node->data.if_var_expr.var_decl.expr) {
- collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.expr, decl_node);
- }
- collect_expr_decl_deps(g, import, node->data.if_var_expr.then_block, decl_node);
- if (node->data.if_bool_expr.else_node) {
- collect_expr_decl_deps(g, import, node->data.if_var_expr.else_node, decl_node);
- }
- break;
- case NodeTypeWhileExpr:
- collect_expr_decl_deps(g, import, node->data.while_expr.condition, decl_node);
- collect_expr_decl_deps(g, import, node->data.while_expr.body, decl_node);
- break;
- case NodeTypeForExpr:
- collect_expr_decl_deps(g, import, node->data.for_expr.array_expr, decl_node);
- collect_expr_decl_deps(g, import, node->data.for_expr.body, decl_node);
- break;
- case NodeTypeBlock:
- for (int i = 0; i < node->data.block.statements.length; i += 1) {
- AstNode *stmt = node->data.block.statements.at(i);
- collect_expr_decl_deps(g, import, stmt, decl_node);
- }
- break;
- case NodeTypeAsmExpr:
- for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
- AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
- if (asm_output->return_type) {
- collect_expr_decl_deps(g, import, asm_output->return_type, decl_node);
- } else {
- decl_node->deps.put(&asm_output->variable_name, node);
- }
- }
- for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
- AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
- collect_expr_decl_deps(g, import, asm_input->expr, decl_node);
- }
- break;
- case NodeTypeContainerInitExpr:
- collect_expr_decl_deps(g, import, node->data.container_init_expr.type, decl_node);
- for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
- AstNode *child_node = node->data.container_init_expr.entries.at(i);
- collect_expr_decl_deps(g, import, child_node, decl_node);
- }
- break;
- case NodeTypeStructValueField:
- collect_expr_decl_deps(g, import, node->data.struct_val_field.expr, decl_node);
- break;
- case NodeTypeArrayType:
- if (node->data.array_type.size) {
- collect_expr_decl_deps(g, import, node->data.array_type.size, decl_node);
- }
- collect_expr_decl_deps(g, import, node->data.array_type.child_type, decl_node);
- break;
- case NodeTypeSwitchExpr:
- collect_expr_decl_deps(g, import, node->data.switch_expr.expr, decl_node);
- for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
- AstNode *prong = node->data.switch_expr.prongs.at(i);
- collect_expr_decl_deps(g, import, prong, decl_node);
- }
- break;
- case NodeTypeSwitchProng:
- for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
- AstNode *child = node->data.switch_prong.items.at(i);
- collect_expr_decl_deps(g, import, child, decl_node);
- }
- collect_expr_decl_deps(g, import, node->data.switch_prong.expr, decl_node);
- break;
- case NodeTypeSwitchRange:
- collect_expr_decl_deps(g, import, node->data.switch_range.start, decl_node);
- collect_expr_decl_deps(g, import, node->data.switch_range.end, decl_node);
- break;
- case NodeTypeFnProto:
- // remember that fn proto node is used for function definitions as well
- // as types
- for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
- AstNode *param = node->data.fn_proto.params.at(i);
- collect_expr_decl_deps(g, import, param, decl_node);
- }
- if (node->data.fn_proto.directives) {
- for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) {
- AstNode *directive = node->data.fn_proto.directives->at(i);
- collect_expr_decl_deps(g, import, directive, decl_node);
- }
- }
- collect_expr_decl_deps(g, import, node->data.fn_proto.return_type, decl_node);
- break;
- case NodeTypeParamDecl:
- collect_expr_decl_deps(g, import, node->data.param_decl.type, decl_node);
- break;
- case NodeTypeTypeDecl:
- collect_expr_decl_deps(g, import, node->data.type_decl.child_type, decl_node);
- break;
- case NodeTypeDirective:
- collect_expr_decl_deps(g, import, node->data.directive.expr, decl_node);
- break;
- case NodeTypeVariableDeclaration:
- case NodeTypeRootExportDecl:
- case NodeTypeFnDef:
- case NodeTypeRoot:
- case NodeTypeFnDecl:
- case NodeTypeImport:
- case NodeTypeCImport:
- case NodeTypeLabel:
- case NodeTypeStructDecl:
- case NodeTypeStructField:
- zig_unreachable();
+ node->block_context = block_context;
+
+ auto entry = block_context->decl_table.maybe_get(name);
+ if (entry) {
+ AstNode *other_decl_node = entry->value;
+ ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
+ add_error_note(g, msg, other_decl_node, buf_sprintf("previous definition is here"));
+ } else {
+ block_context->decl_table.put(name, node);
}
}
-static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {
+static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {
switch (node->type) {
case NodeTypeRoot:
for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
AstNode *child = import->root->data.root.top_level_decls.at(i);
- detect_top_level_decl_deps(g, import, child);
+ scan_decls(g, import, context, child);
}
break;
case NodeTypeStructDecl:
{
Buf *name = &node->data.struct_decl.name;
- auto table_entry = g->primitive_type_table.maybe_get(name);
- if (!table_entry) {
- table_entry = import->type_table.maybe_get(name);
- }
- if (table_entry) {
- node->data.struct_decl.type_entry = table_entry->value;
- add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
- } else {
- TypeTableEntry *entry;
- if (node->data.struct_decl.type_entry) {
- entry = node->data.struct_decl.type_entry;
- } else {
- entry = get_partial_container_type(g, import,
- node->data.struct_decl.kind, node, buf_ptr(name));
- }
-
- import->type_table.put(&entry->name, entry);
- node->data.struct_decl.type_entry = entry;
-
- bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);
- if (is_pub) {
- for (int i = 0; i < import->importers.length; i += 1) {
- ImporterInfo importer = import->importers.at(i);
- auto table_entry = importer.import->type_table.maybe_get(&entry->name);
- if (table_entry) {
- add_node_error(g, importer.source_node,
- buf_sprintf("import of type '%s' overrides existing definition",
- buf_ptr(&entry->name)));
- } else {
- importer.import->type_table.put(&entry->name, entry);
- }
- }
- }
- }
-
- // determine which other top level declarations this struct depends on.
- TopLevelDecl *decl_node = &node->data.struct_decl.top_level_decl;
- decl_node->deps.init(1);
- for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
- AstNode *field_node = node->data.struct_decl.fields.at(i);
- AstNode *type_node = field_node->data.struct_field.type;
- collect_expr_decl_deps(g, import, type_node, decl_node);
- }
- decl_node->name = name;
- decl_node->import = import;
- if (decl_node->deps.size() > 0) {
- g->unresolved_top_level_decls.put(name, node);
- } else {
- resolve_top_level_decl(g, import, node);
- }
+ TypeTableEntry *container_type = get_partial_container_type(g, import,
+ node->data.struct_decl.kind, node, buf_ptr(name));
+ node->data.struct_decl.type_entry = container_type;
+ add_top_level_decl(g, import, context, node, name);
// handle the member function definitions independently
for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
- AstNode *fn_def_node = node->data.struct_decl.fns.at(i);
- AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;
- fn_proto_node->data.fn_proto.struct_node = node;
- detect_top_level_decl_deps(g, import, fn_def_node);
+ AstNode *child_node = node->data.struct_decl.fns.at(i);
+ get_as_top_level_decl(child_node)->parent_decl = node;
+ BlockContext *child_context = get_container_block_context(container_type);
+ scan_decls(g, import, child_context, child_node);
}
break;
}
case NodeTypeFnDef:
node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;
- detect_top_level_decl_deps(g, import, node->data.fn_def.fn_proto);
+ scan_decls(g, import, context, node->data.fn_def.fn_proto);
break;
case NodeTypeVariableDeclaration:
{
- // determine which other top level declarations this variable declaration depends on.
- TopLevelDecl *decl_node = &node->data.variable_declaration.top_level_decl;
- decl_node->deps.init(1);
- if (node->data.variable_declaration.type) {
- collect_expr_decl_deps(g, import, node->data.variable_declaration.type, decl_node);
- }
- if (node->data.variable_declaration.expr) {
- collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node);
- }
Buf *name = &node->data.variable_declaration.symbol;
- decl_node->name = name;
- decl_node->import = import;
- if (decl_node->deps.size() > 0) {
- g->unresolved_top_level_decls.put(name, node);
- } else {
- resolve_top_level_decl(g, import, node);
- }
+ add_top_level_decl(g, import, context, node, name);
break;
}
case NodeTypeTypeDecl:
{
- // determine which other top level declarations this variable declaration depends on.
- TopLevelDecl *decl_node = &node->data.type_decl.top_level_decl;
- decl_node->deps.init(1);
- collect_expr_decl_deps(g, import, node, decl_node);
-
Buf *name = &node->data.type_decl.symbol;
- decl_node->name = name;
- decl_node->import = import;
- if (decl_node->deps.size() > 0) {
- g->unresolved_top_level_decls.put(name, node);
- } else {
- resolve_top_level_decl(g, import, node);
- }
+ add_top_level_decl(g, import, context, node, name);
break;
}
case NodeTypeFnProto:
@@ -5695,60 +5482,22 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
add_node_error(g, node, buf_sprintf("missing function name"));
break;
}
- Buf *qualified_name;
- AstNode *struct_node = node->data.fn_proto.struct_node;
- if (struct_node) {
- Buf *struct_name = &struct_node->data.struct_decl.name;
- qualified_name = buf_sprintf("%s.%s", buf_ptr(struct_name), buf_ptr(fn_name));
- } else {
- qualified_name = fn_name;
- }
-
- // determine which other top level declarations this function prototype depends on.
- TopLevelDecl *decl_node = &node->data.fn_proto.top_level_decl;
- decl_node->deps.init(1);
-
- collect_expr_decl_deps(g, import, node, decl_node);
-
- decl_node->name = qualified_name;
- decl_node->import = import;
- if (decl_node->deps.size() > 0) {
- if (g->unresolved_top_level_decls.maybe_get(qualified_name)) {
- node->data.fn_proto.skip = true;
- add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(fn_name)));
- } else {
- g->unresolved_top_level_decls.put(qualified_name, node);
- }
- } else {
- resolve_top_level_decl(g, import, node);
- }
+ add_top_level_decl(g, import, context, node, fn_name);
break;
}
- case NodeTypeRootExportDecl:
- resolve_top_level_decl(g, import, node);
- break;
- case NodeTypeImport:
- // already taken care of
- break;
- case NodeTypeCImport:
+ case NodeTypeUse:
{
- TopLevelDecl *decl_node = &node->data.c_import.top_level_decl;
- decl_node->deps.init(1);
- collect_expr_decl_deps(g, import, node->data.c_import.block, decl_node);
-
- decl_node->name = buf_sprintf("c_import_%" PRIu32, node->create_index);
- decl_node->import = import;
- if (decl_node->deps.size() > 0) {
- g->unresolved_top_level_decls.put(decl_node->name, node);
- } else {
- resolve_top_level_decl(g, import, node);
- }
+ TopLevelDecl *tld = get_as_top_level_decl(node);
+ tld->import = import;
+ node->block_context = context;
+ g->use_queue.append(node);
+ tld->import->use_decls.append(node);
break;
}
case NodeTypeErrorValueDecl:
// error value declarations do not depend on other top level decls
- resolve_top_level_decl(g, import, node);
+ preview_error_value_decl(g, node);
break;
case NodeTypeDirective:
case NodeTypeParamDecl:
@@ -5792,152 +5541,176 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
}
}
-static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
- auto it = get_resolved_top_level_decl(node)->deps.entry_iterator();
- for (;;) {
- auto *entry = it.next();
- if (!entry)
- break;
+static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) {
+ TopLevelDecl *tld = get_as_top_level_decl(dst_use_node);
+ AstNode *use_target_node = src_use_node->data.use.expr;
+ Expr *expr = get_resolved_expr(use_target_node);
- auto unresolved_entry = g->unresolved_top_level_decls.maybe_get(entry->key);
- if (!unresolved_entry) {
- continue;
- }
+ if (expr->type_entry->id == TypeTableEntryIdInvalid) {
+ return;
+ }
- AstNode *child_node = unresolved_entry->value;
+ ConstExprValue *const_val = &expr->const_val;
+ assert(const_val->ok);
- if (get_resolved_top_level_decl(child_node)->in_current_deps) {
- // dependency loop. we'll let the fact that it's not in the respective
- // table cause an error in resolve_top_level_decl.
+ ImportTableEntry *target_import = const_val->data.x_import;
+ assert(target_import);
+
+ if (target_import->any_imports_failed) {
+ tld->import->any_imports_failed = true;
+ }
+
+ for (int i = 0; i < target_import->root->data.root.top_level_decls.length; i += 1) {
+ AstNode *decl_node = target_import->root->data.root.top_level_decls.at(i);
+ if (decl_node->type == NodeTypeFnDef) {
+ decl_node = decl_node->data.fn_def.fn_proto;
+ }
+ TopLevelDecl *target_tld = get_as_top_level_decl(decl_node);
+ if (!target_tld->name) {
continue;
}
+ if (target_tld->visib_mod != VisibModPrivate) {
+ auto existing_entry = tld->import->block_context->decl_table.maybe_get(target_tld->name);
+ if (existing_entry) {
+ AstNode *existing_decl = existing_entry->value;
+ if (existing_decl != decl_node) {
+ ErrorMsg *msg = add_node_error(g, dst_use_node,
+ buf_sprintf("import of '%s' overrides existing definition",
+ buf_ptr(target_tld->name)));
+ add_error_note(g, msg, existing_decl, buf_sprintf("previous definition here"));
+ add_error_note(g, msg, decl_node, buf_sprintf("imported definition here"));
+ }
+ } else {
+ tld->import->block_context->decl_table.put(target_tld->name, decl_node);
+ }
+ }
+ }
- // set temporary flag
- TopLevelDecl *top_level_decl = get_resolved_top_level_decl(child_node);
- top_level_decl->in_current_deps = true;
+ for (int i = 0; i < target_import->use_decls.length; i += 1) {
+ AstNode *use_decl_node = target_import->use_decls.at(i);
+ TopLevelDecl *target_tld = get_as_top_level_decl(use_decl_node);
+ if (target_tld->visib_mod != VisibModPrivate) {
+ add_symbols_from_import(g, use_decl_node, dst_use_node);
+ }
+ }
- recursive_resolve_decl(g, top_level_decl->import, child_node);
+}
- // unset temporary flag
- top_level_decl->in_current_deps = false;
- }
+static void resolve_use_decl(CodeGen *g, AstNode *node) {
+ assert(node->type == NodeTypeUse);
+ add_symbols_from_import(g, node, node);
+}
- resolve_top_level_decl(g, import, node);
+static void preview_use_decl(CodeGen *g, AstNode *node) {
+ assert(node->type == NodeTypeUse);
+ TopLevelDecl *tld = get_as_top_level_decl(node);
+ TypeTableEntry *use_expr_type = analyze_expression(g, tld->import, tld->import->block_context,
+ g->builtin_types.entry_namespace, node->data.use.expr);
+ if (use_expr_type->id == TypeTableEntryIdInvalid) {
+ tld->import->any_imports_failed = true;
+ }
}
-static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
- assert(node->type == NodeTypeRoot);
+ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
+ Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code)
+{
+ Buf *full_path = buf_alloc();
+ os_path_join(src_dirname, src_basename, full_path);
- while (g->unresolved_top_level_decls.size() > 0) {
- // for the sake of determinism, find the element with the lowest
- // insert index and resolve that one.
- AstNode *decl_node = nullptr;
- auto it = g->unresolved_top_level_decls.entry_iterator();
- for (;;) {
- auto *entry = it.next();
- if (!entry)
- break;
+ if (g->verbose) {
+ fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(full_path));
+ fprintf(stderr, "----------------\n");
+ fprintf(stderr, "%s\n", buf_ptr(source_code));
- AstNode *this_node = entry->value;
- if (!decl_node || this_node->create_index < decl_node->create_index) {
- decl_node = this_node;
- }
+ fprintf(stderr, "\nTokens:\n");
+ fprintf(stderr, "---------\n");
+ }
- }
- // set temporary flag
- TopLevelDecl *top_level_decl = get_resolved_top_level_decl(decl_node);
- top_level_decl->in_current_deps = true;
+ Tokenization tokenization = {0};
+ tokenize(source_code, &tokenization);
- recursive_resolve_decl(g, top_level_decl->import, decl_node);
+ if (tokenization.err) {
+ ErrorMsg *err = err_msg_create_with_line(full_path, tokenization.err_line, tokenization.err_column,
+ source_code, tokenization.line_offsets, tokenization.err);
- // unset temporary flag
- top_level_decl->in_current_deps = false;
+ print_err_msg(err, g->err_color);
+ exit(1);
}
-}
-static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
- assert(node->type == NodeTypeRoot);
+ if (g->verbose) {
+ print_tokens(source_code, tokenization.tokens);
- for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
- AstNode *child = node->data.root.top_level_decls.at(i);
- analyze_top_level_decl(g, import, child);
+ fprintf(stderr, "\nAST:\n");
+ fprintf(stderr, "------\n");
}
-}
-void semantic_analyze(CodeGen *g) {
- {
- auto it = g->import_table.entry_iterator();
- for (;;) {
- auto *entry = it.next();
- if (!entry)
- break;
+ ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
+ import_entry->package = package;
+ import_entry->source_code = source_code;
+ import_entry->line_offsets = tokenization.line_offsets;
+ import_entry->path = full_path;
- ImportTableEntry *import = entry->value;
+ import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
+ &g->next_node_index);
+ assert(import_entry->root);
+ if (g->verbose) {
+ ast_print(stderr, import_entry->root, 0);
+ }
- for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
- AstNode *child = import->root->data.root.top_level_decls.at(i);
- if (child->type == NodeTypeImport) {
- if (child->data.import.directives) {
- for (int i = 0; i < child->data.import.directives->length; i += 1) {
- AstNode *directive_node = child->data.import.directives->at(i);
- Buf *name = &directive_node->data.directive.name;
- add_node_error(g, directive_node,
- buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
- }
- }
+ import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
+ g->import_table.put(abs_full_path, import_entry);
+ g->import_queue.append(import_entry);
- ImportTableEntry *target_import = child->data.import.import;
- assert(target_import);
+ import_entry->block_context = new_block_context(import_entry->root, nullptr);
+ import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
- target_import->importers.append({import, child});
- } else if (child->type == NodeTypeErrorValueDecl) {
- preview_error_value_decl(g, child);
- }
+
+ assert(import_entry->root->type == NodeTypeRoot);
+ for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
+ AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i);
+
+ if (top_level_decl->type == NodeTypeFnDef) {
+ AstNode *proto_node = top_level_decl->data.fn_def.fn_proto;
+ assert(proto_node->type == NodeTypeFnProto);
+ Buf *proto_name = &proto_node->data.fn_proto.name;
+
+ bool is_private = (proto_node->data.fn_proto.top_level_decl.visib_mod == VisibModPrivate);
+
+ if (buf_eql_str(proto_name, "main") && !is_private) {
+ g->have_exported_main = true;
}
}
}
- {
- g->err_tag_type = get_smallest_unsigned_int_type(g, g->error_value_count);
-
- g->builtin_types.entry_pure_error->type_ref = g->err_tag_type->type_ref;
- g->builtin_types.entry_pure_error->di_type = g->err_tag_type->di_type;
- }
+ return import_entry;
+}
- {
- auto it = g->import_table.entry_iterator();
- for (;;) {
- auto *entry = it.next();
- if (!entry)
- break;
- ImportTableEntry *import = entry->value;
+void semantic_analyze(CodeGen *g) {
+ for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) {
+ ImportTableEntry *import = g->import_queue.at(g->import_queue_index);
+ scan_decls(g, import, import->block_context, import->root);
+ }
- detect_top_level_decl_deps(g, import, import->root);
- }
+ for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) {
+ AstNode *use_decl_node = g->use_queue.at(g->use_queue_index);
+ preview_use_decl(g, use_decl_node);
}
- {
- auto it = g->import_table.entry_iterator();
- for (;;) {
- auto *entry = it.next();
- if (!entry)
- break;
+ for (int i = 0; i < g->use_queue.length; i += 1) {
+ AstNode *use_decl_node = g->use_queue.at(i);
+ resolve_use_decl(g, use_decl_node);
+ }
- ImportTableEntry *import = entry->value;
- resolve_top_level_declarations_root(g, import, import->root);
- }
+ for (; g->export_queue_index < g->export_queue.length; g->export_queue_index += 1) {
+ AstNode *decl_node = g->export_queue.at(g->export_queue_index);
+ bool pointer_only = false;
+ resolve_top_level_decl(g, decl_node, pointer_only);
}
- {
- auto it = g->import_table.entry_iterator();
- for (;;) {
- auto *entry = it.next();
- if (!entry)
- break;
- ImportTableEntry *import = entry->value;
- analyze_top_level_decls_root(g, import, import->root);
- }
+ for (int i = 0; i < g->fn_defs.length; i += 1) {
+ FnTableEntry *fn_entry = g->fn_defs.at(i);
+ analyze_fn_body(g, fn_entry);
}
}
@@ -6012,13 +5785,11 @@ Expr *get_resolved_expr(AstNode *node) {
case NodeTypeSwitchProng:
case NodeTypeSwitchRange:
case NodeTypeRoot:
- case NodeTypeRootExportDecl:
case NodeTypeFnDef:
case NodeTypeFnDecl:
case NodeTypeParamDecl:
case NodeTypeDirective:
- case NodeTypeImport:
- case NodeTypeCImport:
+ case NodeTypeUse:
case NodeTypeStructDecl:
case NodeTypeStructField:
case NodeTypeStructValueField:
@@ -6029,18 +5800,20 @@ Expr *get_resolved_expr(AstNode *node) {
zig_unreachable();
}
-TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
+static TopLevelDecl *get_as_top_level_decl(AstNode *node) {
switch (node->type) {
case NodeTypeVariableDeclaration:
return &node->data.variable_declaration.top_level_decl;
case NodeTypeFnProto:
return &node->data.fn_proto.top_level_decl;
+ case NodeTypeFnDef:
+ return &node->data.fn_def.fn_proto->data.fn_proto.top_level_decl;
case NodeTypeStructDecl:
return &node->data.struct_decl.top_level_decl;
case NodeTypeErrorValueDecl:
return &node->data.error_value_decl.top_level_decl;
- case NodeTypeCImport:
- return &node->data.c_import.top_level_decl;
+ case NodeTypeUse:
+ return &node->data.use.top_level_decl;
case NodeTypeTypeDecl:
return &node->data.type_decl.top_level_decl;
case NodeTypeNumberLiteral:
@@ -6063,8 +5836,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
case NodeTypeAsmExpr:
case NodeTypeContainerInitExpr:
case NodeTypeRoot:
- case NodeTypeRootExportDecl:
- case NodeTypeFnDef:
case NodeTypeFnDecl:
case NodeTypeParamDecl:
case NodeTypeBlock:
@@ -6072,7 +5843,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
case NodeTypeStringLiteral:
case NodeTypeCharLiteral:
case NodeTypeSymbol:
- case NodeTypeImport:
case NodeTypeBoolLiteral:
case NodeTypeNullLiteral:
case NodeTypeUndefinedLiteral:
@@ -6140,6 +5910,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
case TypeTableEntryIdNumLitFloat:
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdUndefLit:
+ case TypeTableEntryIdNamespace:
zig_unreachable();
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdVoid:
@@ -6257,6 +6028,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
case TypeTableEntryIdUnreachable:
case TypeTableEntryIdMetaType:
case TypeTableEntryIdVoid:
+ case TypeTableEntryIdNamespace:
zig_unreachable();
case TypeTableEntryIdArray:
return type_of_first_thing_in_memory(type_entry->data.array.child_type);