authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-04 03:31:57-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-04 03:31:57-07:00
log44d5d008d025c7f081d87da393363f40616bfe47
treeaf63ee97991dd83528b21a4c4fccd20abafa629b
parent333a3221275a7bea929f9eb1e2642043027c25f1

partial import segregation

See #3

5 files changed, 115 insertions(+), 35 deletions(-)

src/analyze.cpp+53-24
...@@ -13,15 +13,18 @@...@@ -13,15 +13,18 @@
13static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,13static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
14 TypeTableEntry *expected_type, AstNode *node);14 TypeTableEntry *expected_type, AstNode *node);
1515
16static void alloc_codegen_node(AstNode *node) {
17 assert(!node->codegen_node);
18 node->codegen_node = allocate<CodeGenNode>(1);
19}
20
21static AstNode *first_executing_node(AstNode *node) {16static AstNode *first_executing_node(AstNode *node) {
22 switch (node->type) {17 switch (node->type) {
23 case NodeTypeFnCallExpr:18 case NodeTypeFnCallExpr:
24 return first_executing_node(node->data.fn_call_expr.fn_ref_expr);19 return first_executing_node(node->data.fn_call_expr.fn_ref_expr);
20 case NodeTypeBinOpExpr:
21 return first_executing_node(node->data.bin_op_expr.op1);
22 case NodeTypeArrayAccessExpr:
23 return first_executing_node(node->data.array_access_expr.array_ref_expr);
24 case NodeTypeFieldAccessExpr:
25 return first_executing_node(node->data.field_access_expr.struct_expr);
26 case NodeTypeCastExpr:
27 return first_executing_node(node->data.cast_expr.expr);
25 case NodeTypeRoot:28 case NodeTypeRoot:
26 case NodeTypeRootExportDecl:29 case NodeTypeRootExportDecl:
27 case NodeTypeFnProto:30 case NodeTypeFnProto:
...@@ -34,15 +37,12 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -34,15 +37,12 @@ static AstNode *first_executing_node(AstNode *node) {
34 case NodeTypeDirective:37 case NodeTypeDirective:
35 case NodeTypeReturnExpr:38 case NodeTypeReturnExpr:
36 case NodeTypeVariableDeclaration:39 case NodeTypeVariableDeclaration:
37 case NodeTypeBinOpExpr:
38 case NodeTypeCastExpr:
39 case NodeTypeNumberLiteral:40 case NodeTypeNumberLiteral:
40 case NodeTypeStringLiteral:41 case NodeTypeStringLiteral:
41 case NodeTypeCharLiteral:42 case NodeTypeCharLiteral:
42 case NodeTypeUnreachable:43 case NodeTypeUnreachable:
43 case NodeTypeSymbol:44 case NodeTypeSymbol:
44 case NodeTypePrefixOpExpr:45 case NodeTypePrefixOpExpr:
45 case NodeTypeArrayAccessExpr:
46 case NodeTypeUse:46 case NodeTypeUse:
47 case NodeTypeVoid:47 case NodeTypeVoid:
48 case NodeTypeBoolLiteral:48 case NodeTypeBoolLiteral:
...@@ -53,7 +53,6 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -53,7 +53,6 @@ static AstNode *first_executing_node(AstNode *node) {
53 case NodeTypeBreak:53 case NodeTypeBreak:
54 case NodeTypeContinue:54 case NodeTypeContinue:
55 case NodeTypeAsmExpr:55 case NodeTypeAsmExpr:
56 case NodeTypeFieldAccessExpr:
57 case NodeTypeStructDecl:56 case NodeTypeStructDecl:
58 case NodeTypeStructField:57 case NodeTypeStructField:
59 case NodeTypeStructValueExpr:58 case NodeTypeStructValueExpr:
...@@ -476,7 +475,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -476,7 +475,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
476 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);475 AstNode *fn_decl = node->data.extern_block.fn_decls.at(fn_decl_i);
477 assert(fn_decl->type == NodeTypeFnDecl);476 assert(fn_decl->type == NodeTypeFnDecl);
478 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;477 AstNode *fn_proto = fn_decl->data.fn_decl.fn_proto;
479 bool is_pub = (fn_proto->data.fn_proto.visib_mod == FnProtoVisibModPub);
480478
481 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);479 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
482 fn_table_entry->proto_node = fn_proto;480 fn_table_entry->proto_node = fn_proto;
...@@ -490,9 +488,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -490,9 +488,6 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
490 Buf *name = &fn_proto->data.fn_proto.name;488 Buf *name = &fn_proto->data.fn_proto.name;
491 g->fn_protos.append(fn_table_entry);489 g->fn_protos.append(fn_table_entry);
492 import->fn_table.put(name, fn_table_entry);490 import->fn_table.put(name, fn_table_entry);
493 if (is_pub) {
494 g->fn_table.put(name, fn_table_entry);
495 }
496491
497 alloc_codegen_node(fn_proto);492 alloc_codegen_node(fn_proto);
498 fn_proto->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry;493 fn_proto->codegen_node->data.fn_proto_node.fn_table_entry = fn_table_entry;
...@@ -514,7 +509,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -514,7 +509,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
514 node->codegen_node->data.fn_def_node.skip = true;509 node->codegen_node->data.fn_def_node.skip = true;
515 skip = true;510 skip = true;
516 } else if (is_pub) {511 } else if (is_pub) {
517 auto entry = g->fn_table.maybe_get(proto_name);512 auto entry = import->fn_table.maybe_get(proto_name);
518 if (entry) {513 if (entry) {
519 add_node_error(g, node,514 add_node_error(g, node,
520 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));515 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
...@@ -540,8 +535,9 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,...@@ -540,8 +535,9 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
540 g->fn_defs.append(fn_table_entry);535 g->fn_defs.append(fn_table_entry);
541536
542 import->fn_table.put(proto_name, fn_table_entry);537 import->fn_table.put(proto_name, fn_table_entry);
543 if (is_pub) {538
544 g->fn_table.put(proto_name, fn_table_entry);539 if (g->bootstrap_import && import == g->root_import && buf_eql_str(proto_name, "main")) {
540 g->bootstrap_import->fn_table.put(proto_name, fn_table_entry);
545 }541 }
546542
547 resolve_function_proto(g, proto_node, fn_table_entry, import);543 resolve_function_proto(g, proto_node, fn_table_entry, import);
...@@ -1748,8 +1744,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -1748,8 +1744,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
1748 Buf *name = &fn_ref_expr->data.symbol;1744 Buf *name = &fn_ref_expr->data.symbol;
17491745
1750 auto entry = import->fn_table.maybe_get(name);1746 auto entry = import->fn_table.maybe_get(name);
1751 if (!entry)
1752 entry = g->fn_table.maybe_get(name);
17531747
1754 if (!entry) {1748 if (!entry) {
1755 add_node_error(g, fn_ref_expr,1749 add_node_error(g, fn_ref_expr,
...@@ -2011,13 +2005,41 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,...@@ -2011,13 +2005,41 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
2011 // already looked at these in the preview pass2005 // already looked at these in the preview pass
2012 break;2006 break;
2013 case NodeTypeUse:2007 case NodeTypeUse:
2014 for (int i = 0; i < node->data.use.directives->length; i += 1) {2008 {
2015 AstNode *directive_node = node->data.use.directives->at(i);2009 for (int i = 0; i < node->data.use.directives->length; i += 1) {
2016 Buf *name = &directive_node->data.directive.name;2010 AstNode *directive_node = node->data.use.directives->at(i);
2017 add_node_error(g, directive_node,2011 Buf *name = &directive_node->data.directive.name;
2018 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));2012 add_node_error(g, directive_node,
2013 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
2014 }
2015
2016 ImportTableEntry *target_import = node->codegen_node->data.import_node.import;
2017 assert(target_import);
2018
2019 // import all the public functions
2020 {
2021 auto it = target_import->fn_table.entry_iterator();
2022 for (;;) {
2023 auto *entry = it.next();
2024 if (!entry)
2025 break;
2026
2027 FnTableEntry *fn_entry = entry->value;
2028 bool is_pub = (fn_entry->proto_node->data.fn_proto.visib_mod != FnProtoVisibModPrivate);
2029 if (is_pub) {
2030 auto existing_entry = import->fn_table.maybe_get(entry->key);
2031 if (existing_entry) {
2032 add_node_error(g, node,
2033 buf_sprintf("import of function '%s' overrides existing definition",
2034 buf_ptr(&fn_entry->proto_node->data.fn_proto.name)));
2035 } else {
2036 import->fn_table.put(entry->key, entry->value);
2037 }
2038 }
2039 }
2040 }
2041 break;
2019 }2042 }
2020 break;
2021 case NodeTypeStructDecl:2043 case NodeTypeStructDecl:
2022 // nothing to do2044 // nothing to do
2023 break;2045 break;
...@@ -2118,6 +2140,7 @@ void semantic_analyze(CodeGen *g) {...@@ -2118,6 +2140,7 @@ void semantic_analyze(CodeGen *g) {
2118 find_function_declarations_root(g, import, import->root);2140 find_function_declarations_root(g, import, import->root);
2119 }2141 }
2120 }2142 }
2143
2121 {2144 {
2122 auto it = g->import_table.entry_iterator();2145 auto it = g->import_table.entry_iterator();
2123 for (;;) {2146 for (;;) {
...@@ -2139,3 +2162,9 @@ void semantic_analyze(CodeGen *g) {...@@ -2139,3 +2162,9 @@ void semantic_analyze(CodeGen *g) {
2139 buf_sprintf("missing export declaration and export type not provided"));2162 buf_sprintf("missing export declaration and export type not provided"));
2140 }2163 }
2141}2164}
2165
2166void alloc_codegen_node(AstNode *node) {
2167 assert(!node->codegen_node);
2168 node->codegen_node = allocate<CodeGenNode>(1);
2169}
2170
src/analyze.hpp+8-1
...@@ -150,7 +150,6 @@ struct CodeGen {...@@ -150,7 +150,6 @@ struct CodeGen {
150 ZigList<Buf *> lib_search_paths;150 ZigList<Buf *> lib_search_paths;
151151
152 // reminder: hash tables must be initialized before use152 // reminder: hash tables must be initialized before use
153 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
154 HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;153 HashMap<Buf *, LLVMValueRef, buf_hash, buf_eql_buf> str_table;
155 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;154 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
156 HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;155 HashMap<Buf *, bool, buf_hash, buf_eql_buf> link_table;
...@@ -215,7 +214,9 @@ struct CodeGen {...@@ -215,7 +214,9 @@ struct CodeGen {
215 bool verbose;214 bool verbose;
216 ErrColor err_color;215 ErrColor err_color;
217 ImportTableEntry *root_import;216 ImportTableEntry *root_import;
217 ImportTableEntry *bootstrap_import;
218 LLVMValueRef memcpy_fn_val;218 LLVMValueRef memcpy_fn_val;
219 bool error_during_imports;
219};220};
220221
221struct VariableTableEntry {222struct VariableTableEntry {
...@@ -328,6 +329,10 @@ struct ParamDeclNode {...@@ -328,6 +329,10 @@ struct ParamDeclNode {
328 VariableTableEntry *variable;329 VariableTableEntry *variable;
329};330};
330331
332struct ImportNode {
333 ImportTableEntry *import;
334};
335
331struct CodeGenNode {336struct CodeGenNode {
332 union {337 union {
333 TypeNode type_node; // for NodeTypeType338 TypeNode type_node; // for NodeTypeType
...@@ -345,6 +350,7 @@ struct CodeGenNode {...@@ -345,6 +350,7 @@ struct CodeGenNode {
345 StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr350 StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr
346 IfVarNode if_var_node; // for NodeTypeStructValueExpr351 IfVarNode if_var_node; // for NodeTypeStructValueExpr
347 ParamDeclNode param_decl_node; // for NodeTypeParamDecl352 ParamDeclNode param_decl_node; // for NodeTypeParamDecl
353 ImportNode import_node; // for NodeTypeUse
348 } data;354 } data;
349 ExprNode expr_node; // for all the expression nodes355 ExprNode expr_node; // for all the expression nodes
350};356};
...@@ -358,6 +364,7 @@ static inline Buf *hack_get_fn_call_name(CodeGen *g, AstNode *node) {...@@ -358,6 +364,7 @@ static inline Buf *hack_get_fn_call_name(CodeGen *g, AstNode *node) {
358364
359void semantic_analyze(CodeGen *g);365void semantic_analyze(CodeGen *g);
360void add_node_error(CodeGen *g, AstNode *node, Buf *msg);366void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
367void alloc_codegen_node(AstNode *node);
361TypeTableEntry *new_type_table_entry(TypeTableEntryId id);368TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
362TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);369TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
363VariableTableEntry *find_variable(BlockContext *context, Buf *name);370VariableTableEntry *find_variable(BlockContext *context, Buf *name);
src/codegen.cpp+13-10
...@@ -19,7 +19,6 @@...@@ -19,7 +19,6 @@
1919
20CodeGen *codegen_create(Buf *root_source_dir) {20CodeGen *codegen_create(Buf *root_source_dir) {
21 CodeGen *g = allocate<CodeGen>(1);21 CodeGen *g = allocate<CodeGen>(1);
22 g->fn_table.init(32);
23 g->str_table.init(32);22 g->str_table.init(32);
24 g->type_table.init(32);23 g->type_table.init(32);
25 g->link_table.init(32);24 g->link_table.init(32);
...@@ -146,12 +145,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -146,12 +145,7 @@ static LLVMValueRef gen_fn_call_expr(CodeGen *g, AstNode *node) {
146145
147 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);146 Buf *name = hack_get_fn_call_name(g, node->data.fn_call_expr.fn_ref_expr);
148147
149 FnTableEntry *fn_table_entry;148 FnTableEntry *fn_table_entry = g->cur_fn->import_entry->fn_table.get(name);
150 auto entry = g->cur_fn->import_entry->fn_table.maybe_get(name);
151 if (entry)
152 fn_table_entry = entry->value;
153 else
154 fn_table_entry = g->fn_table.get(name);
155149
156 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);150 assert(fn_table_entry->proto_node->type == NodeTypeFnProto);
157 AstNodeFnProto *fn_proto_data = &fn_table_entry->proto_node->data.fn_proto;151 AstNodeFnProto *fn_proto_data = &fn_table_entry->proto_node->data.fn_proto;
...@@ -2062,6 +2056,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -2062,6 +2056,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
2062 Buf *import_code = buf_alloc();2056 Buf *import_code = buf_alloc();
2063 bool found_it = false;2057 bool found_it = false;
20642058
2059 alloc_codegen_node(top_level_decl);
2060
2065 for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {2061 for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {
2066 Buf *search_path = g->lib_search_paths.at(path_i);2062 Buf *search_path = g->lib_search_paths.at(path_i);
2067 os_path_join(search_path, import_target_path, &full_path);2063 os_path_join(search_path, import_target_path, &full_path);
...@@ -2071,6 +2067,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -2071,6 +2067,7 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
2071 if (err == ErrorFileNotFound) {2067 if (err == ErrorFileNotFound) {
2072 continue;2068 continue;
2073 } else {2069 } else {
2070 g->error_during_imports = true;
2074 add_node_error(g, top_level_decl,2071 add_node_error(g, top_level_decl,
2075 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));2072 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
2076 goto done_looking_at_imports;2073 goto done_looking_at_imports;
...@@ -2080,22 +2077,26 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,...@@ -2080,22 +2077,26 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
2080 auto entry = g->import_table.maybe_get(abs_full_path);2077 auto entry = g->import_table.maybe_get(abs_full_path);
2081 if (entry) {2078 if (entry) {
2082 found_it = true;2079 found_it = true;
2080 top_level_decl->codegen_node->data.import_node.import = entry->value;
2083 } else {2081 } else {
2084 if ((err = os_fetch_file_path(abs_full_path, import_code))) {2082 if ((err = os_fetch_file_path(abs_full_path, import_code))) {
2085 if (err == ErrorFileNotFound) {2083 if (err == ErrorFileNotFound) {
2086 continue;2084 continue;
2087 } else {2085 } else {
2086 g->error_during_imports = true;
2088 add_node_error(g, top_level_decl,2087 add_node_error(g, top_level_decl,
2089 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));2088 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
2090 goto done_looking_at_imports;2089 goto done_looking_at_imports;
2091 }2090 }
2092 }2091 }
2093 codegen_add_code(g, abs_full_path, search_path, &top_level_decl->data.use.path, import_code);2092 top_level_decl->codegen_node->data.import_node.import = codegen_add_code(g,
2093 abs_full_path, search_path, &top_level_decl->data.use.path, import_code);
2094 found_it = true;2094 found_it = true;
2095 }2095 }
2096 break;2096 break;
2097 }2097 }
2098 if (!found_it) {2098 if (!found_it) {
2099 g->error_during_imports = true;
2099 add_node_error(g, top_level_decl,2100 add_node_error(g, top_level_decl,
2100 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));2101 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
2101 }2102 }
...@@ -2147,14 +2148,16 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou...@@ -2147,14 +2148,16 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
2147 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err));2148 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_bootstrap_src), err_str(err));
2148 }2149 }
21492150
2150 codegen_add_code(g, abs_full_path, bootstrap_dir, bootstrap_basename, import_code);2151 g->bootstrap_import = codegen_add_code(g, abs_full_path, bootstrap_dir, bootstrap_basename, import_code);
2151 }2152 }
21522153
2153 if (g->verbose) {2154 if (g->verbose) {
2154 fprintf(stderr, "\nSemantic Analysis:\n");2155 fprintf(stderr, "\nSemantic Analysis:\n");
2155 fprintf(stderr, "--------------------\n");2156 fprintf(stderr, "--------------------\n");
2156 }2157 }
2157 semantic_analyze(g);2158 if (!g->error_during_imports) {
2159 semantic_analyze(g);
2160 }
21582161
2159 if (g->errors.length == 0) {2162 if (g->errors.length == 0) {
2160 if (g->verbose) {2163 if (g->verbose) {
std/bootstrap.zig+3
...@@ -1,5 +1,8 @@...@@ -1,5 +1,8 @@
1use "std.zig";1use "std.zig";
22
3// The compiler treats this file special by implicitly importing the function `main`
4// from the root source file.
5
3#attribute("naked")6#attribute("naked")
4export fn _start() -> unreachable {7export fn _start() -> unreachable {
5 const argc = asm("mov (%%rsp), %[argc]" : [argc] "=r" (-> isize));8 const argc = asm("mov (%%rsp), %[argc]" : [argc] "=r" (-> isize));
test/run_tests.cpp+38
...@@ -173,6 +173,44 @@ pub fn print_text() {...@@ -173,6 +173,44 @@ pub fn print_text() {
173 )SOURCE");173 )SOURCE");
174 }174 }
175175
176 {
177 TestCase *tc = add_simple_case("import segregation", R"SOURCE(
178use "foo.zig";
179use "bar.zig";
180
181pub fn main(argc: isize, argv: &&u8, env: &&u8) -> i32 {
182 foo_function();
183 bar_function();
184 return 0;
185}
186 )SOURCE", "OK\nOK\n");
187
188 add_source_file(tc, "foo.zig", R"SOURCE(
189use "std.zig";
190pub fn foo_function() {
191 print_str("OK\n");
192}
193 )SOURCE");
194
195 add_source_file(tc, "bar.zig", R"SOURCE(
196use "other.zig";
197use "std.zig";
198
199pub fn bar_function() {
200 if (foo_function()) {
201 print_str("OK\n");
202 }
203}
204 )SOURCE");
205
206 add_source_file(tc, "other.zig", R"SOURCE(
207pub fn foo_function() -> bool {
208 // this one conflicts with the one from foo
209 return true;
210}
211 )SOURCE");
212 }
213
176 add_simple_case("if statements", R"SOURCE(214 add_simple_case("if statements", R"SOURCE(
177 use "std.zig";215 use "std.zig";
178216