authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-27 22:06:46-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-03-01 03:13:40-07:00
logf1d338194e9a00e56a42da1298f2ac0ed75797df
tree6768d247960a6e8006fbffa00206ce44152c66d5
parent28fe994a107b4f66d840c50df614504ac2387587

rewrite how importing works

* Introduce the concept of packages. Closes #3 * Add support for error notes. * Introduce `@import` and `@c_import` builtin functions and remove the `import` and `c_import` top level declarations. * Introduce the `use` top level declaration. * Add `--check-unused` parameter to perform semantic analysis and codegen on all top level declarations, not just exported ones and ones referenced by exported ones. * Delete the root export node and add `--library` argument.

32 files changed, 1816 insertions(+), 2190 deletions(-)

CMakeLists.txt+2-1
...@@ -137,12 +137,13 @@ set(ZIG_STD_SRC...@@ -137,12 +137,13 @@ set(ZIG_STD_SRC
137 "${CMAKE_SOURCE_DIR}/std/test_runner.zig"137 "${CMAKE_SOURCE_DIR}/std/test_runner.zig"
138 "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig"138 "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig"
139 "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig"139 "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig"
140 "${CMAKE_SOURCE_DIR}/std/std.zig"140 "${CMAKE_SOURCE_DIR}/std/io.zig"
141 "${CMAKE_SOURCE_DIR}/std/os.zig"141 "${CMAKE_SOURCE_DIR}/std/os.zig"
142 "${CMAKE_SOURCE_DIR}/std/syscall.zig"142 "${CMAKE_SOURCE_DIR}/std/syscall.zig"
143 "${CMAKE_SOURCE_DIR}/std/errno.zig"143 "${CMAKE_SOURCE_DIR}/std/errno.zig"
144 "${CMAKE_SOURCE_DIR}/std/rand.zig"144 "${CMAKE_SOURCE_DIR}/std/rand.zig"
145 "${CMAKE_SOURCE_DIR}/std/math.zig"145 "${CMAKE_SOURCE_DIR}/std/math.zig"
146 "${CMAKE_SOURCE_DIR}/std/index.zig"
146)147)
147148
148149
doc/langref.md+2-6
...@@ -5,9 +5,7 @@...@@ -5,9 +5,7 @@
5```5```
6Root = many(TopLevelDecl) "EOF"6Root = many(TopLevelDecl) "EOF"
77
8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)8TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | ContainerDecl | GlobalVarDecl | ErrorValueDecl | TypeDecl | UseDecl)
9
10CImportDecl = "c_import" Block
119
12TypeDecl = "type" "Symbol" "=" TypeExpr ";"10TypeDecl = "type" "Symbol" "=" TypeExpr ";"
1311
...@@ -23,9 +21,7 @@ StructMember = many(Directive) option(VisibleMod) (StructField | FnDef)...@@ -23,9 +21,7 @@ StructMember = many(Directive) option(VisibleMod) (StructField | FnDef)
2321
24StructField = "Symbol" option(":" Expression) ",")22StructField = "Symbol" option(":" Expression) ",")
2523
26Import = "import" "String" ";"24UseDecl = "use" Expression ";"
27
28RootExportDecl = "export" "Symbol" "String" ";"
2925
30ExternDecl = "extern" (FnProto | VariableDeclaration) ";"26ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
3127
doc/semantic_analysis.md created+75
...@@ -0,0 +1,75 @@
1# How Semantic Analysis Works
2
3We start with a set of files. Typically the user only has one entry point file,
4which imports the other files they want to use. However, the compiler may
5choose to add more files to the compilation, for example bootstrap.zig which
6contains the code that calls main.
7
8Our goal now is to treat everything that is marked with the `export` keyword
9as a root node, and then then parse and semantically analyze as little as
10possible in order to fulfill these exports.
11
12So, some parts of the code very well may have uncaught semantic errors, but as
13long as the code is not referenced in any way, the compiler will not complain
14because the code may as well not exist. This is similar to the fact that code
15excluded from compilation with an `#ifdef` in C is not analyzed. Avoiding
16analyzing unused code will save compilation time - one of Zig's goals.
17
18So, for each file, we iterate over the top level declarations. The set of top
19level declarations are:
20
21 * Function Definition
22 * Global Variable Declaration
23 * Container Declaration (struct or enum)
24 * Type Declaration
25 * Error Value Declaration
26 * Use Declaration
27
28Each of these can have `export` attached to them except for error value
29declarations and use declarations.
30
31When we see a top level declaration during this iteration, we determine its
32unique name identifier within the file. For example, for a function definition,
33the unique name identifier is simply its name. Using this name we add the top
34level declaration to a map.
35
36If the top level declaration is exported, we add it to a set of exported top
37level identifiers.
38
39If the top level declaration is a use declaration, we add it to a set of use
40declarations.
41
42If the top level declaration is an error value declaration, we assign it a value
43and increment the count of error values.
44
45After this preliminary iteration over the top level declarations, we iterate
46over the use declarations and resolve them. To resolve a use declaration, we
47analyze the associated expression, verify that its type is the namespace type,
48and then add all the items from the namespace into the top level declaration
49map for the current file.
50
51To analyze an expression, we recurse the abstract syntax tree of the
52expression. Whenever we must look up a symbol, if the symbol exists already,
53we can use it. Otherwise, we look it up in the top level declaration map.
54If it exists, we can use it. Otherwise, we interrupt resolving this use
55declaration to resolve the next one. If a dependency loop is detected, emit
56an error. If all use declarations are resolved yet the symbol we need still
57does not exist, emit an error.
58
59To analyze an `@import` expression, find the referenced file, parse it, and
60add it to the set of files to perform semantic analysis on.
61
62Proceed through the rest of the use declarations the same way.
63
64If we make it through the use declarations without an error, then we have a
65complete map of all globals that exist in the current file.
66
67Next we iterate over the set of exported top level declarations.
68
69If it's a function definition, add it to the set of exported function
70definitions and resolve the function prototype only. Otherwise, resolve the
71top level declaration completely. This may involve recursively resolving other
72top level declarations that expressions depend on.
73
74Finally, iterate over the set of exported function definitions and analyze the
75bodies.
doc/targets.md+1-1
...@@ -8,7 +8,7 @@ How to pass a byvalue struct parameter in the C calling convention is...@@ -8,7 +8,7 @@ How to pass a byvalue struct parameter in the C calling convention is
8target-specific. Add logic for how to do function prototypes and function calls8target-specific. Add logic for how to do function prototypes and function calls
9for the target when an exported or external function has a byvalue struct.9for the target when an exported or external function has a byvalue struct.
1010
11Write the target-specific code in std.zig.11Write the target-specific code in the standard library.
1212
13Update the C integer types to be the correct size for the target.13Update the C integer types to be the correct size for the target.
1414
doc/vim/syntax/zig.vim+1-1
...@@ -14,7 +14,7 @@ syn keyword zigConditional if else switch...@@ -14,7 +14,7 @@ syn keyword zigConditional if else switch
14syn keyword zigRepeat while for14syn keyword zigRepeat while for
1515
16syn keyword zigConstant null undefined16syn keyword zigConstant null undefined
17syn keyword zigKeyword fn import c_import17syn keyword zigKeyword fn use
18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 void unreachable type error18syn keyword zigType bool i8 u8 i16 u16 i32 u32 i64 u64 isize usize f32 f64 void unreachable type error
19syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong19syn keyword zigType c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong
2020
example/guess_number/main.zig+15-16
...@@ -1,39 +1,38 @@...@@ -1,39 +1,38 @@
1export executable "guess_number";1const std = @import("std");
22const io = std.io;
3import "std.zig";3const Rand = std.Rand;
4import "rand.zig";4const os = std.os;
5import "os.zig";
65
7pub fn main(args: [][]u8) -> %void {6pub fn main(args: [][]u8) -> %void {
8 %%stdout.printf("Welcome to the Guess Number Game in Zig.\n");7 %%io.stdout.printf("Welcome to the Guess Number Game in Zig.\n");
98
10 var seed : u32 = undefined;9 var seed : u32 = undefined;
11 const seed_bytes = (&u8)(&seed)[0...4];10 const seed_bytes = (&u8)(&seed)[0...4];
12 %%os_get_random_bytes(seed_bytes);11 %%os.get_random_bytes(seed_bytes);
1312
14 var rand = rand_new(seed);13 var rand = Rand.init(seed);
1514
16 const answer = rand.range_u64(0, 100) + 1;15 const answer = rand.range_u64(0, 100) + 1;
1716
18 while (true) {17 while (true) {
19 %%stdout.printf("\nGuess a number between 1 and 100: ");18 %%io.stdout.printf("\nGuess a number between 1 and 100: ");
20 var line_buf : [20]u8 = undefined;19 var line_buf : [20]u8 = undefined;
2120
22 const line_len = stdin.read(line_buf) %% |err| {21 const line_len = io.stdin.read(line_buf) %% |err| {
23 %%stdout.printf("Unable to read from stdin.\n");22 %%io.stdout.printf("Unable to read from stdin.\n");
24 return err;23 return err;
25 };24 };
2625
27 const guess = parse_u64(line_buf[0...line_len - 1], 10) %% {26 const guess = io.parse_u64(line_buf[0...line_len - 1], 10) %% {
28 %%stdout.printf("Invalid number.\n");27 %%io.stdout.printf("Invalid number.\n");
29 continue;28 continue;
30 };29 };
31 if (guess > answer) {30 if (guess > answer) {
32 %%stdout.printf("Guess lower.\n");31 %%io.stdout.printf("Guess lower.\n");
33 } else if (guess < answer) {32 } else if (guess < answer) {
34 %%stdout.printf("Guess higher.\n");33 %%io.stdout.printf("Guess higher.\n");
35 } else {34 } else {
36 %%stdout.printf("You win!\n");35 %%io.stdout.printf("You win!\n");
37 return;36 return;
38 }37 }
39 }38 }
example/hello_world/hello.zig+2-4
...@@ -1,7 +1,5 @@...@@ -1,7 +1,5 @@
1export executable "hello";1const io = @import("std").io;
2
3import "std.zig";
42
5pub fn main(args: [][]u8) -> %void {3pub fn main(args: [][]u8) -> %void {
6 %%stdout.printf("Hello, world!\n");4 %%io.stdout.printf("Hello, world!\n");
7}5}
example/hello_world/hello_libc.zig+2-7
...@@ -1,11 +1,6 @@...@@ -1,11 +1,6 @@
1#link("c")1const c = @c_import(@c_include("stdio.h"));
2export executable "hello";
3
4c_import {
5 @c_include("stdio.h");
6}
72
8export fn main(argc: c_int, argv: &&u8) -> c_int {3export fn main(argc: c_int, argv: &&u8) -> c_int {
9 printf(c"Hello, world!\n");4 c.printf(c"Hello, world!\n");
10 return 0;5 return 0;
11}6}
src/all_types.hpp+63-75
...@@ -76,6 +76,7 @@ struct ConstExprValue {...@@ -76,6 +76,7 @@ struct ConstExprValue {
76 ConstStructValue x_struct;76 ConstStructValue x_struct;
77 ConstArrayValue x_array;77 ConstArrayValue x_array;
78 ConstPtrValue x_ptr;78 ConstPtrValue x_ptr;
79 ImportTableEntry *x_import;
79 } data;80 } data;
80};81};
8182
...@@ -91,6 +92,7 @@ enum ReturnKnowledge {...@@ -91,6 +92,7 @@ enum ReturnKnowledge {
91struct Expr {92struct Expr {
92 TypeTableEntry *type_entry;93 TypeTableEntry *type_entry;
93 ReturnKnowledge return_knowledge;94 ReturnKnowledge return_knowledge;
95 VariableTableEntry *variable;
9496
95 LLVMValueRef const_llvm_val;97 LLVMValueRef const_llvm_val;
96 ConstExprValue const_val;98 ConstExprValue const_val;
...@@ -103,13 +105,30 @@ struct StructValExprCodeGen {...@@ -103,13 +105,30 @@ struct StructValExprCodeGen {
103 AstNode *source_node;105 AstNode *source_node;
104};106};
105107
108enum VisibMod {
109 VisibModPrivate,
110 VisibModPub,
111 VisibModExport,
112};
113
114enum TldResolution {
115 TldResolutionUnresolved,
116 TldResolutionInvalid,
117 TldResolutionOk,
118};
119
106struct TopLevelDecl {120struct TopLevelDecl {
107 // reminder: hash tables must be initialized before use121 // populated by parser
108 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> deps;
109 Buf *name;122 Buf *name;
123 ZigList<AstNode *> *directives;
124 VisibMod visib_mod;
125
126 // populated by semantic analyzer
110 ImportTableEntry *import;127 ImportTableEntry *import;
111 // set this flag temporarily to detect infinite loops128 // set this flag temporarily to detect infinite loops
112 bool in_current_deps;129 bool dep_loop_flag;
130 TldResolution resolution;
131 AstNode *parent_decl;
113};132};
114133
115struct TypeEnumField {134struct TypeEnumField {
...@@ -120,7 +139,6 @@ struct TypeEnumField {...@@ -120,7 +139,6 @@ struct TypeEnumField {
120139
121enum NodeType {140enum NodeType {
122 NodeTypeRoot,141 NodeTypeRoot,
123 NodeTypeRootExportDecl,
124 NodeTypeFnProto,142 NodeTypeFnProto,
125 NodeTypeFnDef,143 NodeTypeFnDef,
126 NodeTypeFnDecl,144 NodeTypeFnDecl,
...@@ -143,8 +161,7 @@ enum NodeType {...@@ -143,8 +161,7 @@ enum NodeType {
143 NodeTypeArrayAccessExpr,161 NodeTypeArrayAccessExpr,
144 NodeTypeSliceExpr,162 NodeTypeSliceExpr,
145 NodeTypeFieldAccessExpr,163 NodeTypeFieldAccessExpr,
146 NodeTypeImport,164 NodeTypeUse,
147 NodeTypeCImport,
148 NodeTypeBoolLiteral,165 NodeTypeBoolLiteral,
149 NodeTypeNullLiteral,166 NodeTypeNullLiteral,
150 NodeTypeUndefinedLiteral,167 NodeTypeUndefinedLiteral,
...@@ -173,15 +190,8 @@ struct AstNodeRoot {...@@ -173,15 +190,8 @@ struct AstNodeRoot {
173 ZigList<AstNode *> top_level_decls;190 ZigList<AstNode *> top_level_decls;
174};191};
175192
176enum VisibMod {
177 VisibModPrivate,
178 VisibModPub,
179 VisibModExport,
180};
181
182struct AstNodeFnProto {193struct AstNodeFnProto {
183 ZigList<AstNode *> *directives; // can be null if no directives194 TopLevelDecl top_level_decl;
184 VisibMod visib_mod;
185 Buf name;195 Buf name;
186 ZigList<AstNode *> params;196 ZigList<AstNode *> params;
187 AstNode *return_type;197 AstNode *return_type;
...@@ -191,13 +201,10 @@ struct AstNodeFnProto {...@@ -191,13 +201,10 @@ struct AstNodeFnProto {
191201
192 // populated by semantic analyzer:202 // populated by semantic analyzer:
193203
194 // the struct decl node this fn proto is inside. can be null.
195 AstNode *struct_node;
196 // the function definition this fn proto is inside. can be null.204 // the function definition this fn proto is inside. can be null.
197 AstNode *fn_def_node;205 AstNode *fn_def_node;
198 FnTableEntry *fn_table_entry;206 FnTableEntry *fn_table_entry;
199 bool skip;207 bool skip;
200 TopLevelDecl top_level_decl;
201 Expr resolved_expr;208 Expr resolved_expr;
202};209};
203210
...@@ -263,41 +270,36 @@ struct AstNodeDefer {...@@ -263,41 +270,36 @@ struct AstNodeDefer {
263};270};
264271
265struct AstNodeVariableDeclaration {272struct AstNodeVariableDeclaration {
273 TopLevelDecl top_level_decl;
266 Buf symbol;274 Buf symbol;
267 bool is_const;275 bool is_const;
268 bool is_extern;276 bool is_extern;
269 VisibMod visib_mod;
270 // one or both of type and expr will be non null277 // one or both of type and expr will be non null
271 AstNode *type;278 AstNode *type;
272 AstNode *expr;279 AstNode *expr;
273 ZigList<AstNode *> *directives;
274280
275 // populated by semantic analyzer281 // populated by semantic analyzer
276 TopLevelDecl top_level_decl;
277 Expr resolved_expr;282 Expr resolved_expr;
278 VariableTableEntry *variable;283 VariableTableEntry *variable;
279};284};
280285
281struct AstNodeTypeDecl {286struct AstNodeTypeDecl {
282 VisibMod visib_mod;287 TopLevelDecl top_level_decl;
283 ZigList<AstNode *> *directives;
284 Buf symbol;288 Buf symbol;
285 AstNode *child_type;289 AstNode *child_type;
286290
287 // populated by semantic analyzer291 // populated by semantic analyzer
288 TopLevelDecl top_level_decl;
289 // if this is set, don't process the node; we've already done so292 // if this is set, don't process the node; we've already done so
290 // and here is the type (with id TypeTableEntryIdTypeDecl)293 // and here is the type (with id TypeTableEntryIdTypeDecl)
291 TypeTableEntry *override_type;294 TypeTableEntry *override_type;
295 TypeTableEntry *child_type_entry;
292};296};
293297
294struct AstNodeErrorValueDecl {298struct AstNodeErrorValueDecl {
299 TopLevelDecl top_level_decl;
295 Buf name;300 Buf name;
296 VisibMod visib_mod;
297 ZigList<AstNode *> *directives;
298301
299 // populated by semantic analyzer302 // populated by semantic analyzer
300 TopLevelDecl top_level_decl;
301 ErrorTableEntry *err;303 ErrorTableEntry *err;
302};304};
303305
...@@ -430,12 +432,6 @@ struct AstNodeDirective {...@@ -430,12 +432,6 @@ struct AstNodeDirective {
430 AstNode *expr;432 AstNode *expr;
431};433};
432434
433struct AstNodeRootExportDecl {
434 Buf type;
435 Buf name;
436 ZigList<AstNode *> *directives;
437};
438
439enum PrefixOp {435enum PrefixOp {
440 PrefixOpInvalid,436 PrefixOpInvalid,
441 PrefixOpBoolNot,437 PrefixOpBoolNot,
...@@ -458,19 +454,8 @@ struct AstNodePrefixOpExpr {...@@ -458,19 +454,8 @@ struct AstNodePrefixOpExpr {
458 Expr resolved_expr;454 Expr resolved_expr;
459};455};
460456
461struct AstNodeImport {457struct AstNodeUse {
462 Buf path;458 AstNode *expr;
463 ZigList<AstNode *> *directives;
464 VisibMod visib_mod;
465
466 // populated by semantic analyzer
467 ImportTableEntry *import;
468};
469
470struct AstNodeCImport {
471 ZigList<AstNode *> *directives;
472 VisibMod visib_mod;
473 AstNode *block;
474459
475 // populated by semantic analyzer460 // populated by semantic analyzer
476 TopLevelDecl top_level_decl;461 TopLevelDecl top_level_decl;
...@@ -600,23 +585,21 @@ enum ContainerKind {...@@ -600,23 +585,21 @@ enum ContainerKind {
600};585};
601586
602struct AstNodeStructDecl {587struct AstNodeStructDecl {
588 TopLevelDecl top_level_decl;
603 Buf name;589 Buf name;
604 ContainerKind kind;590 ContainerKind kind;
605 ZigList<AstNode *> fields;591 ZigList<AstNode *> fields;
606 ZigList<AstNode *> fns;592 ZigList<AstNode *> fns;
607 ZigList<AstNode *> *directives;
608 VisibMod visib_mod;
609593
610 // populated by semantic analyzer594 // populated by semantic analyzer
595 BlockContext *block_context;
611 TypeTableEntry *type_entry;596 TypeTableEntry *type_entry;
612 TopLevelDecl top_level_decl;
613};597};
614598
615struct AstNodeStructField {599struct AstNodeStructField {
600 TopLevelDecl top_level_decl;
616 Buf name;601 Buf name;
617 AstNode *type;602 AstNode *type;
618 ZigList<AstNode *> *directives;
619 VisibMod visib_mod;
620};603};
621604
622struct AstNodeStringLiteral {605struct AstNodeStringLiteral {
...@@ -695,8 +678,6 @@ struct AstNodeSymbolExpr {...@@ -695,8 +678,6 @@ struct AstNodeSymbolExpr {
695678
696 // populated by semantic analyzer679 // populated by semantic analyzer
697 Expr resolved_expr;680 Expr resolved_expr;
698 VariableTableEntry *variable;
699 FnTableEntry *fn_entry;
700 // set this to instead of analyzing the node, pretend it's a type entry and it's this one.681 // set this to instead of analyzing the node, pretend it's a type entry and it's this one.
701 TypeTableEntry *override_type_entry;682 TypeTableEntry *override_type_entry;
702 TypeEnumField *enum_field;683 TypeEnumField *enum_field;
...@@ -750,7 +731,6 @@ struct AstNode {...@@ -750,7 +731,6 @@ struct AstNode {
750 BlockContext *block_context;731 BlockContext *block_context;
751 union {732 union {
752 AstNodeRoot root;733 AstNodeRoot root;
753 AstNodeRootExportDecl root_export_decl;
754 AstNodeFnDef fn_def;734 AstNodeFnDef fn_def;
755 AstNodeFnDecl fn_decl;735 AstNodeFnDecl fn_decl;
756 AstNodeFnProto fn_proto;736 AstNodeFnProto fn_proto;
...@@ -768,8 +748,7 @@ struct AstNode {...@@ -768,8 +748,7 @@ struct AstNode {
768 AstNodeFnCallExpr fn_call_expr;748 AstNodeFnCallExpr fn_call_expr;
769 AstNodeArrayAccessExpr array_access_expr;749 AstNodeArrayAccessExpr array_access_expr;
770 AstNodeSliceExpr slice_expr;750 AstNodeSliceExpr slice_expr;
771 AstNodeImport import;751 AstNodeUse use;
772 AstNodeCImport c_import;
773 AstNodeIfBoolExpr if_bool_expr;752 AstNodeIfBoolExpr if_bool_expr;
774 AstNodeIfVarExpr if_var_expr;753 AstNodeIfVarExpr if_var_expr;
775 AstNodeWhileExpr while_expr;754 AstNodeWhileExpr while_expr;
...@@ -868,8 +847,7 @@ struct TypeTableEntryStruct {...@@ -868,8 +847,7 @@ struct TypeTableEntryStruct {
868 uint64_t size_bytes;847 uint64_t size_bytes;
869 bool is_invalid; // true if any fields are invalid848 bool is_invalid; // true if any fields are invalid
870 bool is_unknown_size_array;849 bool is_unknown_size_array;
871 // reminder: hash tables must be initialized before use850 BlockContext *block_context;
872 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
873851
874 // set this flag temporarily to detect infinite loops852 // set this flag temporarily to detect infinite loops
875 bool embedded_in_current;853 bool embedded_in_current;
...@@ -895,8 +873,7 @@ struct TypeTableEntryEnum {...@@ -895,8 +873,7 @@ struct TypeTableEntryEnum {
895 TypeTableEntry *tag_type;873 TypeTableEntry *tag_type;
896 TypeTableEntry *union_type;874 TypeTableEntry *union_type;
897875
898 // reminder: hash tables must be initialized before use876 BlockContext *block_context;
899 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
900877
901 // set this flag temporarily to detect infinite loops878 // set this flag temporarily to detect infinite loops
902 bool embedded_in_current;879 bool embedded_in_current;
...@@ -947,6 +924,7 @@ enum TypeTableEntryId {...@@ -947,6 +924,7 @@ enum TypeTableEntryId {
947 TypeTableEntryIdEnum,924 TypeTableEntryIdEnum,
948 TypeTableEntryIdFn,925 TypeTableEntryIdFn,
949 TypeTableEntryIdTypeDecl,926 TypeTableEntryIdTypeDecl,
927 TypeTableEntryIdNamespace,
950};928};
951929
952struct TypeTableEntry {930struct TypeTableEntry {
...@@ -979,26 +957,26 @@ struct TypeTableEntry {...@@ -979,26 +957,26 @@ struct TypeTableEntry {
979 TypeTableEntry *error_parent;957 TypeTableEntry *error_parent;
980};958};
981959
982struct ImporterInfo {960struct PackageTableEntry {
983 ImportTableEntry *import;961 Buf root_src_dir;
984 AstNode *source_node;962 Buf root_src_path; // relative to root_src_dir
963
964 // reminder: hash tables must be initialized before use
965 HashMap<Buf *, PackageTableEntry *, buf_hash, buf_eql_buf> package_table;
985};966};
986967
987struct ImportTableEntry {968struct ImportTableEntry {
988 AstNode *root;969 AstNode *root;
989 Buf *path; // relative to root_source_dir970 Buf *path; // relative to root_package->root_src_dir
971 PackageTableEntry *package;
990 LLVMZigDIFile *di_file;972 LLVMZigDIFile *di_file;
991 Buf *source_code;973 Buf *source_code;
992 ZigList<int> *line_offsets;974 ZigList<int> *line_offsets;
993 BlockContext *block_context;975 BlockContext *block_context;
994 ZigList<ImporterInfo> importers;
995 AstNode *c_import_node;976 AstNode *c_import_node;
996 bool any_imports_failed;977 bool any_imports_failed;
997978
998 // reminder: hash tables must be initialized before use979 ZigList<AstNode *> use_decls;
999 HashMap<Buf *, FnTableEntry *, buf_hash, buf_eql_buf> fn_table;
1000 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> type_table;
1001 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1002};980};
1003981
1004struct FnTableEntry {982struct FnTableEntry {
...@@ -1008,14 +986,12 @@ struct FnTableEntry {...@@ -1008,14 +986,12 @@ struct FnTableEntry {
1008 ImportTableEntry *import_entry;986 ImportTableEntry *import_entry;
1009 // Required to be a pre-order traversal of the AST. (parents must come before children)987 // Required to be a pre-order traversal of the AST. (parents must come before children)
1010 ZigList<BlockContext *> all_block_contexts;988 ZigList<BlockContext *> all_block_contexts;
1011 TypeTableEntry *member_of_struct;
1012 Buf symbol_name;989 Buf symbol_name;
1013 TypeTableEntry *type_entry; // function type990 TypeTableEntry *type_entry; // function type
1014 bool is_inline;991 bool is_inline;
1015 bool internal_linkage;992 bool internal_linkage;
1016 bool is_extern;993 bool is_extern;
1017 bool is_test;994 bool is_test;
1018 uint32_t ref_count; // if this is 0 we don't have to codegen it
1019995
1020 ZigList<AstNode *> cast_alloca_list;996 ZigList<AstNode *> cast_alloca_list;
1021 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;997 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
...@@ -1042,6 +1018,8 @@ enum BuiltinFnId {...@@ -1042,6 +1018,8 @@ enum BuiltinFnId {
1042 BuiltinFnIdConstEval,1018 BuiltinFnIdConstEval,
1043 BuiltinFnIdCtz,1019 BuiltinFnIdCtz,
1044 BuiltinFnIdClz,1020 BuiltinFnIdClz,
1021 BuiltinFnIdImport,
1022 BuiltinFnIdCImport,
1045};1023};
10461024
1047struct BuiltinFnEntry {1025struct BuiltinFnEntry {
...@@ -1061,17 +1039,22 @@ struct CodeGen {...@@ -1061,17 +1039,22 @@ struct CodeGen {
1061 LLVMZigDIBuilder *dbuilder;1039 LLVMZigDIBuilder *dbuilder;
1062 LLVMZigDICompileUnit *compile_unit;1040 LLVMZigDICompileUnit *compile_unit;
10631041
1064 ZigList<Buf *> lib_search_paths;1042 ZigList<Buf *> link_libs; // non-libc link libs
1065 ZigList<Buf *> link_libs;
10661043
1067 // reminder: hash tables must be initialized before use1044 // reminder: hash tables must be initialized before use
1068 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;1045 HashMap<Buf *, ImportTableEntry *, buf_hash, buf_eql_buf> import_table;
1069 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;1046 HashMap<Buf *, BuiltinFnEntry *, buf_hash, buf_eql_buf> builtin_fn_table;
1070 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;1047 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
1071 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> unresolved_top_level_decls;
1072 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;1048 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
1073 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;1049 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
10741050
1051 ZigList<ImportTableEntry *> import_queue;
1052 int import_queue_index;
1053 ZigList<AstNode *> export_queue;
1054 int export_queue_index;
1055 ZigList<AstNode *> use_queue;
1056 int use_queue_index;
1057
1075 uint32_t next_unresolved_index;1058 uint32_t next_unresolved_index;
10761059
1077 struct {1060 struct {
...@@ -1095,6 +1078,7 @@ struct CodeGen {...@@ -1095,6 +1078,7 @@ struct CodeGen {
1095 TypeTableEntry *entry_unreachable;1078 TypeTableEntry *entry_unreachable;
1096 TypeTableEntry *entry_type;1079 TypeTableEntry *entry_type;
1097 TypeTableEntry *entry_invalid;1080 TypeTableEntry *entry_invalid;
1081 TypeTableEntry *entry_namespace;
1098 TypeTableEntry *entry_num_lit_int;1082 TypeTableEntry *entry_num_lit_int;
1099 TypeTableEntry *entry_num_lit_float;1083 TypeTableEntry *entry_num_lit_float;
1100 TypeTableEntry *entry_undef;1084 TypeTableEntry *entry_undef;
...@@ -1126,7 +1110,8 @@ struct CodeGen {...@@ -1126,7 +1110,8 @@ struct CodeGen {
1126 LLVMTargetMachineRef target_machine;1110 LLVMTargetMachineRef target_machine;
1127 LLVMZigDIFile *dummy_di_file;1111 LLVMZigDIFile *dummy_di_file;
1128 bool is_native_target;1112 bool is_native_target;
1129 Buf *root_source_dir;1113 PackageTableEntry *root_package;
1114 PackageTableEntry *std_package;
1130 Buf *root_out_name;1115 Buf *root_out_name;
1131 bool windows_subsystem_windows;1116 bool windows_subsystem_windows;
1132 bool windows_subsystem_console;1117 bool windows_subsystem_console;
...@@ -1176,6 +1161,8 @@ struct CodeGen {...@@ -1176,6 +1161,8 @@ struct CodeGen {
1176 ZigList<const char *> lib_dirs;1161 ZigList<const char *> lib_dirs;
11771162
1178 uint32_t test_fn_count;1163 uint32_t test_fn_count;
1164
1165 bool check_unused;
1179};1166};
11801167
1181struct VariableTableEntry {1168struct VariableTableEntry {
...@@ -1202,7 +1189,8 @@ struct BlockContext {...@@ -1202,7 +1189,8 @@ struct BlockContext {
1202 AstNode *node;1189 AstNode *node;
12031190
1204 // any variables that are introduced by this scope1191 // any variables that are introduced by this scope
1205 HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> variable_table;1192 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> decl_table;
1193 HashMap<Buf *, VariableTableEntry *, buf_hash, buf_eql_buf> var_table;
12061194
1207 // if the block is inside a function, this is the function it is in:1195 // if the block is inside a function, this is the function it is in:
1208 FnTableEntry *fn_entry;1196 FnTableEntry *fn_entry;
src/analyze.cpp+669-897
...@@ -14,8 +14,10 @@...@@ -14,8 +14,10 @@
14#include "config.h"14#include "config.h"
15#include "ast_render.hpp"15#include "ast_render.hpp"
1616
17static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,17static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
18 TypeTableEntry *expected_type, AstNode *node);18 TypeTableEntry *expected_type, AstNode *node);
19static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEntry *import,
20 BlockContext *context, TypeTableEntry *expected_type, AstNode *node, bool pointer_only);
19static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,21static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableEntry *import,
20 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);22 BlockContext *context, TypeTableEntry *expected_type, AstNode *node);
21static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);23static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableEntry *struct_type);
...@@ -27,13 +29,18 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *...@@ -27,13 +29,18 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
27static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,29static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
28 TypeTableEntry *expected_type, AstNode *node);30 TypeTableEntry *expected_type, AstNode *node);
29static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);31static TypeTableEntry *resolve_expr_const_val_as_void(CodeGen *g, AstNode *node);
30static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context,32static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn);
31 FnTableEntry *fn);
32static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type);33static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node, TypeTableEntry *type);
33static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,34static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
34 TypeTableEntry *expected_type, uint64_t x);35 TypeTableEntry *expected_type, uint64_t x);
35static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node);36static AstNode *find_decl(BlockContext *context, Buf *name);
36static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node);37static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node, bool pointer_only);
38static TopLevelDecl *get_as_top_level_decl(AstNode *node);
39static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
40 BlockContext *context, AstNode *source_node,
41 AstNodeVariableDeclaration *variable_declaration,
42 bool expr_is_maybe, AstNode *decl_node);
43static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);
3744
38static AstNode *first_executing_node(AstNode *node) {45static AstNode *first_executing_node(AstNode *node) {
39 switch (node->type) {46 switch (node->type) {
...@@ -52,7 +59,6 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -52,7 +59,6 @@ static AstNode *first_executing_node(AstNode *node) {
52 case NodeTypeSwitchRange:59 case NodeTypeSwitchRange:
53 return first_executing_node(node->data.switch_range.start);60 return first_executing_node(node->data.switch_range.start);
54 case NodeTypeRoot:61 case NodeTypeRoot:
55 case NodeTypeRootExportDecl:
56 case NodeTypeFnProto:62 case NodeTypeFnProto:
57 case NodeTypeFnDef:63 case NodeTypeFnDef:
58 case NodeTypeFnDecl:64 case NodeTypeFnDecl:
...@@ -69,8 +75,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -69,8 +75,7 @@ static AstNode *first_executing_node(AstNode *node) {
69 case NodeTypeCharLiteral:75 case NodeTypeCharLiteral:
70 case NodeTypeSymbol:76 case NodeTypeSymbol:
71 case NodeTypePrefixOpExpr:77 case NodeTypePrefixOpExpr:
72 case NodeTypeImport:78 case NodeTypeUse:
73 case NodeTypeCImport:
74 case NodeTypeBoolLiteral:79 case NodeTypeBoolLiteral:
75 case NodeTypeNullLiteral:80 case NodeTypeNullLiteral:
76 case NodeTypeUndefinedLiteral:81 case NodeTypeUndefinedLiteral:
...@@ -109,43 +114,47 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {...@@ -109,43 +114,47 @@ ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
109 return err;114 return err;
110}115}
111116
117ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg) {
118 // if this assert fails, then parseh generated code that
119 // failed semantic analysis, which isn't supposed to happen
120 assert(!node->owner->c_import_node);
121
122 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
123 node->owner->source_code, node->owner->line_offsets, msg);
124
125 err_msg_add_note(parent_msg, err);
126 return err;
127}
128
112TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {129TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
113 TypeTableEntry *entry = allocate<TypeTableEntry>(1);130 TypeTableEntry *entry = allocate<TypeTableEntry>(1);
114 entry->arrays_by_size.init(2);131 entry->arrays_by_size.init(2);
115 entry->id = id;132 entry->id = id;
133 return entry;
134}
116135
117 switch (id) {136static BlockContext **get_container_block_context_ptr(TypeTableEntry *type_entry) {
118 case TypeTableEntryIdInvalid:137 if (type_entry->id == TypeTableEntryIdStruct) {
119 case TypeTableEntryIdMetaType:138 return &type_entry->data.structure.block_context;
120 case TypeTableEntryIdVoid:139 } else if (type_entry->id == TypeTableEntryIdEnum) {
121 case TypeTableEntryIdBool:140 return &type_entry->data.enumeration.block_context;
122 case TypeTableEntryIdUnreachable:
123 case TypeTableEntryIdInt:
124 case TypeTableEntryIdFloat:
125 case TypeTableEntryIdPointer:
126 case TypeTableEntryIdArray:
127 case TypeTableEntryIdNumLitFloat:
128 case TypeTableEntryIdNumLitInt:
129 case TypeTableEntryIdMaybe:
130 case TypeTableEntryIdFn:
131 case TypeTableEntryIdErrorUnion:
132 case TypeTableEntryIdPureError:
133 case TypeTableEntryIdUndefLit:
134 case TypeTableEntryIdTypeDecl:
135 // nothing to init
136 break;
137 case TypeTableEntryIdStruct:
138 entry->data.structure.fn_table.init(8);
139 break;
140 case TypeTableEntryIdEnum:
141 entry->data.enumeration.fn_table.init(8);
142 break;
143
144 }141 }
142 zig_unreachable();
143}
144
145static BlockContext *get_container_block_context(TypeTableEntry *type_entry) {
146 return *get_container_block_context_ptr(type_entry);
147}
145148
149static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *source_node,
150 BlockContext *parent_context)
151{
152 TypeTableEntry *entry = new_type_table_entry(id);
153 *get_container_block_context_ptr(entry) = new_block_context(source_node, parent_context);
146 return entry;154 return entry;
147}155}
148156
157
149static int bits_needed_for_unsigned(uint64_t x) {158static int bits_needed_for_unsigned(uint64_t x) {
150 if (x <= UINT8_MAX) {159 if (x <= UINT8_MAX) {
151 return 8;160 return 8;
...@@ -182,6 +191,7 @@ static bool type_is_complete(TypeTableEntry *type_entry) {...@@ -182,6 +191,7 @@ static bool type_is_complete(TypeTableEntry *type_entry) {
182 case TypeTableEntryIdPureError:191 case TypeTableEntryIdPureError:
183 case TypeTableEntryIdFn:192 case TypeTableEntryIdFn:
184 case TypeTableEntryIdTypeDecl:193 case TypeTableEntryIdTypeDecl:
194 case TypeTableEntryIdNamespace:
185 return true;195 return true;
186 }196 }
187 zig_unreachable();197 zig_unreachable();
...@@ -671,7 +681,7 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,...@@ -671,7 +681,7 @@ TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import,
671 ContainerKind kind, AstNode *decl_node, const char *name)681 ContainerKind kind, AstNode *decl_node, const char *name)
672{682{
673 TypeTableEntryId type_id = container_to_type(kind);683 TypeTableEntryId type_id = container_to_type(kind);
674 TypeTableEntry *entry = new_type_table_entry(type_id);684 TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, import->block_context);
675685
676 switch (kind) {686 switch (kind) {
677 case ContainerKindStruct:687 case ContainerKindStruct:
...@@ -730,13 +740,19 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {...@@ -730,13 +740,19 @@ static TypeTableEntry *resolve_type(CodeGen *g, AstNode *node) {
730 return const_val->data.x_type;740 return const_val->data.x_type;
731}741}
732742
743static TypeTableEntry *analyze_type_expr_pointer_only(CodeGen *g, ImportTableEntry *import,
744 BlockContext *context, AstNode *node, bool pointer_only)
745{
746 AstNode **node_ptr = node->parent_field;
747 analyze_expression_pointer_only(g, import, context, nullptr, *node_ptr, pointer_only);
748 return resolve_type(g, *node_ptr);
749}
750
733// Calls analyze_expression on node, and then resolve_type.751// Calls analyze_expression on node, and then resolve_type.
734static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,752static TypeTableEntry *analyze_type_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
735 AstNode *node)753 AstNode *node)
736{754{
737 AstNode **node_ptr = node->parent_field;755 return analyze_type_expr_pointer_only(g, import, context, node, false);
738 analyze_expression(g, import, context, nullptr, *node_ptr);
739 return resolve_type(g, *node_ptr);
740}756}
741757
742static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *import, BlockContext *context,758static 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...@@ -750,7 +766,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
750 }766 }
751767
752 FnTypeId fn_type_id = {0};768 FnTypeId fn_type_id = {0};
753 fn_type_id.is_extern = fn_proto->is_extern || (fn_proto->visib_mod == VisibModExport);769 fn_type_id.is_extern = fn_proto->is_extern || (fn_proto->top_level_decl.visib_mod == VisibModExport);
754 fn_type_id.is_naked = is_naked;770 fn_type_id.is_naked = is_naked;
755 fn_type_id.is_cold = is_cold;771 fn_type_id.is_cold = is_cold;
756 fn_type_id.param_count = node->data.fn_proto.params.length;772 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...@@ -782,6 +798,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
782 case TypeTableEntryIdUndefLit:798 case TypeTableEntryIdUndefLit:
783 case TypeTableEntryIdMetaType:799 case TypeTableEntryIdMetaType:
784 case TypeTableEntryIdUnreachable:800 case TypeTableEntryIdUnreachable:
801 case TypeTableEntryIdNamespace:
785 fn_proto->skip = true;802 fn_proto->skip = true;
786 add_node_error(g, child->data.param_decl.type,803 add_node_error(g, child->data.param_decl.type,
787 buf_sprintf("parameter of type '%s' not allowed'", buf_ptr(&type_entry->name)));804 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...@@ -880,9 +897,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
880 bool is_naked = false;897 bool is_naked = false;
881 bool is_test = false;898 bool is_test = false;
882899
883 if (fn_proto->directives) {900 if (fn_proto->top_level_decl.directives) {
884 for (int i = 0; i < fn_proto->directives->length; i += 1) {901 for (int i = 0; i < fn_proto->top_level_decl.directives->length; i += 1) {
885 AstNode *directive_node = fn_proto->directives->at(i);902 AstNode *directive_node = fn_proto->top_level_decl.directives->at(i);
886 Buf *name = &directive_node->data.directive.name;903 Buf *name = &directive_node->data.directive.name;
887904
888 if (buf_eql_str(name, "attribute")) {905 if (buf_eql_str(name, "attribute")) {
...@@ -907,12 +924,12 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -907,12 +924,12 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
907 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));924 buf_sprintf("invalid function attribute: '%s'", buf_ptr(name)));
908 }925 }
909 } else if (buf_eql_str(name, "condition")) {926 } else if (buf_eql_str(name, "condition")) {
910 if (fn_proto->visib_mod == VisibModExport) {927 if (fn_proto->top_level_decl.visib_mod == VisibModExport) {
911 bool include;928 bool include;
912 bool ok = resolve_const_expr_bool(g, import, import->block_context,929 bool ok = resolve_const_expr_bool(g, import, import->block_context,
913 &directive_node->data.directive.expr, &include);930 &directive_node->data.directive.expr, &include);
914 if (ok && !include) {931 if (ok && !include) {
915 fn_proto->visib_mod = VisibModPub;932 fn_proto->top_level_decl.visib_mod = VisibModPub;
916 }933 }
917 } else {934 } else {
918 add_node_error(g, directive_node,935 add_node_error(g, directive_node,
...@@ -925,12 +942,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -925,12 +942,9 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
925 }942 }
926 }943 }
927944
928 bool is_internal = (fn_proto->visib_mod != VisibModExport);945 bool is_internal = (fn_proto->top_level_decl.visib_mod != VisibModExport);
929 bool is_c_compat = !is_internal || fn_proto->is_extern;946 bool is_c_compat = !is_internal || fn_proto->is_extern;
930 fn_table_entry->internal_linkage = !is_c_compat;947 fn_table_entry->internal_linkage = !is_c_compat;
931 if (!is_internal) {
932 fn_table_entry->ref_count += 1;
933 }
934948
935949
936950
...@@ -972,18 +986,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -972,18 +986,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
972 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoUnwindAttribute);986 LLVMAddFunctionAttr(fn_table_entry->fn_value, LLVMNoUnwindAttribute);
973 }987 }
974988
975 // Add debug info.
976 unsigned line_number = node->line + 1;
977 unsigned scope_line = line_number;
978 bool is_definition = fn_table_entry->fn_def_node != nullptr;
979 unsigned flags = 0;
980 bool is_optimized = g->is_release_build;
981 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
982 import->block_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
983 import->di_file, line_number,
984 fn_type->di_type, fn_table_entry->internal_linkage,
985 is_definition, scope_line, flags, is_optimized, fn_table_entry->fn_value);
986 if (fn_table_entry->fn_def_node) {989 if (fn_table_entry->fn_def_node) {
990 // Add debug info.
991 unsigned line_number = node->line + 1;
992 unsigned scope_line = line_number;
993 bool is_definition = fn_table_entry->fn_def_node != nullptr;
994 unsigned flags = 0;
995 bool is_optimized = g->is_release_build;
996 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
997 import->block_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
998 import->di_file, line_number,
999 fn_type->di_type, fn_table_entry->internal_linkage,
1000 is_definition, scope_line, flags, is_optimized, fn_table_entry->fn_value);
1001
987 BlockContext *context = new_block_context(fn_table_entry->fn_def_node, import->block_context);1002 BlockContext *context = new_block_context(fn_table_entry->fn_def_node, import->block_context);
988 fn_table_entry->fn_def_node->data.fn_def.block_context = context;1003 fn_table_entry->fn_def_node->data.fn_def.block_context = context;
989 context->di_scope = LLVMZigSubprogramToScope(subprogram);1004 context->di_scope = LLVMZigSubprogramToScope(subprogram);
...@@ -1295,59 +1310,43 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE...@@ -1295,59 +1310,43 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
1295 struct_type->zero_bits = (debug_size_in_bits == 0);1310 struct_type->zero_bits = (debug_size_in_bits == 0);
1296}1311}
12971312
1298static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,1313static void get_fully_qualified_decl_name(Buf *buf, AstNode *decl_node, uint8_t sep) {
1299 AstNode *proto_node)1314 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
1300{1315 AstNode *parent_decl = tld->parent_decl;
1316
1317 if (parent_decl) {
1318 get_fully_qualified_decl_name(buf, parent_decl, sep);
1319 buf_append_char(buf, sep);
1320 buf_append_buf(buf, tld->name);
1321 } else {
1322 buf_init_from_buf(buf, tld->name);
1323 }
1324}
1325
1326static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *proto_node) {
1301 if (proto_node->data.fn_proto.skip) {1327 if (proto_node->data.fn_proto.skip) {
1302 return;1328 return;
1303 }1329 }
1330
1331 AstNode *parent_decl = proto_node->data.fn_proto.top_level_decl.parent_decl;
1332
1304 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;1333 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;
1305 AstNode *struct_node = proto_node->data.fn_proto.struct_node;
1306 bool is_extern = proto_node->data.fn_proto.is_extern;1334 bool is_extern = proto_node->data.fn_proto.is_extern;
1307 TypeTableEntry *struct_type;
1308 if (struct_node) {
1309 assert(struct_node->type == NodeTypeStructDecl);
1310 struct_type = struct_node->data.struct_decl.type_entry;
1311 } else {
1312 struct_type = nullptr;
1313 }
13141335
1315 Buf *proto_name = &proto_node->data.fn_proto.name;1336 Buf *proto_name = &proto_node->data.fn_proto.name;
13161337
1317 auto fn_table = struct_type ? &struct_type->data.structure.fn_table : &import->fn_table;
1318
1319 auto entry = fn_table->maybe_get(proto_name);
1320 bool skip = false;
1321 bool is_pub = (proto_node->data.fn_proto.visib_mod != VisibModPrivate);
1322 if (entry) {
1323 add_node_error(g, proto_node,
1324 buf_sprintf("redefinition of '%s'", buf_ptr(proto_name)));
1325 proto_node->data.fn_proto.skip = true;
1326 skip = true;
1327 }
1328 if (!is_extern && proto_node->data.fn_proto.is_var_args) {1338 if (!is_extern && proto_node->data.fn_proto.is_var_args) {
1329 add_node_error(g, proto_node,1339 add_node_error(g, proto_node,
1330 buf_sprintf("variadic arguments only allowed in extern functions"));1340 buf_sprintf("variadic arguments only allowed in extern functions"));
1331 }1341 }
1332 if (skip) {
1333 return;
1334 }
13351342
1336 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);1343 FnTableEntry *fn_table_entry = allocate<FnTableEntry>(1);
1337 fn_table_entry->import_entry = import;1344 fn_table_entry->import_entry = import;
1338 fn_table_entry->proto_node = proto_node;1345 fn_table_entry->proto_node = proto_node;
1339 fn_table_entry->fn_def_node = fn_def_node;1346 fn_table_entry->fn_def_node = fn_def_node;
1340 fn_table_entry->is_extern = is_extern;1347 fn_table_entry->is_extern = is_extern;
1341 fn_table_entry->member_of_struct = struct_type;
13421348
1343 if (struct_type) {1349 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, proto_node, '_');
1344 buf_resize(&fn_table_entry->symbol_name, 0);
1345 buf_appendf(&fn_table_entry->symbol_name, "%s_%s",
1346 buf_ptr(&struct_type->name),
1347 buf_ptr(proto_name));
1348 } else {
1349 buf_init_from_buf(&fn_table_entry->symbol_name, proto_name);
1350 }
13511350
1352 g->fn_protos.append(fn_table_entry);1351 g->fn_protos.append(fn_table_entry);
13531352
...@@ -1355,39 +1354,13 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,...@@ -1355,39 +1354,13 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import,
1355 g->fn_defs.append(fn_table_entry);1354 g->fn_defs.append(fn_table_entry);
1356 }1355 }
13571356
1358 fn_table->put(proto_name, fn_table_entry);1357 bool is_main_fn = !parent_decl && (import == g->root_import) && buf_eql_str(proto_name, "main");
1359
1360 bool is_main_fn = !struct_type && (import == g->root_import) && buf_eql_str(proto_name, "main");
1361 if (is_main_fn) {1358 if (is_main_fn) {
1362 g->main_fn = fn_table_entry;1359 g->main_fn = fn_table_entry;
1363
1364 if (g->bootstrap_import && !g->is_test_build) {
1365 g->bootstrap_import->fn_table.put(buf_create_from_str("zig_user_main"), fn_table_entry);
1366 }
1367 }
1368 bool is_test_main_fn = !struct_type && (import == g->test_runner_import) && buf_eql_str(proto_name, "main");
1369 if (is_test_main_fn) {
1370 assert(g->bootstrap_import);
1371 assert(g->is_test_build);
1372 g->bootstrap_import->fn_table.put(proto_name, fn_table_entry);
1373 }1360 }
13741361
1375 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;1362 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
1376 resolve_function_proto(g, proto_node, fn_table_entry, import);1363 resolve_function_proto(g, proto_node, fn_table_entry, import);
1377
1378 if (is_pub && !struct_type) {
1379 for (int i = 0; i < import->importers.length; i += 1) {
1380 ImporterInfo importer = import->importers.at(i);
1381 auto table_entry = importer.import->fn_table.maybe_get(proto_name);
1382 if (table_entry) {
1383 add_node_error(g, importer.source_node,
1384 buf_sprintf("import of function '%s' overrides existing definition",
1385 buf_ptr(proto_name)));
1386 } else {
1387 importer.import->fn_table.put(proto_name, fn_table_entry);
1388 }
1389 }
1390 }
1391}1364}
13921365
1393static void preview_error_value_decl(CodeGen *g, AstNode *node) {1366static void preview_error_value_decl(CodeGen *g, AstNode *node) {
...@@ -1403,110 +1376,40 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {...@@ -1403,110 +1376,40 @@ static void preview_error_value_decl(CodeGen *g, AstNode *node) {
1403 // duplicate error definitions allowed and they get the same value1376 // duplicate error definitions allowed and they get the same value
1404 err->value = existing_entry->value->value;1377 err->value = existing_entry->value->value;
1405 } else {1378 } else {
1379 assert(g->error_value_count < (1 << g->err_tag_type->data.integral.bit_count));
1406 err->value = g->error_value_count;1380 err->value = g->error_value_count;
1407 g->error_value_count += 1;1381 g->error_value_count += 1;
1408 g->error_table.put(&err->name, err);1382 g->error_table.put(&err->name, err);
1409 }1383 }
14101384
1411 node->data.error_value_decl.err = err;1385 node->data.error_value_decl.err = err;
1386 node->data.error_value_decl.top_level_decl.resolution = TldResolutionOk;
1412}1387}
14131388
1414static void resolve_error_value_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {1389static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) {
1415 assert(node->type == NodeTypeErrorValueDecl);1390 TopLevelDecl *tld = get_as_top_level_decl(node);
14161391 if (tld->resolution != TldResolutionUnresolved) {
1417 ErrorTableEntry *err = node->data.error_value_decl.err;
1418
1419 import->error_table.put(&err->name, err);
1420
1421 bool is_pub = (node->data.error_value_decl.visib_mod != VisibModPrivate);
1422 if (is_pub) {
1423 for (int i = 0; i < import->importers.length; i += 1) {
1424 ImporterInfo importer = import->importers.at(i);
1425 importer.import->error_table.put(&err->name, err);
1426 }
1427 }
1428}
1429
1430static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *parent_import, AstNode *node) {
1431 assert(node->type == NodeTypeCImport);
1432
1433 AstNode *block_node = node->data.c_import.block;
1434
1435 BlockContext *child_context = new_block_context(node, parent_import->block_context);
1436 child_context->c_import_buf = buf_alloc();
1437
1438 TypeTableEntry *resolved_type = analyze_block_expr(g, parent_import, child_context,
1439 g->builtin_types.entry_void, block_node);
1440
1441 if (resolved_type->id == TypeTableEntryIdInvalid) {
1442 return;1392 return;
1443 }1393 }
14441394 if (pointer_only && node->type == NodeTypeStructDecl) {
1445 find_libc_include_path(g);
1446
1447 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
1448 child_import->fn_table.init(32);
1449 child_import->type_table.init(8);
1450 child_import->error_table.init(8);
1451 child_import->c_import_node = node;
1452
1453 child_import->importers.append({parent_import, node});
1454
1455 if (node->data.c_import.visib_mod != VisibModPrivate) {
1456 for (int i = 0; i < parent_import->importers.length; i += 1) {
1457 ImporterInfo importer = parent_import->importers.at(i);
1458 child_import->importers.append(importer);
1459 }
1460 }
1461
1462 ZigList<ErrorMsg *> errors = {0};
1463
1464 int err;
1465 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
1466 zig_panic("unable to parse h file: %s\n", err_str(err));
1467 }
1468
1469 if (errors.length > 0) {
1470 ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
1471 for (int i = 0; i < errors.length; i += 1) {
1472 ErrorMsg *err_msg = errors.at(i);
1473 err_msg_add_note(parent_err_msg, err_msg);
1474 }
1475
1476 for (int i = 0; i < child_import->importers.length; i += 1) {
1477 child_import->importers.at(i).import->any_imports_failed = true;
1478 }
1479 return;1395 return;
1480 }1396 }
14811397
1482 if (g->verbose) {1398 ImportTableEntry *import = tld->import;
1483 fprintf(stderr, "\nc_import:\n");1399 assert(import);
1484 fprintf(stderr, "-----------\n");
1485 ast_render(stderr, child_import->root, 4);
1486 }
1487
1488 child_import->di_file = parent_import->di_file;
1489 child_import->block_context = new_block_context(child_import->root, nullptr);
1490
1491 detect_top_level_decl_deps(g, child_import, child_import->root);
1492 analyze_top_level_decls_root(g, child_import, child_import->root);
1493}
14941400
1495static void satisfy_dep(CodeGen *g, AstNode *node) {1401 if (tld->dep_loop_flag) {
1496 Buf *name = get_resolved_top_level_decl(node)->name;1402 add_node_error(g, node, buf_sprintf("'%s' depends on itself", buf_ptr(tld->name)));
1497 if (name) {1403 tld->resolution = TldResolutionInvalid;
1498 g->unresolved_top_level_decls.maybe_remove(name);1404 return;
1405 } else {
1406 tld->dep_loop_flag = true;
1499 }1407 }
1500}
15011408
1502static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1503 switch (node->type) {1409 switch (node->type) {
1504 case NodeTypeFnProto:1410 case NodeTypeFnProto:
1505 preview_fn_proto(g, import, node);1411 preview_fn_proto(g, import, node);
1506 break;1412 break;
1507 case NodeTypeRootExportDecl:
1508 // handled earlier
1509 return;
1510 case NodeTypeStructDecl:1413 case NodeTypeStructDecl:
1511 {1414 {
1512 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;1415 TypeTableEntry *type_entry = node->data.struct_decl.type_entry;
...@@ -1526,8 +1429,10 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1526,8 +1429,10 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1526 }1429 }
1527 case NodeTypeVariableDeclaration:1430 case NodeTypeVariableDeclaration:
1528 {1431 {
1529 VariableTableEntry *var = analyze_variable_declaration(g, import, import->block_context,1432 AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
1530 nullptr, node);1433 VariableTableEntry *var = analyze_variable_declaration_raw(g, import, import->block_context,
1434 node, variable_declaration, false, node);
1435
1531 g->global_vars.append(var);1436 g->global_vars.append(var);
1532 break;1437 break;
1533 }1438 }
...@@ -1547,34 +1452,13 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1547,34 +1452,13 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1547 entry = get_typedecl_type(g, buf_ptr(decl_name), child_type);1452 entry = get_typedecl_type(g, buf_ptr(decl_name), child_type);
1548 }1453 }
1549 }1454 }
15501455 node->data.type_decl.child_type_entry = entry;
1551 import->type_table.put(decl_name, entry);
1552
1553 bool is_pub = (node->data.type_decl.visib_mod != VisibModPrivate);
1554 if (is_pub) {
1555 for (int i = 0; i < import->importers.length; i += 1) {
1556 ImporterInfo importer = import->importers.at(i);
1557 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
1558 if (table_entry) {
1559 add_node_error(g, importer.source_node,
1560 buf_sprintf("import of type '%s' overrides existing definition",
1561 buf_ptr(&entry->name)));
1562 } else {
1563 importer.import->type_table.put(&entry->name, entry);
1564 }
1565 }
1566 }
1567
1568 break;1456 break;
1569 }1457 }
1570 case NodeTypeErrorValueDecl:1458 case NodeTypeErrorValueDecl:
1571 resolve_error_value_decl(g, import, node);
1572 break;1459 break;
1573 case NodeTypeImport:1460 case NodeTypeUse:
1574 // nothing to do here1461 zig_panic("TODO resolve_top_level_decl NodeTypeUse");
1575 return;
1576 case NodeTypeCImport:
1577 resolve_c_import_decl(g, import, node);
1578 break;1462 break;
1579 case NodeTypeFnDef:1463 case NodeTypeFnDef:
1580 case NodeTypeDirective:1464 case NodeTypeDirective:
...@@ -1619,8 +1503,8 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode...@@ -1619,8 +1503,8 @@ static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode
1619 zig_unreachable();1503 zig_unreachable();
1620 }1504 }
16211505
16221506 tld->resolution = TldResolutionOk;
1623 satisfy_dep(g, node);1507 tld->dep_loop_flag = false;
1624}1508}
16251509
1626static FnTableEntry *get_context_fn_entry(BlockContext *context) {1510static FnTableEntry *get_context_fn_entry(BlockContext *context) {
...@@ -1656,6 +1540,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {...@@ -1656,6 +1540,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
1656 case TypeTableEntryIdNumLitFloat:1540 case TypeTableEntryIdNumLitFloat:
1657 case TypeTableEntryIdNumLitInt:1541 case TypeTableEntryIdNumLitInt:
1658 case TypeTableEntryIdUndefLit:1542 case TypeTableEntryIdUndefLit:
1543 case TypeTableEntryIdNamespace:
1659 return false;1544 return false;
16601545
1661 case TypeTableEntryIdBool:1546 case TypeTableEntryIdBool:
...@@ -2063,7 +1948,8 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -2063,7 +1948,8 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
2063 BlockContext *context = allocate<BlockContext>(1);1948 BlockContext *context = allocate<BlockContext>(1);
2064 context->node = node;1949 context->node = node;
2065 context->parent = parent;1950 context->parent = parent;
2066 context->variable_table.init(4);1951 context->decl_table.init(1);
1952 context->var_table.init(1);
20671953
2068 if (parent) {1954 if (parent) {
2069 context->parent_loop_node = parent->parent_loop_node;1955 context->parent_loop_node = parent->parent_loop_node;
...@@ -2085,23 +1971,28 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {...@@ -2085,23 +1971,28 @@ BlockContext *new_block_context(AstNode *node, BlockContext *parent) {
2085 return context;1971 return context;
2086}1972}
20871973
2088static VariableTableEntry *find_variable(BlockContext *context, Buf *name, bool local_only) {1974static AstNode *find_decl(BlockContext *context, Buf *name) {
2089 while (context && (!local_only || context->fn_entry)) {1975 while (context) {
2090 auto entry = context->variable_table.maybe_get(name);1976 auto entry = context->decl_table.maybe_get(name);
2091 if (entry)1977 if (entry) {
2092 return entry->value;1978 return entry->value;
20931979 }
2094 context = context->parent;1980 context = context->parent;
2095 }1981 }
2096 return nullptr;1982 return nullptr;
2097}1983}
20981984
2099static TypeTableEntry *find_container(ImportTableEntry *import, Buf *name) {1985static VariableTableEntry *find_variable(CodeGen *g, BlockContext *orig_context, Buf *name) {
2100 auto entry = import->type_table.maybe_get(name);1986 BlockContext *context = orig_context;
2101 if (entry)1987 while (context) {
2102 return entry->value;1988 auto entry = context->var_table.maybe_get(name);
2103 else1989 if (entry) {
2104 return nullptr;1990 return entry->value;
1991 }
1992 context = context->parent;
1993 }
1994
1995 return nullptr;
2105}1996}
21061997
2107static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {1998static TypeEnumField *get_enum_field(TypeTableEntry *enum_type, Buf *name) {
...@@ -2155,6 +2046,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp...@@ -2155,6 +2046,7 @@ static TypeTableEntry *analyze_enum_value_expr(CodeGen *g, ImportTableEntry *imp
21552046
2156static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {2047static TypeStructField *find_struct_type_field(TypeTableEntry *type_entry, Buf *name) {
2157 assert(type_entry->id == TypeTableEntryIdStruct);2048 assert(type_entry->id == TypeTableEntryIdStruct);
2049 assert(type_entry->data.structure.complete);
2158 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {2050 for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
2159 TypeStructField *field = &type_entry->data.structure.fields[i];2051 TypeStructField *field = &type_entry->data.structure.fields[i];
2160 if (buf_eql_buf(field->name, name)) {2052 if (buf_eql_buf(field->name, name)) {
...@@ -2330,8 +2222,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2330,8 +2222,8 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
2330{2222{
2331 assert(node->type == NodeTypeFieldAccessExpr);2223 assert(node->type == NodeTypeFieldAccessExpr);
23322224
2333 AstNode *struct_expr_node = node->data.field_access_expr.struct_expr;2225 AstNode **struct_expr_node = &node->data.field_access_expr.struct_expr;
2334 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, struct_expr_node);2226 TypeTableEntry *struct_type = analyze_expression(g, import, context, nullptr, *struct_expr_node);
2335 Buf *field_name = &node->data.field_access_expr.field_name;2227 Buf *field_name = &node->data.field_access_expr.field_name;
23362228
2337 bool wrapped_in_fn_call = node->data.field_access_expr.is_fn_call;2229 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...@@ -2342,17 +2234,30 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
2342 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?2234 TypeTableEntry *bare_struct_type = (struct_type->id == TypeTableEntryIdStruct) ?
2343 struct_type : struct_type->data.pointer.child_type;2235 struct_type : struct_type->data.pointer.child_type;
23442236
2237 if (!bare_struct_type->data.structure.complete) {
2238 resolve_struct_type(g, bare_struct_type->data.structure.decl_node->owner, bare_struct_type);
2239 }
2240
2345 node->data.field_access_expr.bare_struct_type = bare_struct_type;2241 node->data.field_access_expr.bare_struct_type = bare_struct_type;
2346 node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name);2242 node->data.field_access_expr.type_struct_field = find_struct_type_field(bare_struct_type, field_name);
2347 if (node->data.field_access_expr.type_struct_field) {2243 if (node->data.field_access_expr.type_struct_field) {
2348 return node->data.field_access_expr.type_struct_field->type_entry;2244 return node->data.field_access_expr.type_struct_field->type_entry;
2349 } else if (wrapped_in_fn_call) {2245 } else if (wrapped_in_fn_call) {
2350 auto table_entry = bare_struct_type->data.structure.fn_table.maybe_get(field_name);2246 BlockContext *container_block_context = get_container_block_context(bare_struct_type);
2351 if (table_entry) {2247 auto entry = container_block_context->decl_table.maybe_get(field_name);
2248 AstNode *fn_decl_node = entry ? entry->value : nullptr;
2249 if (fn_decl_node && fn_decl_node->type == NodeTypeFnProto) {
2250 resolve_top_level_decl(g, fn_decl_node, false);
2251 TopLevelDecl *tld = get_as_top_level_decl(fn_decl_node);
2252 if (tld->resolution == TldResolutionInvalid) {
2253 return g->builtin_types.entry_invalid;
2254 }
2255
2352 node->data.field_access_expr.is_member_fn = true;2256 node->data.field_access_expr.is_member_fn = true;
2353 return resolve_expr_const_val_as_fn(g, node, context, table_entry->value);2257 FnTableEntry *fn_entry = fn_decl_node->data.fn_proto.fn_table_entry;
2258 return resolve_expr_const_val_as_fn(g, node, fn_entry);
2354 } else {2259 } else {
2355 add_node_error(g, node, buf_sprintf("no member named '%s' in '%s'",2260 add_node_error(g, node, buf_sprintf("no function named '%s' in '%s'",
2356 buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));2261 buf_ptr(field_name), buf_ptr(&bare_struct_type->name)));
2357 return g->builtin_types.entry_invalid;2262 return g->builtin_types.entry_invalid;
2358 }2263 }
...@@ -2372,7 +2277,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2372,7 +2277,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
2372 return g->builtin_types.entry_invalid;2277 return g->builtin_types.entry_invalid;
2373 }2278 }
2374 } else if (struct_type->id == TypeTableEntryIdMetaType) {2279 } else if (struct_type->id == TypeTableEntryIdMetaType) {
2375 TypeTableEntry *child_type = resolve_type(g, struct_expr_node);2280 TypeTableEntry *child_type = resolve_type(g, *struct_expr_node);
23762281
2377 if (child_type->id == TypeTableEntryIdInvalid) {2282 if (child_type->id == TypeTableEntryIdInvalid) {
2378 return g->builtin_types.entry_invalid;2283 return g->builtin_types.entry_invalid;
...@@ -2381,12 +2286,15 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2381,12 +2286,15 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
2381 } else if (child_type->id == TypeTableEntryIdEnum) {2286 } else if (child_type->id == TypeTableEntryIdEnum) {
2382 return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name);2287 return analyze_enum_value_expr(g, import, context, node, nullptr, child_type, field_name);
2383 } else if (child_type->id == TypeTableEntryIdStruct) {2288 } else if (child_type->id == TypeTableEntryIdStruct) {
2384 auto entry = child_type->data.structure.fn_table.maybe_get(field_name);2289 BlockContext *container_block_context = get_container_block_context(child_type);
2385 if (entry) {2290 auto entry = container_block_context->decl_table.maybe_get(field_name);
2386 return resolve_expr_const_val_as_fn(g, node, context, entry->value);2291 AstNode *decl_node = entry ? entry->value : nullptr;
2292 if (decl_node) {
2293 bool pointer_only = false;
2294 return analyze_decl_ref(g, node, decl_node, pointer_only);
2387 } else {2295 } else {
2388 add_node_error(g, node,2296 add_node_error(g, node,
2389 buf_sprintf("struct '%s' has no function called '%s'",2297 buf_sprintf("container '%s' has no member called '%s'",
2390 buf_ptr(&child_type->name), buf_ptr(field_name)));2298 buf_ptr(&child_type->name), buf_ptr(field_name)));
2391 return g->builtin_types.entry_invalid;2299 return g->builtin_types.entry_invalid;
2392 }2300 }
...@@ -2397,6 +2305,26 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2397,6 +2305,26 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
2397 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));2305 buf_sprintf("type '%s' does not support field access", buf_ptr(&struct_type->name)));
2398 return g->builtin_types.entry_invalid;2306 return g->builtin_types.entry_invalid;
2399 }2307 }
2308 } else if (struct_type->id == TypeTableEntryIdNamespace) {
2309 ConstExprValue *const_val = &get_resolved_expr(*struct_expr_node)->const_val;
2310 assert(const_val->ok);
2311 ImportTableEntry *namespace_import = const_val->data.x_import;
2312 AstNode *decl_node = find_decl(namespace_import->block_context, field_name);
2313 if (decl_node) {
2314 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
2315 if (tld->visib_mod == VisibModPrivate) {
2316 ErrorMsg *msg = add_node_error(g, node,
2317 buf_sprintf("'%s' is private", buf_ptr(field_name)));
2318 add_error_note(g, msg, decl_node, buf_sprintf("declared here"));
2319 }
2320 bool pointer_only = false;
2321 return analyze_decl_ref(g, node, decl_node, pointer_only);
2322 } else {
2323 add_node_error(g, node,
2324 buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name),
2325 buf_ptr(namespace_import->path)));
2326 return g->builtin_types.entry_invalid;
2327 }
2400 } else {2328 } else {
2401 if (struct_type->id != TypeTableEntryIdInvalid) {2329 if (struct_type->id != TypeTableEntryIdInvalid) {
2402 add_node_error(g, node,2330 add_node_error(g, node,
...@@ -2500,12 +2428,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode...@@ -2500,12 +2428,7 @@ static TypeTableEntry *resolve_expr_const_val_as_other_expr(CodeGen *g, AstNode
2500 return other_expr->type_entry;2428 return other_expr->type_entry;
2501}2429}
25022430
2503static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, BlockContext *context,2431static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, FnTableEntry *fn) {
2504 FnTableEntry *fn)
2505{
2506 if (!context->codegen_excluded) {
2507 fn->ref_count += 1;
2508 }
2509 Expr *expr = get_resolved_expr(node);2432 Expr *expr = get_resolved_expr(node);
2510 expr->const_val.ok = true;2433 expr->const_val.ok = true;
2511 expr->const_val.data.x_fn = fn;2434 expr->const_val.data.x_fn = fn;
...@@ -2635,7 +2558,7 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *...@@ -2635,7 +2558,7 @@ static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *
2635static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,2558static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
2636 BlockContext *context, AstNode *node, Buf *err_name)2559 BlockContext *context, AstNode *node, Buf *err_name)
2637{2560{
2638 auto err_table_entry = import->error_table.maybe_get(err_name);2561 auto err_table_entry = g->error_table.maybe_get(err_name);
26392562
2640 if (err_table_entry) {2563 if (err_table_entry) {
2641 return resolve_expr_const_val_as_err(g, node, err_table_entry->value);2564 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 *...@@ -2647,9 +2570,48 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
2647 return g->builtin_types.entry_invalid;2570 return g->builtin_types.entry_invalid;
2648}2571}
26492572
2573static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var) {
2574 get_resolved_expr(source_node)->variable = var;
2575 if (var->is_const) {
2576 AstNode *decl_node = var->decl_node;
2577 if (decl_node->type == NodeTypeVariableDeclaration) {
2578 AstNode *expr_node = decl_node->data.variable_declaration.expr;
2579 ConstExprValue *other_const_val = &get_resolved_expr(expr_node)->const_val;
2580 if (other_const_val->ok) {
2581 return resolve_expr_const_val_as_other_expr(g, source_node, expr_node);
2582 }
2583 }
2584 }
2585 return var->type;
2586}
2587
2588static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
2589 bool pointer_only)
2590{
2591 resolve_top_level_decl(g, decl_node, pointer_only);
2592 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
2593 if (tld->resolution == TldResolutionInvalid) {
2594 return g->builtin_types.entry_invalid;
2595 }
2596
2597 if (decl_node->type == NodeTypeVariableDeclaration) {
2598 VariableTableEntry *var = decl_node->data.variable_declaration.variable;
2599 return analyze_var_ref(g, source_node, var);
2600 } else if (decl_node->type == NodeTypeFnProto) {
2601 FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
2602 assert(fn_entry->type_entry);
2603 return resolve_expr_const_val_as_fn(g, source_node, fn_entry);
2604 } else if (decl_node->type == NodeTypeStructDecl) {
2605 return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry);
2606 } else if (decl_node->type == NodeTypeTypeDecl) {
2607 return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry);
2608 } else {
2609 zig_unreachable();
2610 }
2611}
26502612
2651static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2613static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2652 TypeTableEntry *expected_type, AstNode *node)2614 TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
2653{2615{
2654 if (node->data.symbol_expr.override_type_entry) {2616 if (node->data.symbol_expr.override_type_entry) {
2655 return resolve_expr_const_val_as_type(g, node, node->data.symbol_expr.override_type_entry);2617 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,...@@ -2662,32 +2624,14 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
2662 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);2624 return resolve_expr_const_val_as_type(g, node, primitive_table_entry->value);
2663 }2625 }
26642626
2665 VariableTableEntry *var = find_variable(context, variable_name, false);2627 VariableTableEntry *var = find_variable(g, context, variable_name);
2666 if (var) {2628 if (var) {
2667 node->data.symbol_expr.variable = var;2629 return analyze_var_ref(g, node, var);
2668 if (var->is_const) {
2669 AstNode *decl_node = var->decl_node;
2670 if (decl_node->type == NodeTypeVariableDeclaration) {
2671 AstNode *expr_node = decl_node->data.variable_declaration.expr;
2672 ConstExprValue *other_const_val = &get_resolved_expr(expr_node)->const_val;
2673 if (other_const_val->ok) {
2674 return resolve_expr_const_val_as_other_expr(g, node, expr_node);
2675 }
2676 }
2677 }
2678 return var->type;
2679 }
2680
2681 TypeTableEntry *container_type = find_container(import, variable_name);
2682 if (container_type) {
2683 return resolve_expr_const_val_as_type(g, node, container_type);
2684 }2630 }
26852631
2686 auto fn_table_entry = import->fn_table.maybe_get(variable_name);2632 AstNode *decl_node = find_decl(context, variable_name);
2687 if (fn_table_entry) {2633 if (decl_node) {
2688 assert(fn_table_entry->value->type_entry);2634 return analyze_decl_ref(g, node, decl_node, pointer_only);
2689 node->data.symbol_expr.fn_entry = fn_table_entry->value;
2690 return resolve_expr_const_val_as_fn(g, node, context, fn_table_entry->value);
2691 }2635 }
26922636
2693 if (import->any_imports_failed) {2637 if (import->any_imports_failed) {
...@@ -2760,18 +2704,21 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc...@@ -2760,18 +2704,21 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
2760 TypeTableEntry *expected_rhs_type = nullptr;2704 TypeTableEntry *expected_rhs_type = nullptr;
2761 lhs_node->block_context = block_context;2705 lhs_node->block_context = block_context;
2762 if (lhs_node->type == NodeTypeSymbol) {2706 if (lhs_node->type == NodeTypeSymbol) {
2763 Buf *name = &lhs_node->data.symbol_expr.symbol;2707 bool pointer_only = purpose == LValPurposeAddressOf;
2764 if (purpose == LValPurposeAddressOf) {2708 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node, pointer_only);
2765 expected_rhs_type = analyze_symbol_expr(g, import, block_context, nullptr, lhs_node);2709 if (expected_rhs_type->id == TypeTableEntryIdInvalid) {
2766 } else {2710 return g->builtin_types.entry_invalid;
2767 VariableTableEntry *var = find_variable(block_context, name, false);2711 }
2712 if (purpose != LValPurposeAddressOf) {
2713 Buf *name = &lhs_node->data.symbol_expr.symbol;
2714 VariableTableEntry *var = find_variable(g, block_context, name);
2768 if (var) {2715 if (var) {
2769 if (var->is_const) {2716 if (var->is_const) {
2770 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));2717 add_node_error(g, lhs_node, buf_sprintf("cannot assign to constant"));
2771 expected_rhs_type = g->builtin_types.entry_invalid;2718 expected_rhs_type = g->builtin_types.entry_invalid;
2772 } else {2719 } else {
2773 expected_rhs_type = var->type;2720 expected_rhs_type = var->type;
2774 lhs_node->data.symbol_expr.variable = var;2721 get_resolved_expr(lhs_node)->variable = var;
2775 }2722 }
2776 } else {2723 } else {
2777 add_node_error(g, lhs_node,2724 add_node_error(g, lhs_node,
...@@ -3176,29 +3123,36 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor...@@ -3176,29 +3123,36 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor
31763123
3177 if (name) {3124 if (name) {
3178 buf_init_from_buf(&variable_entry->name, name);3125 buf_init_from_buf(&variable_entry->name, name);
3179 VariableTableEntry *existing_var;
31803126
3181 existing_var = find_variable(context, name, context->fn_entry != nullptr);3127 if (type_entry->id != TypeTableEntryIdInvalid) {
31823128 VariableTableEntry *existing_var = find_variable(g, context, name);
3183 if (existing_var) {3129 if (existing_var) {
3184 add_node_error(g, source_node, buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3130 ErrorMsg *msg = add_node_error(g, source_node,
3185 variable_entry->type = g->builtin_types.entry_invalid;3131 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3186 } else {3132 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
3187 auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
3188 TypeTableEntry *type;
3189 if (primitive_table_entry) {
3190 type = primitive_table_entry->value;
3191 } else {
3192 type = find_container(import, name);
3193 }
3194 if (type) {
3195 add_node_error(g, source_node, buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
3196 variable_entry->type = g->builtin_types.entry_invalid;3133 variable_entry->type = g->builtin_types.entry_invalid;
3134 } else {
3135 auto primitive_table_entry = g->primitive_type_table.maybe_get(name);
3136 if (primitive_table_entry) {
3137 TypeTableEntry *type = primitive_table_entry->value;
3138 add_node_error(g, source_node,
3139 buf_sprintf("variable shadows type '%s'", buf_ptr(&type->name)));
3140 variable_entry->type = g->builtin_types.entry_invalid;
3141 } else {
3142 AstNode *decl_node = find_decl(context, name);
3143 if (decl_node && decl_node->type != NodeTypeVariableDeclaration) {
3144 ErrorMsg *msg = add_node_error(g, source_node,
3145 buf_sprintf("redefinition of '%s'", buf_ptr(name)));
3146 add_error_note(g, msg, decl_node, buf_sprintf("previous definition is here"));
3147 variable_entry->type = g->builtin_types.entry_invalid;
3148 }
3149 }
3197 }3150 }
3198 }3151 }
31993152
3200 context->variable_table.put(&variable_entry->name, variable_entry);3153 context->var_table.put(&variable_entry->name, variable_entry);
3201 } else {3154 } else {
3155 // TODO replace _anon with @anon and make sure all tests still pass
3202 buf_init_from_str(&variable_entry->name, "_anon");3156 buf_init_from_str(&variable_entry->name, "_anon");
3203 }3157 }
3204 if (context->fn_entry) {3158 if (context->fn_entry) {
...@@ -3248,10 +3202,10 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i...@@ -3248,10 +3202,10 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i
3248static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,3202static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
3249 BlockContext *context, AstNode *source_node,3203 BlockContext *context, AstNode *source_node,
3250 AstNodeVariableDeclaration *variable_declaration,3204 AstNodeVariableDeclaration *variable_declaration,
3251 bool expr_is_maybe)3205 bool expr_is_maybe, AstNode *decl_node)
3252{3206{
3253 bool is_const = variable_declaration->is_const;3207 bool is_const = variable_declaration->is_const;
3254 bool is_export = (variable_declaration->visib_mod == VisibModExport);3208 bool is_export = (variable_declaration->top_level_decl.visib_mod == VisibModExport);
3255 bool is_extern = variable_declaration->is_extern;3209 bool is_extern = variable_declaration->is_extern;
32563210
3257 TypeTableEntry *explicit_type = nullptr;3211 TypeTableEntry *explicit_type = nullptr;
...@@ -3312,22 +3266,6 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa...@@ -3312,22 +3266,6 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
33123266
3313 variable_declaration->variable = var;3267 variable_declaration->variable = var;
33143268
3315
3316 bool is_pub = (variable_declaration->visib_mod != VisibModPrivate);
3317 if (is_pub) {
3318 for (int i = 0; i < import->importers.length; i += 1) {
3319 ImporterInfo importer = import->importers.at(i);
3320 auto table_entry = importer.import->block_context->variable_table.maybe_get(&var->name);
3321 if (table_entry) {
3322 add_node_error(g, importer.source_node,
3323 buf_sprintf("import of variable '%s' overrides existing definition",
3324 buf_ptr(&var->name)));
3325 } else {
3326 importer.import->block_context->variable_table.put(&var->name, var);
3327 }
3328 }
3329 }
3330
3331 return var;3269 return var;
3332}3270}
33333271
...@@ -3335,7 +3273,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE...@@ -3335,7 +3273,7 @@ static VariableTableEntry *analyze_variable_declaration(CodeGen *g, ImportTableE
3335 BlockContext *context, TypeTableEntry *expected_type, AstNode *node)3273 BlockContext *context, TypeTableEntry *expected_type, AstNode *node)
3336{3274{
3337 AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;3275 AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration;
3338 return analyze_variable_declaration_raw(g, import, context, node, variable_declaration, false);3276 return analyze_variable_declaration_raw(g, import, context, node, variable_declaration, false, nullptr);
3339}3277}
33403278
3341static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *import,3279static TypeTableEntry *analyze_null_literal_expr(CodeGen *g, ImportTableEntry *import,
...@@ -3516,7 +3454,8 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl...@@ -3516,7 +3454,8 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
3516 AstNode *elem_var_node = node->data.for_expr.elem_node;3454 AstNode *elem_var_node = node->data.for_expr.elem_node;
3517 elem_var_node->block_context = child_context;3455 elem_var_node->block_context = child_context;
3518 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;3456 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;
3519 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name, child_type, true);3457 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name,
3458 child_type, true);
35203459
3521 AstNode *index_var_node = node->data.for_expr.index_node;3460 AstNode *index_var_node = node->data.for_expr.index_node;
3522 if (index_var_node) {3461 if (index_var_node) {
...@@ -3673,7 +3612,8 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,...@@ -3673,7 +3612,8 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
36733612
3674 BlockContext *child_context = new_block_context(node, parent_context);3613 BlockContext *child_context = new_block_context(node, parent_context);
36753614
3676 analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true);3615 analyze_variable_declaration_raw(g, import, child_context, node, &node->data.if_var_expr.var_decl, true,
3616 nullptr);
3677 VariableTableEntry *var = node->data.if_var_expr.var_decl.variable;3617 VariableTableEntry *var = node->data.if_var_expr.var_decl.variable;
3678 if (var->type->id == TypeTableEntryIdInvalid) {3618 if (var->type->id == TypeTableEntryIdInvalid) {
3679 return g->builtin_types.entry_invalid;3619 return g->builtin_types.entry_invalid;
...@@ -4069,39 +4009,178 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B...@@ -4069,39 +4009,178 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B
4069 return g->builtin_types.entry_invalid;4009 return g->builtin_types.entry_invalid;
4070}4010}
40714011
4072static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4012static TypeTableEntry *resolve_expr_const_val_as_import(CodeGen *g, AstNode *node, ImportTableEntry *import) {
4073 TypeTableEntry *expected_type, AstNode *node)4013 Expr *expr = get_resolved_expr(node);
4014 expr->const_val.ok = true;
4015 expr->const_val.data.x_import = import;
4016 return g->builtin_types.entry_namespace;
4017}
4018
4019static TypeTableEntry *analyze_import(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4020 AstNode *node)
4074{4021{
4075 assert(node->type == NodeTypeFnCallExpr);4022 assert(node->type == NodeTypeFnCallExpr);
40764023
4077 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;4024 if (context != import->block_context) {
4078 Buf *name = &fn_ref_expr->data.symbol_expr.symbol;4025 add_node_error(g, node, buf_sprintf("@import valid only at top level scope"));
40794026 return g->builtin_types.entry_invalid;
4080 auto entry = g->builtin_fn_table.maybe_get(name);4027 }
40814028
4082 if (!entry) {4029 AstNode *first_param_node = node->data.fn_call_expr.params.at(0);
4083 add_node_error(g, node,4030 Buf *import_target_str = resolve_const_expr_str(g, import, context, first_param_node->parent_field);
4084 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));4031 if (!import_target_str) {
4085 return g->builtin_types.entry_invalid;4032 return g->builtin_types.entry_invalid;
4086 }4033 }
40874034
4088 BuiltinFnEntry *builtin_fn = entry->value;4035 Buf *import_target_path;
4089 int actual_param_count = node->data.fn_call_expr.params.length;4036 Buf *search_dir;
4037 assert(import->package);
4038 PackageTableEntry *target_package;
4039 auto package_entry = import->package->package_table.maybe_get(import_target_str);
4040 if (package_entry) {
4041 target_package = package_entry->value;
4042 import_target_path = &target_package->root_src_path;
4043 search_dir = &target_package->root_src_dir;
4044 } else {
4045 // try it as a filename
4046 target_package = import->package;
4047 import_target_path = import_target_str;
4048 search_dir = &import->package->root_src_dir;
4049 }
40904050
4091 node->data.fn_call_expr.builtin_fn = builtin_fn;4051 Buf full_path = BUF_INIT;
4052 os_path_join(search_dir, import_target_path, &full_path);
40924053
4093 if (builtin_fn->param_count != actual_param_count) {4054 Buf *import_code = buf_alloc();
4094 add_node_error(g, node,4055 Buf *abs_full_path = buf_alloc();
4095 buf_sprintf("expected %d arguments, got %d",4056 int err;
4096 builtin_fn->param_count, actual_param_count));4057 if ((err = os_path_real(&full_path, abs_full_path))) {
4058 if (err == ErrorFileNotFound) {
4059 add_node_error(g, node,
4060 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
4061 return g->builtin_types.entry_invalid;
4062 } else {
4063 g->error_during_imports = true;
4064 add_node_error(g, node,
4065 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
4066 return g->builtin_types.entry_invalid;
4067 }
4068 }
4069
4070 auto import_entry = g->import_table.maybe_get(abs_full_path);
4071 if (import_entry) {
4072 return resolve_expr_const_val_as_import(g, node, import_entry->value);
4073 }
4074
4075 if ((err = os_fetch_file_path(abs_full_path, import_code))) {
4076 if (err == ErrorFileNotFound) {
4077 add_node_error(g, node,
4078 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
4079 return g->builtin_types.entry_invalid;
4080 } else {
4081 add_node_error(g, node,
4082 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
4083 return g->builtin_types.entry_invalid;
4084 }
4085 }
4086 ImportTableEntry *target_import = add_source_file(g, target_package,
4087 abs_full_path, search_dir, import_target_path, import_code);
4088
4089 scan_decls(g, target_import, target_import->block_context, target_import->root);
4090
4091 return resolve_expr_const_val_as_import(g, node, target_import);
4092}
4093
4094static TypeTableEntry *analyze_c_import(CodeGen *g, ImportTableEntry *parent_import,
4095 BlockContext *parent_context, AstNode *node)
4096{
4097 assert(node->type == NodeTypeFnCallExpr);
4098
4099 if (parent_context != parent_import->block_context) {
4100 add_node_error(g, node, buf_sprintf("@c_import valid only at top level scope"));
4097 return g->builtin_types.entry_invalid;4101 return g->builtin_types.entry_invalid;
4098 }4102 }
40994103
4100 builtin_fn->ref_count += 1;4104 AstNode *block_node = node->data.fn_call_expr.params.at(0);
41014105
4102 switch (builtin_fn->id) {4106 BlockContext *child_context = new_block_context(node, parent_context);
4103 case BuiltinFnIdInvalid:4107 child_context->c_import_buf = buf_alloc();
4104 zig_unreachable();4108
4109 TypeTableEntry *resolved_type = analyze_expression(g, parent_import, child_context,
4110 g->builtin_types.entry_void, block_node);
4111
4112 if (resolved_type->id == TypeTableEntryIdInvalid) {
4113 return resolved_type;
4114 }
4115
4116 find_libc_include_path(g);
4117
4118 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
4119 child_import->c_import_node = node;
4120
4121 ZigList<ErrorMsg *> errors = {0};
4122
4123 int err;
4124 if ((err = parse_h_buf(child_import, &errors, child_context->c_import_buf, g, node))) {
4125 zig_panic("unable to parse h file: %s\n", err_str(err));
4126 }
4127
4128 if (errors.length > 0) {
4129 ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
4130 for (int i = 0; i < errors.length; i += 1) {
4131 ErrorMsg *err_msg = errors.at(i);
4132 err_msg_add_note(parent_err_msg, err_msg);
4133 }
4134
4135 return g->builtin_types.entry_invalid;
4136 }
4137
4138 if (g->verbose) {
4139 fprintf(stderr, "\nc_import:\n");
4140 fprintf(stderr, "-----------\n");
4141 ast_render(stderr, child_import->root, 4);
4142 }
4143
4144 child_import->di_file = parent_import->di_file;
4145 child_import->block_context = new_block_context(child_import->root, nullptr);
4146
4147 scan_decls(g, child_import, child_import->block_context, child_import->root);
4148 return resolve_expr_const_val_as_import(g, node, child_import);
4149}
4150
4151static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4152 TypeTableEntry *expected_type, AstNode *node)
4153{
4154 assert(node->type == NodeTypeFnCallExpr);
4155
4156 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
4157 Buf *name = &fn_ref_expr->data.symbol_expr.symbol;
4158
4159 auto entry = g->builtin_fn_table.maybe_get(name);
4160
4161 if (!entry) {
4162 add_node_error(g, node,
4163 buf_sprintf("invalid builtin function: '%s'", buf_ptr(name)));
4164 return g->builtin_types.entry_invalid;
4165 }
4166
4167 BuiltinFnEntry *builtin_fn = entry->value;
4168 int actual_param_count = node->data.fn_call_expr.params.length;
4169
4170 node->data.fn_call_expr.builtin_fn = builtin_fn;
4171
4172 if (builtin_fn->param_count != actual_param_count) {
4173 add_node_error(g, node,
4174 buf_sprintf("expected %d arguments, got %d",
4175 builtin_fn->param_count, actual_param_count));
4176 return g->builtin_types.entry_invalid;
4177 }
4178
4179 builtin_fn->ref_count += 1;
4180
4181 switch (builtin_fn->id) {
4182 case BuiltinFnIdInvalid:
4183 zig_unreachable();
4105 case BuiltinFnIdAddWithOverflow:4184 case BuiltinFnIdAddWithOverflow:
4106 case BuiltinFnIdSubWithOverflow:4185 case BuiltinFnIdSubWithOverflow:
4107 case BuiltinFnIdMulWithOverflow:4186 case BuiltinFnIdMulWithOverflow:
...@@ -4252,6 +4331,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -4252,6 +4331,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
4252 case TypeTableEntryIdNumLitFloat:4331 case TypeTableEntryIdNumLitFloat:
4253 case TypeTableEntryIdNumLitInt:4332 case TypeTableEntryIdNumLitInt:
4254 case TypeTableEntryIdUndefLit:4333 case TypeTableEntryIdUndefLit:
4334 case TypeTableEntryIdNamespace:
4255 add_node_error(g, expr_node,4335 add_node_error(g, expr_node,
4256 buf_sprintf("type '%s' not eligible for @typeof", buf_ptr(&type_entry->name)));4336 buf_sprintf("type '%s' not eligible for @typeof", buf_ptr(&type_entry->name)));
4257 return g->builtin_types.entry_invalid;4337 return g->builtin_types.entry_invalid;
...@@ -4391,6 +4471,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -4391,6 +4471,10 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
4391 return g->builtin_types.entry_invalid;4471 return g->builtin_types.entry_invalid;
4392 }4472 }
4393 }4473 }
4474 case BuiltinFnIdImport:
4475 return analyze_import(g, import, context, node);
4476 case BuiltinFnIdCImport:
4477 return analyze_c_import(g, import, context, node);
43944478
4395 }4479 }
4396 zig_unreachable();4480 zig_unreachable();
...@@ -4456,12 +4540,7 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,...@@ -4456,12 +4540,7 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
44564540
4457 node->data.fn_call_expr.fn_entry = fn_table_entry;4541 node->data.fn_call_expr.fn_entry = fn_table_entry;
44584542
4459 if (!context->codegen_excluded) {
4460 fn_table_entry->ref_count += 1;
4461 }
4462
4463 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);4543 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
4464
4465}4544}
44664545
4467static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,4546static 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...@@ -4515,10 +4594,16 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
4515 }4594 }
4516 } else if (child_type->id == TypeTableEntryIdStruct) {4595 } else if (child_type->id == TypeTableEntryIdStruct) {
4517 Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;4596 Buf *field_name = &fn_ref_expr->data.field_access_expr.field_name;
4518 auto entry = child_type->data.structure.fn_table.maybe_get(field_name);4597 BlockContext *container_block_context = get_container_block_context(child_type);
4519 if (entry) {4598 auto entry = container_block_context->decl_table.maybe_get(field_name);
4520 return analyze_fn_call_raw(g, import, context, expected_type, node,4599 AstNode *decl_node = entry ? entry->value : nullptr;
4521 entry->value, nullptr);4600 if (decl_node && decl_node->type == NodeTypeFnProto) {
4601 bool pointer_only = false;
4602 resolve_top_level_decl(g, decl_node, pointer_only);
4603
4604 FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
4605 assert(fn_entry);
4606 return analyze_fn_call_raw(g, import, context, expected_type, node, fn_entry, nullptr);
4522 } else {4607 } else {
4523 add_node_error(g, node,4608 add_node_error(g, node,
4524 buf_sprintf("struct '%s' has no function called '%s'",4609 buf_sprintf("struct '%s' has no function called '%s'",
...@@ -4565,19 +4650,19 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4565,19 +4650,19 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4565 TypeTableEntry *expected_type, AstNode *node)4650 TypeTableEntry *expected_type, AstNode *node)
4566{4651{
4567 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;4652 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
4568 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;4653 AstNode **expr_node = &node->data.prefix_op_expr.primary_expr;
4569 switch (prefix_op) {4654 switch (prefix_op) {
4570 case PrefixOpInvalid:4655 case PrefixOpInvalid:
4571 zig_unreachable();4656 zig_unreachable();
4572 case PrefixOpBoolNot:4657 case PrefixOpBoolNot:
4573 {4658 {
4574 TypeTableEntry *type_entry = analyze_expression(g, import, context, g->builtin_types.entry_bool,4659 TypeTableEntry *type_entry = analyze_expression(g, import, context, g->builtin_types.entry_bool,
4575 expr_node);4660 *expr_node);
4576 if (type_entry->id == TypeTableEntryIdInvalid) {4661 if (type_entry->id == TypeTableEntryIdInvalid) {
4577 return g->builtin_types.entry_bool;4662 return g->builtin_types.entry_bool;
4578 }4663 }
45794664
4580 ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;4665 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
4581 if (!target_const_val->ok) {4666 if (!target_const_val->ok) {
4582 return g->builtin_types.entry_bool;4667 return g->builtin_types.entry_bool;
4583 }4668 }
...@@ -4588,7 +4673,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4588,7 +4673,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4588 case PrefixOpBinNot:4673 case PrefixOpBinNot:
4589 {4674 {
4590 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,4675 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
4591 expr_node);4676 *expr_node);
4592 if (expr_type->id == TypeTableEntryIdInvalid) {4677 if (expr_type->id == TypeTableEntryIdInvalid) {
4593 return expr_type;4678 return expr_type;
4594 } else if (expr_type->id == TypeTableEntryIdInt ||4679 } else if (expr_type->id == TypeTableEntryIdInt ||
...@@ -4596,7 +4681,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4596,7 +4681,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4596 {4681 {
4597 return expr_type;4682 return expr_type;
4598 } else {4683 } else {
4599 add_node_error(g, expr_node, buf_sprintf("invalid binary not type: '%s'",4684 add_node_error(g, *expr_node, buf_sprintf("invalid binary not type: '%s'",
4600 buf_ptr(&expr_type->name)));4685 buf_ptr(&expr_type->name)));
4601 return g->builtin_types.entry_invalid;4686 return g->builtin_types.entry_invalid;
4602 }4687 }
...@@ -4604,8 +4689,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4604,8 +4689,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4604 }4689 }
4605 case PrefixOpNegation:4690 case PrefixOpNegation:
4606 {4691 {
4607 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,4692 TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type, *expr_node);
4608 expr_node);
4609 if (expr_type->id == TypeTableEntryIdInvalid) {4693 if (expr_type->id == TypeTableEntryIdInvalid) {
4610 return expr_type;4694 return expr_type;
4611 } else if ((expr_type->id == TypeTableEntryIdInt &&4695 } else if ((expr_type->id == TypeTableEntryIdInt &&
...@@ -4614,7 +4698,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4614,7 +4698,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4614 expr_type->id == TypeTableEntryIdNumLitInt ||4698 expr_type->id == TypeTableEntryIdNumLitInt ||
4615 expr_type->id == TypeTableEntryIdNumLitFloat)4699 expr_type->id == TypeTableEntryIdNumLitFloat)
4616 {4700 {
4617 ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;4701 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
4618 if (!target_const_val->ok) {4702 if (!target_const_val->ok) {
4619 return expr_type;4703 return expr_type;
4620 }4704 }
...@@ -4635,12 +4719,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4635,12 +4719,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4635 bool is_const = (prefix_op == PrefixOpConstAddressOf);4719 bool is_const = (prefix_op == PrefixOpConstAddressOf);
46364720
4637 TypeTableEntry *child_type = analyze_lvalue(g, import, context,4721 TypeTableEntry *child_type = analyze_lvalue(g, import, context,
4638 expr_node, LValPurposeAddressOf, is_const);4722 *expr_node, LValPurposeAddressOf, is_const);
46394723
4640 if (child_type->id == TypeTableEntryIdInvalid) {4724 if (child_type->id == TypeTableEntryIdInvalid) {
4641 return g->builtin_types.entry_invalid;4725 return g->builtin_types.entry_invalid;
4642 } else if (child_type->id == TypeTableEntryIdMetaType) {4726 } else if (child_type->id == TypeTableEntryIdMetaType) {
4643 TypeTableEntry *meta_type = analyze_type_expr(g, import, context, expr_node);4727 TypeTableEntry *meta_type = analyze_type_expr_pointer_only(g, import, context,
4728 *expr_node, true);
4644 if (meta_type->id == TypeTableEntryIdInvalid) {4729 if (meta_type->id == TypeTableEntryIdInvalid) {
4645 return g->builtin_types.entry_invalid;4730 return g->builtin_types.entry_invalid;
4646 } else if (meta_type->id == TypeTableEntryIdUnreachable) {4731 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
...@@ -4653,7 +4738,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4653,7 +4738,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4653 } else if (child_type->id == TypeTableEntryIdNumLitInt ||4738 } else if (child_type->id == TypeTableEntryIdNumLitInt ||
4654 child_type->id == TypeTableEntryIdNumLitFloat)4739 child_type->id == TypeTableEntryIdNumLitFloat)
4655 {4740 {
4656 add_node_error(g, expr_node,4741 add_node_error(g, *expr_node,
4657 buf_sprintf("unable to get address of type '%s'", buf_ptr(&child_type->name)));4742 buf_sprintf("unable to get address of type '%s'", buf_ptr(&child_type->name)));
4658 return g->builtin_types.entry_invalid;4743 return g->builtin_types.entry_invalid;
4659 } else {4744 } else {
...@@ -4662,13 +4747,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4662,13 +4747,13 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4662 }4747 }
4663 case PrefixOpDereference:4748 case PrefixOpDereference:
4664 {4749 {
4665 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);4750 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
4666 if (type_entry->id == TypeTableEntryIdInvalid) {4751 if (type_entry->id == TypeTableEntryIdInvalid) {
4667 return type_entry;4752 return type_entry;
4668 } else if (type_entry->id == TypeTableEntryIdPointer) {4753 } else if (type_entry->id == TypeTableEntryIdPointer) {
4669 return type_entry->data.pointer.child_type;4754 return type_entry->data.pointer.child_type;
4670 } else {4755 } else {
4671 add_node_error(g, expr_node,4756 add_node_error(g, *expr_node,
4672 buf_sprintf("indirection requires pointer operand ('%s' invalid)",4757 buf_sprintf("indirection requires pointer operand ('%s' invalid)",
4673 buf_ptr(&type_entry->name)));4758 buf_ptr(&type_entry->name)));
4674 return g->builtin_types.entry_invalid;4759 return g->builtin_types.entry_invalid;
...@@ -4676,12 +4761,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4676,12 +4761,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4676 }4761 }
4677 case PrefixOpMaybe:4762 case PrefixOpMaybe:
4678 {4763 {
4679 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);4764 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
46804765
4681 if (type_entry->id == TypeTableEntryIdInvalid) {4766 if (type_entry->id == TypeTableEntryIdInvalid) {
4682 return type_entry;4767 return type_entry;
4683 } else if (type_entry->id == TypeTableEntryIdMetaType) {4768 } else if (type_entry->id == TypeTableEntryIdMetaType) {
4684 TypeTableEntry *meta_type = resolve_type(g, expr_node);4769 TypeTableEntry *meta_type = resolve_type(g, *expr_node);
4685 if (meta_type->id == TypeTableEntryIdInvalid) {4770 if (meta_type->id == TypeTableEntryIdInvalid) {
4686 return g->builtin_types.entry_invalid;4771 return g->builtin_types.entry_invalid;
4687 } else if (meta_type->id == TypeTableEntryIdUnreachable) {4772 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
...@@ -4691,10 +4776,10 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4691,10 +4776,10 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4691 return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type));4776 return resolve_expr_const_val_as_type(g, node, get_maybe_type(g, meta_type));
4692 }4777 }
4693 } else if (type_entry->id == TypeTableEntryIdUnreachable) {4778 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
4694 add_node_error(g, expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));4779 add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in maybe type"));
4695 return g->builtin_types.entry_invalid;4780 return g->builtin_types.entry_invalid;
4696 } else {4781 } else {
4697 ConstExprValue *target_const_val = &get_resolved_expr(expr_node)->const_val;4782 ConstExprValue *target_const_val = &get_resolved_expr(*expr_node)->const_val;
4698 TypeTableEntry *maybe_type = get_maybe_type(g, type_entry);4783 TypeTableEntry *maybe_type = get_maybe_type(g, type_entry);
4699 if (!target_const_val->ok) {4784 if (!target_const_val->ok) {
4700 return maybe_type;4785 return maybe_type;
...@@ -4704,12 +4789,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4704,12 +4789,12 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4704 }4789 }
4705 case PrefixOpError:4790 case PrefixOpError:
4706 {4791 {
4707 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);4792 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
47084793
4709 if (type_entry->id == TypeTableEntryIdInvalid) {4794 if (type_entry->id == TypeTableEntryIdInvalid) {
4710 return type_entry;4795 return type_entry;
4711 } else if (type_entry->id == TypeTableEntryIdMetaType) {4796 } else if (type_entry->id == TypeTableEntryIdMetaType) {
4712 TypeTableEntry *meta_type = resolve_type(g, expr_node);4797 TypeTableEntry *meta_type = resolve_type(g, *expr_node);
4713 if (meta_type->id == TypeTableEntryIdInvalid) {4798 if (meta_type->id == TypeTableEntryIdInvalid) {
4714 return meta_type;4799 return meta_type;
4715 } else if (meta_type->id == TypeTableEntryIdUnreachable) {4800 } else if (meta_type->id == TypeTableEntryIdUnreachable) {
...@@ -4719,7 +4804,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4719,7 +4804,7 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4719 return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type));4804 return resolve_expr_const_val_as_type(g, node, get_error_type(g, meta_type));
4720 }4805 }
4721 } else if (type_entry->id == TypeTableEntryIdUnreachable) {4806 } else if (type_entry->id == TypeTableEntryIdUnreachable) {
4722 add_node_error(g, expr_node, buf_sprintf("unable to wrap unreachable in error type"));4807 add_node_error(g, *expr_node, buf_sprintf("unable to wrap unreachable in error type"));
4723 return g->builtin_types.entry_invalid;4808 return g->builtin_types.entry_invalid;
4724 } else {4809 } else {
4725 // TODO eval const expr4810 // TODO eval const expr
...@@ -4729,28 +4814,28 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo...@@ -4729,28 +4814,28 @@ static TypeTableEntry *analyze_prefix_op_expr(CodeGen *g, ImportTableEntry *impo
4729 }4814 }
4730 case PrefixOpUnwrapError:4815 case PrefixOpUnwrapError:
4731 {4816 {
4732 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);4817 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
47334818
4734 if (type_entry->id == TypeTableEntryIdInvalid) {4819 if (type_entry->id == TypeTableEntryIdInvalid) {
4735 return type_entry;4820 return type_entry;
4736 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {4821 } else if (type_entry->id == TypeTableEntryIdErrorUnion) {
4737 return type_entry->data.error.child_type;4822 return type_entry->data.error.child_type;
4738 } else {4823 } else {
4739 add_node_error(g, expr_node,4824 add_node_error(g, *expr_node,
4740 buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));4825 buf_sprintf("expected error type, got '%s'", buf_ptr(&type_entry->name)));
4741 return g->builtin_types.entry_invalid;4826 return g->builtin_types.entry_invalid;
4742 }4827 }
4743 }4828 }
4744 case PrefixOpUnwrapMaybe:4829 case PrefixOpUnwrapMaybe:
4745 {4830 {
4746 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, expr_node);4831 TypeTableEntry *type_entry = analyze_expression(g, import, context, nullptr, *expr_node);
47474832
4748 if (type_entry->id == TypeTableEntryIdInvalid) {4833 if (type_entry->id == TypeTableEntryIdInvalid) {
4749 return type_entry;4834 return type_entry;
4750 } else if (type_entry->id == TypeTableEntryIdMaybe) {4835 } else if (type_entry->id == TypeTableEntryIdMaybe) {
4751 return type_entry->data.maybe.child_type;4836 return type_entry->data.maybe.child_type;
4752 } else {4837 } else {
4753 add_node_error(g, expr_node,4838 add_node_error(g, *expr_node,
4754 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));4839 buf_sprintf("expected maybe type, got '%s'", buf_ptr(&type_entry->name)));
4755 return g->builtin_types.entry_invalid;4840 return g->builtin_types.entry_invalid;
4756 }4841 }
...@@ -5094,7 +5179,7 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl...@@ -5094,7 +5179,7 @@ static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, Bl
5094 }5179 }
5095 } else {5180 } else {
5096 Buf *variable_name = &asm_output->variable_name;5181 Buf *variable_name = &asm_output->variable_name;
5097 VariableTableEntry *var = find_variable(context, variable_name, false);5182 VariableTableEntry *var = find_variable(g, context, variable_name);
5098 if (var) {5183 if (var) {
5099 asm_output->variable = var;5184 asm_output->variable = var;
5100 return var->type;5185 return var->type;
...@@ -5120,10 +5205,8 @@ static TypeTableEntry *analyze_goto(CodeGen *g, ImportTableEntry *import, BlockC...@@ -5120,10 +5205,8 @@ static TypeTableEntry *analyze_goto(CodeGen *g, ImportTableEntry *import, BlockC
5120 return g->builtin_types.entry_unreachable;5205 return g->builtin_types.entry_unreachable;
5121}5206}
51225207
5123// When you call analyze_expression, the node you pass might no longer be the child node5208static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEntry *import,
5124// you thought it was due to implicit casting rewriting the AST.5209 BlockContext *context, TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
5125static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5126 TypeTableEntry *expected_type, AstNode *node)
5127{5210{
5128 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);5211 assert(!expected_type || expected_type->id != TypeTableEntryIdInvalid);
5129 TypeTableEntry *return_type = nullptr;5212 TypeTableEntry *return_type = nullptr;
...@@ -5197,7 +5280,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -5197,7 +5280,7 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
5197 return_type = analyze_undefined_literal_expr(g, import, context, expected_type, node);5280 return_type = analyze_undefined_literal_expr(g, import, context, expected_type, node);
5198 break;5281 break;
5199 case NodeTypeSymbol:5282 case NodeTypeSymbol:
5200 return_type = analyze_symbol_expr(g, import, context, expected_type, node);5283 return_type = analyze_symbol_expr(g, import, context, expected_type, node, pointer_only);
5201 break;5284 break;
5202 case NodeTypePrefixOpExpr:5285 case NodeTypePrefixOpExpr:
5203 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);5286 return_type = analyze_prefix_op_expr(g, import, context, expected_type, node);
...@@ -5235,10 +5318,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -5235,10 +5318,8 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
5235 case NodeTypeFnDecl:5318 case NodeTypeFnDecl:
5236 case NodeTypeParamDecl:5319 case NodeTypeParamDecl:
5237 case NodeTypeRoot:5320 case NodeTypeRoot:
5238 case NodeTypeRootExportDecl:
5239 case NodeTypeFnDef:5321 case NodeTypeFnDef:
5240 case NodeTypeImport:5322 case NodeTypeUse:
5241 case NodeTypeCImport:
5242 case NodeTypeLabel:5323 case NodeTypeLabel:
5243 case NodeTypeStructDecl:5324 case NodeTypeStructDecl:
5244 case NodeTypeStructField:5325 case NodeTypeStructField:
...@@ -5263,7 +5344,17 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,...@@ -5263,7 +5344,17 @@ static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import,
5263 return resolved_type;5344 return resolved_type;
5264}5345}
52655346
5266static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNode *node) {5347// When you call analyze_expression, the node you pass might no longer be the child node
5348// you thought it was due to implicit casting rewriting the AST.
5349static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
5350 TypeTableEntry *expected_type, AstNode *node)
5351{
5352 return analyze_expression_pointer_only(g, import, context, expected_type, node, false);
5353}
5354
5355static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
5356 ImportTableEntry *import = fn_table_entry->import_entry;
5357 AstNode *node = fn_table_entry->fn_def_node;
5267 assert(node->type == NodeTypeFnDef);5358 assert(node->type == NodeTypeFnDef);
52685359
5269 AstNode *fn_proto_node = node->data.fn_def.fn_proto;5360 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...@@ -5277,7 +5368,6 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
52775368
5278 BlockContext *context = node->data.fn_def.block_context;5369 BlockContext *context = node->data.fn_def.block_context;
52795370
5280 FnTableEntry *fn_table_entry = fn_proto_node->data.fn_proto.fn_table_entry;
5281 TypeTableEntry *fn_type = fn_table_entry->type_entry;5371 TypeTableEntry *fn_type = fn_table_entry->type_entry;
5282 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;5372 AstNodeFnProto *fn_proto = &fn_proto_node->data.fn_proto;
5283 for (int i = 0; i < fn_proto->params.length; i += 1) {5373 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...@@ -5302,7 +5392,8 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
5302 add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));5392 add_node_error(g, param_decl_node, buf_sprintf("missing parameter name"));
5303 }5393 }
53045394
5305 VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, &param_decl->name, type, true);5395 VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, &param_decl->name,
5396 type, true);
5306 var->src_arg_index = i;5397 var->src_arg_index = i;
5307 param_decl_node->data.param_decl.variable = var;5398 param_decl_node->data.param_decl.variable = var;
53085399
...@@ -5315,375 +5406,71 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo...@@ -5315,375 +5406,71 @@ static void analyze_top_level_fn_def(CodeGen *g, ImportTableEntry *import, AstNo
5315 node->data.fn_def.implicit_return_type = block_return_type;5406 node->data.fn_def.implicit_return_type = block_return_type;
5316}5407}
53175408
5318static void analyze_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {5409static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
5319 switch (node->type) {5410 AstNode *node, Buf *name)
5320 case NodeTypeFnDef:5411{
5321 analyze_top_level_fn_def(g, import, node);5412 assert(import);
5322 break;5413
5323 case NodeTypeStructDecl:5414 TopLevelDecl *tld = get_as_top_level_decl(node);
5324 {5415 tld->import = import;
5325 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {5416 tld->name = name;
5326 AstNode *fn_def_node = node->data.struct_decl.fns.at(i);5417
5327 analyze_top_level_fn_def(g, import, fn_def_node);5418 if (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport) {
5328 }5419 g->export_queue.append(node);
5329 break;
5330 }
5331 case NodeTypeRootExportDecl:
5332 case NodeTypeImport:
5333 case NodeTypeCImport:
5334 case NodeTypeVariableDeclaration:
5335 case NodeTypeErrorValueDecl:
5336 case NodeTypeFnProto:
5337 case NodeTypeTypeDecl:
5338 // already took care of these
5339 break;
5340 case NodeTypeDirective:
5341 case NodeTypeParamDecl:
5342 case NodeTypeFnDecl:
5343 case NodeTypeReturnExpr:
5344 case NodeTypeDefer:
5345 case NodeTypeRoot:
5346 case NodeTypeBlock:
5347 case NodeTypeBinOpExpr:
5348 case NodeTypeUnwrapErrorExpr:
5349 case NodeTypeFnCallExpr:
5350 case NodeTypeArrayAccessExpr:
5351 case NodeTypeSliceExpr:
5352 case NodeTypeNumberLiteral:
5353 case NodeTypeStringLiteral:
5354 case NodeTypeCharLiteral:
5355 case NodeTypeBoolLiteral:
5356 case NodeTypeNullLiteral:
5357 case NodeTypeUndefinedLiteral:
5358 case NodeTypeSymbol:
5359 case NodeTypePrefixOpExpr:
5360 case NodeTypeIfBoolExpr:
5361 case NodeTypeIfVarExpr:
5362 case NodeTypeWhileExpr:
5363 case NodeTypeForExpr:
5364 case NodeTypeSwitchExpr:
5365 case NodeTypeSwitchProng:
5366 case NodeTypeSwitchRange:
5367 case NodeTypeLabel:
5368 case NodeTypeGoto:
5369 case NodeTypeBreak:
5370 case NodeTypeContinue:
5371 case NodeTypeAsmExpr:
5372 case NodeTypeFieldAccessExpr:
5373 case NodeTypeStructField:
5374 case NodeTypeStructValueField:
5375 case NodeTypeContainerInitExpr:
5376 case NodeTypeArrayType:
5377 case NodeTypeErrorType:
5378 case NodeTypeTypeLiteral:
5379 zig_unreachable();
5380 }5420 }
5381}
53825421
5383static void collect_expr_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node,5422 node->block_context = block_context;
5384 TopLevelDecl *decl_node)5423
5385{5424 auto entry = block_context->decl_table.maybe_get(name);
5386 switch (node->type) {5425 if (entry) {
5387 case NodeTypeNumberLiteral:5426 AstNode *other_decl_node = entry->value;
5388 case NodeTypeStringLiteral:5427 ErrorMsg *msg = add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
5389 case NodeTypeCharLiteral:5428 add_error_note(g, msg, other_decl_node, buf_sprintf("previous definition is here"));
5390 case NodeTypeBoolLiteral:5429 } else {
5391 case NodeTypeNullLiteral:5430 block_context->decl_table.put(name, node);
5392 case NodeTypeUndefinedLiteral:
5393 case NodeTypeGoto:
5394 case NodeTypeBreak:
5395 case NodeTypeContinue:
5396 case NodeTypeErrorValueDecl:
5397 case NodeTypeErrorType:
5398 case NodeTypeTypeLiteral:
5399 // no dependencies on other top level declarations
5400 break;
5401 case NodeTypeSymbol:
5402 {
5403 if (node->data.symbol_expr.override_type_entry) {
5404 break;
5405 }
5406 Buf *name = &node->data.symbol_expr.symbol;
5407 auto table_entry = g->primitive_type_table.maybe_get(name);
5408 if (!table_entry) {
5409 table_entry = import->type_table.maybe_get(name);
5410 }
5411 if (!table_entry || !type_is_complete(table_entry->value)) {
5412 decl_node->deps.put(name, node);
5413 }
5414 break;
5415 }
5416 case NodeTypeBinOpExpr:
5417 collect_expr_decl_deps(g, import, node->data.bin_op_expr.op1, decl_node);
5418 collect_expr_decl_deps(g, import, node->data.bin_op_expr.op2, decl_node);
5419 break;
5420 case NodeTypeUnwrapErrorExpr:
5421 collect_expr_decl_deps(g, import, node->data.unwrap_err_expr.op1, decl_node);
5422 collect_expr_decl_deps(g, import, node->data.unwrap_err_expr.op2, decl_node);
5423 break;
5424 case NodeTypeReturnExpr:
5425 collect_expr_decl_deps(g, import, node->data.return_expr.expr, decl_node);
5426 break;
5427 case NodeTypeDefer:
5428 collect_expr_decl_deps(g, import, node->data.defer.expr, decl_node);
5429 break;
5430 case NodeTypePrefixOpExpr:
5431 collect_expr_decl_deps(g, import, node->data.prefix_op_expr.primary_expr, decl_node);
5432 break;
5433 case NodeTypeFnCallExpr:
5434 if (!node->data.fn_call_expr.is_builtin) {
5435 collect_expr_decl_deps(g, import, node->data.fn_call_expr.fn_ref_expr, decl_node);
5436 }
5437 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
5438 AstNode *arg_node = node->data.fn_call_expr.params.at(i);
5439 collect_expr_decl_deps(g, import, arg_node, decl_node);
5440 }
5441 break;
5442 case NodeTypeArrayAccessExpr:
5443 collect_expr_decl_deps(g, import, node->data.array_access_expr.array_ref_expr, decl_node);
5444 collect_expr_decl_deps(g, import, node->data.array_access_expr.subscript, decl_node);
5445 break;
5446 case NodeTypeSliceExpr:
5447 collect_expr_decl_deps(g, import, node->data.slice_expr.array_ref_expr, decl_node);
5448 collect_expr_decl_deps(g, import, node->data.slice_expr.start, decl_node);
5449 if (node->data.slice_expr.end) {
5450 collect_expr_decl_deps(g, import, node->data.slice_expr.end, decl_node);
5451 }
5452 break;
5453 case NodeTypeFieldAccessExpr:
5454 collect_expr_decl_deps(g, import, node->data.field_access_expr.struct_expr, decl_node);
5455 break;
5456 case NodeTypeIfBoolExpr:
5457 collect_expr_decl_deps(g, import, node->data.if_bool_expr.condition, decl_node);
5458 collect_expr_decl_deps(g, import, node->data.if_bool_expr.then_block, decl_node);
5459 if (node->data.if_bool_expr.else_node) {
5460 collect_expr_decl_deps(g, import, node->data.if_bool_expr.else_node, decl_node);
5461 }
5462 break;
5463 case NodeTypeIfVarExpr:
5464 if (node->data.if_var_expr.var_decl.type) {
5465 collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.type, decl_node);
5466 }
5467 if (node->data.if_var_expr.var_decl.expr) {
5468 collect_expr_decl_deps(g, import, node->data.if_var_expr.var_decl.expr, decl_node);
5469 }
5470 collect_expr_decl_deps(g, import, node->data.if_var_expr.then_block, decl_node);
5471 if (node->data.if_bool_expr.else_node) {
5472 collect_expr_decl_deps(g, import, node->data.if_var_expr.else_node, decl_node);
5473 }
5474 break;
5475 case NodeTypeWhileExpr:
5476 collect_expr_decl_deps(g, import, node->data.while_expr.condition, decl_node);
5477 collect_expr_decl_deps(g, import, node->data.while_expr.body, decl_node);
5478 break;
5479 case NodeTypeForExpr:
5480 collect_expr_decl_deps(g, import, node->data.for_expr.array_expr, decl_node);
5481 collect_expr_decl_deps(g, import, node->data.for_expr.body, decl_node);
5482 break;
5483 case NodeTypeBlock:
5484 for (int i = 0; i < node->data.block.statements.length; i += 1) {
5485 AstNode *stmt = node->data.block.statements.at(i);
5486 collect_expr_decl_deps(g, import, stmt, decl_node);
5487 }
5488 break;
5489 case NodeTypeAsmExpr:
5490 for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
5491 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
5492 if (asm_output->return_type) {
5493 collect_expr_decl_deps(g, import, asm_output->return_type, decl_node);
5494 } else {
5495 decl_node->deps.put(&asm_output->variable_name, node);
5496 }
5497 }
5498 for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
5499 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
5500 collect_expr_decl_deps(g, import, asm_input->expr, decl_node);
5501 }
5502 break;
5503 case NodeTypeContainerInitExpr:
5504 collect_expr_decl_deps(g, import, node->data.container_init_expr.type, decl_node);
5505 for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
5506 AstNode *child_node = node->data.container_init_expr.entries.at(i);
5507 collect_expr_decl_deps(g, import, child_node, decl_node);
5508 }
5509 break;
5510 case NodeTypeStructValueField:
5511 collect_expr_decl_deps(g, import, node->data.struct_val_field.expr, decl_node);
5512 break;
5513 case NodeTypeArrayType:
5514 if (node->data.array_type.size) {
5515 collect_expr_decl_deps(g, import, node->data.array_type.size, decl_node);
5516 }
5517 collect_expr_decl_deps(g, import, node->data.array_type.child_type, decl_node);
5518 break;
5519 case NodeTypeSwitchExpr:
5520 collect_expr_decl_deps(g, import, node->data.switch_expr.expr, decl_node);
5521 for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
5522 AstNode *prong = node->data.switch_expr.prongs.at(i);
5523 collect_expr_decl_deps(g, import, prong, decl_node);
5524 }
5525 break;
5526 case NodeTypeSwitchProng:
5527 for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
5528 AstNode *child = node->data.switch_prong.items.at(i);
5529 collect_expr_decl_deps(g, import, child, decl_node);
5530 }
5531 collect_expr_decl_deps(g, import, node->data.switch_prong.expr, decl_node);
5532 break;
5533 case NodeTypeSwitchRange:
5534 collect_expr_decl_deps(g, import, node->data.switch_range.start, decl_node);
5535 collect_expr_decl_deps(g, import, node->data.switch_range.end, decl_node);
5536 break;
5537 case NodeTypeFnProto:
5538 // remember that fn proto node is used for function definitions as well
5539 // as types
5540 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
5541 AstNode *param = node->data.fn_proto.params.at(i);
5542 collect_expr_decl_deps(g, import, param, decl_node);
5543 }
5544 if (node->data.fn_proto.directives) {
5545 for (int i = 0; i < node->data.fn_proto.directives->length; i += 1) {
5546 AstNode *directive = node->data.fn_proto.directives->at(i);
5547 collect_expr_decl_deps(g, import, directive, decl_node);
5548 }
5549 }
5550 collect_expr_decl_deps(g, import, node->data.fn_proto.return_type, decl_node);
5551 break;
5552 case NodeTypeParamDecl:
5553 collect_expr_decl_deps(g, import, node->data.param_decl.type, decl_node);
5554 break;
5555 case NodeTypeTypeDecl:
5556 collect_expr_decl_deps(g, import, node->data.type_decl.child_type, decl_node);
5557 break;
5558 case NodeTypeDirective:
5559 collect_expr_decl_deps(g, import, node->data.directive.expr, decl_node);
5560 break;
5561 case NodeTypeVariableDeclaration:
5562 case NodeTypeRootExportDecl:
5563 case NodeTypeFnDef:
5564 case NodeTypeRoot:
5565 case NodeTypeFnDecl:
5566 case NodeTypeImport:
5567 case NodeTypeCImport:
5568 case NodeTypeLabel:
5569 case NodeTypeStructDecl:
5570 case NodeTypeStructField:
5571 zig_unreachable();
5572 }5431 }
5573}5432}
55745433
5575static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, AstNode *node) {5434static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {
5576 switch (node->type) {5435 switch (node->type) {
5577 case NodeTypeRoot:5436 case NodeTypeRoot:
5578 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {5437 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {
5579 AstNode *child = import->root->data.root.top_level_decls.at(i);5438 AstNode *child = import->root->data.root.top_level_decls.at(i);
5580 detect_top_level_decl_deps(g, import, child);5439 scan_decls(g, import, context, child);
5581 }5440 }
5582 break;5441 break;
5583 case NodeTypeStructDecl:5442 case NodeTypeStructDecl:
5584 {5443 {
5585 Buf *name = &node->data.struct_decl.name;5444 Buf *name = &node->data.struct_decl.name;
5586 auto table_entry = g->primitive_type_table.maybe_get(name);5445 TypeTableEntry *container_type = get_partial_container_type(g, import,
5587 if (!table_entry) {5446 node->data.struct_decl.kind, node, buf_ptr(name));
5588 table_entry = import->type_table.maybe_get(name);5447 node->data.struct_decl.type_entry = container_type;
5589 }5448 add_top_level_decl(g, import, context, node, name);
5590 if (table_entry) {
5591 node->data.struct_decl.type_entry = table_entry->value;
5592 add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name)));
5593 } else {
5594 TypeTableEntry *entry;
5595 if (node->data.struct_decl.type_entry) {
5596 entry = node->data.struct_decl.type_entry;
5597 } else {
5598 entry = get_partial_container_type(g, import,
5599 node->data.struct_decl.kind, node, buf_ptr(name));
5600 }
5601
5602 import->type_table.put(&entry->name, entry);
5603 node->data.struct_decl.type_entry = entry;
5604
5605 bool is_pub = (node->data.struct_decl.visib_mod != VisibModPrivate);
5606 if (is_pub) {
5607 for (int i = 0; i < import->importers.length; i += 1) {
5608 ImporterInfo importer = import->importers.at(i);
5609 auto table_entry = importer.import->type_table.maybe_get(&entry->name);
5610 if (table_entry) {
5611 add_node_error(g, importer.source_node,
5612 buf_sprintf("import of type '%s' overrides existing definition",
5613 buf_ptr(&entry->name)));
5614 } else {
5615 importer.import->type_table.put(&entry->name, entry);
5616 }
5617 }
5618 }
5619 }
5620
5621 // determine which other top level declarations this struct depends on.
5622 TopLevelDecl *decl_node = &node->data.struct_decl.top_level_decl;
5623 decl_node->deps.init(1);
5624 for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
5625 AstNode *field_node = node->data.struct_decl.fields.at(i);
5626 AstNode *type_node = field_node->data.struct_field.type;
5627 collect_expr_decl_deps(g, import, type_node, decl_node);
5628 }
5629 decl_node->name = name;
5630 decl_node->import = import;
5631 if (decl_node->deps.size() > 0) {
5632 g->unresolved_top_level_decls.put(name, node);
5633 } else {
5634 resolve_top_level_decl(g, import, node);
5635 }
56365449
5637 // handle the member function definitions independently5450 // handle the member function definitions independently
5638 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {5451 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
5639 AstNode *fn_def_node = node->data.struct_decl.fns.at(i);5452 AstNode *child_node = node->data.struct_decl.fns.at(i);
5640 AstNode *fn_proto_node = fn_def_node->data.fn_def.fn_proto;5453 get_as_top_level_decl(child_node)->parent_decl = node;
5641 fn_proto_node->data.fn_proto.struct_node = node;5454 BlockContext *child_context = get_container_block_context(container_type);
5642 detect_top_level_decl_deps(g, import, fn_def_node);5455 scan_decls(g, import, child_context, child_node);
5643 }5456 }
56445457
5645 break;5458 break;
5646 }5459 }
5647 case NodeTypeFnDef:5460 case NodeTypeFnDef:
5648 node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;5461 node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node;
5649 detect_top_level_decl_deps(g, import, node->data.fn_def.fn_proto);5462 scan_decls(g, import, context, node->data.fn_def.fn_proto);
5650 break;5463 break;
5651 case NodeTypeVariableDeclaration:5464 case NodeTypeVariableDeclaration:
5652 {5465 {
5653 // determine which other top level declarations this variable declaration depends on.
5654 TopLevelDecl *decl_node = &node->data.variable_declaration.top_level_decl;
5655 decl_node->deps.init(1);
5656 if (node->data.variable_declaration.type) {
5657 collect_expr_decl_deps(g, import, node->data.variable_declaration.type, decl_node);
5658 }
5659 if (node->data.variable_declaration.expr) {
5660 collect_expr_decl_deps(g, import, node->data.variable_declaration.expr, decl_node);
5661 }
5662 Buf *name = &node->data.variable_declaration.symbol;5466 Buf *name = &node->data.variable_declaration.symbol;
5663 decl_node->name = name;5467 add_top_level_decl(g, import, context, node, name);
5664 decl_node->import = import;
5665 if (decl_node->deps.size() > 0) {
5666 g->unresolved_top_level_decls.put(name, node);
5667 } else {
5668 resolve_top_level_decl(g, import, node);
5669 }
5670 break;5468 break;
5671 }5469 }
5672 case NodeTypeTypeDecl:5470 case NodeTypeTypeDecl:
5673 {5471 {
5674 // determine which other top level declarations this variable declaration depends on.
5675 TopLevelDecl *decl_node = &node->data.type_decl.top_level_decl;
5676 decl_node->deps.init(1);
5677 collect_expr_decl_deps(g, import, node, decl_node);
5678
5679 Buf *name = &node->data.type_decl.symbol;5472 Buf *name = &node->data.type_decl.symbol;
5680 decl_node->name = name;5473 add_top_level_decl(g, import, context, node, name);
5681 decl_node->import = import;
5682 if (decl_node->deps.size() > 0) {
5683 g->unresolved_top_level_decls.put(name, node);
5684 } else {
5685 resolve_top_level_decl(g, import, node);
5686 }
5687 break;5474 break;
5688 }5475 }
5689 case NodeTypeFnProto:5476 case NodeTypeFnProto:
...@@ -5695,60 +5482,22 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -5695,60 +5482,22 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
5695 add_node_error(g, node, buf_sprintf("missing function name"));5482 add_node_error(g, node, buf_sprintf("missing function name"));
5696 break;5483 break;
5697 }5484 }
5698 Buf *qualified_name;
5699 AstNode *struct_node = node->data.fn_proto.struct_node;
5700 if (struct_node) {
5701 Buf *struct_name = &struct_node->data.struct_decl.name;
5702 qualified_name = buf_sprintf("%s.%s", buf_ptr(struct_name), buf_ptr(fn_name));
5703 } else {
5704 qualified_name = fn_name;
5705 }
5706
5707
5708 // determine which other top level declarations this function prototype depends on.
5709 TopLevelDecl *decl_node = &node->data.fn_proto.top_level_decl;
5710 decl_node->deps.init(1);
57115485
5712 collect_expr_decl_deps(g, import, node, decl_node);5486 add_top_level_decl(g, import, context, node, fn_name);
5713
5714 decl_node->name = qualified_name;
5715 decl_node->import = import;
5716 if (decl_node->deps.size() > 0) {
5717 if (g->unresolved_top_level_decls.maybe_get(qualified_name)) {
5718 node->data.fn_proto.skip = true;
5719 add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(fn_name)));
5720 } else {
5721 g->unresolved_top_level_decls.put(qualified_name, node);
5722 }
5723 } else {
5724 resolve_top_level_decl(g, import, node);
5725 }
5726 break;5487 break;
5727 }5488 }
5728 case NodeTypeRootExportDecl:5489 case NodeTypeUse:
5729 resolve_top_level_decl(g, import, node);
5730 break;
5731 case NodeTypeImport:
5732 // already taken care of
5733 break;
5734 case NodeTypeCImport:
5735 {5490 {
5736 TopLevelDecl *decl_node = &node->data.c_import.top_level_decl;5491 TopLevelDecl *tld = get_as_top_level_decl(node);
5737 decl_node->deps.init(1);5492 tld->import = import;
5738 collect_expr_decl_deps(g, import, node->data.c_import.block, decl_node);5493 node->block_context = context;
57395494 g->use_queue.append(node);
5740 decl_node->name = buf_sprintf("c_import_%" PRIu32, node->create_index);5495 tld->import->use_decls.append(node);
5741 decl_node->import = import;
5742 if (decl_node->deps.size() > 0) {
5743 g->unresolved_top_level_decls.put(decl_node->name, node);
5744 } else {
5745 resolve_top_level_decl(g, import, node);
5746 }
5747 break;5496 break;
5748 }5497 }
5749 case NodeTypeErrorValueDecl:5498 case NodeTypeErrorValueDecl:
5750 // error value declarations do not depend on other top level decls5499 // error value declarations do not depend on other top level decls
5751 resolve_top_level_decl(g, import, node);5500 preview_error_value_decl(g, node);
5752 break;5501 break;
5753 case NodeTypeDirective:5502 case NodeTypeDirective:
5754 case NodeTypeParamDecl:5503 case NodeTypeParamDecl:
...@@ -5792,152 +5541,176 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast...@@ -5792,152 +5541,176 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast
5792 }5541 }
5793}5542}
57945543
5795static void recursive_resolve_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {5544static void add_symbols_from_import(CodeGen *g, AstNode *src_use_node, AstNode *dst_use_node) {
5796 auto it = get_resolved_top_level_decl(node)->deps.entry_iterator();5545 TopLevelDecl *tld = get_as_top_level_decl(dst_use_node);
5797 for (;;) {5546 AstNode *use_target_node = src_use_node->data.use.expr;
5798 auto *entry = it.next();5547 Expr *expr = get_resolved_expr(use_target_node);
5799 if (!entry)
5800 break;
58015548
5802 auto unresolved_entry = g->unresolved_top_level_decls.maybe_get(entry->key);5549 if (expr->type_entry->id == TypeTableEntryIdInvalid) {
5803 if (!unresolved_entry) {5550 return;
5804 continue;5551 }
5805 }5552
5553 ConstExprValue *const_val = &expr->const_val;
5554 assert(const_val->ok);
5555
5556 ImportTableEntry *target_import = const_val->data.x_import;
5557 assert(target_import);
58065558
5807 AstNode *child_node = unresolved_entry->value;5559 if (target_import->any_imports_failed) {
5560 tld->import->any_imports_failed = true;
5561 }
58085562
5809 if (get_resolved_top_level_decl(child_node)->in_current_deps) {5563 for (int i = 0; i < target_import->root->data.root.top_level_decls.length; i += 1) {
5810 // dependency loop. we'll let the fact that it's not in the respective5564 AstNode *decl_node = target_import->root->data.root.top_level_decls.at(i);
5811 // table cause an error in resolve_top_level_decl.5565 if (decl_node->type == NodeTypeFnDef) {
5566 decl_node = decl_node->data.fn_def.fn_proto;
5567 }
5568 TopLevelDecl *target_tld = get_as_top_level_decl(decl_node);
5569 if (!target_tld->name) {
5812 continue;5570 continue;
5813 }5571 }
5572 if (target_tld->visib_mod != VisibModPrivate) {
5573 auto existing_entry = tld->import->block_context->decl_table.maybe_get(target_tld->name);
5574 if (existing_entry) {
5575 AstNode *existing_decl = existing_entry->value;
5576 if (existing_decl != decl_node) {
5577 ErrorMsg *msg = add_node_error(g, dst_use_node,
5578 buf_sprintf("import of '%s' overrides existing definition",
5579 buf_ptr(target_tld->name)));
5580 add_error_note(g, msg, existing_decl, buf_sprintf("previous definition here"));
5581 add_error_note(g, msg, decl_node, buf_sprintf("imported definition here"));
5582 }
5583 } else {
5584 tld->import->block_context->decl_table.put(target_tld->name, decl_node);
5585 }
5586 }
5587 }
58145588
5815 // set temporary flag5589 for (int i = 0; i < target_import->use_decls.length; i += 1) {
5816 TopLevelDecl *top_level_decl = get_resolved_top_level_decl(child_node);5590 AstNode *use_decl_node = target_import->use_decls.at(i);
5817 top_level_decl->in_current_deps = true;5591 TopLevelDecl *target_tld = get_as_top_level_decl(use_decl_node);
5592 if (target_tld->visib_mod != VisibModPrivate) {
5593 add_symbols_from_import(g, use_decl_node, dst_use_node);
5594 }
5595 }
58185596
5819 recursive_resolve_decl(g, top_level_decl->import, child_node);5597}
58205598
5821 // unset temporary flag5599static void resolve_use_decl(CodeGen *g, AstNode *node) {
5822 top_level_decl->in_current_deps = false;5600 assert(node->type == NodeTypeUse);
5823 }5601 add_symbols_from_import(g, node, node);
5602}
58245603
5825 resolve_top_level_decl(g, import, node);5604static void preview_use_decl(CodeGen *g, AstNode *node) {
5605 assert(node->type == NodeTypeUse);
5606 TopLevelDecl *tld = get_as_top_level_decl(node);
5607 TypeTableEntry *use_expr_type = analyze_expression(g, tld->import, tld->import->block_context,
5608 g->builtin_types.entry_namespace, node->data.use.expr);
5609 if (use_expr_type->id == TypeTableEntryIdInvalid) {
5610 tld->import->any_imports_failed = true;
5611 }
5826}5612}
58275613
5828static void resolve_top_level_declarations_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {5614ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
5829 assert(node->type == NodeTypeRoot);5615 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code)
5616{
5617 Buf *full_path = buf_alloc();
5618 os_path_join(src_dirname, src_basename, full_path);
58305619
5831 while (g->unresolved_top_level_decls.size() > 0) {5620 if (g->verbose) {
5832 // for the sake of determinism, find the element with the lowest5621 fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(full_path));
5833 // insert index and resolve that one.5622 fprintf(stderr, "----------------\n");
5834 AstNode *decl_node = nullptr;5623 fprintf(stderr, "%s\n", buf_ptr(source_code));
5835 auto it = g->unresolved_top_level_decls.entry_iterator();
5836 for (;;) {
5837 auto *entry = it.next();
5838 if (!entry)
5839 break;
58405624
5841 AstNode *this_node = entry->value;5625 fprintf(stderr, "\nTokens:\n");
5842 if (!decl_node || this_node->create_index < decl_node->create_index) {5626 fprintf(stderr, "---------\n");
5843 decl_node = this_node;5627 }
5844 }
58455628
5846 }5629 Tokenization tokenization = {0};
5847 // set temporary flag5630 tokenize(source_code, &tokenization);
5848 TopLevelDecl *top_level_decl = get_resolved_top_level_decl(decl_node);
5849 top_level_decl->in_current_deps = true;
58505631
5851 recursive_resolve_decl(g, top_level_decl->import, decl_node);5632 if (tokenization.err) {
5633 ErrorMsg *err = err_msg_create_with_line(full_path, tokenization.err_line, tokenization.err_column,
5634 source_code, tokenization.line_offsets, tokenization.err);
58525635
5853 // unset temporary flag5636 print_err_msg(err, g->err_color);
5854 top_level_decl->in_current_deps = false;5637 exit(1);
5855 }5638 }
5856}
58575639
5858static void analyze_top_level_decls_root(CodeGen *g, ImportTableEntry *import, AstNode *node) {5640 if (g->verbose) {
5859 assert(node->type == NodeTypeRoot);5641 print_tokens(source_code, tokenization.tokens);
58605642
5861 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {5643 fprintf(stderr, "\nAST:\n");
5862 AstNode *child = node->data.root.top_level_decls.at(i);5644 fprintf(stderr, "------\n");
5863 analyze_top_level_decl(g, import, child);
5864 }5645 }
5865}
58665646
5867void semantic_analyze(CodeGen *g) {5647 ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
5868 {5648 import_entry->package = package;
5869 auto it = g->import_table.entry_iterator();5649 import_entry->source_code = source_code;
5870 for (;;) {5650 import_entry->line_offsets = tokenization.line_offsets;
5871 auto *entry = it.next();5651 import_entry->path = full_path;
5872 if (!entry)
5873 break;
58745652
5875 ImportTableEntry *import = entry->value;5653 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
5654 &g->next_node_index);
5655 assert(import_entry->root);
5656 if (g->verbose) {
5657 ast_print(stderr, import_entry->root, 0);
5658 }
58765659
5877 for (int i = 0; i < import->root->data.root.top_level_decls.length; i += 1) {5660 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
5878 AstNode *child = import->root->data.root.top_level_decls.at(i);5661 g->import_table.put(abs_full_path, import_entry);
5879 if (child->type == NodeTypeImport) {5662 g->import_queue.append(import_entry);
5880 if (child->data.import.directives) {
5881 for (int i = 0; i < child->data.import.directives->length; i += 1) {
5882 AstNode *directive_node = child->data.import.directives->at(i);
5883 Buf *name = &directive_node->data.directive.name;
5884 add_node_error(g, directive_node,
5885 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
5886 }
5887 }
58885663
5889 ImportTableEntry *target_import = child->data.import.import;5664 import_entry->block_context = new_block_context(import_entry->root, nullptr);
5890 assert(target_import);5665 import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
58915666
5892 target_import->importers.append({import, child});5667
5893 } else if (child->type == NodeTypeErrorValueDecl) {5668 assert(import_entry->root->type == NodeTypeRoot);
5894 preview_error_value_decl(g, child);5669 for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
5895 }5670 AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i);
5671
5672 if (top_level_decl->type == NodeTypeFnDef) {
5673 AstNode *proto_node = top_level_decl->data.fn_def.fn_proto;
5674 assert(proto_node->type == NodeTypeFnProto);
5675 Buf *proto_name = &proto_node->data.fn_proto.name;
5676
5677 bool is_private = (proto_node->data.fn_proto.top_level_decl.visib_mod == VisibModPrivate);
5678
5679 if (buf_eql_str(proto_name, "main") && !is_private) {
5680 g->have_exported_main = true;
5896 }5681 }
5897 }5682 }
5898 }5683 }
58995684
5900 {5685 return import_entry;
5901 g->err_tag_type = get_smallest_unsigned_int_type(g, g->error_value_count);5686}
5902
5903 g->builtin_types.entry_pure_error->type_ref = g->err_tag_type->type_ref;
5904 g->builtin_types.entry_pure_error->di_type = g->err_tag_type->di_type;
5905 }
59065687
5907 {
5908 auto it = g->import_table.entry_iterator();
5909 for (;;) {
5910 auto *entry = it.next();
5911 if (!entry)
5912 break;
59135688
5914 ImportTableEntry *import = entry->value;5689void semantic_analyze(CodeGen *g) {
5690 for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) {
5691 ImportTableEntry *import = g->import_queue.at(g->import_queue_index);
5692 scan_decls(g, import, import->block_context, import->root);
5693 }
59155694
5916 detect_top_level_decl_deps(g, import, import->root);5695 for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) {
5917 }5696 AstNode *use_decl_node = g->use_queue.at(g->use_queue_index);
5697 preview_use_decl(g, use_decl_node);
5918 }5698 }
59195699
5920 {5700 for (int i = 0; i < g->use_queue.length; i += 1) {
5921 auto it = g->import_table.entry_iterator();5701 AstNode *use_decl_node = g->use_queue.at(i);
5922 for (;;) {5702 resolve_use_decl(g, use_decl_node);
5923 auto *entry = it.next();5703 }
5924 if (!entry)
5925 break;
59265704
5927 ImportTableEntry *import = entry->value;5705 for (; g->export_queue_index < g->export_queue.length; g->export_queue_index += 1) {
5928 resolve_top_level_declarations_root(g, import, import->root);5706 AstNode *decl_node = g->export_queue.at(g->export_queue_index);
5929 }5707 bool pointer_only = false;
5708 resolve_top_level_decl(g, decl_node, pointer_only);
5930 }5709 }
5931 {
5932 auto it = g->import_table.entry_iterator();
5933 for (;;) {
5934 auto *entry = it.next();
5935 if (!entry)
5936 break;
59375710
5938 ImportTableEntry *import = entry->value;5711 for (int i = 0; i < g->fn_defs.length; i += 1) {
5939 analyze_top_level_decls_root(g, import, import->root);5712 FnTableEntry *fn_entry = g->fn_defs.at(i);
5940 }5713 analyze_fn_body(g, fn_entry);
5941 }5714 }
5942}5715}
59435716
...@@ -6012,13 +5785,11 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -6012,13 +5785,11 @@ Expr *get_resolved_expr(AstNode *node) {
6012 case NodeTypeSwitchProng:5785 case NodeTypeSwitchProng:
6013 case NodeTypeSwitchRange:5786 case NodeTypeSwitchRange:
6014 case NodeTypeRoot:5787 case NodeTypeRoot:
6015 case NodeTypeRootExportDecl:
6016 case NodeTypeFnDef:5788 case NodeTypeFnDef:
6017 case NodeTypeFnDecl:5789 case NodeTypeFnDecl:
6018 case NodeTypeParamDecl:5790 case NodeTypeParamDecl:
6019 case NodeTypeDirective:5791 case NodeTypeDirective:
6020 case NodeTypeImport:5792 case NodeTypeUse:
6021 case NodeTypeCImport:
6022 case NodeTypeStructDecl:5793 case NodeTypeStructDecl:
6023 case NodeTypeStructField:5794 case NodeTypeStructField:
6024 case NodeTypeStructValueField:5795 case NodeTypeStructValueField:
...@@ -6029,18 +5800,20 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -6029,18 +5800,20 @@ Expr *get_resolved_expr(AstNode *node) {
6029 zig_unreachable();5800 zig_unreachable();
6030}5801}
60315802
6032TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {5803static TopLevelDecl *get_as_top_level_decl(AstNode *node) {
6033 switch (node->type) {5804 switch (node->type) {
6034 case NodeTypeVariableDeclaration:5805 case NodeTypeVariableDeclaration:
6035 return &node->data.variable_declaration.top_level_decl;5806 return &node->data.variable_declaration.top_level_decl;
6036 case NodeTypeFnProto:5807 case NodeTypeFnProto:
6037 return &node->data.fn_proto.top_level_decl;5808 return &node->data.fn_proto.top_level_decl;
5809 case NodeTypeFnDef:
5810 return &node->data.fn_def.fn_proto->data.fn_proto.top_level_decl;
6038 case NodeTypeStructDecl:5811 case NodeTypeStructDecl:
6039 return &node->data.struct_decl.top_level_decl;5812 return &node->data.struct_decl.top_level_decl;
6040 case NodeTypeErrorValueDecl:5813 case NodeTypeErrorValueDecl:
6041 return &node->data.error_value_decl.top_level_decl;5814 return &node->data.error_value_decl.top_level_decl;
6042 case NodeTypeCImport:5815 case NodeTypeUse:
6043 return &node->data.c_import.top_level_decl;5816 return &node->data.use.top_level_decl;
6044 case NodeTypeTypeDecl:5817 case NodeTypeTypeDecl:
6045 return &node->data.type_decl.top_level_decl;5818 return &node->data.type_decl.top_level_decl;
6046 case NodeTypeNumberLiteral:5819 case NodeTypeNumberLiteral:
...@@ -6063,8 +5836,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -6063,8 +5836,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
6063 case NodeTypeAsmExpr:5836 case NodeTypeAsmExpr:
6064 case NodeTypeContainerInitExpr:5837 case NodeTypeContainerInitExpr:
6065 case NodeTypeRoot:5838 case NodeTypeRoot:
6066 case NodeTypeRootExportDecl:
6067 case NodeTypeFnDef:
6068 case NodeTypeFnDecl:5839 case NodeTypeFnDecl:
6069 case NodeTypeParamDecl:5840 case NodeTypeParamDecl:
6070 case NodeTypeBlock:5841 case NodeTypeBlock:
...@@ -6072,7 +5843,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {...@@ -6072,7 +5843,6 @@ TopLevelDecl *get_resolved_top_level_decl(AstNode *node) {
6072 case NodeTypeStringLiteral:5843 case NodeTypeStringLiteral:
6073 case NodeTypeCharLiteral:5844 case NodeTypeCharLiteral:
6074 case NodeTypeSymbol:5845 case NodeTypeSymbol:
6075 case NodeTypeImport:
6076 case NodeTypeBoolLiteral:5846 case NodeTypeBoolLiteral:
6077 case NodeTypeNullLiteral:5847 case NodeTypeNullLiteral:
6078 case NodeTypeUndefinedLiteral:5848 case NodeTypeUndefinedLiteral:
...@@ -6140,6 +5910,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {...@@ -6140,6 +5910,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
6140 case TypeTableEntryIdNumLitFloat:5910 case TypeTableEntryIdNumLitFloat:
6141 case TypeTableEntryIdNumLitInt:5911 case TypeTableEntryIdNumLitInt:
6142 case TypeTableEntryIdUndefLit:5912 case TypeTableEntryIdUndefLit:
5913 case TypeTableEntryIdNamespace:
6143 zig_unreachable();5914 zig_unreachable();
6144 case TypeTableEntryIdUnreachable:5915 case TypeTableEntryIdUnreachable:
6145 case TypeTableEntryIdVoid:5916 case TypeTableEntryIdVoid:
...@@ -6257,6 +6028,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)...@@ -6257,6 +6028,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
6257 case TypeTableEntryIdUnreachable:6028 case TypeTableEntryIdUnreachable:
6258 case TypeTableEntryIdMetaType:6029 case TypeTableEntryIdMetaType:
6259 case TypeTableEntryIdVoid:6030 case TypeTableEntryIdVoid:
6031 case TypeTableEntryIdNamespace:
6260 zig_unreachable();6032 zig_unreachable();
6261 case TypeTableEntryIdArray:6033 case TypeTableEntryIdArray:
6262 return type_of_first_thing_in_memory(type_entry->data.array.child_type);6034 return type_of_first_thing_in_memory(type_entry->data.array.child_type);
src/analyze.hpp+5-1
...@@ -12,11 +12,11 @@...@@ -12,11 +12,11 @@
1212
13void semantic_analyze(CodeGen *g);13void semantic_analyze(CodeGen *g);
14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
15ErrorMsg *add_error_note(CodeGen *g, ErrorMsg *parent_msg, AstNode *node, Buf *msg);
15TypeTableEntry *new_type_table_entry(TypeTableEntryId id);16TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
16TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);17TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
17BlockContext *new_block_context(AstNode *node, BlockContext *parent);18BlockContext *new_block_context(AstNode *node, BlockContext *parent);
18Expr *get_resolved_expr(AstNode *node);19Expr *get_resolved_expr(AstNode *node);
19TopLevelDecl *get_resolved_top_level_decl(AstNode *node);
20bool is_node_void_expr(AstNode *node);20bool is_node_void_expr(AstNode *node);
21TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);21TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
22TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);22TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
...@@ -37,4 +37,8 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);...@@ -37,4 +37,8 @@ TypeTableEntry *get_underlying_type(TypeTableEntry *type_entry);
37bool type_has_bits(TypeTableEntry *type_entry);37bool type_has_bits(TypeTableEntry *type_entry);
38uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);38uint64_t get_memcpy_align(CodeGen *g, TypeTableEntry *type_entry);
3939
40
41ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
42 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);
43
40#endif44#endif
src/ast_render.cpp+21-33
...@@ -101,8 +101,6 @@ static const char *node_type_str(NodeType node_type) {...@@ -101,8 +101,6 @@ static const char *node_type_str(NodeType node_type) {
101 switch (node_type) {101 switch (node_type) {
102 case NodeTypeRoot:102 case NodeTypeRoot:
103 return "Root";103 return "Root";
104 case NodeTypeRootExportDecl:
105 return "RootExportDecl";
106 case NodeTypeFnDef:104 case NodeTypeFnDef:
107 return "FnDef";105 return "FnDef";
108 case NodeTypeFnDecl:106 case NodeTypeFnDecl:
...@@ -145,10 +143,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -145,10 +143,8 @@ static const char *node_type_str(NodeType node_type) {
145 return "Symbol";143 return "Symbol";
146 case NodeTypePrefixOpExpr:144 case NodeTypePrefixOpExpr:
147 return "PrefixOpExpr";145 return "PrefixOpExpr";
148 case NodeTypeImport:146 case NodeTypeUse:
149 return "Import";147 return "Use";
150 case NodeTypeCImport:
151 return "CImport";
152 case NodeTypeBoolLiteral:148 case NodeTypeBoolLiteral:
153 return "BoolLiteral";149 return "BoolLiteral";
154 case NodeTypeNullLiteral:150 case NodeTypeNullLiteral:
...@@ -214,11 +210,6 @@ void ast_print(FILE *f, AstNode *node, int indent) {...@@ -214,11 +210,6 @@ void ast_print(FILE *f, AstNode *node, int indent) {
214 ast_print(f, child, indent + 2);210 ast_print(f, child, indent + 2);
215 }211 }
216 break;212 break;
217 case NodeTypeRootExportDecl:
218 fprintf(f, "%s %s '%s'\n", node_type_str(node->type),
219 buf_ptr(&node->data.root_export_decl.type),
220 buf_ptr(&node->data.root_export_decl.name));
221 break;
222 case NodeTypeFnDef:213 case NodeTypeFnDef:
223 {214 {
224 fprintf(f, "%s\n", node_type_str(node->type));215 fprintf(f, "%s\n", node_type_str(node->type));
...@@ -372,12 +363,9 @@ void ast_print(FILE *f, AstNode *node, int indent) {...@@ -372,12 +363,9 @@ void ast_print(FILE *f, AstNode *node, int indent) {
372 case NodeTypeSymbol:363 case NodeTypeSymbol:
373 fprintf(f, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));364 fprintf(f, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
374 break;365 break;
375 case NodeTypeImport:366 case NodeTypeUse:
376 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.import.path));
377 break;
378 case NodeTypeCImport:
379 fprintf(f, "%s\n", node_type_str(node->type));367 fprintf(f, "%s\n", node_type_str(node->type));
380 ast_print(f, node->data.c_import.block, indent + 2);368 ast_print(f, node->data.use.expr, indent + 2);
381 break;369 break;
382 case NodeTypeBoolLiteral:370 case NodeTypeBoolLiteral:
383 fprintf(f, "%s '%s'\n", node_type_str(node->type),371 fprintf(f, "%s '%s'\n", node_type_str(node->type),
...@@ -556,7 +544,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -556,7 +544,7 @@ static void render_node(AstRender *ar, AstNode *node) {
556 print_indent(ar);544 print_indent(ar);
557 render_node(ar, child);545 render_node(ar, child);
558546
559 if (child->type == NodeTypeImport ||547 if (child->type == NodeTypeUse ||
560 child->type == NodeTypeVariableDeclaration ||548 child->type == NodeTypeVariableDeclaration ||
561 child->type == NodeTypeTypeDecl ||549 child->type == NodeTypeTypeDecl ||
562 child->type == NodeTypeErrorValueDecl ||550 child->type == NodeTypeErrorValueDecl ||
...@@ -567,12 +555,10 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -567,12 +555,10 @@ static void render_node(AstRender *ar, AstNode *node) {
567 fprintf(ar->f, "\n");555 fprintf(ar->f, "\n");
568 }556 }
569 break;557 break;
570 case NodeTypeRootExportDecl:
571 zig_panic("TODO");
572 case NodeTypeFnProto:558 case NodeTypeFnProto:
573 {559 {
574 const char *fn_name = buf_ptr(&node->data.fn_proto.name);560 const char *fn_name = buf_ptr(&node->data.fn_proto.name);
575 const char *pub_str = visib_mod_string(node->data.fn_proto.visib_mod);561 const char *pub_str = visib_mod_string(node->data.fn_proto.top_level_decl.visib_mod);
576 const char *extern_str = extern_string(node->data.fn_proto.is_extern);562 const char *extern_str = extern_string(node->data.fn_proto.is_extern);
577 const char *inline_str = inline_string(node->data.fn_proto.is_inline);563 const char *inline_str = inline_string(node->data.fn_proto.is_inline);
578 fprintf(ar->f, "%s%s%sfn %s(", pub_str, inline_str, extern_str, fn_name);564 fprintf(ar->f, "%s%s%sfn %s(", pub_str, inline_str, extern_str, fn_name);
...@@ -605,15 +591,19 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -605,15 +591,19 @@ static void render_node(AstRender *ar, AstNode *node) {
605 break;591 break;
606 }592 }
607 case NodeTypeFnDef:593 case NodeTypeFnDef:
608 if (node->data.fn_def.fn_proto->data.fn_proto.directives) {594 {
609 for (int i = 0; i < node->data.fn_def.fn_proto->data.fn_proto.directives->length; i += 1) {595 ZigList<AstNode *> *directives =
610 render_node(ar, node->data.fn_def.fn_proto->data.fn_proto.directives->at(i));596 node->data.fn_def.fn_proto->data.fn_proto.top_level_decl.directives;
597 if (directives) {
598 for (int i = 0; i < directives->length; i += 1) {
599 render_node(ar, directives->at(i));
600 }
611 }601 }
602 render_node(ar, node->data.fn_def.fn_proto);
603 fprintf(ar->f, " ");
604 render_node(ar, node->data.fn_def.body);
605 break;
612 }606 }
613 render_node(ar, node->data.fn_def.fn_proto);
614 fprintf(ar->f, " ");
615 render_node(ar, node->data.fn_def.body);
616 break;
617 case NodeTypeFnDecl:607 case NodeTypeFnDecl:
618 zig_panic("TODO");608 zig_panic("TODO");
619 case NodeTypeParamDecl:609 case NodeTypeParamDecl:
...@@ -642,7 +632,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -642,7 +632,7 @@ static void render_node(AstRender *ar, AstNode *node) {
642 zig_panic("TODO");632 zig_panic("TODO");
643 case NodeTypeVariableDeclaration:633 case NodeTypeVariableDeclaration:
644 {634 {
645 const char *pub_str = visib_mod_string(node->data.variable_declaration.visib_mod);635 const char *pub_str = visib_mod_string(node->data.variable_declaration.top_level_decl.visib_mod);
646 const char *extern_str = extern_string(node->data.variable_declaration.is_extern);636 const char *extern_str = extern_string(node->data.variable_declaration.is_extern);
647 const char *var_name = buf_ptr(&node->data.variable_declaration.symbol);637 const char *var_name = buf_ptr(&node->data.variable_declaration.symbol);
648 const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);638 const char *const_or_var = const_or_var_string(node->data.variable_declaration.is_const);
...@@ -659,7 +649,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -659,7 +649,7 @@ static void render_node(AstRender *ar, AstNode *node) {
659 }649 }
660 case NodeTypeTypeDecl:650 case NodeTypeTypeDecl:
661 {651 {
662 const char *pub_str = visib_mod_string(node->data.type_decl.visib_mod);652 const char *pub_str = visib_mod_string(node->data.type_decl.top_level_decl.visib_mod);
663 const char *var_name = buf_ptr(&node->data.type_decl.symbol);653 const char *var_name = buf_ptr(&node->data.type_decl.symbol);
664 fprintf(ar->f, "%stype %s = ", pub_str, var_name);654 fprintf(ar->f, "%stype %s = ", pub_str, var_name);
665 render_node(ar, node->data.type_decl.child_type);655 render_node(ar, node->data.type_decl.child_type);
...@@ -748,9 +738,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -748,9 +738,7 @@ static void render_node(AstRender *ar, AstNode *node) {
748 fprintf(ar->f, ".%s", buf_ptr(rhs));738 fprintf(ar->f, ".%s", buf_ptr(rhs));
749 break;739 break;
750 }740 }
751 case NodeTypeImport:741 case NodeTypeUse:
752 zig_panic("TODO");
753 case NodeTypeCImport:
754 zig_panic("TODO");742 zig_panic("TODO");
755 case NodeTypeBoolLiteral:743 case NodeTypeBoolLiteral:
756 zig_panic("TODO");744 zig_panic("TODO");
...@@ -785,7 +773,7 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -785,7 +773,7 @@ static void render_node(AstRender *ar, AstNode *node) {
785 case NodeTypeStructDecl:773 case NodeTypeStructDecl:
786 {774 {
787 const char *struct_name = buf_ptr(&node->data.struct_decl.name);775 const char *struct_name = buf_ptr(&node->data.struct_decl.name);
788 const char *pub_str = visib_mod_string(node->data.struct_decl.visib_mod);776 const char *pub_str = visib_mod_string(node->data.struct_decl.top_level_decl.visib_mod);
789 const char *container_str = container_string(node->data.struct_decl.kind);777 const char *container_str = container_string(node->data.struct_decl.kind);
790 fprintf(ar->f, "%s%s %s {\n", pub_str, container_str, struct_name);778 fprintf(ar->f, "%s%s %s {\n", pub_str, container_str, struct_name);
791 ar->indent += ar->indent_size;779 ar->indent += ar->indent_size;
src/codegen.cpp+95-252
...@@ -47,19 +47,30 @@ static void init_darwin_native(CodeGen *g) {...@@ -47,19 +47,30 @@ static void init_darwin_native(CodeGen *g) {
47 }47 }
48}48}
4949
50static PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path) {
51 PackageTableEntry *entry = allocate<PackageTableEntry>(1);
52 entry->package_table.init(4);
53 buf_init_from_str(&entry->root_src_dir, root_src_dir);
54 buf_init_from_str(&entry->root_src_path, root_src_path);
55 return entry;
56}
57
50CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {58CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
51 CodeGen *g = allocate<CodeGen>(1);59 CodeGen *g = allocate<CodeGen>(1);
52 g->import_table.init(32);60 g->import_table.init(32);
53 g->builtin_fn_table.init(32);61 g->builtin_fn_table.init(32);
54 g->primitive_type_table.init(32);62 g->primitive_type_table.init(32);
55 g->unresolved_top_level_decls.init(32);
56 g->fn_type_table.init(32);63 g->fn_type_table.init(32);
57 g->error_table.init(16);64 g->error_table.init(16);
58 g->is_release_build = false;65 g->is_release_build = false;
59 g->is_test_build = false;66 g->is_test_build = false;
60 g->root_source_dir = root_source_dir;
61 g->error_value_count = 1;67 g->error_value_count = 1;
6268
69 g->root_package = new_package(buf_ptr(root_source_dir), "");
70 g->std_package = new_package(ZIG_STD_DIR, "index.zig");
71 g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);
72
73
63 if (target) {74 if (target) {
64 // cross compiling, so we can't rely on all the configured stuff since75 // cross compiling, so we can't rely on all the configured stuff since
65 // that's for native compilation76 // that's for native compilation
...@@ -117,6 +128,10 @@ void codegen_set_verbose(CodeGen *g, bool verbose) {...@@ -117,6 +128,10 @@ void codegen_set_verbose(CodeGen *g, bool verbose) {
117 g->verbose = verbose;128 g->verbose = verbose;
118}129}
119130
131void codegen_set_check_unused(CodeGen *g, bool check_unused) {
132 g->check_unused = check_unused;
133}
134
120void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {135void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {
121 g->err_color = err_color;136 g->err_color = err_color;
122}137}
...@@ -157,6 +172,14 @@ void codegen_add_lib_dir(CodeGen *g, const char *dir) {...@@ -157,6 +172,14 @@ void codegen_add_lib_dir(CodeGen *g, const char *dir) {
157 g->lib_dirs.append(dir);172 g->lib_dirs.append(dir);
158}173}
159174
175void codegen_add_link_lib(CodeGen *g, const char *lib) {
176 if (strcmp(lib, "c") == 0) {
177 g->link_libc = true;
178 } else {
179 g->link_libs.append(buf_create_from_str(lib));
180 }
181}
182
160void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {183void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole) {
161 g->windows_subsystem_windows = mwindows;184 g->windows_subsystem_windows = mwindows;
162 g->windows_subsystem_console = mconsole;185 g->windows_subsystem_console = mconsole;
...@@ -316,6 +339,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {...@@ -316,6 +339,8 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) {
316 case BuiltinFnIdCInclude:339 case BuiltinFnIdCInclude:
317 case BuiltinFnIdCDefine:340 case BuiltinFnIdCDefine:
318 case BuiltinFnIdCUndef:341 case BuiltinFnIdCUndef:
342 case BuiltinFnIdImport:
343 case BuiltinFnIdCImport:
319 zig_unreachable();344 zig_unreachable();
320 case BuiltinFnIdCtz:345 case BuiltinFnIdCtz:
321 case BuiltinFnIdClz:346 case BuiltinFnIdClz:
...@@ -844,7 +869,7 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou...@@ -844,7 +869,7 @@ static LLVMValueRef gen_field_ptr(CodeGen *g, AstNode *node, TypeTableEntry **ou
844869
845 LLVMValueRef struct_ptr;870 LLVMValueRef struct_ptr;
846 if (struct_expr_node->type == NodeTypeSymbol) {871 if (struct_expr_node->type == NodeTypeSymbol) {
847 VariableTableEntry *var = struct_expr_node->data.symbol_expr.variable;872 VariableTableEntry *var = get_resolved_expr(struct_expr_node)->variable;
848 assert(var);873 assert(var);
849874
850 if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) {875 if (var->is_ptr && var->type->id == TypeTableEntryIdPointer) {
...@@ -983,6 +1008,17 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -983,6 +1008,17 @@ static LLVMValueRef gen_array_access_expr(CodeGen *g, AstNode *node, bool is_lva
983 }1008 }
984}1009}
9851010
1011static LLVMValueRef gen_variable(CodeGen *g, AstNode *source_node, VariableTableEntry *variable) {
1012 if (!type_has_bits(variable->type)) {
1013 return nullptr;
1014 } else if (variable->is_ptr) {
1015 assert(variable->value_ref);
1016 return get_handle_value(g, source_node, variable->value_ref, variable->type);
1017 } else {
1018 return variable->value_ref;
1019 }
1020}
1021
986static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {1022static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lvalue) {
987 assert(node->type == NodeTypeFieldAccessExpr);1023 assert(node->type == NodeTypeFieldAccessExpr);
9881024
...@@ -1016,6 +1052,10 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva...@@ -1016,6 +1052,10 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
1016 } else {1052 } else {
1017 zig_unreachable();1053 zig_unreachable();
1018 }1054 }
1055 } else if (struct_type->id == TypeTableEntryIdNamespace) {
1056 VariableTableEntry *variable = get_resolved_expr(node)->variable;
1057 assert(variable);
1058 return gen_variable(g, node, variable);
1019 } else {1059 } else {
1020 zig_unreachable();1060 zig_unreachable();
1021 }1061 }
...@@ -1027,7 +1067,7 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,...@@ -1027,7 +1067,7 @@ static LLVMValueRef gen_lvalue(CodeGen *g, AstNode *expr_node, AstNode *node,
1027 LLVMValueRef target_ref;1067 LLVMValueRef target_ref;
10281068
1029 if (node->type == NodeTypeSymbol) {1069 if (node->type == NodeTypeSymbol) {
1030 VariableTableEntry *var = node->data.symbol_expr.variable;1070 VariableTableEntry *var = get_resolved_expr(node)->variable;
1031 assert(var);1071 assert(var);
10321072
1033 *out_type_entry = var->type;1073 *out_type_entry = var->type;
...@@ -2468,21 +2508,18 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {...@@ -2468,21 +2508,18 @@ static LLVMValueRef gen_var_decl_expr(CodeGen *g, AstNode *node) {
24682508
2469static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {2509static LLVMValueRef gen_symbol(CodeGen *g, AstNode *node) {
2470 assert(node->type == NodeTypeSymbol);2510 assert(node->type == NodeTypeSymbol);
2471 VariableTableEntry *variable = node->data.symbol_expr.variable;2511 VariableTableEntry *variable = get_resolved_expr(node)->variable;
2472 if (variable) {2512 if (variable) {
2473 if (!type_has_bits(variable->type)) {2513 return gen_variable(g, node, variable);
2474 return nullptr;
2475 } else if (variable->is_ptr) {
2476 assert(variable->value_ref);
2477 return get_handle_value(g, node, variable->value_ref, variable->type);
2478 } else {
2479 return variable->value_ref;
2480 }
2481 }2514 }
24822515
2516 zig_unreachable();
2517
2518 /* TODO delete
2483 FnTableEntry *fn_entry = node->data.symbol_expr.fn_entry;2519 FnTableEntry *fn_entry = node->data.symbol_expr.fn_entry;
2484 assert(fn_entry);2520 assert(fn_entry);
2485 return fn_entry->fn_value;2521 return fn_entry->fn_value;
2522 */
2486}2523}
24872524
2488static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {2525static LLVMValueRef gen_switch_expr(CodeGen *g, AstNode *node) {
...@@ -2703,14 +2740,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -2703,14 +2740,12 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
2703 // caught by constant expression eval codegen2740 // caught by constant expression eval codegen
2704 zig_unreachable();2741 zig_unreachable();
2705 case NodeTypeRoot:2742 case NodeTypeRoot:
2706 case NodeTypeRootExportDecl:
2707 case NodeTypeFnProto:2743 case NodeTypeFnProto:
2708 case NodeTypeFnDef:2744 case NodeTypeFnDef:
2709 case NodeTypeFnDecl:2745 case NodeTypeFnDecl:
2710 case NodeTypeParamDecl:2746 case NodeTypeParamDecl:
2711 case NodeTypeDirective:2747 case NodeTypeDirective:
2712 case NodeTypeImport:2748 case NodeTypeUse:
2713 case NodeTypeCImport:
2714 case NodeTypeStructDecl:2749 case NodeTypeStructDecl:
2715 case NodeTypeStructField:2750 case NodeTypeStructField:
2716 case NodeTypeStructValueField:2751 case NodeTypeStructValueField:
...@@ -2891,6 +2926,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -2891,6 +2926,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
2891 case TypeTableEntryIdNumLitInt:2926 case TypeTableEntryIdNumLitInt:
2892 case TypeTableEntryIdUndefLit:2927 case TypeTableEntryIdUndefLit:
2893 case TypeTableEntryIdVoid:2928 case TypeTableEntryIdVoid:
2929 case TypeTableEntryIdNamespace:
2894 zig_unreachable();2930 zig_unreachable();
28952931
2896 }2932 }
...@@ -2943,14 +2979,14 @@ static bool skip_fn_codegen(CodeGen *g, FnTableEntry *fn_entry) {...@@ -2943,14 +2979,14 @@ static bool skip_fn_codegen(CodeGen *g, FnTableEntry *fn_entry) {
2943 if (fn_entry == g->main_fn) {2979 if (fn_entry == g->main_fn) {
2944 return true;2980 return true;
2945 }2981 }
2946 return fn_entry->ref_count == 0;2982 return false;
2947 }2983 }
29482984
2949 if (fn_entry->is_test) {2985 if (fn_entry->is_test) {
2950 return true;2986 return true;
2951 }2987 }
29522988
2953 return fn_entry->ref_count == 0;2989 return false;
2954}2990}
29552991
2956static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) {2992static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) {
...@@ -3296,6 +3332,12 @@ static void define_builtin_types(CodeGen *g) {...@@ -3296,6 +3332,12 @@ static void define_builtin_types(CodeGen *g) {
3296 entry->zero_bits = true;3332 entry->zero_bits = true;
3297 g->builtin_types.entry_invalid = entry;3333 g->builtin_types.entry_invalid = entry;
3298 }3334 }
3335 {
3336 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNamespace);
3337 buf_init_from_str(&entry->name, "(namespace)");
3338 entry->zero_bits = true;
3339 g->builtin_types.entry_namespace = entry;
3340 }
3299 {3341 {
3300 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);3342 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
3301 buf_init_from_str(&entry->name, "(float literal)");3343 buf_init_from_str(&entry->name, "(float literal)");
...@@ -3499,14 +3541,6 @@ static void define_builtin_types(CodeGen *g) {...@@ -3499,14 +3541,6 @@ static void define_builtin_types(CodeGen *g) {
3499 g->builtin_types.entry_type = entry;3541 g->builtin_types.entry_type = entry;
3500 g->primitive_type_table.put(&entry->name, entry);3542 g->primitive_type_table.put(&entry->name, entry);
3501 }3543 }
3502 {
3503 // partially complete the error type. we complete it later after we know
3504 // error_value_count.
3505 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
3506 buf_init_from_str(&entry->name, "error");
3507 g->builtin_types.entry_pure_error = entry;
3508 g->primitive_type_table.put(&entry->name, entry);
3509 }
35103544
3511 g->builtin_types.entry_u8 = get_int_type(g, false, 8);3545 g->builtin_types.entry_u8 = get_int_type(g, false, 8);
3512 g->builtin_types.entry_u16 = get_int_type(g, false, 16);3546 g->builtin_types.entry_u16 = get_int_type(g, false, 16);
...@@ -3517,6 +3551,21 @@ static void define_builtin_types(CodeGen *g) {...@@ -3517,6 +3551,21 @@ static void define_builtin_types(CodeGen *g) {
3517 g->builtin_types.entry_i32 = get_int_type(g, true, 32);3551 g->builtin_types.entry_i32 = get_int_type(g, true, 32);
3518 g->builtin_types.entry_i64 = get_int_type(g, true, 64);3552 g->builtin_types.entry_i64 = get_int_type(g, true, 64);
35193553
3554 {
3555 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
3556 buf_init_from_str(&entry->name, "error");
3557
3558 // TODO allow overriding this type and keep track of max value and emit an
3559 // error if there are too many errors declared
3560 g->err_tag_type = g->builtin_types.entry_u16;
3561
3562 g->builtin_types.entry_pure_error = entry;
3563 entry->type_ref = g->err_tag_type->type_ref;
3564 entry->di_type = g->err_tag_type->di_type;
3565
3566 g->primitive_type_table.put(&entry->name, entry);
3567 }
3568
3520 {3569 {
3521 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);3570 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
3522 entry->zero_bits = true; // only allowed at compile time3571 entry->zero_bits = true; // only allowed at compile time
...@@ -3685,12 +3734,11 @@ static void define_builtin_fns(CodeGen *g) {...@@ -3685,12 +3734,11 @@ static void define_builtin_fns(CodeGen *g) {
3685 create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "const_eval", 1);3734 create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "const_eval", 1);
3686 create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 2);3735 create_builtin_fn_with_arg_count(g, BuiltinFnIdCtz, "ctz", 2);
3687 create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 2);3736 create_builtin_fn_with_arg_count(g, BuiltinFnIdClz, "clz", 2);
3737 create_builtin_fn_with_arg_count(g, BuiltinFnIdImport, "import", 1);
3738 create_builtin_fn_with_arg_count(g, BuiltinFnIdCImport, "c_import", 1);
3688}3739}
36893740
3690static void init(CodeGen *g, Buf *source_path) {3741static void init(CodeGen *g, Buf *source_path) {
3691 g->lib_search_paths.append(g->root_source_dir);
3692 g->lib_search_paths.append(buf_create_from_str(ZIG_STD_DIR));
3693
3694 g->module = LLVMModuleCreateWithName(buf_ptr(source_path));3742 g->module = LLVMModuleCreateWithName(buf_ptr(source_path));
36953743
3696 get_target_triple(&g->triple_str, &g->zig_target);3744 get_target_triple(&g->triple_str, &g->zig_target);
...@@ -3741,7 +3789,7 @@ static void init(CodeGen *g, Buf *source_path) {...@@ -3741,7 +3789,7 @@ static void init(CodeGen *g, Buf *source_path) {
3741 const char *flags = "";3789 const char *flags = "";
3742 unsigned runtime_version = 0;3790 unsigned runtime_version = 0;
3743 g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),3791 g->compile_unit = LLVMZigCreateCompileUnit(g->dbuilder, LLVMZigLang_DW_LANG_C99(),
3744 buf_ptr(source_path), buf_ptr(g->root_source_dir),3792 buf_ptr(source_path), buf_ptr(&g->root_package->root_src_dir),
3745 buf_ptr(producer), is_optimized, flags, runtime_version,3793 buf_ptr(producer), is_optimized, flags, runtime_version,
3746 "", 0, !g->strip_debug_symbols);3794 "", 0, !g->strip_debug_symbols);
37473795
...@@ -3761,9 +3809,6 @@ void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source...@@ -3761,9 +3809,6 @@ void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source
3761 ImportTableEntry *import = allocate<ImportTableEntry>(1);3809 ImportTableEntry *import = allocate<ImportTableEntry>(1);
3762 import->source_code = source_code;3810 import->source_code = source_code;
3763 import->path = full_path;3811 import->path = full_path;
3764 import->fn_table.init(32);
3765 import->type_table.init(8);
3766 import->error_table.init(8);
3767 g->root_import = import;3812 g->root_import = import;
37683813
3769 init(g, full_path);3814 init(g, full_path);
...@@ -3791,214 +3836,7 @@ void codegen_render_ast(CodeGen *g, FILE *f, int indent_size) {...@@ -3791,214 +3836,7 @@ void codegen_render_ast(CodeGen *g, FILE *f, int indent_size) {
3791}3836}
37923837
37933838
3794static int parse_version_string(Buf *buf, int *major, int *minor, int *patch) {3839static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package, const char *basename) {
3795 char *dot1 = strstr(buf_ptr(buf), ".");
3796 if (!dot1)
3797 return ErrorInvalidFormat;
3798 char *dot2 = strstr(dot1 + 1, ".");
3799 if (!dot2)
3800 return ErrorInvalidFormat;
3801
3802 *major = (int)strtol(buf_ptr(buf), nullptr, 10);
3803 *minor = (int)strtol(dot1 + 1, nullptr, 10);
3804 *patch = (int)strtol(dot2 + 1, nullptr, 10);
3805
3806 return ErrorNone;
3807}
3808
3809static void set_root_export_version(CodeGen *g, Buf *version_buf, AstNode *node) {
3810 int err;
3811 if ((err = parse_version_string(version_buf, &g->version_major, &g->version_minor, &g->version_patch))) {
3812 add_node_error(g, node,
3813 buf_sprintf("invalid version string"));
3814 }
3815}
3816
3817
3818static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
3819 Buf *src_dirname, Buf *src_basename, Buf *source_code)
3820{
3821 int err;
3822 Buf *full_path = buf_alloc();
3823 os_path_join(src_dirname, src_basename, full_path);
3824
3825 if (g->verbose) {
3826 fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(full_path));
3827 fprintf(stderr, "----------------\n");
3828 fprintf(stderr, "%s\n", buf_ptr(source_code));
3829
3830 fprintf(stderr, "\nTokens:\n");
3831 fprintf(stderr, "---------\n");
3832 }
3833
3834 Tokenization tokenization = {0};
3835 tokenize(source_code, &tokenization);
3836
3837 if (tokenization.err) {
3838 ErrorMsg *err = err_msg_create_with_line(full_path, tokenization.err_line, tokenization.err_column,
3839 source_code, tokenization.line_offsets, tokenization.err);
3840
3841 print_err_msg(err, g->err_color);
3842 exit(1);
3843 }
3844
3845 if (g->verbose) {
3846 print_tokens(source_code, tokenization.tokens);
3847
3848 fprintf(stderr, "\nAST:\n");
3849 fprintf(stderr, "------\n");
3850 }
3851
3852 ImportTableEntry *import_entry = allocate<ImportTableEntry>(1);
3853 import_entry->source_code = source_code;
3854 import_entry->line_offsets = tokenization.line_offsets;
3855 import_entry->path = full_path;
3856 import_entry->fn_table.init(32);
3857 import_entry->type_table.init(8);
3858 import_entry->error_table.init(8);
3859
3860 import_entry->root = ast_parse(source_code, tokenization.tokens, import_entry, g->err_color,
3861 &g->next_node_index);
3862 assert(import_entry->root);
3863 if (g->verbose) {
3864 ast_print(stderr, import_entry->root, 0);
3865 }
3866
3867 import_entry->di_file = LLVMZigCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
3868 g->import_table.put(abs_full_path, import_entry);
3869
3870 import_entry->block_context = new_block_context(import_entry->root, nullptr);
3871 import_entry->block_context->di_scope = LLVMZigFileToScope(import_entry->di_file);
3872
3873
3874 assert(import_entry->root->type == NodeTypeRoot);
3875 for (int decl_i = 0; decl_i < import_entry->root->data.root.top_level_decls.length; decl_i += 1) {
3876 AstNode *top_level_decl = import_entry->root->data.root.top_level_decls.at(decl_i);
3877
3878 if (top_level_decl->type == NodeTypeRootExportDecl) {
3879 if (g->root_import) {
3880 add_node_error(g, top_level_decl,
3881 buf_sprintf("root export declaration only valid in root source file"));
3882 } else {
3883 ZigList<AstNode *> *directives = top_level_decl->data.root_export_decl.directives;
3884 if (directives) {
3885 for (int i = 0; i < directives->length; i += 1) {
3886 AstNode *directive_node = directives->at(i);
3887 Buf *name = &directive_node->data.directive.name;
3888 AstNode *param_node = directive_node->data.directive.expr;
3889 assert(param_node->type == NodeTypeStringLiteral);
3890 Buf *param = &param_node->data.string_literal.buf;
3891
3892 if (param) {
3893 if (buf_eql_str(name, "version")) {
3894 set_root_export_version(g, param, directive_node);
3895 } else if (buf_eql_str(name, "link")) {
3896 if (buf_eql_str(param, "c")) {
3897 g->link_libc = true;
3898 } else {
3899 g->link_libs.append(param);
3900 }
3901 } else {
3902 add_node_error(g, directive_node,
3903 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
3904 }
3905 }
3906 }
3907 }
3908
3909 if (g->root_export_decl) {
3910 add_node_error(g, top_level_decl,
3911 buf_sprintf("only one root export declaration allowed"));
3912 } else {
3913 g->root_export_decl = top_level_decl;
3914
3915 if (!g->root_out_name)
3916 g->root_out_name = &top_level_decl->data.root_export_decl.name;
3917
3918 Buf *out_type = &top_level_decl->data.root_export_decl.type;
3919 OutType export_out_type;
3920 if (buf_eql_str(out_type, "executable")) {
3921 export_out_type = OutTypeExe;
3922 } else if (buf_eql_str(out_type, "library")) {
3923 export_out_type = OutTypeLib;
3924 } else if (buf_eql_str(out_type, "object")) {
3925 export_out_type = OutTypeObj;
3926 } else {
3927 add_node_error(g, top_level_decl,
3928 buf_sprintf("invalid export type: '%s'", buf_ptr(out_type)));
3929 }
3930 if (g->out_type == OutTypeUnknown) {
3931 g->out_type = export_out_type;
3932 }
3933 }
3934 }
3935 } else if (top_level_decl->type == NodeTypeImport) {
3936 Buf *import_target_path = &top_level_decl->data.import.path;
3937 Buf full_path = BUF_INIT;
3938 Buf *import_code = buf_alloc();
3939 bool found_it = false;
3940
3941 for (int path_i = 0; path_i < g->lib_search_paths.length; path_i += 1) {
3942 Buf *search_path = g->lib_search_paths.at(path_i);
3943 os_path_join(search_path, import_target_path, &full_path);
3944
3945 Buf *abs_full_path = buf_alloc();
3946 if ((err = os_path_real(&full_path, abs_full_path))) {
3947 if (err == ErrorFileNotFound) {
3948 continue;
3949 } else {
3950 g->error_during_imports = true;
3951 add_node_error(g, top_level_decl,
3952 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
3953 goto done_looking_at_imports;
3954 }
3955 }
3956
3957 auto entry = g->import_table.maybe_get(abs_full_path);
3958 if (entry) {
3959 found_it = true;
3960 top_level_decl->data.import.import = entry->value;
3961 } else {
3962 if ((err = os_fetch_file_path(abs_full_path, import_code))) {
3963 if (err == ErrorFileNotFound) {
3964 continue;
3965 } else {
3966 g->error_during_imports = true;
3967 add_node_error(g, top_level_decl,
3968 buf_sprintf("unable to open '%s': %s", buf_ptr(&full_path), err_str(err)));
3969 goto done_looking_at_imports;
3970 }
3971 }
3972 top_level_decl->data.import.import = codegen_add_code(g,
3973 abs_full_path, search_path, &top_level_decl->data.import.path, import_code);
3974 found_it = true;
3975 }
3976 break;
3977 }
3978 if (!found_it) {
3979 g->error_during_imports = true;
3980 add_node_error(g, top_level_decl,
3981 buf_sprintf("unable to find '%s'", buf_ptr(import_target_path)));
3982 }
3983 } else if (top_level_decl->type == NodeTypeFnDef) {
3984 AstNode *proto_node = top_level_decl->data.fn_def.fn_proto;
3985 assert(proto_node->type == NodeTypeFnProto);
3986 Buf *proto_name = &proto_node->data.fn_proto.name;
3987
3988 bool is_private = (proto_node->data.fn_proto.visib_mod == VisibModPrivate);
3989
3990 if (buf_eql_str(proto_name, "main") && !is_private) {
3991 g->have_exported_main = true;
3992 }
3993 }
3994 }
3995
3996done_looking_at_imports:
3997
3998 return import_entry;
3999}
4000
4001static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) {
4002 Buf *std_dir = buf_create_from_str(ZIG_STD_DIR);3840 Buf *std_dir = buf_create_from_str(ZIG_STD_DIR);
4003 Buf *code_basename = buf_create_from_str(basename);3841 Buf *code_basename = buf_create_from_str(basename);
4004 Buf path_to_code_src = BUF_INIT;3842 Buf path_to_code_src = BUF_INIT;
...@@ -4013,12 +3851,22 @@ static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) {...@@ -4013,12 +3851,22 @@ static ImportTableEntry *add_special_code(CodeGen *g, const char *basename) {
4013 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));3851 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
4014 }3852 }
40153853
4016 return codegen_add_code(g, abs_full_path, std_dir, code_basename, import_code);3854 return add_source_file(g, package, abs_full_path, std_dir, code_basename, import_code);
3855}
3856
3857static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
3858 PackageTableEntry *package = new_package(ZIG_STD_DIR, "");
3859 package->package_table.put(buf_create_from_str("std"), g->std_package);
3860 package->package_table.put(buf_create_from_str("@root"), g->root_package);
3861 return package;
4017}3862}
40183863
4019void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {3864void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
4020 Buf source_path = BUF_INIT;3865 Buf source_path = BUF_INIT;
4021 os_path_join(src_dir, src_basename, &source_path);3866 os_path_join(src_dir, src_basename, &source_path);
3867
3868 buf_init_from_buf(&g->root_package->root_src_path, src_basename);
3869
4022 init(g, &source_path);3870 init(g, &source_path);
40233871
4024 Buf *abs_full_path = buf_alloc();3872 Buf *abs_full_path = buf_alloc();
...@@ -4027,19 +3875,14 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou...@@ -4027,19 +3875,14 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
4027 zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));3875 zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));
4028 }3876 }
40293877
4030 g->root_import = codegen_add_code(g, abs_full_path, src_dir, src_basename, source_code);3878 g->root_import = add_source_file(g, g->root_package, abs_full_path, src_dir, src_basename, source_code);
40313879
4032 if (!g->root_out_name) {3880 assert(g->root_out_name);
4033 add_node_error(g, g->root_import->root,3881 assert(g->out_type != OutTypeUnknown);
4034 buf_sprintf("missing export declaration and output name not provided"));
4035 } else if (g->out_type == OutTypeUnknown) {
4036 add_node_error(g, g->root_import->root,
4037 buf_sprintf("missing export declaration and export type not provided"));
4038 }
40393882
4040 if (!g->link_libc && !g->is_test_build) {3883 if (!g->link_libc && !g->is_test_build) {
4041 if (g->have_exported_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) {3884 if (g->have_exported_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) {
4042 g->bootstrap_import = add_special_code(g, "bootstrap.zig");3885 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
4043 }3886 }
4044 }3887 }
40453888
...@@ -4120,7 +3963,7 @@ void codegen_generate_h_file(CodeGen *g) {...@@ -4120,7 +3963,7 @@ void codegen_generate_h_file(CodeGen *g) {
4120 assert(proto_node->type == NodeTypeFnProto);3963 assert(proto_node->type == NodeTypeFnProto);
4121 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;3964 AstNodeFnProto *fn_proto = &proto_node->data.fn_proto;
41223965
4123 if (fn_proto->visib_mod != VisibModExport)3966 if (fn_proto->top_level_decl.visib_mod != VisibModExport)
4124 continue;3967 continue;
41253968
4126 Buf return_type_c = BUF_INIT;3969 Buf return_type_c = BUF_INIT;
src/codegen.hpp+2
...@@ -19,6 +19,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);...@@ -19,6 +19,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);
19void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len);19void codegen_set_clang_argv(CodeGen *codegen, const char **args, int len);
20void codegen_set_is_release(CodeGen *codegen, bool is_release);20void codegen_set_is_release(CodeGen *codegen, bool is_release);
21void codegen_set_is_test(CodeGen *codegen, bool is_test);21void codegen_set_is_test(CodeGen *codegen, bool is_test);
22void codegen_set_check_unused(CodeGen *codegen, bool check_unused);
2223
23void codegen_set_is_static(CodeGen *codegen, bool is_static);24void codegen_set_is_static(CodeGen *codegen, bool is_static);
24void codegen_set_strip(CodeGen *codegen, bool strip);25void codegen_set_strip(CodeGen *codegen, bool strip);
...@@ -34,6 +35,7 @@ void codegen_set_linker_path(CodeGen *g, Buf *linker_path);...@@ -34,6 +35,7 @@ void codegen_set_linker_path(CodeGen *g, Buf *linker_path);
34void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);35void codegen_set_windows_subsystem(CodeGen *g, bool mwindows, bool mconsole);
35void codegen_set_windows_unicode(CodeGen *g, bool municode);36void codegen_set_windows_unicode(CodeGen *g, bool municode);
36void codegen_add_lib_dir(CodeGen *codegen, const char *dir);37void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
38void codegen_add_link_lib(CodeGen *codegen, const char *lib);
37void codegen_set_mlinker_version(CodeGen *g, Buf *darwin_linker_version);39void codegen_set_mlinker_version(CodeGen *g, Buf *darwin_linker_version);
38void codegen_set_rdynamic(CodeGen *g, bool rdynamic);40void codegen_set_rdynamic(CodeGen *g, bool rdynamic);
39void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min);41void codegen_set_mmacosx_version_min(CodeGen *g, Buf *mmacosx_version_min);
src/errmsg.cpp+33-12
...@@ -4,36 +4,57 @@...@@ -4,36 +4,57 @@
4#include <stdio.h>4#include <stdio.h>
55
6#define RED "\x1b[31;1m"6#define RED "\x1b[31;1m"
7#define WHITE "\x1b[37;1m"
8#define GREEN "\x1b[32;1m"7#define GREEN "\x1b[32;1m"
8#define CYAN "\x1b[36;1m"
9#define WHITE "\x1b[37;1m"
9#define RESET "\x1b[0m"10#define RESET "\x1b[0m"
1011
11void print_err_msg(ErrorMsg *err, ErrColor color) {12enum ErrType {
13 ErrTypeError,
14 ErrTypeNote,
15};
16
17static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type) {
18 const char *path = buf_ptr(err->path);
19 int line = err->line_start + 1;
20 int col = err->column_start + 1;
21 const char *text = buf_ptr(err->msg);
22
23
12 if (color == ErrColorOn || (color == ErrColorAuto && os_stderr_tty())) {24 if (color == ErrColorOn || (color == ErrColorAuto && os_stderr_tty())) {
13 fprintf(stderr, WHITE "%s:%d:%d: " RED "error:" WHITE " %s" RESET "\n",25 if (err_type == ErrTypeError) {
14 buf_ptr(err->path),26 fprintf(stderr, WHITE "%s:%d:%d: " RED "error:" WHITE " %s" RESET "\n", path, line, col, text);
15 err->line_start + 1, err->column_start + 1,27 } else if (err_type == ErrTypeNote) {
16 buf_ptr(err->msg));28 fprintf(stderr, WHITE "%s:%d:%d: " CYAN "note:" WHITE " %s" RESET "\n", path, line, col, text);
29 } else {
30 zig_unreachable();
31 }
1732
18 fprintf(stderr, "%s\n", buf_ptr(&err->line_buf));33 fprintf(stderr, "%s\n", buf_ptr(&err->line_buf));
19 for (int i = 0; i < err->column_start; i += 1) {34 for (int i = 0; i < err->column_start; i += 1) {
20 fprintf(stderr, " ");35 fprintf(stderr, " ");
21 }36 }
22 fprintf(stderr, GREEN "^" RESET "\n");37 fprintf(stderr, GREEN "^" RESET "\n");
23
24 } else {38 } else {
25 fprintf(stderr, "%s:%d:%d: error: %s\n",39 if (err_type == ErrTypeError) {
26 buf_ptr(err->path),40 fprintf(stderr, "%s:%d:%d: error: %s\n", path, line, col, text);
27 err->line_start + 1, err->column_start + 1,41 } else if (err_type == ErrTypeNote) {
28 buf_ptr(err->msg));42 fprintf(stderr, " %s:%d:%d: note: %s\n", path, line, col, text);
43 } else {
44 zig_unreachable();
45 }
29 }46 }
3047
31 for (int i = 0; i < err->notes.length; i += 1) {48 for (int i = 0; i < err->notes.length; i += 1) {
32 ErrorMsg *note = err->notes.at(i);49 ErrorMsg *note = err->notes.at(i);
33 print_err_msg(note, color);50 print_err_msg_type(note, color, ErrTypeNote);
34 }51 }
35}52}
3653
54void print_err_msg(ErrorMsg *err, ErrColor color) {
55 print_err_msg_type(err, color, ErrTypeError);
56}
57
37void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) {58void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) {
38 parent->notes.append(note);59 parent->notes.append(note);
39}60}
src/main.cpp+25-2
...@@ -18,8 +18,8 @@...@@ -18,8 +18,8 @@
18static int usage(const char *arg0) {18static int usage(const char *arg0) {
19 fprintf(stderr, "Usage: %s [command] [options]\n"19 fprintf(stderr, "Usage: %s [command] [options]\n"
20 "Commands:\n"20 "Commands:\n"
21 " build [source] create executable, object, or library from source\n"21 " build [sources] create executable, object, or library from source\n"
22 " test [source] create and run a test build\n"22 " test [sources] create and run a test build\n"
23 " parseh [source] convert a c header file to zig extern declarations\n"23 " parseh [source] convert a c header file to zig extern declarations\n"
24 " version print version number and exit\n"24 " version print version number and exit\n"
25 " targets list available compilation targets\n"25 " targets list available compilation targets\n"
...@@ -40,6 +40,7 @@ static int usage(const char *arg0) {...@@ -40,6 +40,7 @@ static int usage(const char *arg0) {
40 " -isystem [dir] add additional search path for other .h files\n"40 " -isystem [dir] add additional search path for other .h files\n"
41 " -dirafter [dir] same as -isystem but do it last\n"41 " -dirafter [dir] same as -isystem but do it last\n"
42 " --library-path [dir] add a directory to the library search path\n"42 " --library-path [dir] add a directory to the library search path\n"
43 " --library [lib] link against lib\n"
43 " --target-arch [name] specify target architecture\n"44 " --target-arch [name] specify target architecture\n"
44 " --target-os [name] specify target operating system\n"45 " --target-os [name] specify target operating system\n"
45 " --target-environ [name] specify target environment\n"46 " --target-environ [name] specify target environment\n"
...@@ -50,6 +51,7 @@ static int usage(const char *arg0) {...@@ -50,6 +51,7 @@ static int usage(const char *arg0) {
50 " -rdynamic add all symbols to the dynamic symbol table\n"51 " -rdynamic add all symbols to the dynamic symbol table\n"
51 " -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"52 " -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"
52 " -mios-version-min [ver] (darwin only) set iOS deployment target\n"53 " -mios-version-min [ver] (darwin only) set iOS deployment target\n"
54 " --check-unused perform semantic analysis on unused declarations\n"
53 , arg0);55 , arg0);
54 return EXIT_FAILURE;56 return EXIT_FAILURE;
55}57}
...@@ -118,6 +120,7 @@ int main(int argc, char **argv) {...@@ -118,6 +120,7 @@ int main(int argc, char **argv) {
118 const char *linker_path = nullptr;120 const char *linker_path = nullptr;
119 ZigList<const char *> clang_argv = {0};121 ZigList<const char *> clang_argv = {0};
120 ZigList<const char *> lib_dirs = {0};122 ZigList<const char *> lib_dirs = {0};
123 ZigList<const char *> link_libs = {0};
121 int err;124 int err;
122 const char *target_arch = nullptr;125 const char *target_arch = nullptr;
123 const char *target_os = nullptr;126 const char *target_os = nullptr;
...@@ -129,6 +132,7 @@ int main(int argc, char **argv) {...@@ -129,6 +132,7 @@ int main(int argc, char **argv) {
129 bool rdynamic = false;132 bool rdynamic = false;
130 const char *mmacosx_version_min = nullptr;133 const char *mmacosx_version_min = nullptr;
131 const char *mios_version_min = nullptr;134 const char *mios_version_min = nullptr;
135 bool check_unused = false;
132136
133 for (int i = 1; i < argc; i += 1) {137 for (int i = 1; i < argc; i += 1) {
134 char *arg = argv[i];138 char *arg = argv[i];
...@@ -150,6 +154,8 @@ int main(int argc, char **argv) {...@@ -150,6 +154,8 @@ int main(int argc, char **argv) {
150 municode = true;154 municode = true;
151 } else if (strcmp(arg, "-rdynamic") == 0) {155 } else if (strcmp(arg, "-rdynamic") == 0) {
152 rdynamic = true;156 rdynamic = true;
157 } else if (strcmp(arg, "--check-unused") == 0) {
158 check_unused = true;
153 } else if (i + 1 >= argc) {159 } else if (i + 1 >= argc) {
154 return usage(arg0);160 return usage(arg0);
155 } else {161 } else {
...@@ -198,6 +204,8 @@ int main(int argc, char **argv) {...@@ -198,6 +204,8 @@ int main(int argc, char **argv) {
198 clang_argv.append(argv[i]);204 clang_argv.append(argv[i]);
199 } else if (strcmp(arg, "--library-path") == 0) {205 } else if (strcmp(arg, "--library-path") == 0) {
200 lib_dirs.append(argv[i]);206 lib_dirs.append(argv[i]);
207 } else if (strcmp(arg, "--library") == 0) {
208 link_libs.append(argv[i]);
201 } else if (strcmp(arg, "--target-arch") == 0) {209 } else if (strcmp(arg, "--target-arch") == 0) {
202 target_arch = argv[i];210 target_arch = argv[i];
203 } else if (strcmp(arg, "--target-os") == 0) {211 } else if (strcmp(arg, "--target-os") == 0) {
...@@ -258,6 +266,16 @@ int main(int argc, char **argv) {...@@ -258,6 +266,16 @@ int main(int argc, char **argv) {
258 if (!in_file)266 if (!in_file)
259 return usage(arg0);267 return usage(arg0);
260268
269 if (cmd == CmdBuild && !out_name) {
270 fprintf(stderr, "--name [name] not provided\n\n");
271 return usage(arg0);
272 }
273
274 if (cmd == CmdBuild && out_type == OutTypeUnknown) {
275 fprintf(stderr, "--export [exe|lib|obj] not provided\n\n");
276 return usage(arg0);
277 }
278
261 init_all_targets();279 init_all_targets();
262280
263 ZigTarget alloc_target;281 ZigTarget alloc_target;
...@@ -313,6 +331,8 @@ int main(int argc, char **argv) {...@@ -313,6 +331,8 @@ int main(int argc, char **argv) {
313 codegen_set_is_release(g, is_release_build);331 codegen_set_is_release(g, is_release_build);
314 codegen_set_is_test(g, cmd == CmdTest);332 codegen_set_is_test(g, cmd == CmdTest);
315333
334 codegen_set_check_unused(g, check_unused);
335
316 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);336 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
317 codegen_set_strip(g, strip);337 codegen_set_strip(g, strip);
318 codegen_set_is_static(g, is_static);338 codegen_set_is_static(g, is_static);
...@@ -342,6 +362,9 @@ int main(int argc, char **argv) {...@@ -342,6 +362,9 @@ int main(int argc, char **argv) {
342 for (int i = 0; i < lib_dirs.length; i += 1) {362 for (int i = 0; i < lib_dirs.length; i += 1) {
343 codegen_add_lib_dir(g, lib_dirs.at(i));363 codegen_add_lib_dir(g, lib_dirs.at(i));
344 }364 }
365 for (int i = 0; i < link_libs.length; i += 1) {
366 codegen_add_link_lib(g, link_libs.at(i));
367 }
345368
346 codegen_set_windows_subsystem(g, mwindows, mconsole);369 codegen_set_windows_subsystem(g, mwindows, mconsole);
347 codegen_set_windows_unicode(g, municode);370 codegen_set_windows_unicode(g, municode);
src/parseh.cpp+8-8
...@@ -121,9 +121,9 @@ static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char...@@ -121,9 +121,9 @@ static AstNode *create_typed_var_decl_node(Context *c, bool is_const, const char
121 AstNode *node = create_node(c, NodeTypeVariableDeclaration);121 AstNode *node = create_node(c, NodeTypeVariableDeclaration);
122 buf_init_from_str(&node->data.variable_declaration.symbol, var_name);122 buf_init_from_str(&node->data.variable_declaration.symbol, var_name);
123 node->data.variable_declaration.is_const = is_const;123 node->data.variable_declaration.is_const = is_const;
124 node->data.variable_declaration.visib_mod = c->visib_mod;124 node->data.variable_declaration.top_level_decl.visib_mod = c->visib_mod;
125 node->data.variable_declaration.expr = init_node;125 node->data.variable_declaration.expr = init_node;
126 node->data.variable_declaration.directives = nullptr;126 node->data.variable_declaration.top_level_decl.directives = nullptr;
127 node->data.variable_declaration.type = type_node;127 node->data.variable_declaration.type = type_node;
128 normalize_parent_ptrs(node);128 normalize_parent_ptrs(node);
129 return node;129 return node;
...@@ -146,7 +146,7 @@ static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *...@@ -146,7 +146,7 @@ static AstNode *create_struct_field_node(Context *c, const char *name, AstNode *
146 assert(type_node);146 assert(type_node);
147 AstNode *node = create_node(c, NodeTypeStructField);147 AstNode *node = create_node(c, NodeTypeStructField);
148 buf_init_from_str(&node->data.struct_field.name, name);148 buf_init_from_str(&node->data.struct_field.name, name);
149 node->data.struct_field.visib_mod = VisibModPub;149 node->data.struct_field.top_level_decl.visib_mod = VisibModPub;
150 node->data.struct_field.type = type_node;150 node->data.struct_field.type = type_node;
151151
152 normalize_parent_ptrs(node);152 normalize_parent_ptrs(node);
...@@ -202,7 +202,7 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {...@@ -202,7 +202,7 @@ static AstNode *create_num_lit_signed(Context *c, int64_t x) {
202static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {202static AstNode *create_type_decl_node(Context *c, const char *name, AstNode *child_type_node) {
203 AstNode *node = create_node(c, NodeTypeTypeDecl);203 AstNode *node = create_node(c, NodeTypeTypeDecl);
204 buf_init_from_str(&node->data.type_decl.symbol, name);204 buf_init_from_str(&node->data.type_decl.symbol, name);
205 node->data.type_decl.visib_mod = c->visib_mod;205 node->data.type_decl.top_level_decl.visib_mod = c->visib_mod;
206 node->data.type_decl.child_type = child_type_node;206 node->data.type_decl.child_type = child_type_node;
207207
208 normalize_parent_ptrs(node);208 normalize_parent_ptrs(node);
...@@ -219,7 +219,7 @@ static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_t...@@ -219,7 +219,7 @@ static AstNode *create_fn_proto_node(Context *c, Buf *name, TypeTableEntry *fn_t
219 assert(fn_type->id == TypeTableEntryIdFn);219 assert(fn_type->id == TypeTableEntryIdFn);
220 AstNode *node = create_node(c, NodeTypeFnProto);220 AstNode *node = create_node(c, NodeTypeFnProto);
221 node->data.fn_proto.is_inline = true;221 node->data.fn_proto.is_inline = true;
222 node->data.fn_proto.visib_mod = c->visib_mod;222 node->data.fn_proto.top_level_decl.visib_mod = c->visib_mod;
223 buf_init_from_buf(&node->data.fn_proto.name, name);223 buf_init_from_buf(&node->data.fn_proto.name, name);
224 node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);224 node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);
225225
...@@ -677,7 +677,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {...@@ -677,7 +677,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
677 buf_init_from_buf(&node->data.fn_proto.name, &fn_name);677 buf_init_from_buf(&node->data.fn_proto.name, &fn_name);
678678
679 node->data.fn_proto.is_extern = fn_type->data.fn.fn_type_id.is_extern;679 node->data.fn_proto.is_extern = fn_type->data.fn.fn_type_id.is_extern;
680 node->data.fn_proto.visib_mod = c->visib_mod;680 node->data.fn_proto.top_level_decl.visib_mod = c->visib_mod;
681 node->data.fn_proto.is_var_args = fn_type->data.fn.fn_type_id.is_var_args;681 node->data.fn_proto.is_var_args = fn_type->data.fn.fn_type_id.is_var_args;
682 node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);682 node->data.fn_proto.return_type = make_type_node(c, fn_type->data.fn.fn_type_id.return_type);
683683
...@@ -861,7 +861,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {...@@ -861,7 +861,7 @@ static void visit_enum_decl(Context *c, const EnumDecl *enum_decl) {
861 AstNode *enum_node = create_node(c, NodeTypeStructDecl);861 AstNode *enum_node = create_node(c, NodeTypeStructDecl);
862 buf_init_from_buf(&enum_node->data.struct_decl.name, full_type_name);862 buf_init_from_buf(&enum_node->data.struct_decl.name, full_type_name);
863 enum_node->data.struct_decl.kind = ContainerKindEnum;863 enum_node->data.struct_decl.kind = ContainerKindEnum;
864 enum_node->data.struct_decl.visib_mod = VisibModExport;864 enum_node->data.struct_decl.top_level_decl.visib_mod = VisibModExport;
865 enum_node->data.struct_decl.type_entry = enum_type;865 enum_node->data.struct_decl.type_entry = enum_type;
866866
867 for (uint32_t i = 0; i < field_count; i += 1) {867 for (uint32_t i = 0; i < field_count; i += 1) {
...@@ -1043,7 +1043,7 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {...@@ -1043,7 +1043,7 @@ static void visit_record_decl(Context *c, const RecordDecl *record_decl) {
1043 AstNode *struct_node = create_node(c, NodeTypeStructDecl);1043 AstNode *struct_node = create_node(c, NodeTypeStructDecl);
1044 buf_init_from_buf(&struct_node->data.struct_decl.name, &struct_type->name);1044 buf_init_from_buf(&struct_node->data.struct_decl.name, &struct_type->name);
1045 struct_node->data.struct_decl.kind = ContainerKindStruct;1045 struct_node->data.struct_decl.kind = ContainerKindStruct;
1046 struct_node->data.struct_decl.visib_mod = VisibModExport;1046 struct_node->data.struct_decl.top_level_decl.visib_mod = VisibModExport;
1047 struct_node->data.struct_decl.type_entry = struct_type;1047 struct_node->data.struct_decl.type_entry = struct_type;
10481048
1049 for (uint32_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {1049 for (uint32_t i = 0; i < struct_type->data.structure.src_field_count; i += 1) {
src/parser.cpp+32-109
...@@ -20,7 +20,6 @@ struct ParseContext {...@@ -20,7 +20,6 @@ struct ParseContext {
20 ZigList<Token> *tokens;20 ZigList<Token> *tokens;
21 ImportTableEntry *owner;21 ImportTableEntry *owner;
22 ErrColor err_color;22 ErrColor err_color;
23 bool parsed_root_export;
24 uint32_t *next_node_index;23 uint32_t *next_node_index;
25};24};
2625
...@@ -1741,8 +1740,8 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token...@@ -1741,8 +1740,8 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token
1741 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token);1740 AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, first_token);
17421741
1743 node->data.variable_declaration.is_const = is_const;1742 node->data.variable_declaration.is_const = is_const;
1744 node->data.variable_declaration.visib_mod = visib_mod;1743 node->data.variable_declaration.top_level_decl.visib_mod = visib_mod;
1745 node->data.variable_declaration.directives = directives;1744 node->data.variable_declaration.top_level_decl.directives = directives;
17461745
1747 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);1746 Token *name_token = ast_eat_token(pc, token_index, TokenIdSymbol);
1748 ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);1747 ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);
...@@ -2251,8 +2250,8 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand...@@ -2251,8 +2250,8 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
2251 *token_index += 1;2250 *token_index += 1;
22522251
2253 AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);2252 AstNode *node = ast_create_node(pc, NodeTypeFnProto, first_token);
2254 node->data.fn_proto.visib_mod = visib_mod;2253 node->data.fn_proto.top_level_decl.visib_mod = visib_mod;
2255 node->data.fn_proto.directives = directives;2254 node->data.fn_proto.top_level_decl.directives = directives;
22562255
2257 Token *fn_name = &pc->tokens->at(*token_index);2256 Token *fn_name = &pc->tokens->at(*token_index);
2258 if (fn_name->id == TokenIdSymbol) {2257 if (fn_name->id == TokenIdSymbol) {
...@@ -2345,76 +2344,23 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool m...@@ -2345,76 +2344,23 @@ static AstNode *ast_parse_extern_decl(ParseContext *pc, int *token_index, bool m
2345}2344}
23462345
2347/*2346/*
2348RootExportDecl : "export" "Symbol" "String" ";"2347UseDecl = "use" Expression ";"
2349*/2348*/
2350static AstNode *ast_parse_root_export_decl(ParseContext *pc, int *token_index,2349static AstNode *ast_parse_use(ParseContext *pc, int *token_index,
2351 ZigList<AstNode*> *directives)
2352{
2353 Token *export_type = &pc->tokens->at(*token_index);
2354 if (export_type->id != TokenIdSymbol)
2355 return nullptr;
2356
2357 *token_index += 1;
2358
2359 AstNode *node = ast_create_node(pc, NodeTypeRootExportDecl, export_type);
2360 node->data.root_export_decl.directives = directives;
2361
2362 ast_buf_from_token(pc, export_type, &node->data.root_export_decl.type);
2363
2364 Token *export_name = &pc->tokens->at(*token_index);
2365 *token_index += 1;
2366 ast_expect_token(pc, export_name, TokenIdStringLiteral);
2367
2368 parse_string_literal(pc, export_name, &node->data.root_export_decl.name, nullptr, nullptr);
2369
2370 Token *semicolon = &pc->tokens->at(*token_index);
2371 *token_index += 1;
2372 ast_expect_token(pc, semicolon, TokenIdSemicolon);
2373
2374 normalize_parent_ptrs(node);
2375 return node;
2376}
2377
2378/*
2379Import : "import" "String" ";"
2380*/
2381static AstNode *ast_parse_import(ParseContext *pc, int *token_index,
2382 ZigList<AstNode*> *directives, VisibMod visib_mod)2350 ZigList<AstNode*> *directives, VisibMod visib_mod)
2383{2351{
2384 Token *import_kw = &pc->tokens->at(*token_index);2352 Token *use_kw = &pc->tokens->at(*token_index);
2385 if (import_kw->id != TokenIdKeywordImport)2353 if (use_kw->id != TokenIdKeywordUse)
2386 return nullptr;2354 return nullptr;
2387 *token_index += 1;2355 *token_index += 1;
23882356
2389 Token *import_name = ast_eat_token(pc, token_index, TokenIdStringLiteral);2357 AstNode *node = ast_create_node(pc, NodeTypeUse, use_kw);
2358 node->data.use.top_level_decl.visib_mod = visib_mod;
2359 node->data.use.top_level_decl.directives = directives;
2360 node->data.use.expr = ast_parse_expression(pc, token_index, true);
23902361
2391 ast_eat_token(pc, token_index, TokenIdSemicolon);2362 ast_eat_token(pc, token_index, TokenIdSemicolon);
23922363
2393 AstNode *node = ast_create_node(pc, NodeTypeImport, import_kw);
2394 node->data.import.visib_mod = visib_mod;
2395 node->data.import.directives = directives;
2396
2397 parse_string_literal(pc, import_name, &node->data.import.path, nullptr, nullptr);
2398 normalize_parent_ptrs(node);
2399 return node;
2400}
2401
2402/*
2403CImportDecl : "c_import" Block
2404*/
2405static AstNode *ast_parse_c_import(ParseContext *pc, int *token_index,
2406 ZigList<AstNode*> *directives, VisibMod visib_mod)
2407{
2408 Token *c_import_kw = &pc->tokens->at(*token_index);
2409 if (c_import_kw->id != TokenIdKeywordCImport)
2410 return nullptr;
2411 *token_index += 1;
2412
2413 AstNode *node = ast_create_node(pc, NodeTypeCImport, c_import_kw);
2414 node->data.c_import.visib_mod = visib_mod;
2415 node->data.c_import.directives = directives;
2416 node->data.c_import.block = ast_parse_block(pc, token_index, true);
2417
2418 normalize_parent_ptrs(node);2364 normalize_parent_ptrs(node);
2419 return node;2365 return node;
2420}2366}
...@@ -2445,8 +2391,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,...@@ -2445,8 +2391,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
2445 AstNode *node = ast_create_node(pc, NodeTypeStructDecl, first_token);2391 AstNode *node = ast_create_node(pc, NodeTypeStructDecl, first_token);
2446 node->data.struct_decl.kind = kind;2392 node->data.struct_decl.kind = kind;
2447 ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name);2393 ast_buf_from_token(pc, struct_name, &node->data.struct_decl.name);
2448 node->data.struct_decl.visib_mod = visib_mod;2394 node->data.struct_decl.top_level_decl.visib_mod = visib_mod;
2449 node->data.struct_decl.directives = directives;2395 node->data.struct_decl.top_level_decl.directives = directives;
24502396
2451 ast_eat_token(pc, token_index, TokenIdLBrace);2397 ast_eat_token(pc, token_index, TokenIdLBrace);
24522398
...@@ -2486,8 +2432,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,...@@ -2486,8 +2432,8 @@ static AstNode *ast_parse_struct_decl(ParseContext *pc, int *token_index,
2486 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);2432 AstNode *field_node = ast_create_node(pc, NodeTypeStructField, token);
2487 *token_index += 1;2433 *token_index += 1;
24882434
2489 field_node->data.struct_field.visib_mod = visib_mod;2435 field_node->data.struct_field.top_level_decl.visib_mod = visib_mod;
2490 field_node->data.struct_field.directives = directive_list;2436 field_node->data.struct_field.top_level_decl.directives = directive_list;
24912437
2492 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);2438 ast_buf_from_token(pc, token, &field_node->data.struct_field.name);
24932439
...@@ -2529,8 +2475,8 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index,...@@ -2529,8 +2475,8 @@ static AstNode *ast_parse_error_value_decl(ParseContext *pc, int *token_index,
2529 ast_eat_token(pc, token_index, TokenIdSemicolon);2475 ast_eat_token(pc, token_index, TokenIdSemicolon);
25302476
2531 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);2477 AstNode *node = ast_create_node(pc, NodeTypeErrorValueDecl, first_token);
2532 node->data.error_value_decl.visib_mod = visib_mod;2478 node->data.error_value_decl.top_level_decl.visib_mod = visib_mod;
2533 node->data.error_value_decl.directives = directives;2479 node->data.error_value_decl.top_level_decl.directives = directives;
2534 ast_buf_from_token(pc, name_tok, &node->data.error_value_decl.name);2480 ast_buf_from_token(pc, name_tok, &node->data.error_value_decl.name);
25352481
2536 normalize_parent_ptrs(node);2482 normalize_parent_ptrs(node);
...@@ -2559,15 +2505,15 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, int *token_index,...@@ -2559,15 +2505,15 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, int *token_index,
25592505
2560 ast_eat_token(pc, token_index, TokenIdSemicolon);2506 ast_eat_token(pc, token_index, TokenIdSemicolon);
25612507
2562 node->data.type_decl.visib_mod = visib_mod;2508 node->data.type_decl.top_level_decl.visib_mod = visib_mod;
2563 node->data.type_decl.directives = directives;2509 node->data.type_decl.top_level_decl.directives = directives;
25642510
2565 normalize_parent_ptrs(node);2511 normalize_parent_ptrs(node);
2566 return node;2512 return node;
2567}2513}
25682514
2569/*2515/*
2570TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | RootExportDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)2516TopLevelDecl = many(Directive) option(VisibleMod) (FnDef | ExternDecl | Import | ContainerDecl | GlobalVarDecl | ErrorValueDecl | CImportDecl | TypeDecl)
2571*/2517*/
2572static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {2518static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigList<AstNode *> *top_level_decls) {
2573 for (;;) {2519 for (;;) {
...@@ -2587,17 +2533,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis...@@ -2587,17 +2533,6 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
2587 visib_mod = VisibModPrivate;2533 visib_mod = VisibModPrivate;
2588 }2534 }
25892535
2590 bool try_to_parse_root_export = (visib_mod == VisibModExport && !pc->parsed_root_export);
2591 pc->parsed_root_export = true;
2592
2593 if (try_to_parse_root_export) {
2594 AstNode *root_export_decl_node = ast_parse_root_export_decl(pc, token_index, directives);
2595 if (root_export_decl_node) {
2596 top_level_decls->append(root_export_decl_node);
2597 continue;
2598 }
2599 }
2600
2601 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod);2536 AstNode *fn_def_node = ast_parse_fn_def(pc, token_index, false, directives, visib_mod);
2602 if (fn_def_node) {2537 if (fn_def_node) {
2603 top_level_decls->append(fn_def_node);2538 top_level_decls->append(fn_def_node);
...@@ -2610,15 +2545,9 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis...@@ -2610,15 +2545,9 @@ static void ast_parse_top_level_decls(ParseContext *pc, int *token_index, ZigLis
2610 continue;2545 continue;
2611 }2546 }
26122547
2613 AstNode *import_node = ast_parse_import(pc, token_index, directives, visib_mod);2548 AstNode *use_node = ast_parse_use(pc, token_index, directives, visib_mod);
2614 if (import_node) {2549 if (use_node) {
2615 top_level_decls->append(import_node);2550 top_level_decls->append(use_node);
2616 continue;
2617 }
2618
2619 AstNode *c_import_node = ast_parse_c_import(pc, token_index, directives, visib_mod);
2620 if (c_import_node) {
2621 top_level_decls->append(c_import_node);
2622 continue;2551 continue;
2623 }2552 }
26242553
...@@ -2706,12 +2635,9 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2706,12 +2635,9 @@ void normalize_parent_ptrs(AstNode *node) {
2706 case NodeTypeRoot:2635 case NodeTypeRoot:
2707 set_list_fields(&node->data.root.top_level_decls);2636 set_list_fields(&node->data.root.top_level_decls);
2708 break;2637 break;
2709 case NodeTypeRootExportDecl:
2710 set_list_fields(node->data.root_export_decl.directives);
2711 break;
2712 case NodeTypeFnProto:2638 case NodeTypeFnProto:
2713 set_field(&node->data.fn_proto.return_type);2639 set_field(&node->data.fn_proto.return_type);
2714 set_list_fields(node->data.fn_proto.directives);2640 set_list_fields(node->data.fn_proto.top_level_decl.directives);
2715 set_list_fields(&node->data.fn_proto.params);2641 set_list_fields(&node->data.fn_proto.params);
2716 break;2642 break;
2717 case NodeTypeFnDef:2643 case NodeTypeFnDef:
...@@ -2737,12 +2663,12 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2737,12 +2663,12 @@ void normalize_parent_ptrs(AstNode *node) {
2737 set_field(&node->data.defer.expr);2663 set_field(&node->data.defer.expr);
2738 break;2664 break;
2739 case NodeTypeVariableDeclaration:2665 case NodeTypeVariableDeclaration:
2740 set_list_fields(node->data.variable_declaration.directives);2666 set_list_fields(node->data.variable_declaration.top_level_decl.directives);
2741 set_field(&node->data.variable_declaration.type);2667 set_field(&node->data.variable_declaration.type);
2742 set_field(&node->data.variable_declaration.expr);2668 set_field(&node->data.variable_declaration.expr);
2743 break;2669 break;
2744 case NodeTypeTypeDecl:2670 case NodeTypeTypeDecl:
2745 set_list_fields(node->data.type_decl.directives);2671 set_list_fields(node->data.type_decl.top_level_decl.directives);
2746 set_field(&node->data.type_decl.child_type);2672 set_field(&node->data.type_decl.child_type);
2747 break;2673 break;
2748 case NodeTypeErrorValueDecl:2674 case NodeTypeErrorValueDecl:
...@@ -2788,12 +2714,9 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2788,12 +2714,9 @@ void normalize_parent_ptrs(AstNode *node) {
2788 case NodeTypeFieldAccessExpr:2714 case NodeTypeFieldAccessExpr:
2789 set_field(&node->data.field_access_expr.struct_expr);2715 set_field(&node->data.field_access_expr.struct_expr);
2790 break;2716 break;
2791 case NodeTypeImport:2717 case NodeTypeUse:
2792 set_list_fields(node->data.import.directives);2718 set_field(&node->data.use.expr);
2793 break;2719 set_list_fields(node->data.use.top_level_decl.directives);
2794 case NodeTypeCImport:
2795 set_list_fields(node->data.c_import.directives);
2796 set_field(&node->data.c_import.block);
2797 break;2720 break;
2798 case NodeTypeBoolLiteral:2721 case NodeTypeBoolLiteral:
2799 // none2722 // none
...@@ -2863,11 +2786,11 @@ void normalize_parent_ptrs(AstNode *node) {...@@ -2863,11 +2786,11 @@ void normalize_parent_ptrs(AstNode *node) {
2863 case NodeTypeStructDecl:2786 case NodeTypeStructDecl:
2864 set_list_fields(&node->data.struct_decl.fields);2787 set_list_fields(&node->data.struct_decl.fields);
2865 set_list_fields(&node->data.struct_decl.fns);2788 set_list_fields(&node->data.struct_decl.fns);
2866 set_list_fields(node->data.struct_decl.directives);2789 set_list_fields(node->data.struct_decl.top_level_decl.directives);
2867 break;2790 break;
2868 case NodeTypeStructField:2791 case NodeTypeStructField:
2869 set_field(&node->data.struct_field.type);2792 set_field(&node->data.struct_field.type);
2870 set_list_fields(node->data.struct_field.directives);2793 set_list_fields(node->data.struct_field.top_level_decl.directives);
2871 break;2794 break;
2872 case NodeTypeContainerInitExpr:2795 case NodeTypeContainerInitExpr:
2873 set_field(&node->data.container_init_expr.type);2796 set_field(&node->data.container_init_expr.type);
src/tokenizer.cpp+4-7
...@@ -99,7 +99,7 @@...@@ -99,7 +99,7 @@
9999
100const char * zig_keywords[] = {100const char * zig_keywords[] = {
101 "true", "false", "null", "fn", "return", "var", "const", "extern",101 "true", "false", "null", "fn", "return", "var", "const", "extern",
102 "pub", "export", "import", "c_import", "if", "else", "goto", "asm",102 "pub", "export", "use", "if", "else", "goto", "asm",
103 "volatile", "struct", "enum", "while", "for", "continue", "break",103 "volatile", "struct", "enum", "while", "for", "continue", "break",
104 "null", "noalias", "switch", "undefined", "error", "type", "inline",104 "null", "noalias", "switch", "undefined", "error", "type", "inline",
105 "defer",105 "defer",
...@@ -232,10 +232,8 @@ static void end_token(Tokenize *t) {...@@ -232,10 +232,8 @@ static void end_token(Tokenize *t) {
232 t->cur_tok->id = TokenIdKeywordPub;232 t->cur_tok->id = TokenIdKeywordPub;
233 } else if (mem_eql_str(token_mem, token_len, "export")) {233 } else if (mem_eql_str(token_mem, token_len, "export")) {
234 t->cur_tok->id = TokenIdKeywordExport;234 t->cur_tok->id = TokenIdKeywordExport;
235 } else if (mem_eql_str(token_mem, token_len, "c_import")) {235 } else if (mem_eql_str(token_mem, token_len, "use")) {
236 t->cur_tok->id = TokenIdKeywordCImport;236 t->cur_tok->id = TokenIdKeywordUse;
237 } else if (mem_eql_str(token_mem, token_len, "import")) {
238 t->cur_tok->id = TokenIdKeywordImport;
239 } else if (mem_eql_str(token_mem, token_len, "true")) {237 } else if (mem_eql_str(token_mem, token_len, "true")) {
240 t->cur_tok->id = TokenIdKeywordTrue;238 t->cur_tok->id = TokenIdKeywordTrue;
241 } else if (mem_eql_str(token_mem, token_len, "false")) {239 } else if (mem_eql_str(token_mem, token_len, "false")) {
...@@ -1071,8 +1069,7 @@ const char * token_name(TokenId id) {...@@ -1071,8 +1069,7 @@ const char * token_name(TokenId id) {
1071 case TokenIdKeywordExtern: return "extern";1069 case TokenIdKeywordExtern: return "extern";
1072 case TokenIdKeywordPub: return "pub";1070 case TokenIdKeywordPub: return "pub";
1073 case TokenIdKeywordExport: return "export";1071 case TokenIdKeywordExport: return "export";
1074 case TokenIdKeywordImport: return "import";1072 case TokenIdKeywordUse: return "use";
1075 case TokenIdKeywordCImport: return "c_import";
1076 case TokenIdKeywordTrue: return "true";1073 case TokenIdKeywordTrue: return "true";
1077 case TokenIdKeywordFalse: return "false";1074 case TokenIdKeywordFalse: return "false";
1078 case TokenIdKeywordIf: return "if";1075 case TokenIdKeywordIf: return "if";
src/tokenizer.hpp+1-2
...@@ -19,9 +19,8 @@ enum TokenId {...@@ -19,9 +19,8 @@ enum TokenId {
19 TokenIdKeywordConst,19 TokenIdKeywordConst,
20 TokenIdKeywordExtern,20 TokenIdKeywordExtern,
21 TokenIdKeywordPub,21 TokenIdKeywordPub,
22 TokenIdKeywordUse,
22 TokenIdKeywordExport,23 TokenIdKeywordExport,
23 TokenIdKeywordImport,
24 TokenIdKeywordCImport,
25 TokenIdKeywordTrue,24 TokenIdKeywordTrue,
26 TokenIdKeywordFalse,25 TokenIdKeywordFalse,
27 TokenIdKeywordIf,26 TokenIdKeywordIf,
std/bootstrap.zig+15-14
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1import "syscall.zig";1// This file is in a package which has the root source file exposed as "@root".
22
3// The compiler treats this file special by implicitly importing the function `main`3const root = @import("@root");
4// from the root source file as the symbol `zig_user_main`.4const syscall = @import("syscall.zig");
55
6const want_start_symbol = switch(@compile_var("os")) {6const want_start_symbol = switch(@compile_var("os")) {
7 linux => true,7 linux => true,
...@@ -26,7 +26,7 @@ export fn _start() -> unreachable {...@@ -26,7 +26,7 @@ export fn _start() -> unreachable {
26 },26 },
27 else => unreachable{},27 else => unreachable{},
28 }28 }
29 call_main()29 call_main_and_exit()
30}30}
3131
32fn strlen(ptr: &const u8) -> isize {32fn strlen(ptr: &const u8) -> isize {
...@@ -37,23 +37,24 @@ fn strlen(ptr: &const u8) -> isize {...@@ -37,23 +37,24 @@ fn strlen(ptr: &const u8) -> isize {
37 return count;37 return count;
38}38}
3939
40fn call_main() -> unreachable {40fn call_main() -> %void {
41 var args: [argc][]u8 = undefined;41 var args: [argc][]u8 = undefined;
42 for (args) |arg, i| {42 for (args) |arg, i| {
43 const ptr = argv[i];43 const ptr = argv[i];
44 args[i] = ptr[0...strlen(ptr)];44 args[i] = ptr[0...strlen(ptr)];
45 }45 }
46 zig_user_main(args) %% exit(1);46 return root.main(args);
47 exit(0);47}
48
49fn call_main_and_exit() -> unreachable {
50 call_main() %% syscall.exit(1);
51 syscall.exit(0);
48}52}
4953
50#condition(want_main_symbol)54#condition(want_main_symbol)
51export fn main(argc: i32, argv: &&u8) -> i32 {55export fn main(c_argc: i32, c_argv: &&u8) -> i32 {
52 var args: [argc][]u8 = undefined;56 argc = c_argc;
53 for (args) |arg, i| {57 argv = c_argv;
54 const ptr = argv[i];58 call_main() %% return 1;
55 args[i] = ptr[0...strlen(ptr)];
56 }
57 zig_user_main(args) %% return 1;
58 return 0;59 return 0;
59}60}
std/index.zig created+4
...@@ -0,0 +1,4 @@
1pub const Rand = @import("rand.zig").Rand;
2pub const io = @import("io.zig");
3pub const os = @import("os.zig");
4pub const math = @import("math.zig");
std/io.zig created+377
...@@ -0,0 +1,377 @@
1const syscall = @import("syscall.zig");
2const errno = @import("errno.zig");
3const math = @import("math.zig");
4
5pub const stdin_fileno = 0;
6pub const stdout_fileno = 1;
7pub const stderr_fileno = 2;
8
9pub var stdin = InStream {
10 .fd = stdin_fileno,
11};
12
13pub var stdout = OutStream {
14 .fd = stdout_fileno,
15 .buffer = undefined,
16 .index = 0,
17};
18
19pub var stderr = OutStream {
20 .fd = stderr_fileno,
21 .buffer = undefined,
22 .index = 0,
23};
24
25/// The function received invalid input at runtime. An Invalid error means a
26/// bug in the program that called the function.
27pub error Invalid;
28
29/// When an Unexpected error occurs, code that emitted the error likely needs
30/// a patch to recognize the unexpected case so that it can handle it and emit
31/// a more specific error.
32pub error Unexpected;
33
34pub error DiskQuota;
35pub error FileTooBig;
36pub error SigInterrupt;
37pub error Io;
38pub error NoSpaceLeft;
39pub error BadPerm;
40pub error PipeFail;
41pub error BadFd;
42
43const buffer_size = 4 * 1024;
44const max_u64_base10_digits = 20;
45const max_f64_digits = 65;
46
47pub struct OutStream {
48 fd: isize,
49 buffer: [buffer_size]u8,
50 index: isize,
51
52 pub fn print_str(os: &OutStream, str: []const u8) -> %isize {
53 var src_bytes_left = str.len;
54 var src_index: @typeof(str.len) = 0;
55 const dest_space_left = os.buffer.len - os.index;
56
57 while (src_bytes_left > 0) {
58 const copy_amt = math.min_isize(dest_space_left, src_bytes_left);
59 @memcpy(&os.buffer[os.index], &str[src_index], copy_amt);
60 os.index += copy_amt;
61 if (os.index == os.buffer.len) {
62 %return os.flush();
63 }
64 src_bytes_left -= copy_amt;
65 }
66 return str.len;
67 }
68
69 /// Prints a byte buffer, flushes the buffer, then returns the number of
70 /// bytes printed. The "f" is for "flush".
71 pub fn printf(os: &OutStream, str: []const u8) -> %isize {
72 const byte_count = %return os.print_str(str);
73 %return os.flush();
74 return byte_count;
75 }
76
77 pub fn print_u64(os: &OutStream, x: u64) -> %isize {
78 if (os.index + max_u64_base10_digits >= os.buffer.len) {
79 %return os.flush();
80 }
81 const amt_printed = buf_print_u64(os.buffer[os.index...], x);
82 os.index += amt_printed;
83
84 return amt_printed;
85 }
86
87 pub fn print_i64(os: &OutStream, x: i64) -> %isize {
88 if (os.index + max_u64_base10_digits >= os.buffer.len) {
89 %return os.flush();
90 }
91 const amt_printed = buf_print_i64(os.buffer[os.index...], x);
92 os.index += amt_printed;
93
94 return amt_printed;
95 }
96
97 pub fn print_f64(os: &OutStream, x: f64) -> %isize {
98 if (os.index + max_f64_digits >= os.buffer.len) {
99 %return os.flush();
100 }
101 const amt_printed = buf_print_f64(os.buffer[os.index...], x, 4);
102 os.index += amt_printed;
103
104 return amt_printed;
105 }
106
107 pub fn flush(os: &OutStream) -> %void {
108 const amt_written = syscall.write(os.fd, &os.buffer[0], os.index);
109 os.index = 0;
110 if (amt_written < 0) {
111 return switch (-amt_written) {
112 errno.EINVAL => unreachable{},
113 errno.EDQUOT => error.DiskQuota,
114 errno.EFBIG => error.FileTooBig,
115 errno.EINTR => error.SigInterrupt,
116 errno.EIO => error.Io,
117 errno.ENOSPC => error.NoSpaceLeft,
118 errno.EPERM => error.BadPerm,
119 errno.EPIPE => error.PipeFail,
120 else => error.Unexpected,
121 }
122 }
123 }
124
125 pub fn close(os: &OutStream) -> %void {
126 const closed = close(os.fd);
127 if (closed < 0) {
128 return switch (-closed) {
129 EIO => error.Io,
130 EBADF => error.BadFd,
131 EINTR => error.SigInterrupt,
132 else => error.Unexpected,
133 }
134 }
135 }
136}
137
138pub struct InStream {
139 fd: isize,
140
141 pub fn read(is: &InStream, buf: []u8) -> %isize {
142 const amt_read = syscall.read(is.fd, &buf[0], buf.len);
143 if (amt_read < 0) {
144 return switch (-amt_read) {
145 errno.EINVAL => unreachable{},
146 errno.EFAULT => unreachable{},
147 errno.EBADF => error.BadFd,
148 errno.EINTR => error.SigInterrupt,
149 errno.EIO => error.Io,
150 else => error.Unexpected,
151 }
152 }
153 return amt_read;
154 }
155
156 pub fn close(is: &InStream) -> %void {
157 const closed = close(is.fd);
158 if (closed < 0) {
159 return switch (-closed) {
160 EIO => error.Io,
161 EBADF => error.BadFd,
162 EINTR => error.SigInterrupt,
163 else => error.Unexpected,
164 }
165 }
166 }
167}
168
169#attribute("cold")
170pub fn abort() -> unreachable {
171 syscall.raise(syscall.SIGABRT);
172 syscall.raise(syscall.SIGKILL);
173 while (true) {}
174}
175
176pub error InvalidChar;
177pub error Overflow;
178
179pub fn parse_u64(buf: []u8, radix: u8) -> %u64 {
180 var x : u64 = 0;
181
182 for (buf) |c| {
183 const digit = char_to_digit(c);
184
185 if (digit >= radix) {
186 return error.InvalidChar;
187 }
188
189 // x *= radix
190 if (@mul_with_overflow(u64, x, radix, &x)) {
191 return error.Overflow;
192 }
193
194 // x += digit
195 if (@add_with_overflow(u64, x, digit, &x)) {
196 return error.Overflow;
197 }
198 }
199
200 return x;
201}
202
203fn char_to_digit(c: u8) -> u8 {
204 // TODO use switch with range
205 if ('0' <= c && c <= '9') {
206 c - '0'
207 } else if ('A' <= c && c <= 'Z') {
208 c - 'A' + 10
209 } else if ('a' <= c && c <= 'z') {
210 c - 'a' + 10
211 } else {
212 @max_value(u8)
213 }
214}
215
216pub fn buf_print_i64(out_buf: []u8, x: i64) -> isize {
217 if (x < 0) {
218 out_buf[0] = '-';
219 return 1 + buf_print_u64(out_buf[1...], u64(-(x + 1)) + 1);
220 } else {
221 return buf_print_u64(out_buf, u64(x));
222 }
223}
224
225pub fn buf_print_u64(out_buf: []u8, x: u64) -> isize {
226 var buf: [max_u64_base10_digits]u8 = undefined;
227 var a = x;
228 var index: isize = buf.len;
229
230 while (true) {
231 const digit = a % 10;
232 index -= 1;
233 buf[index] = '0' + u8(digit);
234 a /= 10;
235 if (a == 0)
236 break;
237 }
238
239 const len = buf.len - index;
240
241 @memcpy(&out_buf[0], &buf[index], len);
242
243 return len;
244}
245
246pub fn buf_print_f64(out_buf: []u8, x: f64, decimals: isize) -> isize {
247 const numExpBits = 11;
248 const numRawSigBits = 52; // not including implicit 1 bit
249 const expBias = 1023;
250
251 var decs = decimals;
252 if (decs >= max_u64_base10_digits) {
253 decs = max_u64_base10_digits - 1;
254 }
255
256 if (x == math.f64_get_pos_inf()) {
257 const buf2 = "+Inf";
258 @memcpy(&out_buf[0], &buf2[0], buf2.len);
259 return 4;
260 } else if (x == math.f64_get_neg_inf()) {
261 const buf2 = "-Inf";
262 @memcpy(&out_buf[0], &buf2[0], buf2.len);
263 return 4;
264 } else if (math.f64_is_nan(x)) {
265 const buf2 = "NaN";
266 @memcpy(&out_buf[0], &buf2[0], buf2.len);
267 return 3;
268 }
269
270 var buf: [max_f64_digits]u8 = undefined;
271
272 var len: isize = 0;
273
274 // 1 sign bit
275 // 11 exponent bits
276 // 52 significand bits (+ 1 implicit always non-zero bit)
277
278 const bits = math.f64_to_bits(x);
279 if (bits & (1 << 63) != 0) {
280 buf[0] = '-';
281 len += 1;
282 }
283
284 const rexponent: i64 = i64((bits >> numRawSigBits) & ((1 << numExpBits) - 1));
285 const exponent = rexponent - expBias - numRawSigBits;
286
287 if (rexponent == 0) {
288 buf[len] = '0';
289 len += 1;
290 @memcpy(&out_buf[0], &buf[0], len);
291 return len;
292 }
293
294 const sig = (bits & ((1 << numRawSigBits) - 1)) | (1 << numRawSigBits);
295
296 if (exponent >= 0) {
297 // number is an integer
298
299 if (exponent >= 64 - 53) {
300 // use XeX form
301
302 // TODO support printing large floats
303 //len += buf_print_u64(buf[len...], sig << 10);
304 const str = "LARGEF64";
305 @memcpy(&buf[len], &str[0], str.len);
306 len += str.len;
307 } else {
308 // use typical form
309
310 len += buf_print_u64(buf[len...], sig << u64(exponent));
311 buf[len] = '.';
312 len += 1;
313
314 var i: isize = 0;
315 while (i < decs) {
316 buf[len] = '0';
317 len += 1;
318 i += 1;
319 }
320 }
321 } else {
322 // number is not an integer
323
324 // print out whole part
325 len += buf_print_u64(buf[len...], sig >> u64(-exponent));
326 buf[len] = '.';
327 len += 1;
328
329 // print out fractional part
330 // dec_num holds: fractional part * 10 ^ decs
331 var dec_num: u64 = 0;
332
333 var a: isize = 1;
334 var i: isize = 0;
335 while (i < decs + 5) {
336 a *= 10;
337 i += 1;
338 }
339
340 // create a mask: 1's for the fractional part, 0's for whole part
341 var masked_sig = sig & ((1 << u64(-exponent)) - 1);
342 i = -1;
343 while (i >= exponent) {
344 var bit_set = ((1 << u64(i-exponent)) & masked_sig) != 0;
345
346 if (bit_set) {
347 dec_num += usize(a) >> usize(-i);
348 }
349
350 i -= 1;
351 }
352
353 dec_num /= 100000;
354
355 len += decs;
356
357 i = len - 1;
358 while (i >= len - decs) {
359 buf[i] = '0' + u8(dec_num % 10);
360 dec_num /= 10;
361 i -= 1;
362 }
363 }
364
365 @memcpy(&out_buf[0], &buf[0], len);
366
367 len
368}
369
370#attribute("test")
371fn parse_u64_digit_too_big() {
372 parse_u64("123a", 10) %% |err| {
373 if (err == error.InvalidChar) return;
374 unreachable{};
375 };
376 unreachable{};
377}
std/os.zig+8-8
...@@ -1,19 +1,19 @@...@@ -1,19 +1,19 @@
1import "syscall.zig";1const syscall = @import("syscall.zig");
2import "errno.zig";2const errno = @import("errno.zig");
33
4pub error SigInterrupt;4pub error SigInterrupt;
5pub error Unexpected;5pub error Unexpected;
66
7pub fn os_get_random_bytes(buf: []u8) -> %void {7pub fn get_random_bytes(buf: []u8) -> %void {
8 switch (@compile_var("os")) {8 switch (@compile_var("os")) {
9 linux => {9 linux => {
10 const amt_got = getrandom(buf.ptr, buf.len, 0);10 const amt_got = syscall.getrandom(buf.ptr, buf.len, 0);
11 if (amt_got < 0) {11 if (amt_got < 0) {
12 return switch (-amt_got) {12 return switch (-amt_got) {
13 EINVAL => unreachable{},13 errno.EINVAL => unreachable{},
14 EFAULT => unreachable{},14 errno.EFAULT => unreachable{},
15 EINTR => error.SigInterrupt,15 errno.EINTR => error.SigInterrupt,
16 else => error.Unexpected,16 else => error.Unexpected,
17 }17 }
18 }18 }
19 },19 },
std/rand.zig+14-14
...@@ -84,26 +84,26 @@ pub struct Rand {...@@ -84,26 +84,26 @@ pub struct Rand {
84 }84 }
85 return bytes_left;85 return bytes_left;
86 }86 }
87}
8887
89/// Initialize random state with the given seed.88 /// Initialize random state with the given seed.
90pub fn rand_new(seed: u32) -> Rand {89 pub fn init(seed: u32) -> Rand {
91 var r: Rand = undefined;90 var r: Rand = undefined;
92 r.index = 0;91 r.index = 0;
93 r.array[0] = seed;92 r.array[0] = seed;
94 var i : isize = 1;93 var i : isize = 1;
95 var prev_value: u64 = seed;94 var prev_value: u64 = seed;
96 while (i < ARRAY_SIZE) {95 while (i < ARRAY_SIZE) {
97 r.array[i] = u32((prev_value ^ (prev_value << 30)) * 0x6c078965 + u32(i));96 r.array[i] = u32((prev_value ^ (prev_value << 30)) * 0x6c078965 + u32(i));
98 prev_value = r.array[i];97 prev_value = r.array[i];
99 i += 1;98 i += 1;
99 }
100 return r;
100 }101 }
101 return r;
102}102}
103103
104#attribute("test")104#attribute("test")
105fn test_float32() {105fn test_float32() {
106 var r = rand_new(42);106 var r = Rand.init(42);
107107
108 // TODO for loop with range108 // TODO for loop with range
109 var i: i32 = 0;109 var i: i32 = 0;
std/std.zig deleted-377
...@@ -1,377 +0,0 @@
1import "syscall.zig";
2import "errno.zig";
3import "math.zig";
4
5pub const stdin_fileno = 0;
6pub const stdout_fileno = 1;
7pub const stderr_fileno = 2;
8
9pub var stdin = InStream {
10 .fd = stdin_fileno,
11};
12
13pub var stdout = OutStream {
14 .fd = stdout_fileno,
15 .buffer = undefined,
16 .index = 0,
17};
18
19pub var stderr = OutStream {
20 .fd = stderr_fileno,
21 .buffer = undefined,
22 .index = 0,
23};
24
25/// The function received invalid input at runtime. An Invalid error means a
26/// bug in the program that called the function.
27pub error Invalid;
28
29/// When an Unexpected error occurs, code that emitted the error likely needs
30/// a patch to recognize the unexpected case so that it can handle it and emit
31/// a more specific error.
32pub error Unexpected;
33
34pub error DiskQuota;
35pub error FileTooBig;
36pub error SigInterrupt;
37pub error Io;
38pub error NoSpaceLeft;
39pub error BadPerm;
40pub error PipeFail;
41pub error BadFd;
42
43const buffer_size = 4 * 1024;
44const max_u64_base10_digits = 20;
45const max_f64_digits = 65;
46
47pub struct OutStream {
48 fd: isize,
49 buffer: [buffer_size]u8,
50 index: isize,
51
52 pub fn print_str(os: &OutStream, str: []const u8) -> %isize {
53 var src_bytes_left = str.len;
54 var src_index: @typeof(str.len) = 0;
55 const dest_space_left = os.buffer.len - os.index;
56
57 while (src_bytes_left > 0) {
58 const copy_amt = min_isize(dest_space_left, src_bytes_left);
59 @memcpy(&os.buffer[os.index], &str[src_index], copy_amt);
60 os.index += copy_amt;
61 if (os.index == os.buffer.len) {
62 %return os.flush();
63 }
64 src_bytes_left -= copy_amt;
65 }
66 return str.len;
67 }
68
69 /// Prints a byte buffer, flushes the buffer, then returns the number of
70 /// bytes printed. The "f" is for "flush".
71 pub fn printf(os: &OutStream, str: []const u8) -> %isize {
72 const byte_count = %return os.print_str(str);
73 %return os.flush();
74 return byte_count;
75 }
76
77 pub fn print_u64(os: &OutStream, x: u64) -> %isize {
78 if (os.index + max_u64_base10_digits >= os.buffer.len) {
79 %return os.flush();
80 }
81 const amt_printed = buf_print_u64(os.buffer[os.index...], x);
82 os.index += amt_printed;
83
84 return amt_printed;
85 }
86
87 pub fn print_i64(os: &OutStream, x: i64) -> %isize {
88 if (os.index + max_u64_base10_digits >= os.buffer.len) {
89 %return os.flush();
90 }
91 const amt_printed = buf_print_i64(os.buffer[os.index...], x);
92 os.index += amt_printed;
93
94 return amt_printed;
95 }
96
97 pub fn print_f64(os: &OutStream, x: f64) -> %isize {
98 if (os.index + max_f64_digits >= os.buffer.len) {
99 %return os.flush();
100 }
101 const amt_printed = buf_print_f64(os.buffer[os.index...], x, 4);
102 os.index += amt_printed;
103
104 return amt_printed;
105 }
106
107 pub fn flush(os: &OutStream) -> %void {
108 const amt_written = write(os.fd, &os.buffer[0], os.index);
109 os.index = 0;
110 if (amt_written < 0) {
111 return switch (-amt_written) {
112 EINVAL => unreachable{},
113 EDQUOT => error.DiskQuota,
114 EFBIG => error.FileTooBig,
115 EINTR => error.SigInterrupt,
116 EIO => error.Io,
117 ENOSPC => error.NoSpaceLeft,
118 EPERM => error.BadPerm,
119 EPIPE => error.PipeFail,
120 else => error.Unexpected,
121 }
122 }
123 }
124
125 pub fn close(os: &OutStream) -> %void {
126 const closed = close(os.fd);
127 if (closed < 0) {
128 return switch (-closed) {
129 EIO => error.Io,
130 EBADF => error.BadFd,
131 EINTR => error.SigInterrupt,
132 else => error.Unexpected,
133 }
134 }
135 }
136}
137
138pub struct InStream {
139 fd: isize,
140
141 pub fn read(is: &InStream, buf: []u8) -> %isize {
142 const amt_read = read(is.fd, &buf[0], buf.len);
143 if (amt_read < 0) {
144 return switch (-amt_read) {
145 EINVAL => unreachable{},
146 EFAULT => unreachable{},
147 EBADF => error.BadFd,
148 EINTR => error.SigInterrupt,
149 EIO => error.Io,
150 else => error.Unexpected,
151 }
152 }
153 return amt_read;
154 }
155
156 pub fn close(is: &InStream) -> %void {
157 const closed = close(is.fd);
158 if (closed < 0) {
159 return switch (-closed) {
160 EIO => error.Io,
161 EBADF => error.BadFd,
162 EINTR => error.SigInterrupt,
163 else => error.Unexpected,
164 }
165 }
166 }
167}
168
169#attribute("cold")
170pub fn abort() -> unreachable {
171 raise(SIGABRT);
172 raise(SIGKILL);
173 while (true) {}
174}
175
176pub error InvalidChar;
177pub error Overflow;
178
179pub fn parse_u64(buf: []u8, radix: u8) -> %u64 {
180 var x : u64 = 0;
181
182 for (buf) |c| {
183 const digit = char_to_digit(c);
184
185 if (digit >= radix) {
186 return error.InvalidChar;
187 }
188
189 // x *= radix
190 if (@mul_with_overflow(u64, x, radix, &x)) {
191 return error.Overflow;
192 }
193
194 // x += digit
195 if (@add_with_overflow(u64, x, digit, &x)) {
196 return error.Overflow;
197 }
198 }
199
200 return x;
201}
202
203fn char_to_digit(c: u8) -> u8 {
204 // TODO use switch with range
205 if ('0' <= c && c <= '9') {
206 c - '0'
207 } else if ('A' <= c && c <= 'Z') {
208 c - 'A' + 10
209 } else if ('a' <= c && c <= 'z') {
210 c - 'a' + 10
211 } else {
212 @max_value(u8)
213 }
214}
215
216pub fn buf_print_i64(out_buf: []u8, x: i64) -> isize {
217 if (x < 0) {
218 out_buf[0] = '-';
219 return 1 + buf_print_u64(out_buf[1...], u64(-(x + 1)) + 1);
220 } else {
221 return buf_print_u64(out_buf, u64(x));
222 }
223}
224
225pub fn buf_print_u64(out_buf: []u8, x: u64) -> isize {
226 var buf: [max_u64_base10_digits]u8 = undefined;
227 var a = x;
228 var index: isize = buf.len;
229
230 while (true) {
231 const digit = a % 10;
232 index -= 1;
233 buf[index] = '0' + u8(digit);
234 a /= 10;
235 if (a == 0)
236 break;
237 }
238
239 const len = buf.len - index;
240
241 @memcpy(&out_buf[0], &buf[index], len);
242
243 return len;
244}
245
246pub fn buf_print_f64(out_buf: []u8, x: f64, decimals: isize) -> isize {
247 const numExpBits = 11;
248 const numRawSigBits = 52; // not including implicit 1 bit
249 const expBias = 1023;
250
251 var decs = decimals;
252 if (decs >= max_u64_base10_digits) {
253 decs = max_u64_base10_digits - 1;
254 }
255
256 if (x == f64_get_pos_inf()) {
257 const buf2 = "+Inf";
258 @memcpy(&out_buf[0], &buf2[0], buf2.len);
259 return 4;
260 } else if (x == f64_get_neg_inf()) {
261 const buf2 = "-Inf";
262 @memcpy(&out_buf[0], &buf2[0], buf2.len);
263 return 4;
264 } else if (f64_is_nan(x)) {
265 const buf2 = "NaN";
266 @memcpy(&out_buf[0], &buf2[0], buf2.len);
267 return 3;
268 }
269
270 var buf: [max_f64_digits]u8 = undefined;
271
272 var len: isize = 0;
273
274 // 1 sign bit
275 // 11 exponent bits
276 // 52 significand bits (+ 1 implicit always non-zero bit)
277
278 const bits = f64_to_bits(x);
279 if (bits & (1 << 63) != 0) {
280 buf[0] = '-';
281 len += 1;
282 }
283
284 const rexponent: i64 = i64((bits >> numRawSigBits) & ((1 << numExpBits) - 1));
285 const exponent = rexponent - expBias - numRawSigBits;
286
287 if (rexponent == 0) {
288 buf[len] = '0';
289 len += 1;
290 @memcpy(&out_buf[0], &buf[0], len);
291 return len;
292 }
293
294 const sig = (bits & ((1 << numRawSigBits) - 1)) | (1 << numRawSigBits);
295
296 if (exponent >= 0) {
297 // number is an integer
298
299 if (exponent >= 64 - 53) {
300 // use XeX form
301
302 // TODO support printing large floats
303 //len += buf_print_u64(buf[len...], sig << 10);
304 const str = "LARGEF64";
305 @memcpy(&buf[len], &str[0], str.len);
306 len += str.len;
307 } else {
308 // use typical form
309
310 len += buf_print_u64(buf[len...], sig << u64(exponent));
311 buf[len] = '.';
312 len += 1;
313
314 var i: isize = 0;
315 while (i < decs) {
316 buf[len] = '0';
317 len += 1;
318 i += 1;
319 }
320 }
321 } else {
322 // number is not an integer
323
324 // print out whole part
325 len += buf_print_u64(buf[len...], sig >> u64(-exponent));
326 buf[len] = '.';
327 len += 1;
328
329 // print out fractional part
330 // dec_num holds: fractional part * 10 ^ decs
331 var dec_num: u64 = 0;
332
333 var a: isize = 1;
334 var i: isize = 0;
335 while (i < decs + 5) {
336 a *= 10;
337 i += 1;
338 }
339
340 // create a mask: 1's for the fractional part, 0's for whole part
341 var masked_sig = sig & ((1 << u64(-exponent)) - 1);
342 i = -1;
343 while (i >= exponent) {
344 var bit_set = ((1 << u64(i-exponent)) & masked_sig) != 0;
345
346 if (bit_set) {
347 dec_num += usize(a) >> usize(-i);
348 }
349
350 i -= 1;
351 }
352
353 dec_num /= 100000;
354
355 len += decs;
356
357 i = len - 1;
358 while (i >= len - decs) {
359 buf[i] = '0' + u8(dec_num % 10);
360 dec_num /= 10;
361 i -= 1;
362 }
363 }
364
365 @memcpy(&out_buf[0], &buf[0], len);
366
367 len
368}
369
370#attribute("test")
371fn parse_u64_digit_too_big() {
372 parse_u64("123a", 10) %% |err| {
373 if (err == error.InvalidChar) return;
374 unreachable{};
375 };
376 unreachable{};
377}
std/test_runner.zig+11-11
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1import "std.zig";1const io = @import("std").io;
22
3struct TestFn {3struct TestFn {
4 name: []u8,4 name: []u8,
...@@ -9,19 +9,19 @@ extern var zig_test_fn_list: []TestFn;...@@ -9,19 +9,19 @@ extern var zig_test_fn_list: []TestFn;
99
10pub fn run_tests() -> %void {10pub fn run_tests() -> %void {
11 for (zig_test_fn_list) |test_fn, i| {11 for (zig_test_fn_list) |test_fn, i| {
12 %%stderr.print_str("Test ");12 %%io.stderr.print_str("Test ");
13 %%stderr.print_i64(i + 1);13 %%io.stderr.print_i64(i + 1);
14 %%stderr.print_str("/");14 %%io.stderr.print_str("/");
15 %%stderr.print_i64(zig_test_fn_list.len);15 %%io.stderr.print_i64(zig_test_fn_list.len);
16 %%stderr.print_str(" ");16 %%io.stderr.print_str(" ");
17 %%stderr.print_str(test_fn.name);17 %%io.stderr.print_str(test_fn.name);
18 %%stderr.print_str("...");18 %%io.stderr.print_str("...");
19 %%stderr.flush();19 %%io.stderr.flush();
2020
21 test_fn.func();21 test_fn.func();
2222
2323
24 %%stderr.print_str("OK\n");24 %%io.stderr.print_str("OK\n");
25 %%stderr.flush();25 %%io.stderr.flush();
26 }26 }
27}27}
std/test_runner_libc.zig+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1import "test_runner.zig";1const test_runner = @import("test_runner.zig");
22
3export fn main(argc: c_int, argv: &&u8) -> c_int {3export fn main(argc: c_int, argv: &&u8) -> c_int {
4 run_tests() %% return -1;4 test_runner.run_tests() %% return -1;
5 return 0;5 return 0;
6}6}
std/test_runner_nolibc.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1import "test_runner.zig";1const test_runner = @import("test_runner.zig");
22
3pub fn main(args: [][]u8) -> %void {3pub fn main(args: [][]u8) -> %void {
4 return run_tests();4 return test_runner.run_tests();
5}5}
test/run_tests.cpp+323-326
...@@ -70,12 +70,20 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons...@@ -70,12 +70,20 @@ static TestCase *add_simple_case(const char *case_name, const char *source, cons
70 test_case->compiler_args.append("--strip");70 test_case->compiler_args.append("--strip");
71 test_case->compiler_args.append("--color");71 test_case->compiler_args.append("--color");
72 test_case->compiler_args.append("on");72 test_case->compiler_args.append("on");
73 test_case->compiler_args.append("--check-unused");
7374
74 test_cases.append(test_case);75 test_cases.append(test_case);
7576
76 return test_case;77 return test_case;
77}78}
7879
80static TestCase *add_simple_case_libc(const char *case_name, const char *source, const char *output) {
81 TestCase *tc = add_simple_case(case_name, source, output);
82 tc->compiler_args.append("--library");
83 tc->compiler_args.append("c");
84 return tc;
85}
86
79static TestCase *add_compile_fail_case(const char *case_name, const char *source, int count, ...) {87static TestCase *add_compile_fail_case(const char *case_name, const char *source, int count, ...) {
80 va_list ap;88 va_list ap;
81 va_start(ap, count);89 va_start(ap, count);
...@@ -93,11 +101,19 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source...@@ -93,11 +101,19 @@ static TestCase *add_compile_fail_case(const char *case_name, const char *source
93101
94 test_case->compiler_args.append("build");102 test_case->compiler_args.append("build");
95 test_case->compiler_args.append(tmp_source_path);103 test_case->compiler_args.append(tmp_source_path);
104
105 test_case->compiler_args.append("--name");
106 test_case->compiler_args.append("test");
107
108 test_case->compiler_args.append("--export");
109 test_case->compiler_args.append("obj");
110
96 test_case->compiler_args.append("--output");111 test_case->compiler_args.append("--output");
97 test_case->compiler_args.append(tmp_exe_path);112 test_case->compiler_args.append(tmp_exe_path);
113
98 test_case->compiler_args.append("--release");114 test_case->compiler_args.append("--release");
99 test_case->compiler_args.append("--strip");115 test_case->compiler_args.append("--strip");
100 //test_case->compiler_args.append("--verbose");116 test_case->compiler_args.append("--check-unused");
101117
102 test_cases.append(test_case);118 test_cases.append(test_case);
103119
...@@ -134,43 +150,18 @@ static TestCase *add_parseh_case(const char *case_name, const char *source, int...@@ -134,43 +150,18 @@ static TestCase *add_parseh_case(const char *case_name, const char *source, int
134}150}
135151
136static void add_compiling_test_cases(void) {152static void add_compiling_test_cases(void) {
137 add_simple_case("hello world with libc", R"SOURCE(153 add_simple_case_libc("hello world with libc", R"SOURCE(
138#link("c")154const c = @c_import(@c_include("stdio.h"));
139export executable "test";
140
141c_import {
142 @c_include("stdio.h");
143}
144
145export fn main(argc: c_int, argv: &&u8) -> c_int {155export fn main(argc: c_int, argv: &&u8) -> c_int {
146 puts(c"Hello, world!");156 c.puts(c"Hello, world!");
147 return 0;157 return 0;
148}158}
149 )SOURCE", "Hello, world!" NL);159 )SOURCE", "Hello, world!" NL);
150160
151 add_simple_case("function call", R"SOURCE(
152import "std.zig";
153import "syscall.zig";
154
155fn empty_function_1() {}
156fn empty_function_2() { return; }
157
158pub fn main(args: [][]u8) -> %void {
159 empty_function_1();
160 empty_function_2();
161 this_is_a_function();
162}
163
164fn this_is_a_function() -> unreachable {
165 %%stdout.printf("OK\n");
166 exit(0);
167}
168 )SOURCE", "OK\n");
169
170 {161 {
171 TestCase *tc = add_simple_case("multiple files with private function", R"SOURCE(162 TestCase *tc = add_simple_case("multiple files with private function", R"SOURCE(
172import "std.zig";163use @import("std").io;
173import "foo.zig";164use @import("foo.zig");
174165
175pub fn main(args: [][]u8) -> %void {166pub fn main(args: [][]u8) -> %void {
176 private_function();167 private_function();
...@@ -183,7 +174,7 @@ fn private_function() {...@@ -183,7 +174,7 @@ fn private_function() {
183 )SOURCE", "OK 1\nOK 2\n");174 )SOURCE", "OK 1\nOK 2\n");
184175
185 add_source_file(tc, "foo.zig", R"SOURCE(176 add_source_file(tc, "foo.zig", R"SOURCE(
186import "std.zig";177use @import("std").io;
187178
188// purposefully conflicting function with main.zig179// purposefully conflicting function with main.zig
189// but it's private so it should be OK180// but it's private so it should be OK
...@@ -199,8 +190,8 @@ pub fn print_text() {...@@ -199,8 +190,8 @@ pub fn print_text() {
199190
200 {191 {
201 TestCase *tc = add_simple_case("import segregation", R"SOURCE(192 TestCase *tc = add_simple_case("import segregation", R"SOURCE(
202import "foo.zig";193use @import("foo.zig");
203import "bar.zig";194use @import("bar.zig");
204195
205pub fn main(args: [][]u8) -> %void {196pub fn main(args: [][]u8) -> %void {
206 foo_function();197 foo_function();
...@@ -209,15 +200,15 @@ pub fn main(args: [][]u8) -> %void {...@@ -209,15 +200,15 @@ pub fn main(args: [][]u8) -> %void {
209 )SOURCE", "OK\nOK\n");200 )SOURCE", "OK\nOK\n");
210201
211 add_source_file(tc, "foo.zig", R"SOURCE(202 add_source_file(tc, "foo.zig", R"SOURCE(
212import "std.zig";203use @import("std").io;
213pub fn foo_function() {204pub fn foo_function() {
214 %%stdout.printf("OK\n");205 %%stdout.printf("OK\n");
215}206}
216 )SOURCE");207 )SOURCE");
217208
218 add_source_file(tc, "bar.zig", R"SOURCE(209 add_source_file(tc, "bar.zig", R"SOURCE(
219import "other.zig";210use @import("other.zig");
220import "std.zig";211use @import("std").io;
221212
222pub fn bar_function() {213pub fn bar_function() {
223 if (foo_function()) {214 if (foo_function()) {
...@@ -234,8 +225,35 @@ pub fn foo_function() -> bool {...@@ -234,8 +225,35 @@ pub fn foo_function() -> bool {
234 )SOURCE");225 )SOURCE");
235 }226 }
236227
228 {
229 TestCase *tc = add_simple_case("two files use import each other", R"SOURCE(
230use @import("a.zig");
231
232pub fn main(args: [][]u8) -> %void {
233 ok();
234}
235 )SOURCE", "OK\n");
236
237 add_source_file(tc, "a.zig", R"SOURCE(
238use @import("b.zig");
239const io = @import("std").io;
240
241pub const a_text = "OK\n";
242
243pub fn ok() {
244 %%io.stdout.printf(b_text);
245}
246 )SOURCE");
247
248 add_source_file(tc, "b.zig", R"SOURCE(
249use @import("a.zig");
250
251pub const b_text = a_text;
252 )SOURCE");
253 }
254
237 add_simple_case("params", R"SOURCE(255 add_simple_case("params", R"SOURCE(
238import "std.zig";256const io = @import("std").io;
239257
240fn add(a: i32, b: i32) -> i32 {258fn add(a: i32, b: i32) -> i32 {
241 a + b259 a + b
...@@ -243,13 +261,13 @@ fn add(a: i32, b: i32) -> i32 {...@@ -243,13 +261,13 @@ fn add(a: i32, b: i32) -> i32 {
243261
244pub fn main(args: [][]u8) -> %void {262pub fn main(args: [][]u8) -> %void {
245 if (add(22, 11) == 33) {263 if (add(22, 11) == 33) {
246 %%stdout.printf("pass\n");264 %%io.stdout.printf("pass\n");
247 }265 }
248}266}
249 )SOURCE", "pass\n");267 )SOURCE", "pass\n");
250268
251 add_simple_case("void parameters", R"SOURCE(269 add_simple_case("void parameters", R"SOURCE(
252import "std.zig";270const io = @import("std").io;
253271
254pub fn main(args: [][]u8) -> %void {272pub fn main(args: [][]u8) -> %void {
255 void_fun(1, void{}, 2);273 void_fun(1, void{}, 2);
...@@ -258,28 +276,28 @@ pub fn main(args: [][]u8) -> %void {...@@ -258,28 +276,28 @@ pub fn main(args: [][]u8) -> %void {
258fn void_fun(a : i32, b : void, c : i32) {276fn void_fun(a : i32, b : void, c : i32) {
259 const v = b;277 const v = b;
260 const vv : void = if (a == 1) {v} else {};278 const vv : void = if (a == 1) {v} else {};
261 if (a + c == 3) { %%stdout.printf("OK\n"); }279 if (a + c == 3) { %%io.stdout.printf("OK\n"); }
262 return vv;280 return vv;
263}281}
264 )SOURCE", "OK\n");282 )SOURCE", "OK\n");
265283
266 add_simple_case("mutable local variables", R"SOURCE(284 add_simple_case("mutable local variables", R"SOURCE(
267import "std.zig";285const io = @import("std").io;
268286
269pub fn main(args: [][]u8) -> %void {287pub fn main(args: [][]u8) -> %void {
270 var zero : i32 = 0;288 var zero : i32 = 0;
271 if (zero == 0) { %%stdout.printf("zero\n"); }289 if (zero == 0) { %%io.stdout.printf("zero\n"); }
272290
273 var i = i32(0);291 var i = i32(0);
274 while (i != 3) {292 while (i != 3) {
275 %%stdout.printf("loop\n");293 %%io.stdout.printf("loop\n");
276 i += 1;294 i += 1;
277 }295 }
278}296}
279 )SOURCE", "zero\nloop\nloop\nloop\n");297 )SOURCE", "zero\nloop\nloop\nloop\n");
280298
281 add_simple_case("arrays", R"SOURCE(299 add_simple_case("arrays", R"SOURCE(
282import "std.zig";300const io = @import("std").io;
283301
284pub fn main(args: [][]u8) -> %void {302pub fn main(args: [][]u8) -> %void {
285 var array : [5]i32 = undefined;303 var array : [5]i32 = undefined;
...@@ -299,11 +317,11 @@ pub fn main(args: [][]u8) -> %void {...@@ -299,11 +317,11 @@ pub fn main(args: [][]u8) -> %void {
299 }317 }
300318
301 if (accumulator == 15) {319 if (accumulator == 15) {
302 %%stdout.printf("OK\n");320 %%io.stdout.printf("OK\n");
303 }321 }
304322
305 if (get_array_len(array) != 5) {323 if (get_array_len(array) != 5) {
306 %%stdout.printf("BAD\n");324 %%io.stdout.printf("BAD\n");
307 }325 }
308}326}
309fn get_array_len(a: []i32) -> isize {327fn get_array_len(a: []i32) -> isize {
...@@ -313,144 +331,139 @@ fn get_array_len(a: []i32) -> isize {...@@ -313,144 +331,139 @@ fn get_array_len(a: []i32) -> isize {
313331
314332
315 add_simple_case("hello world without libc", R"SOURCE(333 add_simple_case("hello world without libc", R"SOURCE(
316import "std.zig";334const io = @import("std").io;
317335
318pub fn main(args: [][]u8) -> %void {336pub fn main(args: [][]u8) -> %void {
319 %%stdout.printf("Hello, world!\n");337 %%io.stdout.printf("Hello, world!\n");
320}338}
321 )SOURCE", "Hello, world!\n");339 )SOURCE", "Hello, world!\n");
322340
323341
324 add_simple_case("short circuit", R"SOURCE(342 add_simple_case("short circuit", R"SOURCE(
325import "std.zig";343const io = @import("std").io;
326344
327pub fn main(args: [][]u8) -> %void {345pub fn main(args: [][]u8) -> %void {
328 if (true || { %%stdout.printf("BAD 1\n"); false }) {346 if (true || { %%io.stdout.printf("BAD 1\n"); false }) {
329 %%stdout.printf("OK 1\n");347 %%io.stdout.printf("OK 1\n");
330 }348 }
331 if (false || { %%stdout.printf("OK 2\n"); false }) {349 if (false || { %%io.stdout.printf("OK 2\n"); false }) {
332 %%stdout.printf("BAD 2\n");350 %%io.stdout.printf("BAD 2\n");
333 }351 }
334352
335 if (true && { %%stdout.printf("OK 3\n"); false }) {353 if (true && { %%io.stdout.printf("OK 3\n"); false }) {
336 %%stdout.printf("BAD 3\n");354 %%io.stdout.printf("BAD 3\n");
337 }355 }
338 if (false && { %%stdout.printf("BAD 4\n"); false }) {356 if (false && { %%io.stdout.printf("BAD 4\n"); false }) {
339 } else {357 } else {
340 %%stdout.printf("OK 4\n");358 %%io.stdout.printf("OK 4\n");
341 }359 }
342}360}
343 )SOURCE", "OK 1\nOK 2\nOK 3\nOK 4\n");361 )SOURCE", "OK 1\nOK 2\nOK 3\nOK 4\n");
344362
345 add_simple_case("modify operators", R"SOURCE(363 add_simple_case("modify operators", R"SOURCE(
346import "std.zig";364const io = @import("std").io;
347365
348pub fn main(args: [][]u8) -> %void {366pub fn main(args: [][]u8) -> %void {
349 var i : i32 = 0;367 var i : i32 = 0;
350 i += 5; if (i != 5) { %%stdout.printf("BAD +=\n"); }368 i += 5; if (i != 5) { %%io.stdout.printf("BAD +=\n"); }
351 i -= 2; if (i != 3) { %%stdout.printf("BAD -=\n"); }369 i -= 2; if (i != 3) { %%io.stdout.printf("BAD -=\n"); }
352 i *= 20; if (i != 60) { %%stdout.printf("BAD *=\n"); }370 i *= 20; if (i != 60) { %%io.stdout.printf("BAD *=\n"); }
353 i /= 3; if (i != 20) { %%stdout.printf("BAD /=\n"); }371 i /= 3; if (i != 20) { %%io.stdout.printf("BAD /=\n"); }
354 i %= 11; if (i != 9) { %%stdout.printf("BAD %=\n"); }372 i %= 11; if (i != 9) { %%io.stdout.printf("BAD %=\n"); }
355 i <<= 1; if (i != 18) { %%stdout.printf("BAD <<=\n"); }373 i <<= 1; if (i != 18) { %%io.stdout.printf("BAD <<=\n"); }
356 i >>= 2; if (i != 4) { %%stdout.printf("BAD >>=\n"); }374 i >>= 2; if (i != 4) { %%io.stdout.printf("BAD >>=\n"); }
357 i = 6;375 i = 6;
358 i &= 5; if (i != 4) { %%stdout.printf("BAD &=\n"); }376 i &= 5; if (i != 4) { %%io.stdout.printf("BAD &=\n"); }
359 i ^= 6; if (i != 2) { %%stdout.printf("BAD ^=\n"); }377 i ^= 6; if (i != 2) { %%io.stdout.printf("BAD ^=\n"); }
360 i = 6;378 i = 6;
361 i |= 3; if (i != 7) { %%stdout.printf("BAD |=\n"); }379 i |= 3; if (i != 7) { %%io.stdout.printf("BAD |=\n"); }
362380
363 %%stdout.printf("OK\n");381 %%io.stdout.printf("OK\n");
364}382}
365 )SOURCE", "OK\n");383 )SOURCE", "OK\n");
366384
367 add_simple_case("number literals", R"SOURCE(385 add_simple_case_libc("number literals", R"SOURCE(
368#link("c")386const c = @c_import(@c_include("stdio.h"));
369export executable "test";
370
371c_import {
372 @c_include("stdio.h");
373}
374387
375export fn main(argc: c_int, argv: &&u8) -> c_int {388export fn main(argc: c_int, argv: &&u8) -> c_int {
376 printf(c"\n");389 c.printf(c"\n");
377390
378 printf(c"0: %llu\n",391 c.printf(c"0: %llu\n",
379 u64(0));392 u64(0));
380 printf(c"320402575052271: %llu\n",393 c.printf(c"320402575052271: %llu\n",
381 u64(320402575052271));394 u64(320402575052271));
382 printf(c"0x01236789abcdef: %llu\n",395 c.printf(c"0x01236789abcdef: %llu\n",
383 u64(0x01236789abcdef));396 u64(0x01236789abcdef));
384 printf(c"0xffffffffffffffff: %llu\n",397 c.printf(c"0xffffffffffffffff: %llu\n",
385 u64(0xffffffffffffffff));398 u64(0xffffffffffffffff));
386 printf(c"0x000000ffffffffffffffff: %llu\n",399 c.printf(c"0x000000ffffffffffffffff: %llu\n",
387 u64(0x000000ffffffffffffffff));400 u64(0x000000ffffffffffffffff));
388 printf(c"0o1777777777777777777777: %llu\n",401 c.printf(c"0o1777777777777777777777: %llu\n",
389 u64(0o1777777777777777777777));402 u64(0o1777777777777777777777));
390 printf(c"0o0000001777777777777777777777: %llu\n",403 c.printf(c"0o0000001777777777777777777777: %llu\n",
391 u64(0o0000001777777777777777777777));404 u64(0o0000001777777777777777777777));
392 printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",405 c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
393 u64(0b1111111111111111111111111111111111111111111111111111111111111111));406 u64(0b1111111111111111111111111111111111111111111111111111111111111111));
394 printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",407 c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
395 u64(0b0000001111111111111111111111111111111111111111111111111111111111111111));408 u64(0b0000001111111111111111111111111111111111111111111111111111111111111111));
396409
397 printf(c"\n");410 c.printf(c"\n");
398411
399 printf(c"0.0: %a\n",412 c.printf(c"0.0: %a\n",
400 f64(0.0));413 f64(0.0));
401 printf(c"0e0: %a\n",414 c.printf(c"0e0: %a\n",
402 f64(0e0));415 f64(0e0));
403 printf(c"0.0e0: %a\n",416 c.printf(c"0.0e0: %a\n",
404 f64(0.0e0));417 f64(0.0e0));
405 printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",418 c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %a\n",
406 f64(000000000000000000000000000000000000000000000000000000000.0e0));419 f64(000000000000000000000000000000000000000000000000000000000.0e0));
407 printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",420 c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %a\n",
408 f64(0.000000000000000000000000000000000000000000000000000000000e0));421 f64(0.000000000000000000000000000000000000000000000000000000000e0));
409 printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",422 c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %a\n",
410 f64(0.0e000000000000000000000000000000000000000000000000000000000));423 f64(0.0e000000000000000000000000000000000000000000000000000000000));
411 printf(c"1.0: %a\n",424 c.printf(c"1.0: %a\n",
412 f64(1.0));425 f64(1.0));
413 printf(c"10.0: %a\n",426 c.printf(c"10.0: %a\n",
414 f64(10.0));427 f64(10.0));
415 printf(c"10.5: %a\n",428 c.printf(c"10.5: %a\n",
416 f64(10.5));429 f64(10.5));
417 printf(c"10.5e5: %a\n",430 c.printf(c"10.5e5: %a\n",
418 f64(10.5e5));431 f64(10.5e5));
419 printf(c"10.5e+5: %a\n",432 c.printf(c"10.5e+5: %a\n",
420 f64(10.5e+5));433 f64(10.5e+5));
421 printf(c"50.0e-2: %a\n",434 c.printf(c"50.0e-2: %a\n",
422 f64(50.0e-2));435 f64(50.0e-2));
423 printf(c"50e-2: %a\n",436 c.printf(c"50e-2: %a\n",
424 f64(50e-2));437 f64(50e-2));
425438
426 printf(c"\n");439 c.printf(c"\n");
427440
428 printf(c"0x1.0: %a\n",441 c.printf(c"0x1.0: %a\n",
429 f64(0x1.0));442 f64(0x1.0));
430 printf(c"0x10.0: %a\n",443 c.printf(c"0x10.0: %a\n",
431 f64(0x10.0));444 f64(0x10.0));
432 printf(c"0x100.0: %a\n",445 c.printf(c"0x100.0: %a\n",
433 f64(0x100.0));446 f64(0x100.0));
434 printf(c"0x103.0: %a\n",447 c.printf(c"0x103.0: %a\n",
435 f64(0x103.0));448 f64(0x103.0));
436 printf(c"0x103.7: %a\n",449 c.printf(c"0x103.7: %a\n",
437 f64(0x103.7));450 f64(0x103.7));
438 printf(c"0x103.70: %a\n",451 c.printf(c"0x103.70: %a\n",
439 f64(0x103.70));452 f64(0x103.70));
440 printf(c"0x103.70p4: %a\n",453 c.printf(c"0x103.70p4: %a\n",
441 f64(0x103.70p4));454 f64(0x103.70p4));
442 printf(c"0x103.70p5: %a\n",455 c.printf(c"0x103.70p5: %a\n",
443 f64(0x103.70p5));456 f64(0x103.70p5));
444 printf(c"0x103.70p+5: %a\n",457 c.printf(c"0x103.70p+5: %a\n",
445 f64(0x103.70p+5));458 f64(0x103.70p+5));
446 printf(c"0x103.70p-5: %a\n",459 c.printf(c"0x103.70p-5: %a\n",
447 f64(0x103.70p-5));460 f64(0x103.70p-5));
448461
449 printf(c"\n");462 c.printf(c"\n");
450463
451 printf(c"0b10100.00010e0: %a\n",464 c.printf(c"0b10100.00010e0: %a\n",
452 f64(0b10100.00010e0));465 f64(0b10100.00010e0));
453 printf(c"0o10700.00010e0: %a\n",466 c.printf(c"0o10700.00010e0: %a\n",
454 f64(0o10700.00010e0));467 f64(0o10700.00010e0));
455468
456 return 0;469 return 0;
...@@ -496,7 +509,7 @@ export fn main(argc: c_int, argv: &&u8) -> c_int {...@@ -496,7 +509,7 @@ export fn main(argc: c_int, argv: &&u8) -> c_int {
496)OUTPUT");509)OUTPUT");
497510
498 add_simple_case("structs", R"SOURCE(511 add_simple_case("structs", R"SOURCE(
499import "std.zig";512const io = @import("std").io;
500513
501pub fn main(args: [][]u8) -> %void {514pub fn main(args: [][]u8) -> %void {
502 var foo : Foo = undefined;515 var foo : Foo = undefined;
...@@ -506,12 +519,12 @@ pub fn main(args: [][]u8) -> %void {...@@ -506,12 +519,12 @@ pub fn main(args: [][]u8) -> %void {
506 test_foo(foo);519 test_foo(foo);
507 test_mutation(&foo);520 test_mutation(&foo);
508 if (foo.c != 100) {521 if (foo.c != 100) {
509 %%stdout.printf("BAD\n");522 %%io.stdout.printf("BAD\n");
510 }523 }
511 test_point_to_self();524 test_point_to_self();
512 test_byval_assign();525 test_byval_assign();
513 test_initializer();526 test_initializer();
514 %%stdout.printf("OK\n");527 %%io.stdout.printf("OK\n");
515}528}
516struct Foo {529struct Foo {
517 a : i32,530 a : i32,
...@@ -520,7 +533,7 @@ struct Foo {...@@ -520,7 +533,7 @@ struct Foo {
520}533}
521fn test_foo(foo : Foo) {534fn test_foo(foo : Foo) {
522 if (!foo.b) {535 if (!foo.b) {
523 %%stdout.printf("BAD\n");536 %%io.stdout.printf("BAD\n");
524 }537 }
525}538}
526fn test_mutation(foo : &Foo) {539fn test_mutation(foo : &Foo) {
...@@ -545,7 +558,7 @@ fn test_point_to_self() {...@@ -545,7 +558,7 @@ fn test_point_to_self() {
545 root.next = &node;558 root.next = &node;
546559
547 if (node.next.next.next.val.x != 1) {560 if (node.next.next.next.val.x != 1) {
548 %%stdout.printf("BAD\n");561 %%io.stdout.printf("BAD\n");
549 }562 }
550}563}
551fn test_byval_assign() {564fn test_byval_assign() {
...@@ -554,38 +567,38 @@ fn test_byval_assign() {...@@ -554,38 +567,38 @@ fn test_byval_assign() {
554567
555 foo1.a = 1234;568 foo1.a = 1234;
556569
557 if (foo2.a != 0) { %%stdout.printf("BAD\n"); }570 if (foo2.a != 0) { %%io.stdout.printf("BAD\n"); }
558571
559 foo2 = foo1;572 foo2 = foo1;
560573
561 if (foo2.a != 1234) { %%stdout.printf("BAD - byval assignment failed\n"); }574 if (foo2.a != 1234) { %%io.stdout.printf("BAD - byval assignment failed\n"); }
562}575}
563fn test_initializer() {576fn test_initializer() {
564 const val = Val { .x = 42 };577 const val = Val { .x = 42 };
565 if (val.x != 42) { %%stdout.printf("BAD\n"); }578 if (val.x != 42) { %%io.stdout.printf("BAD\n"); }
566}579}
567 )SOURCE", "OK\n");580 )SOURCE", "OK\n");
568581
569 add_simple_case("global variables", R"SOURCE(582 add_simple_case("global variables", R"SOURCE(
570import "std.zig";583const io = @import("std").io;
571584
572const g1 : i32 = 1233 + 1;585const g1 : i32 = 1233 + 1;
573var g2 : i32 = 0;586var g2 : i32 = 0;
574587
575pub fn main(args: [][]u8) -> %void {588pub fn main(args: [][]u8) -> %void {
576 if (g2 != 0) { %%stdout.printf("BAD\n"); }589 if (g2 != 0) { %%io.stdout.printf("BAD\n"); }
577 g2 = g1;590 g2 = g1;
578 if (g2 != 1234) { %%stdout.printf("BAD\n"); }591 if (g2 != 1234) { %%io.stdout.printf("BAD\n"); }
579 %%stdout.printf("OK\n");592 %%io.stdout.printf("OK\n");
580}593}
581 )SOURCE", "OK\n");594 )SOURCE", "OK\n");
582595
583 add_simple_case("while loop", R"SOURCE(596 add_simple_case("while loop", R"SOURCE(
584import "std.zig";597const io = @import("std").io;
585pub fn main(args: [][]u8) -> %void {598pub fn main(args: [][]u8) -> %void {
586 var i : i32 = 0;599 var i : i32 = 0;
587 while (i < 4) {600 while (i < 4) {
588 %%stdout.printf("loop\n");601 %%io.stdout.printf("loop\n");
589 i += 1;602 i += 1;
590 }603 }
591 g();604 g();
...@@ -601,11 +614,11 @@ fn f() -> i32 {...@@ -601,11 +614,11 @@ fn f() -> i32 {
601 )SOURCE", "loop\nloop\nloop\nloop\n");614 )SOURCE", "loop\nloop\nloop\nloop\n");
602615
603 add_simple_case("continue and break", R"SOURCE(616 add_simple_case("continue and break", R"SOURCE(
604import "std.zig";617const io = @import("std").io;
605pub fn main(args: [][]u8) -> %void {618pub fn main(args: [][]u8) -> %void {
606 var i : i32 = 0;619 var i : i32 = 0;
607 while (true) {620 while (true) {
608 %%stdout.printf("loop\n");621 %%io.stdout.printf("loop\n");
609 i += 1;622 i += 1;
610 if (i < 4) {623 if (i < 4) {
611 continue;624 continue;
...@@ -616,11 +629,11 @@ pub fn main(args: [][]u8) -> %void {...@@ -616,11 +629,11 @@ pub fn main(args: [][]u8) -> %void {
616 )SOURCE", "loop\nloop\nloop\nloop\n");629 )SOURCE", "loop\nloop\nloop\nloop\n");
617630
618 add_simple_case("implicit cast after unreachable", R"SOURCE(631 add_simple_case("implicit cast after unreachable", R"SOURCE(
619import "std.zig";632const io = @import("std").io;
620pub fn main(args: [][]u8) -> %void {633pub fn main(args: [][]u8) -> %void {
621 const x = outer();634 const x = outer();
622 if (x == 1234) {635 if (x == 1234) {
623 %%stdout.printf("OK\n");636 %%io.stdout.printf("OK\n");
624 }637 }
625}638}
626fn inner() -> i32 { 1234 }639fn inner() -> i32 { 1234 }
...@@ -630,18 +643,18 @@ fn outer() -> isize {...@@ -630,18 +643,18 @@ fn outer() -> isize {
630 )SOURCE", "OK\n");643 )SOURCE", "OK\n");
631644
632 add_simple_case("@sizeof() and @typeof()", R"SOURCE(645 add_simple_case("@sizeof() and @typeof()", R"SOURCE(
633import "std.zig";646const io = @import("std").io;
634const x: u16 = 13;647const x: u16 = 13;
635const z: @typeof(x) = 19;648const z: @typeof(x) = 19;
636pub fn main(args: [][]u8) -> %void {649pub fn main(args: [][]u8) -> %void {
637 const y: @typeof(x) = 120;650 const y: @typeof(x) = 120;
638 %%stdout.print_u64(@sizeof(@typeof(y)));651 %%io.stdout.print_u64(@sizeof(@typeof(y)));
639 %%stdout.printf("\n");652 %%io.stdout.printf("\n");
640}653}
641 )SOURCE", "2\n");654 )SOURCE", "2\n");
642655
643 add_simple_case("member functions", R"SOURCE(656 add_simple_case("member functions", R"SOURCE(
644import "std.zig";657const io = @import("std").io;
645struct Rand {658struct Rand {
646 seed: u32,659 seed: u32,
647 pub fn get_seed(r: Rand) -> u32 {660 pub fn get_seed(r: Rand) -> u32 {
...@@ -651,14 +664,14 @@ struct Rand {...@@ -651,14 +664,14 @@ struct Rand {
651pub fn main(args: [][]u8) -> %void {664pub fn main(args: [][]u8) -> %void {
652 const r = Rand {.seed = 1234};665 const r = Rand {.seed = 1234};
653 if (r.get_seed() != 1234) {666 if (r.get_seed() != 1234) {
654 %%stdout.printf("BAD seed\n");667 %%io.stdout.printf("BAD seed\n");
655 }668 }
656 %%stdout.printf("OK\n");669 %%io.stdout.printf("OK\n");
657}670}
658 )SOURCE", "OK\n");671 )SOURCE", "OK\n");
659672
660 add_simple_case("pointer dereferencing", R"SOURCE(673 add_simple_case("pointer dereferencing", R"SOURCE(
661import "std.zig";674const io = @import("std").io;
662675
663pub fn main(args: [][]u8) -> %void {676pub fn main(args: [][]u8) -> %void {
664 var x = i32(3);677 var x = i32(3);
...@@ -667,93 +680,93 @@ pub fn main(args: [][]u8) -> %void {...@@ -667,93 +680,93 @@ pub fn main(args: [][]u8) -> %void {
667 *y += 1;680 *y += 1;
668681
669 if (x != 4) {682 if (x != 4) {
670 %%stdout.printf("BAD\n");683 %%io.stdout.printf("BAD\n");
671 }684 }
672 if (*y != 4) {685 if (*y != 4) {
673 %%stdout.printf("BAD\n");686 %%io.stdout.printf("BAD\n");
674 }687 }
675 %%stdout.printf("OK\n");688 %%io.stdout.printf("OK\n");
676}689}
677 )SOURCE", "OK\n");690 )SOURCE", "OK\n");
678691
679 add_simple_case("constant expressions", R"SOURCE(692 add_simple_case("constant expressions", R"SOURCE(
680import "std.zig";693const io = @import("std").io;
681694
682const ARRAY_SIZE : i8 = 20;695const ARRAY_SIZE : i8 = 20;
683696
684pub fn main(args: [][]u8) -> %void {697pub fn main(args: [][]u8) -> %void {
685 var array : [ARRAY_SIZE]u8 = undefined;698 var array : [ARRAY_SIZE]u8 = undefined;
686 %%stdout.print_u64(@sizeof(@typeof(array)));699 %%io.stdout.print_u64(@sizeof(@typeof(array)));
687 %%stdout.printf("\n");700 %%io.stdout.printf("\n");
688}701}
689 )SOURCE", "20\n");702 )SOURCE", "20\n");
690703
691 add_simple_case("@min_value() and @max_value()", R"SOURCE(704 add_simple_case("@min_value() and @max_value()", R"SOURCE(
692import "std.zig";705const io = @import("std").io;
693pub fn main(args: [][]u8) -> %void {706pub fn main(args: [][]u8) -> %void {
694 %%stdout.printf("max u8: ");707 %%io.stdout.printf("max u8: ");
695 %%stdout.print_u64(@max_value(u8));708 %%io.stdout.print_u64(@max_value(u8));
696 %%stdout.printf("\n");709 %%io.stdout.printf("\n");
697710
698 %%stdout.printf("max u16: ");711 %%io.stdout.printf("max u16: ");
699 %%stdout.print_u64(@max_value(u16));712 %%io.stdout.print_u64(@max_value(u16));
700 %%stdout.printf("\n");713 %%io.stdout.printf("\n");
701714
702 %%stdout.printf("max u32: ");715 %%io.stdout.printf("max u32: ");
703 %%stdout.print_u64(@max_value(u32));716 %%io.stdout.print_u64(@max_value(u32));
704 %%stdout.printf("\n");717 %%io.stdout.printf("\n");
705718
706 %%stdout.printf("max u64: ");719 %%io.stdout.printf("max u64: ");
707 %%stdout.print_u64(@max_value(u64));720 %%io.stdout.print_u64(@max_value(u64));
708 %%stdout.printf("\n");721 %%io.stdout.printf("\n");
709722
710 %%stdout.printf("max i8: ");723 %%io.stdout.printf("max i8: ");
711 %%stdout.print_i64(@max_value(i8));724 %%io.stdout.print_i64(@max_value(i8));
712 %%stdout.printf("\n");725 %%io.stdout.printf("\n");
713726
714 %%stdout.printf("max i16: ");727 %%io.stdout.printf("max i16: ");
715 %%stdout.print_i64(@max_value(i16));728 %%io.stdout.print_i64(@max_value(i16));
716 %%stdout.printf("\n");729 %%io.stdout.printf("\n");
717730
718 %%stdout.printf("max i32: ");731 %%io.stdout.printf("max i32: ");
719 %%stdout.print_i64(@max_value(i32));732 %%io.stdout.print_i64(@max_value(i32));
720 %%stdout.printf("\n");733 %%io.stdout.printf("\n");
721734
722 %%stdout.printf("max i64: ");735 %%io.stdout.printf("max i64: ");
723 %%stdout.print_i64(@max_value(i64));736 %%io.stdout.print_i64(@max_value(i64));
724 %%stdout.printf("\n");737 %%io.stdout.printf("\n");
725738
726 %%stdout.printf("min u8: ");739 %%io.stdout.printf("min u8: ");
727 %%stdout.print_u64(@min_value(u8));740 %%io.stdout.print_u64(@min_value(u8));
728 %%stdout.printf("\n");741 %%io.stdout.printf("\n");
729742
730 %%stdout.printf("min u16: ");743 %%io.stdout.printf("min u16: ");
731 %%stdout.print_u64(@min_value(u16));744 %%io.stdout.print_u64(@min_value(u16));
732 %%stdout.printf("\n");745 %%io.stdout.printf("\n");
733746
734 %%stdout.printf("min u32: ");747 %%io.stdout.printf("min u32: ");
735 %%stdout.print_u64(@min_value(u32));748 %%io.stdout.print_u64(@min_value(u32));
736 %%stdout.printf("\n");749 %%io.stdout.printf("\n");
737750
738 %%stdout.printf("min u64: ");751 %%io.stdout.printf("min u64: ");
739 %%stdout.print_u64(@min_value(u64));752 %%io.stdout.print_u64(@min_value(u64));
740 %%stdout.printf("\n");753 %%io.stdout.printf("\n");
741754
742 %%stdout.printf("min i8: ");755 %%io.stdout.printf("min i8: ");
743 %%stdout.print_i64(@min_value(i8));756 %%io.stdout.print_i64(@min_value(i8));
744 %%stdout.printf("\n");757 %%io.stdout.printf("\n");
745758
746 %%stdout.printf("min i16: ");759 %%io.stdout.printf("min i16: ");
747 %%stdout.print_i64(@min_value(i16));760 %%io.stdout.print_i64(@min_value(i16));
748 %%stdout.printf("\n");761 %%io.stdout.printf("\n");
749762
750 %%stdout.printf("min i32: ");763 %%io.stdout.printf("min i32: ");
751 %%stdout.print_i64(@min_value(i32));764 %%io.stdout.print_i64(@min_value(i32));
752 %%stdout.printf("\n");765 %%io.stdout.printf("\n");
753766
754 %%stdout.printf("min i64: ");767 %%io.stdout.printf("min i64: ");
755 %%stdout.print_i64(@min_value(i64));768 %%io.stdout.print_i64(@min_value(i64));
756 %%stdout.printf("\n");769 %%io.stdout.printf("\n");
757}770}
758 )SOURCE",771 )SOURCE",
759 "max u8: 255\n"772 "max u8: 255\n"
...@@ -775,10 +788,10 @@ pub fn main(args: [][]u8) -> %void {...@@ -775,10 +788,10 @@ pub fn main(args: [][]u8) -> %void {
775788
776789
777 add_simple_case("else if expression", R"SOURCE(790 add_simple_case("else if expression", R"SOURCE(
778import "std.zig";791const io = @import("std").io;
779pub fn main(args: [][]u8) -> %void {792pub fn main(args: [][]u8) -> %void {
780 if (f(1) == 1) {793 if (f(1) == 1) {
781 %%stdout.printf("OK\n");794 %%io.stdout.printf("OK\n");
782 }795 }
783}796}
784fn f(c: u8) -> u8 {797fn f(c: u8) -> u8 {
...@@ -793,82 +806,82 @@ fn f(c: u8) -> u8 {...@@ -793,82 +806,82 @@ fn f(c: u8) -> u8 {
793 )SOURCE", "OK\n");806 )SOURCE", "OK\n");
794807
795 add_simple_case("overflow intrinsics", R"SOURCE(808 add_simple_case("overflow intrinsics", R"SOURCE(
796import "std.zig";809const io = @import("std").io;
797pub fn main(args: [][]u8) -> %void {810pub fn main(args: [][]u8) -> %void {
798 var result: u8 = undefined;811 var result: u8 = undefined;
799 if (!@add_with_overflow(u8, 250, 100, &result)) {812 if (!@add_with_overflow(u8, 250, 100, &result)) {
800 %%stdout.printf("BAD\n");813 %%io.stdout.printf("BAD\n");
801 }814 }
802 if (@add_with_overflow(u8, 100, 150, &result)) {815 if (@add_with_overflow(u8, 100, 150, &result)) {
803 %%stdout.printf("BAD\n");816 %%io.stdout.printf("BAD\n");
804 }817 }
805 if (result != 250) {818 if (result != 250) {
806 %%stdout.printf("BAD\n");819 %%io.stdout.printf("BAD\n");
807 }820 }
808 %%stdout.printf("OK\n");821 %%io.stdout.printf("OK\n");
809}822}
810 )SOURCE", "OK\n");823 )SOURCE", "OK\n");
811824
812 add_simple_case("order-independent declarations", R"SOURCE(825 add_simple_case("order-independent declarations", R"SOURCE(
813import "std.zig";826const io = @import("std").io;
814const z = stdin_fileno;827const z = io.stdin_fileno;
815const x : @typeof(y) = 1234;828const x : @typeof(y) = 1234;
816const y : u16 = 5678;829const y : u16 = 5678;
817pub fn main(args: [][]u8) -> %void {830pub fn main(args: [][]u8) -> %void {
818 var x : i32 = print_ok(x);831 var x_local : i32 = print_ok(x);
819}832}
820fn print_ok(val: @typeof(x)) -> @typeof(foo) {833fn print_ok(val: @typeof(x)) -> @typeof(foo) {
821 %%stdout.printf("OK\n");834 %%io.stdout.printf("OK\n");
822 return 0;835 return 0;
823}836}
824const foo : i32 = 0;837const foo : i32 = 0;
825 )SOURCE", "OK\n");838 )SOURCE", "OK\n");
826839
827 add_simple_case("nested arrays", R"SOURCE(840 add_simple_case("nested arrays", R"SOURCE(
828import "std.zig";841const io = @import("std").io;
829842
830pub fn main(args: [][]u8) -> %void {843pub fn main(args: [][]u8) -> %void {
831 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};844 const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"};
832 for (array_of_strings) |str| {845 for (array_of_strings) |str| {
833 %%stdout.printf(str);846 %%io.stdout.printf(str);
834 %%stdout.printf("\n");847 %%io.stdout.printf("\n");
835 }848 }
836}849}
837 )SOURCE", "hello\nthis\nis\nmy\nthing\n");850 )SOURCE", "hello\nthis\nis\nmy\nthing\n");
838851
839 add_simple_case("for loops", R"SOURCE(852 add_simple_case("for loops", R"SOURCE(
840import "std.zig";853const io = @import("std").io;
841854
842pub fn main(args: [][]u8) -> %void {855pub fn main(args: [][]u8) -> %void {
843 const array = []u8 {9, 8, 7, 6};856 const array = []u8 {9, 8, 7, 6};
844 for (array) |item| {857 for (array) |item| {
845 %%stdout.print_u64(item);858 %%io.stdout.print_u64(item);
846 %%stdout.printf("\n");859 %%io.stdout.printf("\n");
847 }860 }
848 for (array) |item, index| {861 for (array) |item, index| {
849 %%stdout.print_i64(index);862 %%io.stdout.print_i64(index);
850 %%stdout.printf("\n");863 %%io.stdout.printf("\n");
851 }864 }
852 const unknown_size: []u8 = array;865 const unknown_size: []u8 = array;
853 for (unknown_size) |item| {866 for (unknown_size) |item| {
854 %%stdout.print_u64(item);867 %%io.stdout.print_u64(item);
855 %%stdout.printf("\n");868 %%io.stdout.printf("\n");
856 }869 }
857 for (unknown_size) |item, index| {870 for (unknown_size) |item, index| {
858 %%stdout.print_i64(index);871 %%io.stdout.print_i64(index);
859 %%stdout.printf("\n");872 %%io.stdout.printf("\n");
860 }873 }
861}874}
862 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n");875 )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n");
863876
864 add_simple_case("function pointers", R"SOURCE(877 add_simple_case("function pointers", R"SOURCE(
865import "std.zig";878const io = @import("std").io;
866879
867pub fn main(args: [][]u8) -> %void {880pub fn main(args: [][]u8) -> %void {
868 const fns = []@typeof(fn1) { fn1, fn2, fn3, fn4, };881 const fns = []@typeof(fn1) { fn1, fn2, fn3, fn4, };
869 for (fns) |f| {882 for (fns) |f| {
870 %%stdout.print_u64(f());883 %%io.stdout.print_u64(f());
871 %%stdout.printf("\n");884 %%io.stdout.printf("\n");
872 }885 }
873}886}
874887
...@@ -879,7 +892,7 @@ fn fn4() -> u32 {8}...@@ -879,7 +892,7 @@ fn fn4() -> u32 {8}
879 )SOURCE", "5\n6\n7\n8\n");892 )SOURCE", "5\n6\n7\n8\n");
880893
881 add_simple_case("statically initialized struct", R"SOURCE(894 add_simple_case("statically initialized struct", R"SOURCE(
882import "std.zig";895const io = @import("std").io;
883struct Foo {896struct Foo {
884 x: i32,897 x: i32,
885 y: bool,898 y: bool,
...@@ -888,38 +901,38 @@ var foo = Foo { .x = 13, .y = true, };...@@ -888,38 +901,38 @@ var foo = Foo { .x = 13, .y = true, };
888pub fn main(args: [][]u8) -> %void {901pub fn main(args: [][]u8) -> %void {
889 foo.x += 1;902 foo.x += 1;
890 if (foo.x != 14) {903 if (foo.x != 14) {
891 %%stdout.printf("BAD\n");904 %%io.stdout.printf("BAD\n");
892 }905 }
893906
894 %%stdout.printf("OK\n");907 %%io.stdout.printf("OK\n");
895}908}
896 )SOURCE", "OK\n");909 )SOURCE", "OK\n");
897910
898 add_simple_case("statically initialized array literal", R"SOURCE(911 add_simple_case("statically initialized array literal", R"SOURCE(
899import "std.zig";912const io = @import("std").io;
900const x = []u8{1,2,3,4};913const x = []u8{1,2,3,4};
901pub fn main(args: [][]u8) -> %void {914pub fn main(args: [][]u8) -> %void {
902 const y : [4]u8 = x;915 const y : [4]u8 = x;
903 if (y[3] != 4) {916 if (y[3] != 4) {
904 %%stdout.printf("BAD\n");917 %%io.stdout.printf("BAD\n");
905 }918 }
906919
907 %%stdout.printf("OK\n");920 %%io.stdout.printf("OK\n");
908}921}
909 )SOURCE", "OK\n");922 )SOURCE", "OK\n");
910923
911 add_simple_case("return with implicit cast from while loop", R"SOURCE(924 add_simple_case("return with implicit cast from while loop", R"SOURCE(
912import "std.zig";925const io = @import("std").io;
913pub fn main(args: [][]u8) -> %void {926pub fn main(args: [][]u8) -> %void {
914 while (true) {927 while (true) {
915 %%stdout.printf("OK\n");928 %%io.stdout.printf("OK\n");
916 return;929 return;
917 }930 }
918}931}
919 )SOURCE", "OK\n");932 )SOURCE", "OK\n");
920933
921 add_simple_case("return struct byval from function", R"SOURCE(934 add_simple_case("return struct byval from function", R"SOURCE(
922import "std.zig";935const io = @import("std").io;
923struct Foo {936struct Foo {
924 x: i32,937 x: i32,
925 y: i32,938 y: i32,
...@@ -933,14 +946,14 @@ fn make_foo(x: i32, y: i32) -> Foo {...@@ -933,14 +946,14 @@ fn make_foo(x: i32, y: i32) -> Foo {
933pub fn main(args: [][]u8) -> %void {946pub fn main(args: [][]u8) -> %void {
934 const foo = make_foo(1234, 5678);947 const foo = make_foo(1234, 5678);
935 if (foo.y != 5678) {948 if (foo.y != 5678) {
936 %%stdout.printf("BAD\n");949 %%io.stdout.printf("BAD\n");
937 }950 }
938 %%stdout.printf("OK\n");951 %%io.stdout.printf("OK\n");
939}952}
940 )SOURCE", "OK\n");953 )SOURCE", "OK\n");
941954
942 add_simple_case("%% binary operator", R"SOURCE(955 add_simple_case("%% binary operator", R"SOURCE(
943import "std.zig";956const io = @import("std").io;
944error ItBroke;957error ItBroke;
945fn g(x: bool) -> %isize {958fn g(x: bool) -> %isize {
946 if (x) {959 if (x) {
...@@ -953,24 +966,24 @@ pub fn main(args: [][]u8) -> %void {...@@ -953,24 +966,24 @@ pub fn main(args: [][]u8) -> %void {
953 const a = g(true) %% 3;966 const a = g(true) %% 3;
954 const b = g(false) %% 3;967 const b = g(false) %% 3;
955 if (a != 3) {968 if (a != 3) {
956 %%stdout.printf("BAD\n");969 %%io.stdout.printf("BAD\n");
957 }970 }
958 if (b != 10) {971 if (b != 10) {
959 %%stdout.printf("BAD\n");972 %%io.stdout.printf("BAD\n");
960 }973 }
961 %%stdout.printf("OK\n");974 %%io.stdout.printf("OK\n");
962}975}
963 )SOURCE", "OK\n");976 )SOURCE", "OK\n");
964977
965 add_simple_case("string concatenation", R"SOURCE(978 add_simple_case("string concatenation", R"SOURCE(
966import "std.zig";979const io = @import("std").io;
967pub fn main(args: [][]u8) -> %void {980pub fn main(args: [][]u8) -> %void {
968 %%stdout.printf("OK" ++ " IT " ++ "WORKED\n");981 %%io.stdout.printf("OK" ++ " IT " ++ "WORKED\n");
969}982}
970 )SOURCE", "OK IT WORKED\n");983 )SOURCE", "OK IT WORKED\n");
971984
972 add_simple_case("constant struct with negation", R"SOURCE(985 add_simple_case("constant struct with negation", R"SOURCE(
973import "std.zig";986const io = @import("std").io;
974struct Vertex {987struct Vertex {
975 x: f32,988 x: f32,
976 y: f32,989 y: f32,
...@@ -985,30 +998,30 @@ const vertices = []Vertex {...@@ -985,30 +998,30 @@ const vertices = []Vertex {
985};998};
986pub fn main(args: [][]u8) -> %void {999pub fn main(args: [][]u8) -> %void {
987 if (vertices[0].x != -0.6) {1000 if (vertices[0].x != -0.6) {
988 %%stdout.printf("BAD\n");1001 %%io.stdout.printf("BAD\n");
989 }1002 }
990 %%stdout.printf("OK\n");1003 %%io.stdout.printf("OK\n");
991}1004}
992 )SOURCE", "OK\n");1005 )SOURCE", "OK\n");
9931006
994 add_simple_case("int to ptr cast", R"SOURCE(1007 add_simple_case("int to ptr cast", R"SOURCE(
995import "std.zig";1008const io = @import("std").io;
996pub fn main(args: [][]u8) -> %void {1009pub fn main(args: [][]u8) -> %void {
997 const x = isize(13);1010 const x = isize(13);
998 const y = (&u8)(x);1011 const y = (&u8)(x);
999 const z = usize(y);1012 const z = usize(y);
1000 if (z != 13) {1013 if (z != 13) {
1001 %%stdout.printf("BAD\n");1014 %%io.stdout.printf("BAD\n");
1002 }1015 }
1003 %%stdout.printf("OK\n");1016 %%io.stdout.printf("OK\n");
1004}1017}
1005 )SOURCE", "OK\n");1018 )SOURCE", "OK\n");
10061019
1007 add_simple_case("pointer to void return type", R"SOURCE(1020 add_simple_case("pointer to void return type", R"SOURCE(
1008import "std.zig";1021const io = @import("std").io;
1009const x = void{};1022const x = void{};
1010fn f() -> &void {1023fn f() -> &void {
1011 %%stdout.printf("OK\n");1024 %%io.stdout.printf("OK\n");
1012 return &x;1025 return &x;
1013}1026}
1014pub fn main(args: [][]u8) -> %void {1027pub fn main(args: [][]u8) -> %void {
...@@ -1018,7 +1031,7 @@ pub fn main(args: [][]u8) -> %void {...@@ -1018,7 +1031,7 @@ pub fn main(args: [][]u8) -> %void {
1018 )SOURCE", "OK\n");1031 )SOURCE", "OK\n");
10191032
1020 add_simple_case("unwrap simple value from error", R"SOURCE(1033 add_simple_case("unwrap simple value from error", R"SOURCE(
1021import "std.zig";1034const io = @import("std").io;
1022fn do() -> %isize {1035fn do() -> %isize {
1023 131036 13
1024}1037}
...@@ -1026,14 +1039,14 @@ fn do() -> %isize {...@@ -1026,14 +1039,14 @@ fn do() -> %isize {
1026pub fn main(args: [][]u8) -> %void {1039pub fn main(args: [][]u8) -> %void {
1027 const i = %%do();1040 const i = %%do();
1028 if (i != 13) {1041 if (i != 13) {
1029 %%stdout.printf("BAD\n");1042 %%io.stdout.printf("BAD\n");
1030 }1043 }
1031 %%stdout.printf("OK\n");1044 %%io.stdout.printf("OK\n");
1032}1045}
1033 )SOURCE", "OK\n");1046 )SOURCE", "OK\n");
10341047
1035 add_simple_case("store member function in variable", R"SOURCE(1048 add_simple_case("store member function in variable", R"SOURCE(
1036import "std.zig";1049const io = @import("std").io;
1037struct Foo {1050struct Foo {
1038 x: i32,1051 x: i32,
1039 fn member(foo: Foo) -> i32 { foo.x }1052 fn member(foo: Foo) -> i32 { foo.x }
...@@ -1043,14 +1056,14 @@ pub fn main(args: [][]u8) -> %void {...@@ -1043,14 +1056,14 @@ pub fn main(args: [][]u8) -> %void {
1043 const member_fn = Foo.member;1056 const member_fn = Foo.member;
1044 const result = member_fn(instance);1057 const result = member_fn(instance);
1045 if (result != 1234) {1058 if (result != 1234) {
1046 %%stdout.printf("BAD\n");1059 %%io.stdout.printf("BAD\n");
1047 }1060 }
1048 %%stdout.printf("OK\n");1061 %%io.stdout.printf("OK\n");
1049}1062}
1050 )SOURCE", "OK\n");1063 )SOURCE", "OK\n");
10511064
1052 add_simple_case("call member function directly", R"SOURCE(1065 add_simple_case("call member function directly", R"SOURCE(
1053import "std.zig";1066const io = @import("std").io;
1054struct Foo {1067struct Foo {
1055 x: i32,1068 x: i32,
1056 fn member(foo: Foo) -> i32 { foo.x }1069 fn member(foo: Foo) -> i32 { foo.x }
...@@ -1059,18 +1072,18 @@ pub fn main(args: [][]u8) -> %void {...@@ -1059,18 +1072,18 @@ pub fn main(args: [][]u8) -> %void {
1059 const instance = Foo { .x = 1234, };1072 const instance = Foo { .x = 1234, };
1060 const result = Foo.member(instance);1073 const result = Foo.member(instance);
1061 if (result != 1234) {1074 if (result != 1234) {
1062 %%stdout.printf("BAD\n");1075 %%io.stdout.printf("BAD\n");
1063 }1076 }
1064 %%stdout.printf("OK\n");1077 %%io.stdout.printf("OK\n");
1065}1078}
1066 )SOURCE", "OK\n");1079 )SOURCE", "OK\n");
10671080
1068 add_simple_case("call result of if else expression", R"SOURCE(1081 add_simple_case("call result of if else expression", R"SOURCE(
1069import "std.zig";1082const io = @import("std").io;
1070fn a() -> []u8 { "a\n" }1083fn a() -> []u8 { "a\n" }
1071fn b() -> []u8 { "b\n" }1084fn b() -> []u8 { "b\n" }
1072fn f(x: bool) {1085fn f(x: bool) {
1073 %%stdout.printf((if (x) a else b)());1086 %%io.stdout.printf((if (x) a else b)());
1074}1087}
1075pub fn main(args: [][]u8) -> %void {1088pub fn main(args: [][]u8) -> %void {
1076 f(true);1089 f(true);
...@@ -1079,15 +1092,10 @@ pub fn main(args: [][]u8) -> %void {...@@ -1079,15 +1092,10 @@ pub fn main(args: [][]u8) -> %void {
1079 )SOURCE", "a\nb\n");1092 )SOURCE", "a\nb\n");
10801093
10811094
1082 add_simple_case("expose function pointer to C land", R"SOURCE(1095 add_simple_case_libc("expose function pointer to C land", R"SOURCE(
1083#link("c")1096const c = @c_import(@c_include("stdlib.h"));
1084export executable "test";
1085
1086c_import {
1087 @c_include("stdlib.h");
1088}
10891097
1090export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {1098export fn compare_fn(a: ?&const c.c_void, b: ?&const c.c_void) -> c_int {
1091 const a_int = (&i32)(a ?? unreachable{});1099 const a_int = (&i32)(a ?? unreachable{});
1092 const b_int = (&i32)(b ?? unreachable{});1100 const b_int = (&i32)(b ?? unreachable{});
1093 if (*a_int < *b_int) {1101 if (*a_int < *b_int) {
...@@ -1102,11 +1110,11 @@ export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {...@@ -1102,11 +1110,11 @@ export fn compare_fn(a: ?&const c_void, b: ?&const c_void) -> c_int {
1102export fn main(args: c_int, argv: &&u8) -> c_int {1110export fn main(args: c_int, argv: &&u8) -> c_int {
1103 var array = []i32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };1111 var array = []i32 { 1, 7, 3, 2, 0, 9, 4, 8, 6, 5 };
11041112
1105 qsort((&c_void)(&array[0]), c_ulong(array.len), @sizeof(i32), compare_fn);1113 c.qsort((&c.c_void)(&array[0]), c_ulong(array.len), @sizeof(i32), compare_fn);
11061114
1107 for (array) |item, i| {1115 for (array) |item, i| {
1108 if (item != i) {1116 if (item != i) {
1109 abort();1117 c.abort();
1110 }1118 }
1111 }1119 }
11121120
...@@ -1116,37 +1124,33 @@ export fn main(args: c_int, argv: &&u8) -> c_int {...@@ -1116,37 +1124,33 @@ export fn main(args: c_int, argv: &&u8) -> c_int {
11161124
11171125
11181126
1119 add_simple_case("casting between float and integer types", R"SOURCE(1127 add_simple_case_libc("casting between float and integer types", R"SOURCE(
1120#link("c")1128const c = @c_import(@c_include("stdio.h"));
1121export executable "test";
1122c_import {
1123 @c_include("stdio.h");
1124}
1125export fn main(argc: c_int, argv: &&u8) -> c_int {1129export fn main(argc: c_int, argv: &&u8) -> c_int {
1126 const small: f32 = 3.25;1130 const small: f32 = 3.25;
1127 const x: f64 = small;1131 const x: f64 = small;
1128 const y = i32(x);1132 const y = i32(x);
1129 const z = f64(y);1133 const z = f64(y);
1130 printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4));1134 c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, f64(-0.4));
1131 return 0;1135 return 0;
1132}1136}
1133 )SOURCE", "3.25\n3\n3.00\n-0.40\n");1137 )SOURCE", "3.25\n3\n3.00\n-0.40\n");
11341138
11351139
1136 add_simple_case("const expression eval handling of variables", R"SOURCE(1140 add_simple_case("const expression eval handling of variables", R"SOURCE(
1137import "std.zig";1141const io = @import("std").io;
1138pub fn main(args: [][]u8) -> %void {1142pub fn main(args: [][]u8) -> %void {
1139 var x = true;1143 var x = true;
1140 while (x) {1144 while (x) {
1141 x = false;1145 x = false;
1142 }1146 }
1143 %%stdout.printf("OK\n");1147 %%io.stdout.printf("OK\n");
1144}1148}
1145 )SOURCE", "OK\n");1149 )SOURCE", "OK\n");
11461150
11471151
1148 add_simple_case("incomplete struct parameter top level decl", R"SOURCE(1152 add_simple_case("incomplete struct parameter top level decl", R"SOURCE(
1149import "std.zig";1153const io = @import("std").io;
1150struct A {1154struct A {
1151 b: B,1155 b: B,
1152}1156}
...@@ -1159,7 +1163,7 @@ struct C {...@@ -1159,7 +1163,7 @@ struct C {
1159 x: i32,1163 x: i32,
11601164
1161 fn d(c: C) {1165 fn d(c: C) {
1162 %%stdout.printf("OK\n");1166 %%io.stdout.printf("OK\n");
1163 }1167 }
1164}1168}
11651169
...@@ -1182,7 +1186,7 @@ pub fn main(args: [][]u8) -> %void {...@@ -1182,7 +1186,7 @@ pub fn main(args: [][]u8) -> %void {
11821186
11831187
1184 add_simple_case("same named methods in incomplete struct", R"SOURCE(1188 add_simple_case("same named methods in incomplete struct", R"SOURCE(
1185import "std.zig";1189const io = @import("std").io;
11861190
1187struct Foo {1191struct Foo {
1188 field1: Bar,1192 field1: Bar,
...@@ -1200,53 +1204,53 @@ pub fn main(args: [][]u8) -> %void {...@@ -1200,53 +1204,53 @@ pub fn main(args: [][]u8) -> %void {
1200 const bar = Bar {.field2 = 13,};1204 const bar = Bar {.field2 = 13,};
1201 const foo = Foo {.field1 = bar,};1205 const foo = Foo {.field1 = bar,};
1202 if (!foo.method()) {1206 if (!foo.method()) {
1203 %%stdout.printf("BAD\n");1207 %%io.stdout.printf("BAD\n");
1204 }1208 }
1205 if (!bar.method()) {1209 if (!bar.method()) {
1206 %%stdout.printf("BAD\n");1210 %%io.stdout.printf("BAD\n");
1207 }1211 }
1208 %%stdout.printf("OK\n");1212 %%io.stdout.printf("OK\n");
1209}1213}
1210 )SOURCE", "OK\n");1214 )SOURCE", "OK\n");
12111215
12121216
1213 add_simple_case("defer with only fallthrough", R"SOURCE(1217 add_simple_case("defer with only fallthrough", R"SOURCE(
1214import "std.zig";1218const io = @import("std").io;
1215pub fn main(args: [][]u8) -> %void {1219pub fn main(args: [][]u8) -> %void {
1216 %%stdout.printf("before\n");1220 %%io.stdout.printf("before\n");
1217 defer %%stdout.printf("defer1\n");1221 defer %%io.stdout.printf("defer1\n");
1218 defer %%stdout.printf("defer2\n");1222 defer %%io.stdout.printf("defer2\n");
1219 defer %%stdout.printf("defer3\n");1223 defer %%io.stdout.printf("defer3\n");
1220 %%stdout.printf("after\n");1224 %%io.stdout.printf("after\n");
1221}1225}
1222 )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");1226 )SOURCE", "before\nafter\ndefer3\ndefer2\ndefer1\n");
12231227
12241228
1225 add_simple_case("defer with return", R"SOURCE(1229 add_simple_case("defer with return", R"SOURCE(
1226import "std.zig";1230const io = @import("std").io;
1227pub fn main(args: [][]u8) -> %void {1231pub fn main(args: [][]u8) -> %void {
1228 %%stdout.printf("before\n");1232 %%io.stdout.printf("before\n");
1229 defer %%stdout.printf("defer1\n");1233 defer %%io.stdout.printf("defer1\n");
1230 defer %%stdout.printf("defer2\n");1234 defer %%io.stdout.printf("defer2\n");
1231 if (args.len == 1) return;1235 if (args.len == 1) return;
1232 defer %%stdout.printf("defer3\n");1236 defer %%io.stdout.printf("defer3\n");
1233 %%stdout.printf("after\n");1237 %%io.stdout.printf("after\n");
1234}1238}
1235 )SOURCE", "before\ndefer2\ndefer1\n");1239 )SOURCE", "before\ndefer2\ndefer1\n");
12361240
12371241
1238 add_simple_case("%defer and it fails", R"SOURCE(1242 add_simple_case("%defer and it fails", R"SOURCE(
1239import "std.zig";1243const io = @import("std").io;
1240pub fn main(args: [][]u8) -> %void {1244pub fn main(args: [][]u8) -> %void {
1241 do_test() %% return;1245 do_test() %% return;
1242}1246}
1243fn do_test() -> %void {1247fn do_test() -> %void {
1244 %%stdout.printf("before\n");1248 %%io.stdout.printf("before\n");
1245 defer %%stdout.printf("defer1\n");1249 defer %%io.stdout.printf("defer1\n");
1246 %defer %%stdout.printf("deferErr\n");1250 %defer %%io.stdout.printf("deferErr\n");
1247 %return its_gonna_fail();1251 %return its_gonna_fail();
1248 defer %%stdout.printf("defer3\n");1252 defer %%io.stdout.printf("defer3\n");
1249 %%stdout.printf("after\n");1253 %%io.stdout.printf("after\n");
1250}1254}
1251error IToldYouItWouldFail;1255error IToldYouItWouldFail;
1252fn its_gonna_fail() -> %void {1256fn its_gonna_fail() -> %void {
...@@ -1256,17 +1260,17 @@ fn its_gonna_fail() -> %void {...@@ -1256,17 +1260,17 @@ fn its_gonna_fail() -> %void {
12561260
12571261
1258 add_simple_case("%defer and it passes", R"SOURCE(1262 add_simple_case("%defer and it passes", R"SOURCE(
1259import "std.zig";1263const io = @import("std").io;
1260pub fn main(args: [][]u8) -> %void {1264pub fn main(args: [][]u8) -> %void {
1261 do_test() %% return;1265 do_test() %% return;
1262}1266}
1263fn do_test() -> %void {1267fn do_test() -> %void {
1264 %%stdout.printf("before\n");1268 %%io.stdout.printf("before\n");
1265 defer %%stdout.printf("defer1\n");1269 defer %%io.stdout.printf("defer1\n");
1266 %defer %%stdout.printf("deferErr\n");1270 %defer %%io.stdout.printf("deferErr\n");
1267 %return its_gonna_pass();1271 %return its_gonna_pass();
1268 defer %%stdout.printf("defer3\n");1272 defer %%io.stdout.printf("defer3\n");
1269 %%stdout.printf("after\n");1273 %%io.stdout.printf("after\n");
1270}1274}
1271fn its_gonna_pass() -> %void { }1275fn its_gonna_pass() -> %void { }
1272 )SOURCE", "before\nafter\ndefer3\ndefer1\n");1276 )SOURCE", "before\nafter\ndefer3\ndefer1\n");
...@@ -1327,14 +1331,9 @@ fn a() {...@@ -1327,14 +1331,9 @@ fn a() {
1327fn b() {}1331fn b() {}
1328 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");1332 )SOURCE", 1, ".tmp_source.zig:4:5: error: unreachable code");
13291333
1330 add_compile_fail_case("bad version string", R"SOURCE(
1331#version("aoeu")
1332export executable "test";
1333 )SOURCE", 1, ".tmp_source.zig:2:1: error: invalid version string");
1334
1335 add_compile_fail_case("bad import", R"SOURCE(1334 add_compile_fail_case("bad import", R"SOURCE(
1336import "bogus-does-not-exist.zig";1335const bogus = @import("bogus-does-not-exist.zig");
1337 )SOURCE", 1, ".tmp_source.zig:2:1: error: unable to find 'bogus-does-not-exist.zig'");1336 )SOURCE", 1, ".tmp_source.zig:2:15: error: unable to find 'bogus-does-not-exist.zig'");
13381337
1339 add_compile_fail_case("undeclared identifier", R"SOURCE(1338 add_compile_fail_case("undeclared identifier", R"SOURCE(
1340fn a() {1339fn a() {
...@@ -1450,13 +1449,13 @@ fn f() {...@@ -1450,13 +1449,13 @@ fn f() {
14501449
1451 add_compile_fail_case("direct struct loop", R"SOURCE(1450 add_compile_fail_case("direct struct loop", R"SOURCE(
1452struct A { a : A, }1451struct A { a : A, }
1453 )SOURCE", 1, ".tmp_source.zig:2:1: error: struct has infinite size");1452 )SOURCE", 1, ".tmp_source.zig:2:1: error: 'A' depends on itself");
14541453
1455 add_compile_fail_case("indirect struct loop", R"SOURCE(1454 add_compile_fail_case("indirect struct loop", R"SOURCE(
1456struct A { b : B, }1455struct A { b : B, }
1457struct B { c : C, }1456struct B { c : C, }
1458struct C { a : A, }1457struct C { a : A, }
1459 )SOURCE", 1, ".tmp_source.zig:4:1: error: struct has infinite size");1458 )SOURCE", 1, ".tmp_source.zig:2:1: error: 'A' depends on itself");
14601459
1461 add_compile_fail_case("invalid struct field", R"SOURCE(1460 add_compile_fail_case("invalid struct field", R"SOURCE(
1462struct A { x : i32, }1461struct A { x : i32, }
...@@ -1568,7 +1567,7 @@ fn f() -> @bogus(foo) {...@@ -1568,7 +1567,7 @@ fn f() -> @bogus(foo) {
1568 add_compile_fail_case("top level decl dependency loop", R"SOURCE(1567 add_compile_fail_case("top level decl dependency loop", R"SOURCE(
1569const a : @typeof(b) = 0;1568const a : @typeof(b) = 0;
1570const b : @typeof(a) = 0;1569const b : @typeof(a) = 0;
1571 )SOURCE", 1, ".tmp_source.zig:3:19: error: use of undeclared identifier 'a'");1570 )SOURCE", 1, ".tmp_source.zig:2:1: error: 'a' depends on itself");
15721571
1573 add_compile_fail_case("noalias on non pointer param", R"SOURCE(1572 add_compile_fail_case("noalias on non pointer param", R"SOURCE(
1574fn f(noalias x: i32) {}1573fn f(noalias x: i32) {}
...@@ -1589,8 +1588,11 @@ struct Bar {}...@@ -1589,8 +1588,11 @@ struct Bar {}
1589fn f(Foo: i32) {1588fn f(Foo: i32) {
1590 var Bar : i32 = undefined;1589 var Bar : i32 = undefined;
1591}1590}
1592 )SOURCE", 2, ".tmp_source.zig:5:6: error: variable shadows type 'Foo'",1591 )SOURCE", 4,
1593 ".tmp_source.zig:6:5: error: variable shadows type 'Bar'");1592 ".tmp_source.zig:5:6: error: redefinition of 'Foo'",
1593 ".tmp_source.zig:2:1: note: previous definition is here",
1594 ".tmp_source.zig:6:5: error: redefinition of 'Bar'",
1595 ".tmp_source.zig:3:1: note: previous definition is here");
15941596
1595 add_compile_fail_case("multiple else prongs in a switch", R"SOURCE(1597 add_compile_fail_case("multiple else prongs in a switch", R"SOURCE(
1596fn f(x: u32) {1598fn f(x: u32) {
...@@ -1614,14 +1616,9 @@ fn f(s: []u8) -> []u8 {...@@ -1614,14 +1616,9 @@ fn f(s: []u8) -> []u8 {
1614 )SOURCE", 1, ".tmp_source.zig:3:5: error: string concatenation requires constant expression");1616 )SOURCE", 1, ".tmp_source.zig:3:5: error: string concatenation requires constant expression");
16151617
1616 add_compile_fail_case("c_import with bogus include", R"SOURCE(1618 add_compile_fail_case("c_import with bogus include", R"SOURCE(
1617c_import {1619const c = @c_import(@c_include("bogus.h"));
1618 @c_include("bogus.h");1620 )SOURCE", 2, ".tmp_source.zig:2:11: error: C import failed",
1619}1621 ".h:1:10: note: 'bogus.h' file not found");
1620 )SOURCE", 2, ".tmp_source.zig:2:1: error: C import failed",
1621 ".h:1:10: error: 'bogus.h' file not found");
1622
1623 add_compile_fail_case("empty file", "",
1624 1, ".tmp_source.zig:1:1: error: missing export declaration and output name not provided");
16251622
1626 add_compile_fail_case("address of number literal", R"SOURCE(1623 add_compile_fail_case("address of number literal", R"SOURCE(
1627const x = 3;1624const x = 3;
test/self_hosted.zig+2-1
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1import "test_std.zig";1// test std library
2const std = @import("std");
23
3#attribute("test")4#attribute("test")
4fn empty_function() {}5fn empty_function() {}
test/test_std.zig deleted-1
...@@ -1 +0,0 @@
1import "std.zig";