mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
parent
49d0971cd4
commit
35b74d4013
185
src/analyze.cpp
185
src/analyze.cpp
@ -807,6 +807,20 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
|
||||
if (fn_def_node) {
|
||||
preview_function_labels(g, fn_def_node->data.fn_def.body, fn_table_entry);
|
||||
}
|
||||
|
||||
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 resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||
@ -1715,6 +1729,23 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
|
||||
variable_entry->is_ptr = true;
|
||||
variable_entry->decl_node = source_node;
|
||||
context->variable_table.put(&variable_entry->name, variable_entry);
|
||||
|
||||
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(&variable_entry->name);
|
||||
if (table_entry) {
|
||||
add_node_error(g, importer.source_node,
|
||||
buf_sprintf("import of variable '%s' overrides existing definition",
|
||||
buf_ptr(&variable_entry->name)));
|
||||
} else {
|
||||
importer.import->block_context->variable_table.put(&variable_entry->name, variable_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return variable_entry;
|
||||
}
|
||||
return nullptr;
|
||||
@ -2563,90 +2594,8 @@ static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
|
||||
// already looked at these in the preview pass
|
||||
break;
|
||||
case NodeTypeUse:
|
||||
{
|
||||
for (int i = 0; i < node->data.use.directives->length; i += 1) {
|
||||
AstNode *directive_node = node->data.use.directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
|
||||
ImportTableEntry *target_import = node->codegen_node->data.import_node.import;
|
||||
assert(target_import);
|
||||
|
||||
// import all the public functions
|
||||
{
|
||||
auto it = target_import->fn_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
FnTableEntry *fn_entry = entry->value;
|
||||
bool is_pub = (fn_entry->proto_node->data.fn_proto.visib_mod != VisibModPrivate);
|
||||
if (is_pub) {
|
||||
auto existing_entry = import->fn_table.maybe_get(entry->key);
|
||||
if (existing_entry) {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("import of function '%s' overrides existing definition",
|
||||
buf_ptr(&fn_entry->proto_node->data.fn_proto.name)));
|
||||
} else {
|
||||
import->fn_table.put(entry->key, entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import all the public types
|
||||
{
|
||||
auto it = target_import->type_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
TypeTableEntry *type_entry = entry->value;
|
||||
if (type_entry->id == TypeTableEntryIdStruct) {
|
||||
AstNode *decl_node = type_entry->data.structure.decl_node;
|
||||
bool is_pub = (decl_node->data.struct_decl.visib_mod != VisibModPrivate);
|
||||
if (is_pub) {
|
||||
auto existing_entry = import->type_table.maybe_get(entry->key);
|
||||
if (existing_entry) {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("import of type '%s' overrides existing definition",
|
||||
buf_ptr(&type_entry->name)));
|
||||
} else {
|
||||
import->type_table.put(entry->key, entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// import all the public variables
|
||||
{
|
||||
auto it = target_import->block_context->variable_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
VariableTableEntry *var = entry->value;
|
||||
bool is_pub = (var->decl_node->data.variable_declaration.visib_mod != VisibModPrivate);
|
||||
if (is_pub) {
|
||||
auto existing_entry = import->type_table.maybe_get(entry->key);
|
||||
if (existing_entry) {
|
||||
add_node_error(g, node,
|
||||
buf_sprintf("import of variable '%s' overrides existing definition",
|
||||
buf_ptr(&var->name)));
|
||||
} else {
|
||||
import->block_context->variable_table.put(entry->key, entry->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// already took care of this
|
||||
break;
|
||||
case NodeTypeStructDecl:
|
||||
{
|
||||
for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
|
||||
@ -2869,9 +2818,9 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
|
||||
StructDeclNode *struct_codegen = &node->codegen_node->data.struct_decl_node;
|
||||
|
||||
Buf *name = &node->data.struct_decl.name;
|
||||
auto table_entry = import->type_table.maybe_get(name);
|
||||
auto table_entry = g->primitive_type_table.maybe_get(name);
|
||||
if (!table_entry) {
|
||||
table_entry = g->primitive_type_table.maybe_get(name);
|
||||
table_entry = import->type_table.maybe_get(name);
|
||||
}
|
||||
if (table_entry) {
|
||||
struct_codegen->type_entry = table_entry->value;
|
||||
@ -2890,6 +2839,21 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
|
||||
// this type is incomplete until we do another pass
|
||||
import->type_table.put(&entry->name, entry);
|
||||
struct_codegen->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.
|
||||
@ -2977,7 +2941,7 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
|
||||
resolve_top_level_decl(g, import, node);
|
||||
break;
|
||||
case NodeTypeUse:
|
||||
// nothing to do
|
||||
// already taken care of
|
||||
break;
|
||||
case NodeTypeDirective:
|
||||
case NodeTypeParamDecl:
|
||||
@ -3054,11 +3018,6 @@ static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode
|
||||
static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {
|
||||
assert(node->type == NodeTypeRoot);
|
||||
|
||||
for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
|
||||
AstNode *child = node->data.root.top_level_decls.at(i);
|
||||
detect_top_level_decl_deps(g, import, child);
|
||||
}
|
||||
|
||||
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.
|
||||
@ -3095,6 +3054,48 @@ static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, A
|
||||
}
|
||||
|
||||
void semantic_analyze(CodeGen *g) {
|
||||
{
|
||||
auto it = g->import_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
ImportTableEntry *import = entry->value;
|
||||
|
||||
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 == NodeTypeUse) {
|
||||
for (int i = 0; i < child->data.use.directives->length; i += 1) {
|
||||
AstNode *directive_node = child->data.use.directives->at(i);
|
||||
Buf *name = &directive_node->data.directive.name;
|
||||
add_node_error(g, directive_node,
|
||||
buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
|
||||
}
|
||||
|
||||
ImportTableEntry *target_import = child->codegen_node->data.import_node.import;
|
||||
assert(target_import);
|
||||
|
||||
target_import->importers.append({import, child});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto it = g->import_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
if (!entry)
|
||||
break;
|
||||
|
||||
ImportTableEntry *import = entry->value;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
auto it = g->import_table.entry_iterator();
|
||||
for (;;) {
|
||||
|
||||
@ -105,6 +105,11 @@ struct TypeTableEntry {
|
||||
|
||||
};
|
||||
|
||||
struct ImporterInfo {
|
||||
ImportTableEntry *import;
|
||||
AstNode *source_node;
|
||||
};
|
||||
|
||||
struct ImportTableEntry {
|
||||
AstNode *root;
|
||||
Buf *path; // relative to root_source_dir
|
||||
@ -112,6 +117,7 @@ struct ImportTableEntry {
|
||||
Buf *source_code;
|
||||
ZigList<int> *line_offsets;
|
||||
BlockContext *block_context;
|
||||
ZigList<ImporterInfo> importers;
|
||||
|
||||
// reminder: hash tables must be initialized before use
|
||||
HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
|
||||
|
||||
@ -994,6 +994,7 @@ pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||
|
||||
add_simple_case("order-independent declarations", R"SOURCE(
|
||||
use "std.zig";
|
||||
const z : #typeof(stdin_fileno) = 0;
|
||||
const x : #typeof(y) = 1234;
|
||||
const y : u16 = 5678;
|
||||
pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user