| author | |
| committer | |
| log | 44d5d008d025c7f081d87da393363f40616bfe47 |
| tree | af63ee97991dd83528b21a4c4fccd20abafa629b |
| parent | 333a3221275a7bea929f9eb1e2642043027c25f1 |
See #35 files changed, 115 insertions(+), 35 deletions(-)
src/analyze.cpp+53-24| ... | @@ -13,15 +13,18 @@ | ... | @@ -13,15 +13,18 @@ |
| 13 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, | 13 | static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 14 | TypeTableEntry *expected_type, AstNode *node); | 14 | TypeTableEntry *expected_type, AstNode *node); |
| 15 | 15 | ||
| 16 | static void alloc_codegen_node(AstNode *node) { | ||
| 17 | assert(!node->codegen_node); | ||
| 18 | node->codegen_node = allocate<CodeGenNode>(1); | ||
| 19 | } | ||
| 20 | |||
| 21 | static AstNode *first_executing_node(AstNode *node) { | 16 | static 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); | ||
| 480 | 478 | ||
| 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 | } | ||
| 496 | 491 | ||
| 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); |
| 541 | 536 | ||
| 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 | } |
| 546 | 542 | ||
| 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; |
| 1749 | 1745 | ||
| 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); | ||
| 1753 | 1747 | ||
| 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 pass | 2005 | // 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 do | 2044 | // 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 | |||
| 2166 | void 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; |
| 151 | 151 | ||
| 152 | // reminder: hash tables must be initialized before use | 152 | // 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 | }; |
| 220 | 221 | ||
| 221 | struct VariableTableEntry { | 222 | struct VariableTableEntry { |
| ... | @@ -328,6 +329,10 @@ struct ParamDeclNode { | ... | @@ -328,6 +329,10 @@ struct ParamDeclNode { |
| 328 | VariableTableEntry *variable; | 329 | VariableTableEntry *variable; |
| 329 | }; | 330 | }; |
| 330 | 331 | ||
| 332 | struct ImportNode { | ||
| 333 | ImportTableEntry *import; | ||
| 334 | }; | ||
| 335 | |||
| 331 | struct CodeGenNode { | 336 | struct CodeGenNode { |
| 332 | union { | 337 | union { |
| 333 | TypeNode type_node; // for NodeTypeType | 338 | TypeNode type_node; // for NodeTypeType |
| ... | @@ -345,6 +350,7 @@ struct CodeGenNode { | ... | @@ -345,6 +350,7 @@ struct CodeGenNode { |
| 345 | StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr | 350 | StructValExprNode struct_val_expr_node; // for NodeTypeStructValueExpr |
| 346 | IfVarNode if_var_node; // for NodeTypeStructValueExpr | 351 | IfVarNode if_var_node; // for NodeTypeStructValueExpr |
| 347 | ParamDeclNode param_decl_node; // for NodeTypeParamDecl | 352 | ParamDeclNode param_decl_node; // for NodeTypeParamDecl |
| 353 | ImportNode import_node; // for NodeTypeUse | ||
| 348 | } data; | 354 | } data; |
| 349 | ExprNode expr_node; // for all the expression nodes | 355 | 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) { |
| 358 | 364 | ||
| 359 | void semantic_analyze(CodeGen *g); | 365 | void semantic_analyze(CodeGen *g); |
| 360 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); | 366 | void add_node_error(CodeGen *g, AstNode *node, Buf *msg); |
| 367 | void alloc_codegen_node(AstNode *node); | ||
| 361 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); | 368 | TypeTableEntry *new_type_table_entry(TypeTableEntryId id); |
| 362 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); | 369 | TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const); |
| 363 | VariableTableEntry *find_variable(BlockContext *context, Buf *name); | 370 | VariableTableEntry *find_variable(BlockContext *context, Buf *name); |
src/codegen.cpp+13-10| ... | @@ -19,7 +19,6 @@ | ... | @@ -19,7 +19,6 @@ |
| 19 | 19 | ||
| 20 | CodeGen *codegen_create(Buf *root_source_dir) { | 20 | CodeGen *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) { |
| 146 | 145 | ||
| 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); |
| 148 | 147 | ||
| 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); | ||
| 155 | 149 | ||
| 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; |
| 2064 | 2058 | ||
| 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 | } |
| 2149 | 2150 | ||
| 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 | } |
| 2152 | 2153 | ||
| 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 | } | ||
| 2158 | 2161 | ||
| 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 @@ |
| 1 | use "std.zig"; | 1 | use "std.zig"; |
| 2 | 2 | ||
| 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") |
| 4 | export fn _start() -> unreachable { | 7 | export 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 | } |
| 175 | 175 | ||
| 176 | { | ||
| 177 | TestCase *tc = add_simple_case("import segregation", R"SOURCE( | ||
| 178 | use "foo.zig"; | ||
| 179 | use "bar.zig"; | ||
| 180 | |||
| 181 | pub 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( | ||
| 189 | use "std.zig"; | ||
| 190 | pub fn foo_function() { | ||
| 191 | print_str("OK\n"); | ||
| 192 | } | ||
| 193 | )SOURCE"); | ||
| 194 | |||
| 195 | add_source_file(tc, "bar.zig", R"SOURCE( | ||
| 196 | use "other.zig"; | ||
| 197 | use "std.zig"; | ||
| 198 | |||
| 199 | pub 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( | ||
| 207 | pub 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"; |
| 178 | 216 |